feat(uhci): Add uhci_continuous api for example and doc

This commit is contained in:
C.S.M
2026-07-30 15:25:51 +08:00
parent fcd5c55194
commit ae64f66617
4 changed files with 68 additions and 20 deletions

View File

@@ -200,6 +200,30 @@ This mechanism allows the user to achieve continuous and fast reception using a
The parameter ``read_buffer`` of :cpp:func:`uhci_receive` cannot be freed until receive finishes.
Continuous Reception
^^^^^^^^^^^^^^^^^^^^^
:cpp:func:`uhci_receive` is a one-shot API: it stops the DMA after a single frame and has to be re-armed for the next one. During that re-arm gap incoming bytes can be lost. For continuous streaming, use :cpp:func:`uhci_start_receive_continuous` instead. It keeps the GDMA running across EOFs, so the reception never idles and no data is dropped between frames.
The provided ``read_buffer`` is split across the DMA nodes and used as a ring: each finished frame (for example, a UART idle or length EOF) is delivered through the :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` callback with :cpp:member:`uhci_rx_event_data_t::flags::totally_received` set to 1, while a filled-but-not-yet-complete node is delivered with it set to 0. The callback hands out a pointer directly into the ring buffer (zero-copy), so the application must consume the data before the DMA wraps around and overwrites it. Size the buffer according to the expected throughput and consumer latency; overrun protection is not provided.
Call :cpp:func:`uhci_stop_receive` to end the session and return the controller to the idle state, after which it can be re-armed or deleted.
.. code:: c
// Register callback and start continuous reception.
ESP_ERROR_CHECK(uhci_register_event_callbacks(uhci_ctrl, &uhci_cbs, ctx));
ESP_ERROR_CHECK(uhci_start_receive_continuous(uhci_ctrl, pdata, buffer_size));
// ... consume the frames delivered through on_rx_trans_event ...
// Stop the session before freeing pdata or deleting the controller.
ESP_ERROR_CHECK(uhci_stop_receive(uhci_ctrl));
.. note::
The parameter ``read_buffer`` of :cpp:func:`uhci_start_receive_continuous` must stay valid until :cpp:func:`uhci_stop_receive` returns.
Uninstall UHCI controller
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -200,6 +200,30 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
在接收完成之前,:cpp:func:`uhci_receive` 的参数 ``read_buffer`` 不可被释放。
连续接收
^^^^^^^^
:cpp:func:`uhci_receive` 是一次性 (one-shot) 接口:它在接收完一帧后便会停止 DMA需要重新调用才能接收下一帧而在这个重新装载的间隙里可能会丢失到来的数据。若需要持续接收数据流请改用 :cpp:func:`uhci_start_receive_continuous`。它会让 GDMA 跨越 EOF 持续运行,接收过程不会中断,因此帧与帧之间不会丢数据。
传入的 ``read_buffer`` 会被拆分到各个 DMA 节点上,并作为环形缓冲区循环使用:每接收完一帧(例如 UART idle 或 length EOF都会通过 :cpp:member:`uhci_event_callbacks_t::on_rx_trans_event` 回调交付,且 :cpp:member:`uhci_rx_event_data_t::flags::totally_received` 置为 1而某个节点填满但整帧尚未结束时则以该标志为 0 交付。回调直接给出指向环形缓冲区内部的指针(零拷贝),因此应用必须在 DMA 绕回并覆盖数据之前将其消费掉。请根据预期的吞吐量与消费延迟来确定缓冲区大小;驱动不提供溢出保护。
调用 :cpp:func:`uhci_stop_receive` 可结束本次接收会话,并使控制器回到空闲状态,之后便可重新装载或删除控制器。
.. code:: c
// 注册回调并启动连续接收。
ESP_ERROR_CHECK(uhci_register_event_callbacks(uhci_ctrl, &uhci_cbs, ctx));
ESP_ERROR_CHECK(uhci_start_receive_continuous(uhci_ctrl, pdata, buffer_size));
// ... 消费通过 on_rx_trans_event 交付的各帧数据 ...
// 在释放 pdata 或删除控制器之前,先停止接收会话。
ESP_ERROR_CHECK(uhci_stop_receive(uhci_ctrl));
.. note::
:cpp:func:`uhci_start_receive_continuous` 的参数 ``read_buffer`` 必须保持有效,直到 :cpp:func:`uhci_stop_receive` 返回。
卸载 UHCI 控制器
^^^^^^^^^^^^^^^^^^^^^^^^^