Skip to content

Commit 1867e71

Browse files
jfischer-nofabiobaltieri
authored andcommitted
doc: usb: describe CDC ACM virtual UART IRQ API behavior
In general, it mirrors what is described in Interrupt-driven API documentation, but here a little more explicitly and with a simplified example, so that we can finally chisel it into the stone. Signed-off-by: Johann Fischer <[email protected]>
1 parent 64ee885 commit 1867e71

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

doc/connectivity/usb/device_next/usb_device.rst

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,62 @@ instance (``n``) and is used as an argument to the :c:func:`usbd_register_class`
223223
+-----------------------------------+-------------------------+-------------------------+
224224
| Bluetooth HCI USB transport layer | :ref:`bt_hci_raw` | :samp:`bt_hci_{n}` |
225225
+-----------------------------------+-------------------------+-------------------------+
226+
227+
CDC ACM UART
228+
============
229+
230+
CDC ACM implements a virtual UART controller and provides Interrupt-driven UART
231+
API and Polling UART API.
232+
233+
Interrupt-driven UART API
234+
-------------------------
235+
236+
Internally the implementation uses two ringbuffers, these take over the
237+
function of the TX/RX FIFOs (TX/RX buffers) from the :ref:`uart_interrupt_api`.
238+
239+
As described in the :ref:`uart_interrupt_api`, the functions
240+
:c:func:`uart_irq_update()`, :c:func:`uart_irq_is_pending`,
241+
:c:func:`uart_irq_rx_ready()`, :c:func:`uart_irq_tx_ready()`
242+
:c:func:`uart_fifo_read()`, and :c:func:`uart_fifo_fill()`
243+
should be called from the interrupt handler, see
244+
:c:func:`uart_irq_callback_user_data_set()`. To prevent undefined behaviour,
245+
the implementation of these functions checks in what context they are called
246+
and fails if it is not an interrupt handler.
247+
248+
Also, as described in the UART API, :c:func:`uart_irq_is_pending`
249+
:c:func:`uart_irq_rx_ready()`, and :c:func:`uart_irq_tx_ready()`
250+
can only be called after :c:func:`uart_irq_update()`.
251+
252+
Simplified, the interrupt handler should look something like:
253+
254+
.. code-block:: c
255+
256+
static void interrupt_handler(const struct device *dev, void *user_data)
257+
{
258+
while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
259+
if (uart_irq_rx_ready(dev)) {
260+
int len;
261+
int n;
262+
263+
/* ... */
264+
n = uart_fifo_read(dev, buffer, len);
265+
/* ... */
266+
}
267+
268+
if (uart_irq_tx_ready(dev)) {
269+
int len;
270+
int n;
271+
272+
/* ... */
273+
n = uart_fifo_fill(dev, buffer, len);
274+
/* ... */
275+
}
276+
}
277+
278+
All these functions are not directly dependent on the status of the USB device.
279+
Filling the TX FIFO does not mean that data is being sent to the host. And
280+
successfully reading the RX FIFO does not mean that the device is still
281+
connected to the host. If there is space in the TX FIFO, and the TX interrupt
282+
is enabled, :c:func:`uart_irq_tx_ready()` will succeed. If there is data in the
283+
RX FIFO, and the RX interrupt is enabled, :c:func:`uart_irq_rx_ready()` will
284+
succeed. Function :c:func:`uart_irq_tx_complete()` is not implemented yet.

0 commit comments

Comments
 (0)