From 1e6c61daa6b6ea79d0e1ae1652e1ee76b02cee7b Mon Sep 17 00:00:00 2001 From: wanlei Date: Thu, 9 Mar 2023 15:07:21 +0800 Subject: [PATCH] spi_master: sct mode support set line mode, transaction interval time support line mode 1-2-4-8 depend on targets. fix sct mode dma descriptor counter compute issue. add conf_bits_len setting API to control interval time. --- .../spi/master/main/test_spi_master_sct.c | 154 +----------------- .../include/driver/spi_master.h | 1 + .../esp_driver_spi/src/gpspi/spi_master.c | 41 ++++- components/hal/esp32c2/include/hal/spi_ll.h | 58 ++++++- components/hal/esp32c3/include/hal/spi_ll.h | 58 ++++++- components/hal/esp32c6/include/hal/spi_ll.h | 2 +- components/hal/esp32h2/include/hal/spi_ll.h | 65 +++++++- components/hal/esp32s2/include/hal/spi_ll.h | 79 ++++++++- components/hal/esp32s3/include/hal/spi_ll.h | 66 +++++++- components/hal/include/hal/spi_hal.h | 12 ++ components/hal/spi_hal.c | 3 + components/hal/spi_hal_iram.c | 11 +- .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c2/include/soc/soc_caps.h | 1 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c3/include/soc/soc_caps.h | 1 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h2/include/soc/soc_caps.h | 1 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s2/include/soc/soc_caps.h | 1 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s3/include/soc/soc_caps.h | 1 + 22 files changed, 398 insertions(+), 177 deletions(-) diff --git a/components/driver/test_apps/spi/master/main/test_spi_master_sct.c b/components/driver/test_apps/spi/master/main/test_spi_master_sct.c index 1c30d267b4..915a520b16 100644 --- a/components/driver/test_apps/spi/master/main/test_spi_master_sct.c +++ b/components/driver/test_apps/spi/master/main/test_spi_master_sct.c @@ -22,158 +22,6 @@ __attribute__((unused)) static const char *TAG = "SCT"; -#if SOC_SPI_SCT_SUPPORTED -/*----------------------------------------------------------- - * FD SCT Functional Test - *-----------------------------------------------------------*/ -#define TEST_FD_SEG_NUM 4 -#define TEST_FD_LEN 8 -#define TEST_FD_LEN_STEP 8 -#define TEST_FD_LEN_MAX 32 - - -#include "soc/spi_struct.h" - -static void fd_master(void) -{ - spi_device_handle_t handle; - - spi_bus_config_t buscfg={ - .mosi_io_num = SPI2_IOMUX_PIN_NUM_MOSI, - .miso_io_num = SPI2_IOMUX_PIN_NUM_MISO, - .sclk_io_num = SPI2_IOMUX_PIN_NUM_CLK, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 4092 * 10, - }; - - spi_device_interface_config_t devcfg = { - .command_bits = 0, - .address_bits = 0, - .dummy_bits = 0, - .clock_speed_hz = 10 * 1000, - .duty_cycle_pos = 128, //50% duty cycle - .mode = 0, - .spics_io_num = SPI2_IOMUX_PIN_NUM_CS, - .cs_ena_posttrans = 3, //Keep the CS low 3 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than CLK - .queue_size = 3, - }; - - TEST_ESP_OK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - TEST_ESP_OK(spi_bus_add_device(SPI2_HOST, &devcfg, &handle)); - unity_send_signal("Master ready"); - - uint8_t *master_tx_buf[TEST_FD_SEG_NUM] = {}; - uint8_t *master_rx_buf[TEST_FD_SEG_NUM] = {}; - uint8_t *slave_tx_buf[TEST_FD_SEG_NUM] = {}; - uint32_t seed = 199; - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - master_tx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - master_rx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - slave_tx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - get_tx_buffer(seed, master_tx_buf[i], slave_tx_buf[i], TEST_FD_LEN_MAX); - seed++; - } - - uint32_t test_len = TEST_FD_LEN; - spi_seg_transaction_t seg_trans[TEST_FD_SEG_NUM] = {}; - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - seg_trans[i].base.tx_buffer = master_tx_buf[i]; - seg_trans[i].base.rx_buffer = master_rx_buf[i]; - seg_trans[i].base.length = test_len * 8; - test_len += TEST_FD_LEN_STEP; - } - - unity_wait_for_signal("Slave ready"); - spi_seg_transaction_t *ret_seg_trans = NULL; - TEST_ESP_OK(spi_bus_segment_trans_mode_enable(handle, true)); - TEST_ESP_OK(spi_device_queue_segment_trans(handle, seg_trans, TEST_FD_SEG_NUM, portMAX_DELAY)); - TEST_ESP_OK(spi_device_get_segment_trans_result(handle, &ret_seg_trans, portMAX_DELAY)); - TEST_ASSERT(ret_seg_trans == seg_trans); - - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - ESP_LOG_BUFFER_HEX("master tx:", ret_seg_trans[i].base.tx_buffer, ret_seg_trans[i].base.length / 8); - ESP_LOG_BUFFER_HEX("master rx:", ret_seg_trans[i].base.rx_buffer, ret_seg_trans[i].base.length / 8); - printf("\n"); - TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_tx_buf[i], master_rx_buf[i], ret_seg_trans[i].base.length / 8); - - free(master_tx_buf[i]); - free(master_rx_buf[i]); - free(slave_tx_buf[i]); - } - - TEST_ESP_OK(spi_bus_remove_device(handle)); - TEST_ESP_OK(spi_bus_free(SPI2_HOST)); -} - -static void fd_slave(void) -{ - unity_wait_for_signal("Master ready"); - spi_bus_config_t buscfg = { - .mosi_io_num = SPI2_IOMUX_PIN_NUM_MOSI, - .miso_io_num = SPI2_IOMUX_PIN_NUM_MISO, - .sclk_io_num = SPI2_IOMUX_PIN_NUM_CLK, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - }; - - spi_slave_interface_config_t slvcfg = { - .mode = 0, - .spics_io_num = SPI2_IOMUX_PIN_NUM_CS, - .queue_size = 4, - }; - TEST_ESP_OK(spi_slave_initialize(SPI2_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO)); - - uint8_t *slave_tx_buf[TEST_FD_SEG_NUM] = {}; - uint8_t *slave_rx_buf[TEST_FD_SEG_NUM] = {}; - uint8_t *master_tx_buf[TEST_FD_SEG_NUM] = {}; - uint32_t seed = 199; - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - slave_tx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - slave_rx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - master_tx_buf[i] = heap_caps_calloc(1, TEST_FD_LEN_MAX, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - get_tx_buffer(seed, master_tx_buf[i], slave_tx_buf[i], TEST_FD_LEN_MAX); - seed++; - } - - uint32_t test_len = TEST_FD_LEN; - spi_slave_transaction_t trans[TEST_FD_SEG_NUM] = {}; - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - trans[i].tx_buffer = slave_tx_buf[i]; - trans[i].rx_buffer = slave_rx_buf[i]; - trans[i].length = test_len * 8; - test_len += TEST_FD_LEN_STEP; - } - - unity_send_signal("Slave ready"); - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &trans[i], portMAX_DELAY)); - } - - spi_slave_transaction_t *ret_trans = NULL; - for (int i = 0; i < TEST_FD_SEG_NUM; i++) { - ESP_LOGI(TAG, "Slave Trans %d", i); - TEST_ESP_OK(spi_slave_get_trans_result(SPI2_HOST, &ret_trans, portMAX_DELAY)); - TEST_ASSERT(ret_trans == &trans[i]); - - //show result - ESP_LOGI("slave", "trans_len: %d", trans[i].trans_len / 8); - ESP_LOG_BUFFER_HEX("slave tx:", trans[i].tx_buffer, trans[i].length / 8); - ESP_LOG_BUFFER_HEX("slave rx:", trans[i].rx_buffer, trans[i].length / 8); - printf("\n"); - TEST_ASSERT_EQUAL_HEX8_ARRAY(master_tx_buf[i], slave_rx_buf[i], trans[i].length / 8); - - free(slave_tx_buf[i]); - free(slave_rx_buf[i]); - free(master_tx_buf[i]); - } - - TEST_ESP_OK(spi_slave_free(SPI2_HOST)); -} - -TEST_CASE_MULTIPLE_DEVICES("SPI_Master_SCT_FD_Functional", "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]", fd_master, fd_slave); -#endif //#if SOC_SPI_SCT_SUPPORTED - #if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED) /*----------------------------------------------------------- * HD SCT Functional Test @@ -403,6 +251,6 @@ static void hd_slave(void) TEST_ESP_OK(spi_slave_hd_deinit(SPI2_HOST)); } -TEST_CASE_MULTIPLE_DEVICES("SPI_Master_SCT_HD_Functional", "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]", hd_master, hd_slave); +TEST_CASE_MULTIPLE_DEVICES("SPI_Master_SCT_HD_Functional", "[spi_ms]", hd_master, hd_slave); #endif //#if (SOC_SPI_SUPPORT_SLAVE_HD_VER2 && SOC_SPI_SCT_SUPPORTED) diff --git a/components/esp_driver_spi/include/driver/spi_master.h b/components/esp_driver_spi/include/driver/spi_master.h index 43f8ddf647..3c3698046f 100644 --- a/components/esp_driver_spi/include/driver/spi_master.h +++ b/components/esp_driver_spi/include/driver/spi_master.h @@ -192,6 +192,7 @@ typedef struct { uint8_t command_bits; ///< The command length in this transaction, in bits. uint8_t address_bits; ///< The address length in this transaction, in bits. uint8_t dummy_bits; ///< The dummy length in this transaction, in bits. + uint32_t seg_gap_clock_len; ///< The len of CS inactive time between segments, in clocks. uint32_t seg_trans_flags; ///< SCT specific flags. See `SPI_SEG_TRANS_XXX` macros. /**< Necessary buffer required by HW, don't touch this. >**/ diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index 67f3599caf..0579b630be 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -781,6 +781,21 @@ static void SPI_MASTER_ISR_ATTR spi_post_trans(spi_host_t *host) } #if SOC_SPI_SCT_SUPPORTED +static void SPI_MASTER_ISR_ATTR spi_sct_set_hal_trans_config(spi_seg_transaction_t *trans_header, spi_hal_trans_config_t *hal_trans) +{ + spi_transaction_t *trans = &trans_header->base; + + //Set up OIO/QIO/DIO if needed + hal_trans->line_mode.data_lines = (trans->flags & SPI_TRANS_MODE_DIO) ? 2 : (trans->flags & SPI_TRANS_MODE_QIO) ? 4 : 1; +#if SOC_SPI_SUPPORT_OCT + if (trans->flags & SPI_TRANS_MODE_OCT) { + hal_trans->line_mode.data_lines = 8; + } +#endif + hal_trans->line_mode.addr_lines = (trans->flags & SPI_TRANS_MULTILINE_ADDR) ? hal_trans->line_mode.data_lines : 1; + hal_trans->line_mode.cmd_lines = (trans->flags & SPI_TRANS_MULTILINE_CMD) ? hal_trans->line_mode.data_lines : 1; +} + static void SPI_MASTER_ISR_ATTR spi_new_sct_trans(spi_device_t *dev, spi_sct_desc_priv_t *cur_sct_trans) { dev->host->cur_cs = dev->id; @@ -788,6 +803,10 @@ static void SPI_MASTER_ISR_ATTR spi_new_sct_trans(spi_device_t *dev, spi_sct_des //Reconfigure according to device settings, the function only has effect when the dev_id is changed. spi_setup_device(dev); +#if !CONFIG_IDF_TARGET_ESP32S2 + // s2 update this seg_gap_clock_len by dma from conf_buffer + spi_hal_sct_set_conf_bits_len(&dev->host->hal, cur_sct_trans->sct_trans_desc_head->seg_gap_clock_len); +#endif spi_hal_sct_load_dma_link(&dev->host->hal, cur_sct_trans->rx_seg_head, cur_sct_trans->tx_seg_head); if (dev->cfg.pre_cb) { dev->cfg.pre_cb((spi_transaction_t *)cur_sct_trans->sct_trans_desc_head); @@ -869,7 +888,9 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) if (host->sct_mode_enabled) { //cur_cs is changed to DEV_NUM_MAX here spi_post_sct_trans(host); - xQueueSendFromISR(host->device[cs]->ret_queue, &host->cur_sct_trans, &do_yield); + if (!(host->device[cs]->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT)) { + xQueueSendFromISR(host->device[cs]->ret_queue, &host->cur_sct_trans, &do_yield); + } } else #endif //#if SOC_SPI_SCT_SUPPORTED { @@ -1402,6 +1423,7 @@ esp_err_t spi_bus_segment_trans_mode_enable(spi_device_handle_t handle, bool ena { SPI_CHECK(handle, "Invalid arguments.", ESP_ERR_INVALID_ARG); SPI_CHECK(SOC_SPI_SCT_SUPPORTED_PERIPH(handle->host->id), "Invalid arguments", ESP_ERR_INVALID_ARG); + SPI_CHECK(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX, "SCT mode only available under Half Duplex mode", ESP_ERR_INVALID_STATE); SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE); SPI_CHECK(uxQueueMessagesWaiting(handle->trans_queue) == 0, "Cannot enable SCT mode when internal Queue still has items", ESP_ERR_INVALID_STATE); @@ -1432,8 +1454,13 @@ esp_err_t spi_bus_segment_trans_mode_enable(spi_device_handle_t handle, bool ena spi_hal_trans_config_t hal_trans = {}; spi_format_hal_trans_struct(handle, &trans_buf, &hal_trans); spi_hal_setup_trans(hal, hal_dev, &hal_trans); +#if CONFIG_IDF_TARGET_ESP32S2 + // conf_base need ensure transaction gap len more than about 2us under different freq. + // conf_base only configurable on s2. + spi_hal_sct_setup_conf_base(hal, handle->real_clk_freq_hz/600000); +#endif - spi_hal_sct_init(&handle->host->hal); + spi_hal_sct_init(hal); } else { spi_hal_sct_deinit(&handle->host->hal); } @@ -1445,8 +1472,13 @@ esp_err_t spi_bus_segment_trans_mode_enable(spi_device_handle_t handle, bool ena static void SPI_MASTER_ATTR s_sct_init_conf_buffer(spi_hal_context_t *hal, spi_seg_transaction_t *seg_trans_desc, uint32_t seg_num) { + // read from HW need waiting for slower APB clock domain return data, loop to contact slow clock domain will waste time. + // use one imagen then copied by cpu instead. + uint32_t conf_buffer_img[SOC_SPI_SCT_BUFFER_NUM_MAX]; + spi_hal_sct_init_conf_buffer(hal, conf_buffer_img); + for (int i = 0; i < seg_num; i++) { - spi_hal_sct_init_conf_buffer(hal, seg_trans_desc[i].conf_buffer); + memcpy(seg_trans_desc[i].conf_buffer, conf_buffer_img, sizeof(conf_buffer_img)); } } @@ -1503,7 +1535,10 @@ static void SPI_MASTER_ATTR s_sct_format_conf_buffer(spi_device_handle_t handle, if (seg_end) { seg_config.seg_end = true; } + seg_config.seg_gap_len = seg_trans_desc->seg_gap_clock_len; + // set line mode or ... + spi_sct_set_hal_trans_config(seg_trans_desc, &hal->trans_config); spi_hal_sct_format_conf_buffer(hal, &seg_config, hal_dev, seg_trans_desc->conf_buffer); } diff --git a/components/hal/esp32c2/include/hal/spi_ll.h b/components/hal/esp32c2/include/hal/spi_ll.h index 8acbf98906..ddfab2e2ae 100644 --- a/components/hal/esp32c2/include/hal/spi_ll.h +++ b/components/hal/esp32c2/include/hal/spi_ll.h @@ -296,7 +296,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - return hw->cmd.val; + return hw->cmd.usr; } /** @@ -650,8 +650,8 @@ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t li hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); hw->ctrl.fread_dual = (line_mode.data_lines == 2); - hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->user.fwrite_quad = (line_mode.data_lines == 4); } @@ -1302,13 +1302,27 @@ static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode) #define SPI_LL_SCT_MAGIC_NUMBER (0x2) +/** + * Set conf phase bits len to HW for segment config trans mode. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_bitlen Value of field conf_bitslen in cmd reg. + */ +static inline void spi_ll_set_conf_phase_bits_len(spi_dev_t *hw, uint32_t conf_bitlen) +{ + if (conf_bitlen <= SOC_SPI_SCT_CONF_BITLEN_MAX) { + hw->cmd.conf_bitlen = conf_bitlen; + } +} + /** * Update the conf buffer for conf phase * * @param hw Beginning address of the peripheral registers. + * @param is_end Is this transaction the end of this segment. * @param conf_buffer Conf buffer to be updated. */ -static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end) +static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, bool is_end, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { //user reg: usr_conf_nxt if (is_end) { @@ -1318,6 +1332,44 @@ static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t } } +/** + * Update the line mode of conf buffer for conf phase + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode line mode struct of each phase. + * @param conf_buffer Conf buffer to be updated. + */ +static inline void spi_ll_format_line_mode_conf_buff(spi_dev_t *hw, spi_line_mode_t line_mode, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_CTRL_MASK; + conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_USER_MASK; + + switch (line_mode.cmd_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_QUAD_M); break; + default: break; + } + + switch (line_mode.addr_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_QUAD_M); break; + default: break; + } + + switch (line_mode.data_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_DUAL_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_DUAL_M); + break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_QUAD_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_QUAD_M); + break; + default: break; + } +} + /** * Update the conf buffer for prep phase * diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index 97bfad5b50..c99a23e70b 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -298,7 +298,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - return hw->cmd.val; + return hw->cmd.usr; } /** @@ -652,8 +652,8 @@ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t li hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); hw->ctrl.fread_dual = (line_mode.data_lines == 2); - hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->user.fwrite_quad = (line_mode.data_lines == 4); } @@ -1215,13 +1215,27 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) #define SPI_LL_SCT_MAGIC_NUMBER (0x2) +/** + * Set conf phase bits len to HW for segment config trans mode. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_bitlen Value of field conf_bitslen in cmd reg. + */ +static inline void spi_ll_set_conf_phase_bits_len(spi_dev_t *hw, uint32_t conf_bitlen) +{ + if (conf_bitlen <= SOC_SPI_SCT_CONF_BITLEN_MAX) { + hw->cmd.conf_bitlen = conf_bitlen; + } +} + /** * Update the conf buffer for conf phase * * @param hw Beginning address of the peripheral registers. + * @param is_end Is this transaction the end of this segment. * @param conf_buffer Conf buffer to be updated. */ -static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end) +static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, bool is_end, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { //user reg: usr_conf_nxt if (is_end) { @@ -1231,6 +1245,44 @@ static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t } } +/** + * Update the line mode of conf buffer for conf phase + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode line mode struct of each phase. + * @param conf_buffer Conf buffer to be updated. + */ +static inline void spi_ll_format_line_mode_conf_buff(spi_dev_t *hw, spi_line_mode_t line_mode, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_CTRL_MASK; + conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_USER_MASK; + + switch (line_mode.cmd_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_QUAD_M); break; + default: break; + } + + switch (line_mode.addr_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_QUAD_M); break; + default: break; + } + + switch (line_mode.data_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_DUAL_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_DUAL_M); + break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_QUAD_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_QUAD_M); + break; + default: break; + } +} + /** * Update the conf buffer for prep phase * diff --git a/components/hal/esp32c6/include/hal/spi_ll.h b/components/hal/esp32c6/include/hal/spi_ll.h index 05de203fc3..843d0dab21 100644 --- a/components/hal/esp32c6/include/hal/spi_ll.h +++ b/components/hal/esp32c6/include/hal/spi_ll.h @@ -290,7 +290,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - return hw->cmd.val; + return hw->cmd.usr; } /** diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index 68b6434406..89a9f58c45 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -289,7 +289,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - return hw->cmd.val; + return hw->cmd.usr; } /** @@ -643,8 +643,8 @@ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t li hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); hw->ctrl.fread_dual = (line_mode.data_lines == 2); - hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->user.fwrite_quad = (line_mode.data_lines == 4); } @@ -1207,13 +1207,27 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) #define SPI_LL_SCT_MAGIC_NUMBER (0x2) +/** + * Set conf phase bits len to HW for segment config trans mode. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_bitlen Value of field conf_bitslen in cmd reg. + */ +static inline void spi_ll_set_conf_phase_bits_len(spi_dev_t *hw, uint32_t conf_bitlen) +{ + if (conf_bitlen <= SOC_SPI_SCT_CONF_BITLEN_MAX) { + hw->cmd.conf_bitlen = conf_bitlen; + } +} + /** * Update the conf buffer for conf phase * * @param hw Beginning address of the peripheral registers. + * @param is_end Is this transaction the end of this segment. * @param conf_buffer Conf buffer to be updated. */ -static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end) +static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, bool is_end, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { //user reg: usr_conf_nxt if (is_end) { @@ -1223,6 +1237,49 @@ static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t } } +/** + * Update the line mode of conf buffer for conf phase + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode line mode struct of each phase. + * @param conf_buffer Conf buffer to be updated. + */ +static inline void spi_ll_format_line_mode_conf_buff(spi_dev_t *hw, spi_line_mode_t line_mode, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_CTRL_MASK; + conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_USER_MASK; + + switch (line_mode.cmd_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_OCT_M ); break; + default: break; + } + + switch (line_mode.addr_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_OCT_M ); break; + default: break; + } + + switch (line_mode.data_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_DUAL_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_DUAL_M); + break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_QUAD_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_QUAD_M); + break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_OCT_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_OCT_M); + break; + default: break; + } +} + /** * Update the conf buffer for prep phase * @@ -1402,7 +1459,7 @@ __attribute__((always_inline)) static inline void spi_ll_init_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { conf_buffer[SPI_LL_CONF_BITMAP_POS] = 0x7FFF | (SPI_LL_SCT_MAGIC_NUMBER << 28); - conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr; + conf_buffer[SPI_LL_ADDR_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->addr.usr_addr_value; conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->ctrl.val; conf_buffer[SPI_LL_CLOCK_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->clock.val; conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] = hw->user.val; diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 2a0d6f925e..1bd5aa058a 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -644,10 +644,10 @@ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t li hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); hw->ctrl.faddr_oct = (line_mode.addr_lines == 8); hw->ctrl.fread_dual = (line_mode.data_lines == 2); - hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->ctrl.fread_quad = (line_mode.data_lines == 4); - hw->user.fwrite_quad = (line_mode.data_lines == 4); hw->ctrl.fread_oct = (line_mode.data_lines == 8); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->user.fwrite_quad = (line_mode.data_lines == 4); hw->user.fwrite_oct = (line_mode.data_lines == 8); } @@ -1518,13 +1518,43 @@ static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw) #define SPI_LL_SCT_MAGIC_NUMBER (0x2) +/** + * Set conf phase base bits len to HW for segment config trans mode. + * need let transaction gap more than approx 2 us under different freq, calculated by driver layer. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_base Conf base bits len. + */ +static inline void spi_ll_set_conf_base_bitslen(spi_dev_t *hw, uint8_t conf_base) +{ + // 7 bits wide + if(conf_base < 128) { + hw->slv_wrbuf_dlen.conf_base_bitlen = conf_base; + } +} + +/** + * Set conf phase bits len to config buffer for segment config trans mode. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_bitlen Value of field conf_bitslen in cmd reg. + */ +static inline void spi_ll_format_conf_bitslen_buffer(spi_dev_t *hw, uint32_t conf_bitlen, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + //cmd reg: conf_bitlen + if (conf_bitlen <= SOC_SPI_SCT_CONF_BITLEN_MAX) { + SPI_LL_CONF_BUF_SET_FIELD(conf_buffer[SPI_LL_CMD_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_CONF_BITLEN, conf_bitlen); + } +} + /** * Update the conf buffer for conf phase * * @param hw Beginning address of the peripheral registers. + * @param is_end Is this transaction the end of this segment. * @param conf_buffer Conf buffer to be updated. */ -static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end) +static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, bool is_end, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { //user reg: usr_conf_nxt if (is_end) { @@ -1534,6 +1564,49 @@ static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t } } +/** + * Update the line mode of conf buffer for conf phase + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode line mode struct of each phase. + * @param conf_buffer Conf buffer to be updated. + */ +static inline void spi_ll_format_line_mode_conf_buff(spi_dev_t *hw, spi_line_mode_t line_mode, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_CTRL_MASK; + conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_USER_MASK; + + switch (line_mode.cmd_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_OCT_M ); break; + default: break; + } + + switch (line_mode.addr_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_OCT_M ); break; + default: break; + } + + switch (line_mode.data_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_DUAL_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_DUAL_M); + break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_QUAD_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_QUAD_M); + break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_OCT_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_OCT_M); + break; + default: break; + } +} + /** * Update the conf buffer for prep phase * diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index 3c77a79358..3c756ddb87 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -305,7 +305,7 @@ static inline void spi_ll_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - return hw->cmd.val; + return hw->cmd.usr; } /** @@ -661,10 +661,10 @@ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t li hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); hw->ctrl.faddr_oct = (line_mode.addr_lines == 8); hw->ctrl.fread_dual = (line_mode.data_lines == 2); - hw->user.fwrite_dual = (line_mode.data_lines == 2); hw->ctrl.fread_quad = (line_mode.data_lines == 4); - hw->user.fwrite_quad = (line_mode.data_lines == 4); hw->ctrl.fread_oct = (line_mode.data_lines == 8); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->user.fwrite_quad = (line_mode.data_lines == 4); hw->user.fwrite_oct = (line_mode.data_lines == 8); } @@ -1236,13 +1236,28 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) #define SPI_LL_SCT_MAGIC_NUMBER (0x2) + +/** + * Set conf phase bits len to HW for segment config trans mode. + * + * @param hw Beginning address of the peripheral registers. + * @param conf_bitlen Value of field conf_bitslen in cmd reg. + */ +static inline void spi_ll_set_conf_phase_bits_len(spi_dev_t *hw, uint32_t conf_bitlen) +{ + if (conf_bitlen <= SOC_SPI_SCT_CONF_BITLEN_MAX) { + hw->cmd.conf_bitlen = conf_bitlen; + } +} + /** * Update the conf buffer for conf phase * * @param hw Beginning address of the peripheral registers. + * @param is_end Is this transaction the end of this segment. * @param conf_buffer Conf buffer to be updated. */ -static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX], bool is_end) +static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, bool is_end, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { //user reg: usr_conf_nxt if (is_end) { @@ -1252,6 +1267,49 @@ static inline void spi_ll_format_conf_phase_conf_buffer(spi_dev_t *hw, uint32_t } } +/** + * Update the line mode of conf buffer for conf phase + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode line mode struct of each phase. + * @param conf_buffer Conf buffer to be updated. + */ +static inline void spi_ll_format_line_mode_conf_buff(spi_dev_t *hw, spi_line_mode_t line_mode, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) +{ + conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_CTRL_MASK; + conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET] &= ~SPI_LL_ONE_LINE_USER_MASK; + + switch (line_mode.cmd_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FCMD_OCT_M ); break; + default: break; + } + + switch (line_mode.addr_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_DUAL_M); break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_QUAD_M); break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FADDR_OCT_M ); break; + default: break; + } + + switch (line_mode.data_lines) + { + case 2: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_DUAL_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_DUAL_M); + break; + case 4: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_QUAD_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_QUAD_M); + break; + case 8: SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_CTRL_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FREAD_OCT_M ); + SPI_LL_CONF_BUF_SET_BIT(conf_buffer[SPI_LL_USER_REG_POS + SPI_LL_CONF_BUFFER_OFFSET], SPI_FWRITE_OCT_M); + break; + default: break; + } +} + /** * Update the conf buffer for prep phase * diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index d7b1e15fd8..c9e5e3017b 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -160,6 +160,7 @@ typedef struct { typedef struct { /* CONF State */ bool seg_end; ///< True: this segment is the end; False: this segment isn't the end; + uint32_t seg_gap_len; ///< spi clock length of CS inactive on config phase for sct /* PREP State */ int cs_setup; ///< Setup time of CS active edge before the first SPI clock /* CMD State */ @@ -430,6 +431,17 @@ void spi_hal_sct_load_dma_link(spi_hal_context_t *hal, lldesc_t *rx_seg_head, ll * Deinit SCT mode related registers and hal states */ void spi_hal_sct_deinit(spi_hal_context_t *hal); + +/** + * Set conf_bitslen to HW for sct. + */ +#define spi_hal_sct_set_conf_bits_len(hal, conf_len) spi_ll_set_conf_phase_bits_len((hal)->hw, conf_len) + +/** + * Set conf_bitslen base to HW for sct, only supported on s2. + */ +#define spi_hal_sct_setup_conf_base(hal, conf_base) spi_ll_set_conf_base_bitslen((hal)->hw, conf_base) + #endif //#if SOC_SPI_SCT_SUPPORTED #endif //#if SOC_GPSPI_SUPPORTED diff --git a/components/hal/spi_hal.c b/components/hal/spi_hal.c index cc51fa0b7a..eab8594829 100644 --- a/components/hal/spi_hal.c +++ b/components/hal/spi_hal.c @@ -68,6 +68,7 @@ void spi_hal_sct_init(spi_hal_context_t *hal) s_sct_reset_dma_link(hal); spi_ll_conf_state_enable(hal->hw, true); spi_ll_set_magic_number(hal->hw, SPI_LL_SCT_MAGIC_NUMBER); + spi_ll_disable_int(hal->hw); //trans_done intr enabled in `add device` phase, sct mode shoud use sct_trans_done only spi_ll_enable_intr(hal->hw, SPI_LL_INTR_SEG_DONE); spi_ll_set_intr(hal->hw, SPI_LL_INTR_SEG_DONE); } @@ -77,6 +78,8 @@ void spi_hal_sct_deinit(spi_hal_context_t *hal) spi_ll_conf_state_enable(hal->hw, false); spi_ll_disable_intr(hal->hw, SPI_LL_INTR_SEG_DONE); spi_ll_clear_intr(hal->hw, SPI_LL_INTR_SEG_DONE); + spi_ll_clear_int_stat(hal->hw); + spi_ll_enable_int(hal->hw); //recover trans_done intr } #endif //#if SOC_SPI_SCT_SUPPORTED diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index 3db2f89638..c19d02be0c 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -174,6 +174,7 @@ void spi_hal_sct_init_conf_buffer(spi_hal_context_t *hal, uint32_t conf_buffer[S void spi_hal_sct_format_conf_buffer(spi_hal_context_t *hal, const spi_hal_seg_config_t *config, const spi_hal_dev_config_t *dev, uint32_t conf_buffer[SOC_SPI_SCT_BUFFER_NUM_MAX]) { + spi_ll_format_line_mode_conf_buff(hal->hw, hal->trans_config.line_mode, conf_buffer); spi_ll_format_prep_phase_conf_buffer(hal->hw, config->cs_setup, conf_buffer); spi_ll_format_cmd_phase_conf_buffer(hal->hw, config->cmd, config->cmd_bits, dev->tx_lsbfirst, conf_buffer); spi_ll_format_addr_phase_conf_buffer(hal->hw, config->addr, config->addr_bits, dev->rx_lsbfirst, conf_buffer); @@ -181,7 +182,11 @@ void spi_hal_sct_format_conf_buffer(spi_hal_context_t *hal, const spi_hal_seg_co spi_ll_format_dout_phase_conf_buffer(hal->hw, config->tx_bitlen, conf_buffer); spi_ll_format_din_phase_conf_buffer(hal->hw, config->rx_bitlen, conf_buffer); spi_ll_format_done_phase_conf_buffer(hal->hw, config->cs_hold, conf_buffer); - spi_ll_format_conf_phase_conf_buffer(hal->hw, conf_buffer, config->seg_end); + spi_ll_format_conf_phase_conf_buffer(hal->hw, config->seg_end, conf_buffer); +#if CONFIG_IDF_TARGET_ESP32S2 + // only s2 support update seg_gap_len by conf_buffer + spi_ll_format_conf_bitslen_buffer(hal->hw, config->seg_gap_len, conf_buffer); +#endif } void spi_hal_sct_load_dma_link(spi_hal_context_t *hal, lldesc_t *rx_seg_head, lldesc_t *tx_seg_head) @@ -275,7 +280,7 @@ spi_hal_dma_desc_status_t spi_hal_sct_link_tx_seg_dma_desc(spi_hal_context_t *ha lldesc_t *internal_head = NULL; s_sct_prepare_tx_seg(hal, conf_buffer, send_buffer, buf_len_bytes, &internal_head); - *used_desc_num = 1 + lldesc_get_required_num(buf_len_bytes); + *used_desc_num += 1 + lldesc_get_required_num(buf_len_bytes); return SPI_HAL_DMA_DESC_LINKED; } @@ -331,7 +336,7 @@ spi_hal_dma_desc_status_t spi_hal_sct_link_rx_seg_dma_desc(spi_hal_context_t *ha lldesc_t *internal_head = NULL; s_sct_prepare_rx_seg(hal, recv_buffer, buf_len_bytes, &internal_head); - *used_desc_num = lldesc_get_required_num(buf_len_bytes); + *used_desc_num += lldesc_get_required_num(buf_len_bytes); return SPI_HAL_DMA_DESC_LINKED; } diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index b65bee4d40..2ec638f74e 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -483,6 +483,10 @@ config SOC_SPI_SCT_BUFFER_NUM_MAX bool default y +config SOC_SPI_SCT_CONF_BITLEN_MAX + hex + default 0x3FFFA + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 194e5a0ba7..05c60b0899 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -231,6 +231,7 @@ #define SOC_SPI_SCT_SUPPORTED_PERIPH(PERIPH_NUM) ((PERIPH_NUM==1) ? 1 : 0) //Support Segmented-Configure-Transfer #define SOC_SPI_SCT_REG_NUM 14 #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs +#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg #define SOC_MEMSPI_IS_INDEPENDENT 1 #define SOC_SPI_MAX_PRE_DIVIDER 16 diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index dbfdc2ab94..ad46552c11 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -711,6 +711,10 @@ config SOC_SPI_SCT_BUFFER_NUM_MAX bool default y +config SOC_SPI_SCT_CONF_BITLEN_MAX + hex + default 0x3FFFA + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 851bc357e4..468b0d858a 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -315,6 +315,7 @@ #define SOC_SPI_SCT_SUPPORTED_PERIPH(PERIPH_NUM) ((PERIPH_NUM==1) ? 1 : 0) //Support Segmented-Configure-Transfer #define SOC_SPI_SCT_REG_NUM 14 #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs +#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg #define SOC_MEMSPI_IS_INDEPENDENT 1 #define SOC_SPI_MAX_PRE_DIVIDER 16 diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index adf7a665e6..2e41f0cb3c 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -971,6 +971,10 @@ config SOC_SPI_SCT_BUFFER_NUM_MAX bool default y +config SOC_SPI_SCT_CONF_BITLEN_MAX + hex + default 0x3FFFA + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index b5e7bb534b..7dc38d4486 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -390,6 +390,7 @@ #define SOC_SPI_SCT_SUPPORTED_PERIPH(PERIPH_NUM) ((PERIPH_NUM==1) ? 1 : 0) //Support Segmented-Configure-Transfer #define SOC_SPI_SCT_REG_NUM 14 #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs +#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg #define SOC_MEMSPI_IS_INDEPENDENT 1 #define SOC_SPI_MAX_PRE_DIVIDER 16 diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index b4b2f5b77e..d986427ee4 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -711,6 +711,10 @@ config SOC_SPI_SCT_BUFFER_NUM_MAX bool default y +config SOC_SPI_SCT_CONF_BITLEN_MAX + hex + default 0x7FFFFD + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 4bacf33d89..4c5365fc66 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -307,6 +307,7 @@ #define SOC_SPI_SCT_SUPPORTED_PERIPH(PERIPH_NUM) (((PERIPH_NUM==1) || (PERIPH_NUM==2)) ? 1 : 0) //Support Segmented-Configure-Transfer #define SOC_SPI_SCT_REG_NUM 27 #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 27-word-regs +#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x7FFFFD //23 bit wide reg #define SOC_MEMSPI_IS_INDEPENDENT 1 #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 8437b6513d..7314e76574 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -851,6 +851,10 @@ config SOC_SPI_SCT_BUFFER_NUM_MAX bool default y +config SOC_SPI_SCT_CONF_BITLEN_MAX + hex + default 0x3FFFA + config SOC_MEMSPI_SRC_FREQ_120M bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 9b6240a153..4d8eba5221 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -336,6 +336,7 @@ #define SOC_SPI_SCT_SUPPORTED_PERIPH(PERIPH_NUM) ((PERIPH_NUM==1) ? 1 : 0) //Support Segmented-Configure-Transfer #define SOC_SPI_SCT_REG_NUM 14 #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs +#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg #define SOC_MEMSPI_SRC_FREQ_120M 1 #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1