mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
* This completes task list in https://github.com/apache/nuttx/issues/11127. * This preserves selected content from cwiki and moves it to new docs. * Most pages are simple copy-paste with a simple RST formatting updates, with minor updates. * Content update / reorganization will follow later on when needed. * Files added (or updated title from cwiki -> current docs): * Documentation/implementation: * index. * cancellation_points. * Asynchronous vs. Synchronous Context Switches -> context_switches.rst. * ARMv7-M Hardfaults, SVCALL, and Debuggers -> hardfatuls.rst. * chip.h FAQ -> chip_h.rst. * Debug Output (SYSLOG) Issues -> syslog.rst. * Detaching File Descriptors -> file_descriptors.rst. * device_nodes.rst. * Dynamic Clocking -> power_management.rst. * ENOTTY ioctl() Return Value -> ioctl.rst. * memory_configurations.rst. * kernel_modules_vs_shared_libraries.rst. * NAKing USB OUT/IN Tokens -> usb.rst. * naming_arch_mcu_board_interfaces.rst. * naming_os_internals.rst. * nuttx_tasking.rst. * oneshot_timers_and_cpu_load.rst. * nuttx_initialization_sequence.rst. * short_time_delays.rst. * Signal Handler Tour -> signal_handlers.rst. * smp.rst. * syslog.rst. * Task Exit Sequence -> nuttx_tasking.rst. * tasks_vs_threads.rst. * tls.rst. * tickless_os.rst. * Why Can't Kernel Threads Have pthreads -> kernel_threads_vs_pthreads.rst. * Documentation/components/filesystem: * smartfs.rst. Signed-off-by: Tomasz 'CeDeROM' CEDRO <tomek@cedro.info>
147 lines
7.1 KiB
ReStructuredText
147 lines
7.1 KiB
ReStructuredText
==========================
|
||
USB (Universal Serial Bus)
|
||
==========================
|
||
|
||
NAKing USB OUT/IN Tokens
|
||
------------------------
|
||
|
||
USB supports a NAKing mechanism to pace incoming OUT data from the USB host.
|
||
The USB device class driver can control this NAKing only indirectly
|
||
by the manner in which it manages read requests.
|
||
|
||
Similarly, USB will refuse to perform the USB host's requests for IN data
|
||
by NAKing the host's IN tokens.
|
||
|
||
.. note:: USB direction naming is host-centric. This makes life difficult for
|
||
people working USB device drivers:
|
||
IN refers to data coming from the device INto the host.
|
||
But for the device, this is a write operation (write being
|
||
peripheral-centric: from-memory-to-peripheral).
|
||
OUT refers to data sent from the host OUT to the device.
|
||
For the device this is a read (peripheral-to-memory) operation.
|
||
|
||
|
||
NAKing USB OUT Tokens
|
||
^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
Below is how the NAKing is implemented in the interaction between the USB
|
||
device class driver and USB Device Controller Drivers (DCDs):
|
||
|
||
1. At initialization time when the USB device class driver is enumerated
|
||
by the host, the class driver will allocates a number of read requests
|
||
(which contain request buffers).
|
||
2. The USB device class driver sends each allocated read request to the device
|
||
DCD via ``DRVR_EPSUBMIT()``.
|
||
3. Upon receipt, the DCD will keep all of these empty read requests in a list.
|
||
4. When the OUT token is received what happens next depends upon the state
|
||
of the list of empty read requests:
|
||
|
||
4a. If there are no requests in the list of empty read requests, the DCD
|
||
will have configured the endpoint to NAK the OUT token. This NAKing
|
||
will continue until the list of read requests is non-empty and the DCD
|
||
disables the NAKing to signal that it can accept the OUT packet data.
|
||
|
||
4b. If the list of read requests is not empty, the DCD will remove the next
|
||
read request from the list, receive the DATA accompanying the OUT
|
||
token, copy the received packet data into the read request's buffer,
|
||
and return the filled reqd request to the USB device class driver.
|
||
The data is returned using a callback function pointer that is
|
||
contained inside of the read request.
|
||
|
||
5. When the filled read request if returned, the USB device class driver will
|
||
add the newly filled read request to the TAIL of a list of filled read
|
||
requests. This will then be available to the the driver read logic when
|
||
the application requests more data.
|
||
This step will also wake up read logic that has been suspended waiting
|
||
for the availability of incoming data.
|
||
6. The receive logic starts when the application requests data (or it is
|
||
resumed after the receipt of new data) it will look at the read request
|
||
at the HEAD of the list of filled read requests. If will return the data
|
||
payload to the application by copying it from the read request's buffer
|
||
into the application-provided receive buffer:
|
||
|
||
6a. If the application's receive buffer becomes full and it cannot accept
|
||
more data, the receive logic will save the offset in the data buffer
|
||
where it left off. If the application asks for more data, it will
|
||
resume transferring at the point where it left off.
|
||
|
||
6b. If the receive logic transfers all of the data from the receive
|
||
buffer. It will remove the read request from the HEAD of the list
|
||
of filled read requests and return the receive buffer to the driver
|
||
via ``DRVR_EPSUBMIT()`` (See step 3).
|
||
The receive logic will then continue at step 6.
|
||
|
||
6c. If the receive logic needs more data in order to complete
|
||
the application read operation, it will wait until it is awakened
|
||
by the receipt of a newly filled.
|
||
|
||
|
||
CDC/ACM driver
|
||
~~~~~~~~~~~~~~
|
||
|
||
The CDC/ACM driver differs from all other drivers because it is REQUIRED
|
||
to discard data if there is no application ready to receive the data.
|
||
This is how a serial device works. So there is nothing like step 5
|
||
in the CDC/ACM driver and in step 6 the CDC/ACM driver will not remember
|
||
the point where it left off; if the application cannot accept any further
|
||
data, it will return the partially emptied read request to the DCD
|
||
immediately to be filled – dropping an untransferred data into the bit bucket.
|
||
|
||
This is not an error or an oversight in the CDC/ACM. This is the intentional
|
||
design. This is the CORRECT behavior of the CDC/ACM driver. Data overrun can
|
||
only be prevented on a serial connection by using either XON/XOFF software
|
||
flow control or hardware flow control. A special endpoint 0 control request
|
||
is reserved for the CDC/ACM implementation.
|
||
|
||
.. note:: As of this writing, the logic that implements the CDC/ACM
|
||
_hardware flow control has not been implemented.
|
||
There is a place holder for such logic, but the implementation
|
||
is missing._
|
||
|
||
|
||
NAKing USB IN Tokens
|
||
^^^^^^^^^^^^^^^^^^^^
|
||
|
||
The DCD will NAK IN tokens whenever it has nothing to send to the host PC.
|
||
Without going into as much detail, suffice it to say that the logic flow
|
||
is very similar to the case off OUT tokens with the following differences:
|
||
|
||
1. The list of empty write requests are not provided to the DCD at
|
||
initialization time, but are instead are retained in a list of empty write
|
||
requests in the USB device class driver.
|
||
|
||
2. When the USB class driver has data to send, it will remove a write request
|
||
from this list, copy the outgoing application data into the write buffer,
|
||
and send the filled write request to the DCD via ``DRVR_EPSUBMIT()``.
|
||
If there are no available write requests, the application thread may block
|
||
waiting for the next write request to be returned from the DCD.
|
||
|
||
3. The DCD will keep a list of filled write requests for each endpoint.
|
||
When that list becomes non-empty, the DCD will disable the NAKing and
|
||
set up to transfer data to the host. Normally this involves copying
|
||
the IN data into an outgoing FIFO or setting up some write DMA transfers:
|
||
|
||
3a. After the data has been transferred to the USB device hardware,
|
||
the emptied write request will be returned to the USB device class driver.
|
||
This is done through a callback function pointer within the write request.
|
||
|
||
3b. If the DCD's list of write requests becomes empty, it will set up
|
||
the endpoint to NAK any further IN tokens (after the final IN transfer
|
||
completes).
|
||
|
||
4. When the USB device class driver receives the emptied write request from
|
||
the DCD, it will return the write request to its list of empty write
|
||
request and may, perhaps, wake up any thread that was waiting
|
||
for an available write request to send more data.
|
||
|
||
So the fundamental different between IN and OUT processing is that for
|
||
IN transfers, empty write requests are saved in the USB device class driver
|
||
and then given to the DCD when they are filled with outgoing data.
|
||
For OUT transfers empty read requests are retained in the DCD and returned
|
||
to the USB device class driver when they filled with incoming data.
|
||
|
||
Similarly, filled read requests are queued for application read processing
|
||
in the USB device class driver; filled write requests are queued for transfer
|
||
to the host in the DCD.
|
||
|
||
But in either case, NAKing occurs when associated DCD request queue is empty.
|