Merge branch 'fix/uhci_rx_size_check_v6.1' into 'release/v6.1'

fix(uhci): rx fsm race condition and buffer size check (v6.1)

See merge request espressif/esp-idf!51228
This commit is contained in:
morris
2026-07-30 11:43:13 +08:00
7 changed files with 178 additions and 109 deletions

View File

@@ -52,7 +52,7 @@ If the configurations in :cpp:type:`uhci_controller_config_t` is specified, user
uhci_controller_config_t uhci_cfg = {
.uart_port = EX_UART_NUM, // Connect uart port to UHCI hardware.
.tx_trans_queue_depth = 30, // Queue depth of transaction queue.
.max_receive_internal_mem = 10 * 1024, // internal memory usage, for more information, please refer to API reference.
.max_receive_internal_mem = 10 * 1024, // Expected max uhci_receive() buffer size; also sizes the RX DMA descriptor chain. For large transfers, configure it so that at least two descriptors are available for ping-pong operation.
.max_transmit_size = 10 * 1024, // Maximum transfer size in one transaction, in bytes (including all buffers).
.max_transmit_buffer_count = 1, // Maximum number of buffers in one transmit transaction. 0 or 1 means only single-buffer transmit is used.
.dma_burst_size = 32, // Burst size.
@@ -190,7 +190,7 @@ Data can be received via UHCI as follows:
}
}
In the API :cpp:func:`uhci_receive` interface, the parameter `read_buffer` is a buffer that must be provided by the user, and parameter `buffer_size` represents the size of the buffer supplied by the user. In the configuration structure of the UHCI controller, the parameter :cpp:member:`uhci_controller_config_t::max_receive_internal_mem` specifies the desired size of the internal DMA working space. The software allocates a certain number of DMA nodes based on this working space size. These nodes form a circular linked list.
In the API :cpp:func:`uhci_receive` interface, the parameter ``read_buffer`` is a buffer that must be provided by the user, and parameter ``buffer_size`` represents the size of the buffer supplied by the user. ``buffer_size`` should generally not exceed :cpp:member:`uhci_controller_config_t::max_receive_internal_mem`.
When a node is filled, but the reception has not yet completed, the event :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` will be triggered, accompanied by :cpp:member:`uhci_rx_event_data_t::flags::totally_received` set to 0. When all the data has been fully received, the :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` event will be triggered again with :cpp:member:`uhci_rx_event_data_t::flags::totally_received` set to 1.
@@ -198,7 +198,7 @@ This mechanism allows the user to achieve continuous and fast reception using a
.. note::
The parameter `read_buffer` of :cpp:func:`uhci_receive` cannot be freed until receive finishes.
The parameter ``read_buffer`` of :cpp:func:`uhci_receive` cannot be freed until receive finishes.
Uninstall UHCI controller
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -52,7 +52,7 @@ UHCI 控制器需要通过 :cpp:type:`uhci_controller_config_t` 进行配置。
uhci_controller_config_t uhci_cfg = {
.uart_port = EX_UART_NUM, // 将指定 UART 端口连接到 UHCI 硬件
.tx_trans_queue_depth = 30, // 发送队列的队列深度
.max_receive_internal_mem = 10 * 1024, // 内部接收内存大小,更多信息请参考 API 注释
.max_receive_internal_mem = 10 * 1024, // uhci_receive() 期望的最大缓冲区大小,同时决定 RX DMA 描述符链长度。对于较大的传输,建议将该值配置为至少会分配两个描述符,以便进行乒乓操作
.max_transmit_size = 10 * 1024, // 一次传输事务中的最大总字节数(包含该次传入的所有缓冲区)
.max_transmit_buffer_count = 1, // 一次传输事务中的最大缓冲区数量。设为 0 或 1 表示只使用单缓冲区传输。
.dma_burst_size = 32, // 突发传输大小
@@ -190,9 +190,9 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
}
}
在 API :cpp:func:`uhci_receive` 接口中,参数 ``read_buffer`` 是用户必须提供的缓冲区,参数 ``buffer_size`` 表示用户提供的缓冲区大小。在 UHCI 控制器的配置结构中,参数 :cpp:member:`uhci_controller_config_t::max_receive_internal_mem` 指定了内部 DMA 工作空间的期望大小。软件将根据此工作空间大小分配一定数量的 DMA 节点,这些节点形成一个循环链表
在 API :cpp:func:`uhci_receive` 接口中,参数 ``read_buffer`` 是用户必须提供的缓冲区,参数 ``buffer_size`` 表示用户提供的缓冲区大小。``buffer_size`` 一般不得超过 :cpp:member:`uhci_controller_config_t::max_receive_internal_mem`
当一个节点被填满,但接收尚未完成时,将触发 :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` 事件,且 :cpp:member:`uhci_rx_event_data_t::flags::totally_received` 的值为 0。 当所有数据接收完成时,该事件将再次被触发,并且 :cpp:member:`uhci_rx_event_data_t::flags::totally_received` 的值为 1。
当一个节点被填满,但接收尚未完成时,将触发 :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` 事件,且 :cpp:member:`uhci_rx_event_data_t::flags::totally_received` 的值为 0。当所有数据接收完成时该事件将再次被触发并且 :cpp:member:`uhci_rx_event_data_t::flags::totally_received` 的值为 1。
此机制允许用户使用相对较小的缓冲区实现连续且快速的接收,而无需分配与接收总数据量相等大小的缓冲区。