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/README.md b/components/esp_driver_uart/test_apps/uhci/README.md index cb475b8112..77a98e02d0 100644 --- a/components/esp_driver_uart/test_apps/uhci/README.md +++ b/components/esp_driver_uart/test_apps/uhci/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | 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 c35edaf5b0..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 @@ -143,7 +143,7 @@ static void uhci_receive_test(void *arg) if (xQueueReceive(ctx->uhci_queue, &evt, portMAX_DELAY) == pdTRUE) { if (evt == UHCI_EVT_EOF) { disp_buf(receive_data, ctx->receive_size); - for (int i = 0; i < DATA_LENGTH; i++) { + for (int i = 0; i < ctx->receive_size; i++) { TEST_ASSERT(receive_data[i] == (uint8_t)i); } printf("Received size: %d\n", ctx->receive_size); @@ -160,7 +160,7 @@ static void uhci_receive_test(void *arg) vTaskDelete(NULL); } -TEST_CASE("UHCI write and receive", "[uhci]") +TEST_CASE("UHCI write and receive with idle eof", "[uhci]") { uart_config_t uart_config = { .baud_rate = 5 * 1000 * 1000, @@ -202,8 +202,51 @@ TEST_CASE("UHCI write and receive", "[uhci]") vSemaphoreDelete(exit_sema); } +TEST_CASE("UHCI write and receive with length eof", "[uhci]") +{ + uart_config_t uart_config = { + .baud_rate = 5 * 1000 * 1000, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_XTAL, + }; + TEST_ESP_OK(uart_param_config(EX_UART_NUM, &uart_config)); + // Connect TX and RX together for testing self send-receive + TEST_ESP_OK(uart_set_pin(EX_UART_NUM, UART_TX_IO, UART_TX_IO, -1, -1)); + + uhci_controller_config_t uhci_cfg = { + .uart_port = EX_UART_NUM, + .tx_trans_queue_depth = 30, + .max_receive_internal_mem = 10 * 1024, + .max_transmit_size = 10 * 1024, + .dma_burst_size = 32, + .max_packet_receive = 100, + .rx_eof_flags.length_eof = 1, + }; + + uhci_controller_handle_t uhci_ctrl; + SemaphoreHandle_t exit_sema = xSemaphoreCreateBinary(); + TEST_ESP_OK(uhci_new_controller(&uhci_cfg, &uhci_ctrl)); + + void *args[] = { uhci_ctrl, exit_sema }; + xTaskCreate(uhci_receive_test, "uhci_receive_test", 4096 * 2, args, 5, NULL); + + uint8_t data_wr[DATA_LENGTH]; + for (int i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + TEST_ESP_OK(uhci_transmit(uhci_ctrl, data_wr, DATA_LENGTH)); + uhci_wait_all_tx_transaction_done(uhci_ctrl, portMAX_DELAY); + xSemaphoreTake(exit_sema, portMAX_DELAY); + vTaskDelay(2); + TEST_ESP_OK(uhci_del_controller(uhci_ctrl)); + vSemaphoreDelete(exit_sema); +} + #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/esp32c3/include/hal/uhci_ll.h b/components/hal/esp32c3/include/hal/uhci_ll.h index c82246900e..1fd74f59ae 100644 --- a/components/hal/esp32c3/include/hal/uhci_ll.h +++ b/components/hal/esp32c3/include/hal/uhci_ll.h @@ -19,6 +19,7 @@ extern "C" { #endif #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) typedef enum { UHCI_RX_BREAK_CHR_EOF = 0x1, @@ -159,6 +160,11 @@ static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) } } +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.thrs = length; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/uhci_ll.h b/components/hal/esp32c5/include/hal/uhci_ll.h new file mode 100644 index 0000000000..974377c79a --- /dev/null +++ b/components/hal/esp32c5/include/hal/uhci_ll.h @@ -0,0 +1,160 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for UHCI register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once +#include +#include "hal/uhci_types.h" +#include "soc/uhci_struct.h" +#include "soc/pcr_struct.h" +#include "hal/misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) + +typedef enum { + UHCI_RX_BREAK_CHR_EOF = 0x1, + UHCI_RX_IDLE_EOF = 0x2, + UHCI_RX_LEN_EOF = 0x4, + UHCI_RX_EOF_MAX = 0x7, +} uhci_rxeof_cfg_t; + +/** + * @brief Enable the bus clock for UHCI module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void uhci_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.uhci_conf.uhci_clk_en = enable; +} + +/** + * @brief Reset the UHCI module + * + * @param group_id Group ID + */ +static inline void uhci_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.uhci_conf.uhci_rst_en = 1; + PCR.uhci_conf.uhci_rst_en = 0; +} + +static inline void uhci_ll_init(uhci_dev_t *hw) +{ + typeof(hw->conf0) conf0_reg; + conf0_reg.val = 0; + conf0_reg.clk_en = 1; + hw->conf0.val = conf0_reg.val; + hw->conf1.val = 0; +} + +static inline void uhci_ll_attach_uart_port(uhci_dev_t *hw, int uart_num) +{ + hw->conf0.uart_sel = uart_num; +} + +static inline void uhci_ll_set_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_char) +{ + if (seper_char->sub_chr_en) { + hw->conf0.seper_en = 1; + typeof(hw->esc_conf0) esc_conf0_reg; + esc_conf0_reg.val = hw->esc_conf0.val; + + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf0_reg, seper_char, seper_char->seper_chr); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf0_reg, seper_esc_char0, seper_char->sub_chr1); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf0_reg, seper_esc_char1, seper_char->sub_chr2); + hw->esc_conf0.val = esc_conf0_reg.val; + hw->escape_conf.tx_c0_esc_en = 1; + hw->escape_conf.rx_c0_esc_en = 1; + } else { + hw->conf0.seper_en = 0; + hw->escape_conf.val = 0; + } +} + +static inline void uhci_ll_set_swflow_ctrl_sub_chr(uhci_dev_t *hw, uhci_swflow_ctrl_sub_chr_t *sub_ctr) +{ + typeof(hw->escape_conf) escape_conf_reg; + escape_conf_reg.val = hw->escape_conf.val; + + if (sub_ctr->flow_en == 1) { + typeof(hw->esc_conf2) esc_conf2_reg; + esc_conf2_reg.val = hw->esc_conf2.val; + typeof(hw->esc_conf3) esc_conf3_reg; + esc_conf3_reg.val = hw->esc_conf3.val; + + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1, sub_ctr->xon_chr); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1_char0, sub_ctr->xon_sub1); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1_char1, sub_ctr->xon_sub2); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2, sub_ctr->xoff_chr); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2_char0, sub_ctr->xoff_sub1); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2_char1, sub_ctr->xoff_sub2); + escape_conf_reg.tx_11_esc_en = 1; + escape_conf_reg.tx_13_esc_en = 1; + escape_conf_reg.rx_11_esc_en = 1; + escape_conf_reg.rx_13_esc_en = 1; + hw->esc_conf2.val = esc_conf2_reg.val; + hw->esc_conf3.val = esc_conf3_reg.val; + } else { + escape_conf_reg.tx_11_esc_en = 0; + escape_conf_reg.tx_13_esc_en = 0; + escape_conf_reg.rx_11_esc_en = 0; + escape_conf_reg.rx_13_esc_en = 0; + } + hw->escape_conf.val = escape_conf_reg.val; +} + +static inline void uhci_ll_enable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val |= intr_mask; +} + +static inline void uhci_ll_disable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val &= (~intr_mask); +} + +static inline void uhci_ll_clear_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_clr.val = intr_mask; +} + +static inline uint32_t uhci_ll_get_intr(uhci_dev_t *hw) +{ + return hw->int_st.val; +} + +static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) +{ + if (eof_mode & UHCI_RX_BREAK_CHR_EOF) { + hw->conf0.uart_rx_brk_eof_en = 1; + } + if (eof_mode & UHCI_RX_IDLE_EOF) { + hw->conf0.uart_idle_eof_en = 1; + } + if (eof_mode & UHCI_RX_LEN_EOF) { + hw->conf0.len_eof_en = 1; + } +} + +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.pkt_thrs = length; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/uhci_ll.h b/components/hal/esp32c6/include/hal/uhci_ll.h index 881e26b20e..8af4d9c5f5 100644 --- a/components/hal/esp32c6/include/hal/uhci_ll.h +++ b/components/hal/esp32c6/include/hal/uhci_ll.h @@ -19,6 +19,7 @@ extern "C" { #endif #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) typedef enum { UHCI_RX_BREAK_CHR_EOF = 0x1, @@ -151,6 +152,11 @@ static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) } } +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.pkt_thrs = length; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/uhci_ll.h b/components/hal/esp32h2/include/hal/uhci_ll.h index 0e19c3c80b..420fdf8424 100644 --- a/components/hal/esp32h2/include/hal/uhci_ll.h +++ b/components/hal/esp32h2/include/hal/uhci_ll.h @@ -8,6 +8,7 @@ #include #include "hal/uhci_types.h" #include "soc/uhci_struct.h" +#include "soc/pcr_struct.h" #include "hal/misc.h" #ifdef __cplusplus @@ -15,6 +16,7 @@ extern "C" { #endif #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) typedef enum { UHCI_RX_BREAK_CHR_EOF = 0x1, @@ -23,10 +25,33 @@ typedef enum { UHCI_RX_EOF_MAX = 0x7, } uhci_rxeof_cfg_t; +/** + * @brief Enable the bus clock for UHCI module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void uhci_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.uhci_conf.uhci_clk_en = enable; +} + +/** + * @brief Reset the UHCI module + * + * @param group_id Group ID + */ +static inline void uhci_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.uhci_conf.uhci_rst_en = 1; + PCR.uhci_conf.uhci_rst_en = 0; +} + 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; @@ -35,8 +60,8 @@ static inline void uhci_ll_init(uhci_dev_t *hw) static inline void uhci_ll_attach_uart_port(uhci_dev_t *hw, int uart_num) { - hw->conf0.uart0_ce = (uart_num == 0)? 1: 0; - hw->conf0.uart1_ce = (uart_num == 1)? 1: 0; + hw->conf0.uart0_ce = (uart_num == 0) ? 1 : 0; + hw->conf0.uart1_ce = (uart_num == 1) ? 1 : 0; } static inline void uhci_ll_set_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_char) @@ -69,12 +94,12 @@ static inline void uhci_ll_set_swflow_ctrl_sub_chr(uhci_dev_t *hw, uhci_swflow_c typeof(hw->esc_conf3) esc_conf3_reg; esc_conf3_reg.val = hw->esc_conf3.val; - esc_conf2_reg.esc_seq1 = sub_ctr->xon_chr; - esc_conf2_reg.esc_seq1_char0 = sub_ctr->xon_sub1; - esc_conf2_reg.esc_seq1_char1 = sub_ctr->xon_sub2; - esc_conf3_reg.esc_seq2 = sub_ctr->xoff_chr; - esc_conf3_reg.esc_seq2_char0 = sub_ctr->xoff_sub1; - esc_conf3_reg.esc_seq2_char1 = sub_ctr->xoff_sub2; + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1, sub_ctr->xon_chr); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1_char0, sub_ctr->xon_sub1); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf2_reg, esc_seq1_char1, sub_ctr->xon_sub2); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2, sub_ctr->xoff_chr); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2_char0, sub_ctr->xoff_sub1); + HAL_FORCE_MODIFY_U32_REG_FIELD(esc_conf3_reg, esc_seq2_char1, sub_ctr->xoff_sub2); escape_conf_reg.tx_11_esc_en = 1; escape_conf_reg.tx_13_esc_en = 1; escape_conf_reg.rx_11_esc_en = 1; @@ -110,7 +135,6 @@ static inline uint32_t uhci_ll_get_intr(uhci_dev_t *hw) return hw->int_st.val; } - static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) { if (eof_mode & UHCI_RX_BREAK_CHR_EOF) { @@ -124,6 +148,11 @@ static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) } } +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.pkt_thrs = length; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/uhci_ll.h b/components/hal/esp32p4/include/hal/uhci_ll.h index 5aebf70fe5..70066c14ab 100644 --- a/components/hal/esp32p4/include/hal/uhci_ll.h +++ b/components/hal/esp32p4/include/hal/uhci_ll.h @@ -19,6 +19,7 @@ extern "C" { #endif #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) typedef enum { UHCI_RX_BREAK_CHR_EOF = 0x1, @@ -107,6 +108,11 @@ static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) } } +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.pkt_thrs = length; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/uhci_ll.h b/components/hal/esp32s3/include/hal/uhci_ll.h index be14c3c485..fb164b601a 100644 --- a/components/hal/esp32s3/include/hal/uhci_ll.h +++ b/components/hal/esp32s3/include/hal/uhci_ll.h @@ -19,6 +19,7 @@ extern "C" { #endif #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) +#define UHCI_LL_MAX_RECEIVE_PACKET_THRESHOLD (8192) typedef enum { UHCI_RX_BREAK_CHR_EOF = 0x1, @@ -160,6 +161,11 @@ static inline void uhci_ll_rx_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) } } +static inline void uhci_ll_rx_set_packet_threshold(uhci_dev_t *hw, uint16_t length) +{ + hw->pkt_thres.thrs = length; +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index ff0651fc81..7f878cc80c 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -19,6 +19,10 @@ config SOC_UART_SUPPORTED bool default y +config SOC_UHCI_SUPPORTED + bool + default y + config SOC_GDMA_SUPPORTED bool default y @@ -1439,6 +1443,10 @@ config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE bool default y +config SOC_UHCI_NUM + int + default 1 + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 524ad30d59..774a5287bd 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -21,6 +21,7 @@ #define SOC_ANA_CMPR_SUPPORTED 1 #define SOC_DEDICATED_GPIO_SUPPORTED 1 #define SOC_UART_SUPPORTED 1 +#define SOC_UHCI_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 @@ -573,6 +574,9 @@ #define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1) #define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1) +/*--------------------------- UHCI CAPS -------------------------------------*/ +#define SOC_UHCI_NUM (1UL) + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32c5/register/soc/uhci_struct.h b/components/soc/esp32c5/register/soc/uhci_struct.h index 9737beddff..2bc8854092 100644 --- a/components/soc/esp32c5/register/soc/uhci_struct.h +++ b/components/soc/esp32c5/register/soc/uhci_struct.h @@ -861,7 +861,7 @@ typedef union { } uhci_date_reg_t; -typedef struct { +typedef struct uhci_dev_t { volatile uhci_conf0_reg_t conf0; volatile uhci_int_raw_reg_t int_raw; volatile uhci_int_st_reg_t int_st; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 3d1d9e95f1..dbaeaf41aa 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -23,6 +23,10 @@ config SOC_UART_SUPPORTED bool default y +config SOC_UHCI_SUPPORTED + bool + default y + config SOC_GDMA_SUPPORTED bool default y @@ -1379,6 +1383,10 @@ config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE bool default y +config SOC_UHCI_NUM + int + default 1 + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index cd371b08b7..f9cd578329 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -38,6 +38,7 @@ #define SOC_ANA_CMPR_SUPPORTED 1 #define SOC_DEDICATED_GPIO_SUPPORTED 1 #define SOC_UART_SUPPORTED 1 +#define SOC_UHCI_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 @@ -550,6 +551,9 @@ #define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1) #define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1) +/*--------------------------- UHCI CAPS -------------------------------------*/ +#define SOC_UHCI_NUM (1UL) + // TODO: IDF-5679 (Copy from esp32c6, need check) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) 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/README.md b/examples/peripherals/uart/uart_dma_ota/README.md index c3626f9ccf..5a0a845977 100644 --- a/examples/peripherals/uart/uart_dma_ota/README.md +++ b/examples/peripherals/uart/uart_dma_ota/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | # UART OTA Example 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