diff --git a/components/esp_driver_uart/include/driver/uhci.h b/components/esp_driver_uart/include/driver/uhci.h index 23e015b23f..c01af0d9b5 100644 --- a/components/esp_driver_uart/include/driver/uhci.h +++ b/components/esp_driver_uart/include/driver/uhci.h @@ -24,6 +24,7 @@ typedef struct { size_t max_transmit_size; /*!< Maximum transfer size in one transaction, in bytes. This decides the number of DMA nodes will be used for each transaction */ size_t max_receive_internal_mem; /*!< Maximum transfer size in one transaction, in bytes. Each DMA node can point to a maximum of 4096 bytes. This value determines the number of DMA nodes used for each transaction. When your transfer size is large enough, it is recommended to set this value greater than 4096 to facilitate efficient ping-pong operations, such as 10 * 1024. */ size_t dma_burst_size; /*!< DMA burst size, in bytes */ + size_t max_packet_receive; /*!< Max receive size, auto stop receiving after reach this value, only valid when `length_eof` set true */ struct { uint16_t rx_brk_eof: 1; /*!< UHCI will end payload receive process when NULL frame is received by UART. */ diff --git a/components/esp_driver_uart/linker.lf b/components/esp_driver_uart/linker.lf index a7610403c2..ab18e75b35 100644 --- a/components/esp_driver_uart/linker.lf +++ b/components/esp_driver_uart/linker.lf @@ -26,3 +26,5 @@ entries: gdma_link: gdma_link_mount_buffers (noflash) gdma_link: gdma_link_get_head_addr (noflash) gdma: gdma_start (noflash) + gdma: gdma_stop (noflash) + gdma: gdma_reset (noflash) diff --git a/components/esp_driver_uart/src/uhci.c b/components/esp_driver_uart/src/uhci.c index 399f7875b4..7ee7fdc4b5 100644 --- a/components/esp_driver_uart/src/uhci.c +++ b/components/esp_driver_uart/src/uhci.c @@ -149,6 +149,10 @@ static bool uhci_gdma_rx_callback_done(gdma_channel_handle_t dma_chan, gdma_even need_yield |= uhci_ctrl->rx_dir.on_rx_trans_event(uhci_ctrl, &evt_data, uhci_ctrl->user_data); } + // Stop the transaction when EOF is detected. In case for length EOF, there is no further more callback to be invoked. + gdma_stop(uhci_ctrl->rx_dir.dma_chan); + gdma_reset(uhci_ctrl->rx_dir.dma_chan); + uhci_ctrl->rx_dir.rx_fsm = UHCI_RX_FSM_ENABLE; } @@ -330,6 +334,7 @@ esp_err_t uhci_receive(uhci_controller_handle_t uhci_ctrl, uint8_t *read_buffer, } }; ESP_LOGD(TAG, "The DMA node %d has %d byte", i, uhci_ctrl->rx_dir.buffer_size_per_desc_node[i]); + ESP_RETURN_ON_FALSE(uhci_ctrl->rx_dir.buffer_size_per_desc_node[i] != 0, ESP_ERR_INVALID_STATE, TAG, "Allocate dma node length is 0, please reconfigure the buffer_size"); read_buffer += uhci_ctrl->rx_dir.buffer_size_per_desc_node[i]; } @@ -451,6 +456,9 @@ esp_err_t uhci_new_controller(const uhci_controller_config_t *config, uhci_contr uhci_controller_handle_t uhci_ctrl = (uhci_controller_handle_t)heap_caps_calloc(1, sizeof(uhci_controller_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); ESP_RETURN_ON_FALSE(uhci_ctrl, ESP_ERR_NO_MEM, TAG, "no mem for uhci controller handle"); + if (config->rx_eof_flags.length_eof) { + ESP_RETURN_ON_FALSE(config->max_packet_receive < UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD, ESP_ERR_INVALID_ARG, TAG, "max receive packet is over threshold"); + } atomic_init(&uhci_ctrl->tx_dir.tx_fsm, UHCI_TX_FSM_ENABLE); atomic_init(&uhci_ctrl->rx_dir.rx_fsm, UHCI_TX_FSM_ENABLE); @@ -509,6 +517,7 @@ esp_err_t uhci_new_controller(const uhci_controller_config_t *config, uhci_contr } if (config->rx_eof_flags.length_eof) { uhci_ll_rx_set_eof_mode(uhci_ctrl->hal.dev, UHCI_RX_LEN_EOF); + uhci_ll_rx_set_packet_threshold(uhci_ctrl->hal.dev, config->max_packet_receive); } if (config->rx_eof_flags.rx_brk_eof) { uhci_ll_rx_set_eof_mode(uhci_ctrl->hal.dev, UHCI_RX_BREAK_CHR_EOF); diff --git a/components/esp_driver_uart/test_apps/.build-test-rules.yml b/components/esp_driver_uart/test_apps/.build-test-rules.yml index 9f4e19d6f5..02f215e5c3 100644 --- a/components/esp_driver_uart/test_apps/.build-test-rules.yml +++ b/components/esp_driver_uart/test_apps/.build-test-rules.yml @@ -32,6 +32,6 @@ components/esp_driver_uart/test_apps/uart_vfs: components/esp_driver_uart/test_apps/uhci: disable: - if: SOC_UHCI_SUPPORTED != 1 - - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 + - if: CONFIG_NAME == "psram" and SOC_AHB_GDMA_SUPPORT_PSRAM != 1 depends_components: - esp_driver_uart diff --git a/components/esp_driver_uart/test_apps/uhci/main/test_uhci.c b/components/esp_driver_uart/test_apps/uhci/main/test_uhci.c index a22ef6297e..a9cb04a6bf 100644 --- a/components/esp_driver_uart/test_apps/uhci/main/test_uhci.c +++ b/components/esp_driver_uart/test_apps/uhci/main/test_uhci.c @@ -246,7 +246,7 @@ TEST_CASE("UHCI write and receive with length eof", "[uhci]") } #if CONFIG_SPIRAM -#if CONFIG_IDF_TARGET_ESP32S3 +#if SOC_AHB_GDMA_SUPPORT_PSRAM static void uhci_receive_test_in_psram(void *arg) { uhci_controller_handle_t uhci_ctrl = ((uhci_controller_handle_t *)arg)[0]; diff --git a/components/hal/esp32c5/include/hal/uhci_ll.h b/components/hal/esp32c5/include/hal/uhci_ll.h index db8f9524bd..974377c79a 100644 --- a/components/hal/esp32c5/include/hal/uhci_ll.h +++ b/components/hal/esp32c5/include/hal/uhci_ll.h @@ -55,7 +55,6 @@ static inline void uhci_ll_reset_register(int group_id) static inline void uhci_ll_init(uhci_dev_t *hw) { typeof(hw->conf0) conf0_reg; - hw->conf0.clk_en = 1; conf0_reg.val = 0; conf0_reg.clk_en = 1; hw->conf0.val = conf0_reg.val; diff --git a/components/hal/esp32h2/include/hal/uhci_ll.h b/components/hal/esp32h2/include/hal/uhci_ll.h index f3b5a87443..420fdf8424 100644 --- a/components/hal/esp32h2/include/hal/uhci_ll.h +++ b/components/hal/esp32h2/include/hal/uhci_ll.h @@ -52,7 +52,6 @@ static inline void uhci_ll_reset_register(int group_id) static inline void uhci_ll_init(uhci_dev_t *hw) { typeof(hw->conf0) conf0_reg; - hw->conf0.clk_en = 1; conf0_reg.val = 0; conf0_reg.clk_en = 1; hw->conf0.val = conf0_reg.val; diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index e5ca1a383c..b8234e47f3 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -516,7 +516,7 @@ examples/peripherals/uart/uart_dma_ota: disable: - if: SOC_UHCI_SUPPORTED != 1 disable_test: - - if: IDF_TARGET in ["esp32p4"] + - if: IDF_TARGET in ["esp32p4", "esp32c5"] temporary: true reason: Lack runners diff --git a/examples/peripherals/uart/uart_dma_ota/pytest_uart_dma_ota.py b/examples/peripherals/uart/uart_dma_ota/pytest_uart_dma_ota.py index 74f8da27e4..9937ac17af 100644 --- a/examples/peripherals/uart/uart_dma_ota/pytest_uart_dma_ota.py +++ b/examples/peripherals/uart/uart_dma_ota/pytest_uart_dma_ota.py @@ -42,7 +42,7 @@ def send_file_via_uart(port: str, baud_rate: int, file_path: str, packet_size: i ], indirect=True, ) -@idf_parametrize('target', ['esp32c6', 'esp32c3', 'esp32s3'], indirect=['target']) +@idf_parametrize('target', ['esp32c6', 'esp32c3', 'esp32s3', 'esp32h2'], indirect=['target']) def test_uart_dma_ota(dut: Dut) -> None: dut.expect_exact('uhci-example: OTA process started') # We OTA the same binary to another partition and switch to there. diff --git a/examples/peripherals/uart/uart_dma_ota/sdkconfig.ci.defaults.esp32h2 b/examples/peripherals/uart/uart_dma_ota/sdkconfig.ci.defaults.esp32h2 new file mode 100644 index 0000000000..10d5b213f0 --- /dev/null +++ b/examples/peripherals/uart/uart_dma_ota/sdkconfig.ci.defaults.esp32h2 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32h2" +CONFIG_UART_RX_IO=23