From 21a8c222e1f2b8b4714dcb7f3e55ed7af8d7eb17 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 10 Jan 2025 15:55:46 +0800 Subject: [PATCH] feat(bitscrambler): add driver support on esp32c5 --- .../src/bitscrambler.c | 6 +- .../src/bitscrambler_esp32c5.c | 21 + .../src/bitscrambler_loopback.c | 26 +- .../test_apps/bitscrambler/CMakeLists.txt | 5 + .../test_apps/bitscrambler/README.md | 4 +- .../bitscrambler/pytest_bitscrambler.py | 3 +- .../hal/esp32c5/include/hal/bitscrambler_ll.h | 373 ++++++++++++++++++ .../hal/esp32p4/include/hal/bitscrambler_ll.h | 39 +- .../hal/include/hal/bitscrambler_types.h | 10 +- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 + .../include/soc/bitscrambler_peri_select.h | 20 + components/soc/esp32c5/include/soc/soc_caps.h | 1 + .../register/soc/bitscrambler_struct.h | 206 +++++++++- .../register/soc/bitscrambler_struct.h | 2 +- docs/docs_not_updated/esp32c5.txt | 2 - docs/doxygen/Doxyfile_esp32c5 | 3 + examples/peripherals/bitscrambler/README.md | 4 +- .../pytest_bitscrambler_loopback_example.py | 1 + 18 files changed, 684 insertions(+), 46 deletions(-) create mode 100644 components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c create mode 100644 components/hal/esp32c5/include/hal/bitscrambler_ll.h create mode 100644 components/soc/esp32c5/include/soc/bitscrambler_peri_select.h diff --git a/components/esp_driver_bitscrambler/src/bitscrambler.c b/components/esp_driver_bitscrambler/src/bitscrambler.c index 8e9f17945cf9..aae1f96d376f 100644 --- a/components/esp_driver_bitscrambler/src/bitscrambler.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler.c @@ -100,6 +100,7 @@ static void enable_clocks(bitscrambler_t *bs) if (ref_count == 0) { //we're the first to enable the BitScrambler module bitscrambler_ll_set_bus_clock_sys_enable(1); bitscrambler_ll_reset_sys(); + bitscrambler_ll_mem_power_by_pmu(); } if (bs->cfg.dir == BITSCRAMBLER_DIR_RX || bs->loopback) { bitscrambler_ll_set_bus_clock_rx_enable(1); @@ -123,6 +124,7 @@ static void disable_clocks(bitscrambler_t *bs) } if (ref_count == 0) { //we're the last to disable the BitScrambler module bitscrambler_ll_set_bus_clock_sys_enable(0); + bitscrambler_ll_mem_force_power_off(); } } } @@ -221,7 +223,7 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra //Set options from header bitscrambler_ll_set_lut_width(bs->hw, bs->cfg.dir, hdr.lut_width); - bitscrambler_ll_set_prefetch_mode(bs->hw, bs->cfg.dir, hdr.prefetch ? BITSCRAMBLER_PREFETCH_ENABLED : BITSCRAMBLER_PREFETCH_DISABLED); + bitscrambler_ll_enable_prefetch_on_reset(bs->hw, bs->cfg.dir, hdr.prefetch); bitscrambler_ll_set_eof_mode(bs->hw, bs->cfg.dir, hdr.eof_on); bitscrambler_ll_set_tailing_bits(bs->hw, bs->cfg.dir, hdr.trailing_bits); //fixed options @@ -298,7 +300,7 @@ esp_err_t bitscrambler_reset(bitscrambler_handle_t handle) //If the halt bit is set, the Bitscrambler should (eventually) go to idle state. If it //does not, something got stuck. int timeout = BITSCRAMBLER_RESET_ITERATIONS; - while ((bitscrambler_ll_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) { + while ((bitscrambler_ll_get_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) { timeout--; } if (timeout == 0) { diff --git a/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c b/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c new file mode 100644 index 000000000000..741fc61af2ee --- /dev/null +++ b/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "soc/gdma_channel.h" +#include "bitscrambler_soc_specific.h" + +// Note: these are indexed by the values of the SOC_BITSCRAMBLER_ATTACH_ defines +// in soc/bitscrambler_peri_select.h +// This map is used by the bitscrambler loopback driver only. + +const bitscrambler_periph_desc_t g_bitscrambler_periph_desc[] = { + [SOC_BITSCRAMBLER_ATTACH_GPSPI2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2), SOC_GDMA_TRIG_PERIPH_SPI2_BUS}, + [SOC_BITSCRAMBLER_ATTACH_UHCI] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0), SOC_GDMA_TRIG_PERIPH_UHCI0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_I2S0] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S, 0), SOC_GDMA_TRIG_PERIPH_I2S0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_AES] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0), SOC_GDMA_TRIG_PERIPH_AES0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_SHA] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA, 0), SOC_GDMA_TRIG_PERIPH_SHA0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_ADC] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0), SOC_GDMA_TRIG_PERIPH_ADC0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_PARL_IO] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0), SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS}, +}; diff --git a/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c index b4f2c199389a..6969f31f435f 100644 --- a/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c @@ -11,6 +11,8 @@ #include "esp_private/gdma_link.h" #include "esp_private/bitscrambler.h" #include "hal/dma_types.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "bitscrambler_private.h" #include "bitscrambler_soc_specific.h" #include "esp_err.h" @@ -18,6 +20,7 @@ #include "esp_heap_caps.h" #include "esp_cache.h" #include "esp_dma_utils.h" +#include "esp_memory_utils.h" const static char *TAG = "bs_loop"; @@ -97,7 +100,11 @@ esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach bs->max_transfer_sz_bytes = max_transfer_sz_bytes; int desc_ct = (max_transfer_sz_bytes + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; int bus = g_bitscrambler_periph_desc[attach_to].bus; +#ifdef SOC_GDMA_BUS_AXI size_t align = (bus == SOC_GDMA_BUS_AXI) ? 8 : 4; +#else + size_t align = 4; +#endif // create DMA link list for TX and RX gdma_link_list_config_t dma_link_cfg = { @@ -239,10 +246,16 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s }; gdma_link_mount_buffers(bsl->rx_link_list, 0, &out_buf_mount_config, 1, NULL); - //Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about - //the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to - //be improved, but potentially needs a fix in esp_cache_msync not to check the size. - esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + int int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + int ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); + + bool need_cache_sync = esp_ptr_internal(buffer_in) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0); + if (need_cache_sync) { + //Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about + //the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to + //be improved, but potentially needs a fix in esp_cache_msync not to check the size. + esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } gdma_start(bsl->rx_channel, gdma_link_get_head_addr(bsl->rx_link_list)); gdma_start(bsl->tx_channel, gdma_link_get_head_addr(bsl->tx_link_list)); @@ -258,7 +271,10 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s ret = ESP_ERR_TIMEOUT; } - esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + need_cache_sync = esp_ptr_internal(buffer_out) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0); + if (need_cache_sync) { + esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + } if (bytes_written) { *bytes_written = gdma_link_count_buffer_size_till_eof(bsl->rx_link_list, 0); diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt b/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt index 7d5f20871e4c..15b0569b511f 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt @@ -6,3 +6,8 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_bitscrambler) + +message(STATUS "Checking bitscrambler registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "bitscrambler" "pcr" "hp_sys_clkrst" + HAL_MODULES "bitscrambler") diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md b/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md index 909282018f26..c40f7cc09732 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-P4 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-P4 | +| ----------------- | -------- | -------- | diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py index 1b73fbd6e86e..d73d1fed4b0b 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic def test_bitscrambler(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/hal/esp32c5/include/hal/bitscrambler_ll.h b/components/hal/esp32c5/include/hal/bitscrambler_ll.h new file mode 100644 index 000000000000..e0bb8b6cde0a --- /dev/null +++ b/components/hal/esp32c5/include/hal/bitscrambler_ll.h @@ -0,0 +1,373 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#pragma once + +#include +#include +#include +#include "soc/bitscrambler_struct.h" +#include "hal/bitscrambler_types.h" +#include "soc/pcr_struct.h" +#include "soc/hp_system_struct.h" +#include "hal/misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL) + +#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW + +/** + * @brief Select peripheral BitScrambler is attached to + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param peri Peripheral to select, should pick the value from soc/bitscrambler_peri_select.h + */ +static inline void bitscrambler_ll_select_peripheral(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int peri) +{ + if (dir == BITSCRAMBLER_DIR_TX) { + HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_tx_sel = peri; + } else { // RX + HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_rx_sel = peri; + } +} + +/** + * @brief Enable the BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_enable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].ena = 1; +} + +/** + * @brief Disable the BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_disable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].ena = 0; +} + + +/** + * @brief Write a word to the instruction memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param inst_idx Instruction to write to + * @param word_idx Word within the instruction to write to + * @param data Data to write + */ +static inline void bitscrambler_ll_instmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx, uint32_t data) +{ + hw->inst_cfg[dir].cfg0.inst_idx = inst_idx; + hw->inst_cfg[dir].cfg0.inst_pos = word_idx; + hw->inst_cfg[dir].cfg1.inst = data; +} + +/** + * @brief Read a word from the instruction memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param inst_idx Instruction to write to + * @param word_idx Word within the instruction to write to + * + * @returns Word read from instruction memory + */ +static inline uint32_t bitscrambler_ll_instmem_read(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx) +{ + hw->inst_cfg[dir].cfg0.inst_idx = inst_idx; + hw->inst_cfg[dir].cfg0.inst_pos = word_idx; + return hw->inst_cfg[dir].cfg1.inst; +} + +/** + * @brief Write a word to LUT memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param word_idx Word within the LUT to write to + * @param data Data to write + */ +static inline void bitscrambler_ll_lutmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int word_idx, uint32_t data) +{ + hw->lut_cfg[dir].cfg0.lut_idx = word_idx; + hw->lut_cfg[dir].cfg1.lut = data; +} + +/** + * @brief Set width of LUT memory (as seen by Bitscrambler, not by host) + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param width Width selection + */ +static inline void bitscrambler_ll_set_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_lut_width_t width) +{ + hw->lut_cfg[dir].cfg0.lut_mode = width; +} + +/** + * @brief Get width of LUT memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline int bitscrambler_ll_get_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + return hw->lut_cfg[dir].cfg0.lut_mode; +} + +/** + * @brief Enable loopback mode, where the RX BitScrambler is disabled and the TX BitScrambler loops + * back to the receive DMA path to memory. + * + * @param hw BitScrambler hardware instance address. + * @param en True if loopback mode is enabled; false otherwise + */ +static inline void bitscrambler_ll_enable_loopback(bitscrambler_dev_t *hw, bool en) +{ + hw->sys.loop_mode = en ? 1 : 0; +} + +/** + * @brief Set condition-checking mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_cond_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_cond_mode_t mode) +{ + hw->ctrl[dir].cond_mode = mode; +} + +/** + * @brief Enable prefetch mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param en True to enable prefetch mode; false to disable + */ +static inline void bitscrambler_ll_enable_prefetch_on_reset(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bool en) +{ + // 0: means do prefetch on reset, 1: means no reset prefetch, user has to load the instruction manually in the assembly code + hw->ctrl[dir].fetch_mode = en ? 0 : 1; +} + +/** + * @brief Set EOF mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_eof_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_eof_mode_t mode) +{ + hw->ctrl[dir].eof_mode = mode; +} + +/** + * @brief Set mode of dummy-reading after EOF + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_dummy_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_dummy_mode_t mode) +{ + hw->ctrl[dir].rd_dummy = mode; +} + +/** + * @brief Set halting mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_halt_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_halt_mode_t mode) +{ + hw->ctrl[dir].halt_mode = mode; +} + +/** + * @brief Set amount of bits to ignore after EOF + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param bitcount Number of bits to ignore + */ +static inline void bitscrambler_ll_set_tailing_bits(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int bitcount) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tail_bits[dir], tailing_bits, bitcount); +} + +/** + * @brief Reset BitScrambler FIFO + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_reset_fifo(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].fifo_rst = 1; + hw->ctrl[dir].fifo_rst = 0; +} + +/** + * @brief Clear trace of EOF counts + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_clear_eof_trace(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->state[dir].eof_trace_clr = 1; + hw->state[dir].eof_trace_clr = 0; +} + +/** + * @brief Set state of BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param state One of BITSCRAMBLER_SET_STATE_[RUN|HALT|PAUSE]. Note the WAIT state cannot be set externally. + */ +static inline void bitscrambler_ll_set_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_set_state_t state) +{ + hw->ctrl[dir].pause = (state == BITSCRAMBLER_SET_STATE_PAUSE) ? 1 : 0; + hw->ctrl[dir].halt = (state == BITSCRAMBLER_SET_STATE_HALT) ? 1 : 0; +} + +/** + * @brief Return current BitScrambler state + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * + * @returns one of BITSCRAMBLER_STATE_* values + */ +static inline bitscrambler_state_t bitscrambler_ll_get_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + if (hw->state[dir].in_idle) { + return BITSCRAMBLER_STATE_IDLE; + } + if (hw->state[dir].in_run) { + return BITSCRAMBLER_STATE_RUN; + } + if (hw->state[dir].in_wait) { + return BITSCRAMBLER_STATE_WAIT; + } + if (hw->state[dir].in_pause) { + return BITSCRAMBLER_STATE_PAUSED; + } + return BITSCRAMBLER_STATE_UNKNOWN; +} + +/** + * @brief Enable the bus clock for BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_sys_enable(bool enable) +{ + PCR.bs_conf.bs_clk_en = enable; +} + +/** + * @brief Enable the bus clock for RX BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_rx_enable(bool enable) +{ + // empty +} + +/** + * @brief Enable the bus clock for TX BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable) +{ + // empty +} + +/** + * @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_on(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pu = 1; + PCR.bs_pd_ctrl.bs_mem_force_pd = 0; +} + +/** + * @brief Force power off the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_off(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pd = 1; + PCR.bs_pd_ctrl.bs_mem_force_pu = 0; +} + +/** + * @brief Power control the bitscrambler memory block by the outside PMU logic + */ +static inline void bitscrambler_ll_mem_power_by_pmu(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pd = 0; + PCR.bs_pd_ctrl.bs_mem_force_pu = 0; +} + +/** + * @brief Reset the BitScrambler module + */ +static inline void _bitscrambler_ll_reset_sys(void) +{ + PCR.bs_conf.bs_rst_en = 1; + PCR.bs_conf.bs_rst_en = 0; +} + +/** + * @brief Reset the BitScrambler RX module + */ +static inline void _bitscrambler_ll_reset_rx(void) +{ + PCR.bs_func_conf.bs_rx_rst_en = 1; + PCR.bs_func_conf.bs_rx_rst_en = 0; +} + +/** + * @brief Reset the BitScrambler TX module + */ +static inline void _bitscrambler_ll_reset_tx(void) +{ + PCR.bs_func_conf.bs_tx_rst_en = 1; + PCR.bs_func_conf.bs_tx_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define bitscrambler_ll_set_bus_clock_sys_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_sys_enable(__VA_ARGS__) +#define bitscrambler_ll_set_bus_clock_rx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_rx_enable(__VA_ARGS__) +#define bitscrambler_ll_set_bus_clock_tx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_tx_enable(__VA_ARGS__) + +#define bitscrambler_ll_reset_sys(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_sys(__VA_ARGS__) +#define bitscrambler_ll_reset_rx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_rx(__VA_ARGS__) +#define bitscrambler_ll_reset_tx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_tx(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32p4/include/hal/bitscrambler_ll.h b/components/hal/esp32p4/include/hal/bitscrambler_ll.h index 78114082d164..647cd75a3f5c 100644 --- a/components/hal/esp32p4/include/hal/bitscrambler_ll.h +++ b/components/hal/esp32p4/include/hal/bitscrambler_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -158,15 +158,16 @@ static inline void bitscrambler_ll_set_cond_mode(bitscrambler_dev_t *hw, bitscra } /** - * @brief Set prefetch mode + * @brief Enable prefetch mode * * @param hw BitScrambler hardware instance address. * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX - * @param mode Mode to set + * @param en True to enable prefetch mode; false to disable */ -static inline void bitscrambler_ll_set_prefetch_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_prefetch_mode_t mode) +static inline void bitscrambler_ll_enable_prefetch_on_reset(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bool en) { - hw->ctrl[dir].fetch_mode = mode; + // 0: means do prefetch on reset, 1: means no reset prefetch, user has to load the instruction manually in the assembly code + hw->ctrl[dir].fetch_mode = en ? 0 : 1; } /** @@ -214,7 +215,7 @@ static inline void bitscrambler_ll_set_halt_mode(bitscrambler_dev_t *hw, bitscra */ static inline void bitscrambler_ll_set_tailing_bits(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int bitcount) { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tailing_bits[dir], tailing_bits, bitcount); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tail_bits[dir], tailing_bits, bitcount); } /** @@ -262,7 +263,7 @@ static inline void bitscrambler_ll_set_state(bitscrambler_dev_t *hw, bitscramble * * @returns one of BITSCRAMBLER_STATE_* values */ -static inline bitscrambler_state_t bitscrambler_ll_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +static inline bitscrambler_state_t bitscrambler_ll_get_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) { if (hw->state[dir].in_idle) { return BITSCRAMBLER_STATE_IDLE; @@ -303,6 +304,30 @@ static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable) HP_SYS_CLKRST.soc_clk_ctrl1.reg_bitscrambler_tx_sys_clk_en = enable; } +/** + * @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_on(void) +{ + // empty +} + +/** + * @brief Force power off the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_off(void) +{ + // empty +} + +/** + * @brief Power control the bitscrambler memory block by the outside PMU logic + */ +static inline void bitscrambler_ll_mem_power_by_pmu(void) +{ + // empty +} + /** * @brief Reset the BitScrambler module */ diff --git a/components/hal/include/hal/bitscrambler_types.h b/components/hal/include/hal/bitscrambler_types.h index 25f0f8421bc4..56516fa14d7d 100644 --- a/components/hal/include/hal/bitscrambler_types.h +++ b/components/hal/include/hal/bitscrambler_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,14 +44,6 @@ typedef enum { BITSCRAMBLER_COND_MODE_NOTEQUAL = 1, /*!< Use "!=" to generate the condition */ } bitscrambler_cond_mode_t; -/** - * @brief Prefetch mode of bitscrambler - */ -typedef enum { - BITSCRAMBLER_PREFETCH_ENABLED = 0, /*!< Hardware prefetch is enabled */ - BITSCRAMBLER_PREFETCH_DISABLED = 1, /*!< Hardware prefetch is disabled, but the bitscrambler instructions can still do the prefetch */ -} bitscrambler_prefetch_mode_t; - /** * @brief Halt mode of bitscrambler */ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 4d7cfaf710b6..77670c4e895a 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -251,6 +251,10 @@ config SOC_PHY_SUPPORTED bool default y +config SOC_BITSCRAMBLER_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y diff --git a/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h b/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h new file mode 100644 index 000000000000..131bcfaa232b --- /dev/null +++ b/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/* + * @brief BitScrambler attachment targets + * Note that these are the values written to HP_SYSTEM_BITSCRAMBLER_PERI_SEL_REG. + */ + +#define SOC_BITSCRAMBLER_ATTACH_GPSPI2 1 +#define SOC_BITSCRAMBLER_ATTACH_UHCI 2 +#define SOC_BITSCRAMBLER_ATTACH_I2S0 3 +#define SOC_BITSCRAMBLER_ATTACH_AES 4 +#define SOC_BITSCRAMBLER_ATTACH_SHA 5 +#define SOC_BITSCRAMBLER_ATTACH_ADC 6 +#define SOC_BITSCRAMBLER_ATTACH_PARL_IO 7 +#define SOC_BITSCRAMBLER_ATTACH_MAX 7 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 911977a2edff..a33e04ba2fa9 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -84,6 +84,7 @@ #define SOC_SPIRAM_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 #define SOC_PHY_SUPPORTED 1 +#define SOC_BITSCRAMBLER_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 diff --git a/components/soc/esp32c5/register/soc/bitscrambler_struct.h b/components/soc/esp32c5/register/soc/bitscrambler_struct.h index 7bf84e8264be..dc98ec027b12 100644 --- a/components/soc/esp32c5/register/soc/bitscrambler_struct.h +++ b/components/soc/esp32c5/register/soc/bitscrambler_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -405,22 +405,198 @@ typedef union { uint32_t val; } bitscrambler_version_reg_t; +///////////////////// TX and RX registers are exactly the same ////////////////////////////////// +// The following registers are used for both TX and RX, so we can use the same struct for both // +///////////////////////////////////////////////////////////////////////////////////////////////// + +/** Type of inst_cfg0 register + * Control and configuration registers + */ +typedef union { + struct { + /** inst_idx : R/W; bitpos: [2:0]; default: 0; + * write this bits to specify the one of 8 instruction + */ + uint32_t inst_idx:3; + /** inst_pos : R/W; bitpos: [6:3]; default: 0; + * write this bits to specify the bit position of 257 bit instruction which in units + * of 32 bits + */ + uint32_t inst_pos:4; + uint32_t reserved_7:25; + }; + uint32_t val; +} bitscrambler_inst_cfg0_reg_t; + +/** Type of inst_cfg1 register + * Control and configuration registers + */ +typedef union { + struct { + /** inst : R/W; bitpos: [31:0]; default: 4; + * write this bits to update instruction, Read this bits to get instruction. + */ + uint32_t inst:32; + }; + uint32_t val; +} bitscrambler_inst_cfg1_reg_t; + +/** Type of lut_cfg0 register + * Control and configuration registers + */ +typedef union { + struct { + /** lut_idx : R/W; bitpos: [10:0]; default: 0; + * write this bits to specify the bytes position of LUT RAM based on lut_mode + */ + uint32_t lut_idx:11; + /** lut_mode : R/W; bitpos: [12:11]; default: 0; + * write this bits to specify the bytes mode of LUT RAM, 0: 1 byte,1: 2bytes, 2: 4 + * bytes + */ + uint32_t lut_mode:2; + uint32_t reserved_13:19; + }; + uint32_t val; +} bitscrambler_lut_cfg0_reg_t; + +/** Type of lut_cfg1 register + * Control and configuration registers + */ +typedef union { + struct { + /** lut : R/W; bitpos: [31:0]; default: 20; + * write this bits to update LUT, Read this bits to get LUT + */ + uint32_t lut:32; + }; + uint32_t val; +} bitscrambler_lut_cfg1_reg_t; + +/** Type of tailing_bits register + * Control and configuration registers + */ +typedef union { + struct { + /** tailing_bits : R/W; bitpos: [15:0]; default: 0; + * write this bits to specify the extra data bit length after getting EOF + */ + uint32_t tailing_bits:16; + uint32_t reserved_16:16; + }; + uint32_t val; +} bitscrambler_tailing_bits_reg_t; + +/** Type of ctrl register + * Control and configuration registers + */ +typedef union { + struct { + /** ena : R/W; bitpos: [0]; default: 0; + * write this bit to enable the bitscrambler tx + */ + uint32_t ena:1; + /** pause : R/W; bitpos: [1]; default: 0; + * write this bit to pause the bitscrambler tx core + */ + uint32_t pause:1; + /** halt : R/W; bitpos: [2]; default: 1; + * write this bit to halt the bitscrambler tx core + */ + uint32_t halt:1; + /** eof_mode : R/W; bitpos: [3]; default: 0; + * write this bit to ser the bitscrambler tx core EOF signal generating mode which is + * combined with reg_bitscrambler_tailing_bits, 0: counter by read dma fifo, 0 + * counter by write peripheral buffer + */ + uint32_t eof_mode:1; + /** cond_mode : R/W; bitpos: [4]; default: 0; + * write this bit to specify the LOOP instruction condition mode of bitscrambler tx + * core, 0: use the little than operator to get the condition, 1: use not equal + * operator to get the condition + */ + uint32_t cond_mode:1; + /** fetch_mode : R/W; bitpos: [5]; default: 0; + * write this bit to set the bitscrambler tx core fetch instruction mode, 0: prefetch + * by reset, 1: fetch by instructions + */ + uint32_t fetch_mode:1; + /** halt_mode : R/W; bitpos: [6]; default: 0; + * write this bit to set the bitscrambler tx core halt mode when halt is set, 0: + * wait write data back done, , 1: ignore write data back + */ + uint32_t halt_mode:1; + /** rd_dummy : R/W; bitpos: [7]; default: 0; + * write this bit to set the bitscrambler tx core read data mode when EOF received.0: + * wait read data, 1: ignore read data + */ + uint32_t rd_dummy:1; + /** fifo_rst : WT; bitpos: [8]; default: 0; + * write this bit to reset the bitscrambler tx fifo + */ + uint32_t fifo_rst:1; + uint32_t reserved_9:23; + }; + uint32_t val; +} bitscrambler_ctrl_reg_t; + +/** Group: Status registers */ +/** Type of state register + * Status registers + */ +typedef union { + struct { + /** in_idle : RO; bitpos: [0]; default: 1; + * represents the bitscrambler tx core in halt mode + */ + uint32_t in_idle:1; + /** in_run : RO; bitpos: [1]; default: 0; + * represents the bitscrambler tx core in run mode + */ + uint32_t in_run:1; + /** in_wait : RO; bitpos: [2]; default: 0; + * represents the bitscrambler tx core in wait mode to wait write back done + */ + uint32_t in_wait:1; + /** in_pause : RO; bitpos: [3]; default: 0; + * represents the bitscrambler tx core in pause mode + */ + uint32_t in_pause:1; + /** fifo_empty : RO; bitpos: [4]; default: 0; + * represents the bitscrambler tx fifo in empty state + */ + uint32_t fifo_empty:1; + uint32_t reserved_5:11; + /** eof_get_cnt : RO; bitpos: [29:16]; default: 0; + * represents the bytes numbers of bitscrambler tx core when get EOF + */ + uint32_t eof_get_cnt:14; + /** eof_overload : RO; bitpos: [30]; default: 0; + * represents the some EOFs will be lost for bitscrambler tx core + */ + uint32_t eof_overload:1; + /** eof_trace_clr : WT; bitpos: [31]; default: 0; + * write this bit to clear reg_bitscrambler_eof_overload and + * reg_bitscrambler_eof_get_cnt registers + */ + uint32_t eof_trace_clr:1; + }; + uint32_t val; +} bitscrambler_state_reg_t; + typedef struct { - volatile bitscrambler_tx_inst_cfg0_reg_t tx_inst_cfg0; - volatile bitscrambler_tx_inst_cfg1_reg_t tx_inst_cfg1; - volatile bitscrambler_rx_inst_cfg0_reg_t rx_inst_cfg0; - volatile bitscrambler_rx_inst_cfg1_reg_t rx_inst_cfg1; - volatile bitscrambler_tx_lut_cfg0_reg_t tx_lut_cfg0; - volatile bitscrambler_tx_lut_cfg1_reg_t tx_lut_cfg1; - volatile bitscrambler_rx_lut_cfg0_reg_t rx_lut_cfg0; - volatile bitscrambler_rx_lut_cfg1_reg_t rx_lut_cfg1; - volatile bitscrambler_tx_tailing_bits_reg_t tx_tailing_bits; - volatile bitscrambler_rx_tailing_bits_reg_t rx_tailing_bits; - volatile bitscrambler_tx_ctrl_reg_t tx_ctrl; - volatile bitscrambler_rx_ctrl_reg_t rx_ctrl; - volatile bitscrambler_tx_state_reg_t tx_state; - volatile bitscrambler_rx_state_reg_t rx_state; + volatile struct { + bitscrambler_inst_cfg0_reg_t cfg0; + bitscrambler_inst_cfg1_reg_t cfg1; + } inst_cfg[2]; + volatile struct { + bitscrambler_lut_cfg0_reg_t cfg0; + bitscrambler_lut_cfg1_reg_t cfg1; + } lut_cfg[2]; + volatile bitscrambler_tailing_bits_reg_t tail_bits[2]; + volatile bitscrambler_ctrl_reg_t ctrl[2]; + volatile bitscrambler_state_reg_t state[2]; uint32_t reserved_038[48]; volatile bitscrambler_sys_reg_t sys; volatile bitscrambler_version_reg_t version; diff --git a/components/soc/esp32p4/register/soc/bitscrambler_struct.h b/components/soc/esp32p4/register/soc/bitscrambler_struct.h index aeb4fee033c1..c21874b22666 100644 --- a/components/soc/esp32p4/register/soc/bitscrambler_struct.h +++ b/components/soc/esp32p4/register/soc/bitscrambler_struct.h @@ -593,7 +593,7 @@ typedef struct { bitscrambler_lut_cfg0_reg_t cfg0; bitscrambler_lut_cfg1_reg_t cfg1; } lut_cfg[2]; - volatile bitscrambler_tailing_bits_reg_t tailing_bits[2]; + volatile bitscrambler_tailing_bits_reg_t tail_bits[2]; volatile bitscrambler_ctrl_reg_t ctrl[2]; volatile bitscrambler_state_reg_t state[2]; uint32_t reserved_038[48]; diff --git a/docs/docs_not_updated/esp32c5.txt b/docs/docs_not_updated/esp32c5.txt index ad52183126b8..65bf76fc83ef 100644 --- a/docs/docs_not_updated/esp32c5.txt +++ b/docs/docs_not_updated/esp32c5.txt @@ -24,9 +24,7 @@ api-reference/storage/fatfsgen.rst api-reference/storage/index.rst api-reference/storage/nvs_partition_parse.rst api-reference/peripherals/twai.rst -api-reference/peripherals/gptimer.rst api-reference/peripherals/touch_element.rst -api-reference/peripherals/lcd.rst api-reference/peripherals/spi_features.rst api-reference/peripherals/touch_pad.rst api-reference/peripherals/sd_pullup_requirements.rst diff --git a/docs/doxygen/Doxyfile_esp32c5 b/docs/doxygen/Doxyfile_esp32c5 index 853631e4efb9..1d3f3c758456 100644 --- a/docs/doxygen/Doxyfile_esp32c5 +++ b/docs/doxygen/Doxyfile_esp32c5 @@ -1,4 +1,7 @@ INPUT += \ + $(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler.h \ + $(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler_loopback.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/bitscrambler_peri_select.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_i2c.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_uart.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_etm.h \ diff --git a/examples/peripherals/bitscrambler/README.md b/examples/peripherals/bitscrambler/README.md index 617285ed85ff..6a5f00a00d22 100644 --- a/examples/peripherals/bitscrambler/README.md +++ b/examples/peripherals/bitscrambler/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-P4 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-P4 | +| ----------------- | -------- | -------- | # BitScrambler Loopback Example diff --git a/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py index d627629f9730..df9bbf7617ff 100644 --- a/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py +++ b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py @@ -5,6 +5,7 @@ @pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic def test_bitscrambler_loopback_example(dut: Dut) -> None: dut.expect_exact('BitScrambler example main', timeout=5)