454 lines
15 KiB
HTML
454 lines
15 KiB
HTML
<html>
|
|
<head>
|
|
<title>NuttX USB Trace Capability</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
|
|
<body background="backgd.gif">
|
|
<hr><hr>
|
|
<table width ="100%">
|
|
<tr align="center" bgcolor="#e4e4e4">
|
|
<td>
|
|
<h1><big><font color="#3c34ec"><i>NuttX USB Device Trace</i></font></big></h1>
|
|
<p>Last Updated: March 20, 2011</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr><hr>
|
|
<p><b>USB Device Tracing Controls</b>.
|
|
The NuttX USB device subsystem supports a fairly sophisticated tracing facility.
|
|
The basic trace cabability is controlled by these NuttX configuration settings:
|
|
</p>
|
|
<ul>
|
|
<li><code>CONFIG_USBDEV_TRACE</code>: Enables USB tracing</li>
|
|
<li><code>CONFIG_USBDEV_TRACE_NRECORDS</code>: Number of trace entries to remember</li>
|
|
</ul>
|
|
<p><b>Trace IDs</b>.
|
|
The trace facility works like this:
|
|
When enabled, USB events that occur in either the USB device driver or in the USB class driver are logged.
|
|
These events are described in <code>include/nuttx/usb/usbdev_trace.h</code>.
|
|
The logged events are identified by a set of event IDs:
|
|
</p>
|
|
<ul><table>
|
|
<tr>
|
|
<td><code>TRACE_INIT_ID</code></td>
|
|
<td>Initialization events</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_EP_ID</code></td>
|
|
<td>Endpoint API calls</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_DEV_ID</code></td>
|
|
<td>USB device API calls</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_CLASS_ID</code></td>
|
|
<td>USB class driver API calls</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_CLASSAPI_ID</code></td>
|
|
<td>Other class driver system API calls</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_CLASSSTATE_ID</code></td>
|
|
<td>Track class driver state changes</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_INTENTRY_ID</code></td>
|
|
<td>Interrupt handler entry</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_INTDECODE_ID</code></td>
|
|
<td>Decoded interrupt event</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_INTEXIT_ID</code></td>
|
|
<td>Interrupt handler exit</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_OUTREQQUEUED_ID</code></td>
|
|
<td>Request queued for OUT endpoint</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_INREQQUEUED_ID</code></td>
|
|
<td>Request queued for IN endpoint</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_READ_ID</code></td>
|
|
<td>Read (OUT) action</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_WRITE_ID</code></td>
|
|
<td>Write (IN) action</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_COMPLETE_ID</code></td>
|
|
<td>Request completed</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_DEVERROR_ID</code></td>
|
|
<td>USB controller driver error event</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>TRACE_CLSERROR_ID</code></td>
|
|
<td>USB class driver error event</td>
|
|
</tr>
|
|
</table></ul>
|
|
<p><b>Logged Events</b>.
|
|
Each logged event is 32-bits in size and includes
|
|
</p>
|
|
<ol>
|
|
<li>8-bits of the trace ID (values associated with the above)</li>
|
|
<li>8-bits of additional trace ID data, and</li>
|
|
<li>16-bits of additional data.</li>
|
|
</ol>
|
|
<p><b>8-bit Trace Data</b>
|
|
The 8-bit trace data depends on the specific event ID. As examples,
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
For the USB serial and mass storage class, the 8-bit event data is provided in <code>include/nuttx/usb/usbdev_trace.h</code>.
|
|
</li>
|
|
<li>
|
|
For the USB device driver, that 8-bit event data is provided within the USB device driver itself.
|
|
So, for example, the 8-bit event data for the LPC1768 USB device driver is found in <code>arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c</code>.
|
|
</li>
|
|
</ul>
|
|
<p><b>16-bit Trace Data</b>.
|
|
The 16-bit trace data provided additional context data relevant to the specific logged event.
|
|
</p>
|
|
<p><b>Trace Control Interfaces</b>.
|
|
Logging of each of these kinds events can be enabled or disabled using the interfaces described in <code>include/nuttx/usb/usbdev_trace.h</code>.
|
|
</p>
|
|
<p><b>Enabling USB Device Tracing</b>.
|
|
USB device tracing will be configured if <code>CONFIG_USBDEV</code> and either of the following are set in the NuttX configuration file:
|
|
</p>
|
|
<ul>
|
|
<li><code>CONFIG_USBDEV_TRACE</code>, or</li>
|
|
<li><code>CONFIG_DEBUG_FEATURES and CONFIG_DEBUG_USB</code></li>
|
|
</ul>
|
|
<p><b>Log Data Sink</b>.
|
|
The logged data itself may go to either (1) an internal circular buffer, or (2) may be provided on the console.
|
|
If <code>CONFIG_USBDEV_TRACE</code> is defined, then the trace data will go to the circular buffer.
|
|
The size of the circular buffer is determined by <code>CONFIG_USBDEV_TRACE_NRECORDS</code>.
|
|
Otherwise, the trace data goes to console.
|
|
<p>
|
|
<p><b>Example</b>.
|
|
Here is an example of USB trace output using <code>apps/examples/usbserial</code> for an LPC1768 platform with the following NuttX configuration settings:
|
|
</p>
|
|
<ul>
|
|
<li><code>CONFIG_DEBUG_FEATURES</code>, <code>CONFIG_DEBUG_INFO</code>, <code>CONFIG_USB</code>
|
|
<li><code>CONFIG_EXAMPLES_USBSERIAL_TRACEINIT</code>, <code>CONFIG_EXAMPLES_USBSERIAL_TRACECLASS</code>,
|
|
<code>CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS</code>, <code>CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER</code>,
|
|
<code>CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS</code>
|
|
</ul>
|
|
<p>Console Output:</p>
|
|
<ul><table>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>ABDE</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>usbserial_main: Registering USB serial driver</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>uart_register: Registering /dev/ttyUSB0</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>usbserial_main: Successfully registered the serial driver</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">1</td>
|
|
<td align="left"><code>Class API call 1: 0000</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">2</td>
|
|
<td align="left"><code>Class error: 19:0000</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>usbserial_main: ERROR: Failed to open /dev/ttyUSB0 for reading: 107</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center"> </td>
|
|
<td align="left"><code>usbserial_main: Not connected. Wait and try again.</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">3</td>
|
|
<td align="left"><code>Interrupt 1 entry: 0039</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">4</td>
|
|
<td align="left"><code>Interrupt decode 7: 0019</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">5</td>
|
|
<td align="left"><code>Interrupt decode 32: 0019</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">6</td>
|
|
<td align="left"><code>Interrupt decode 6: 0019</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">7</td>
|
|
<td align="left"><code>Class disconnect(): 0000</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">8</td>
|
|
<td align="left"><code>Device pullup(): 0001</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">9</td>
|
|
<td align="left"><code>Interrupt 1 exit: 0000</code></td>
|
|
</tr>
|
|
</table></ul>
|
|
<p>
|
|
The numbered items are USB USB trace output.
|
|
You can look in the file <code>drivers/usbdev/usbdev_trprintf.c</code> to see examctly how each output line is formatted.
|
|
Here is how each line should be interpreted:
|
|
</p>
|
|
<ul><table>
|
|
<tr>
|
|
<th align="center"> </th>
|
|
<td align="left">USB EVENT ID</td>
|
|
<td align="right">8-bit<br>EVENT<br>DATA</td>
|
|
<td align="left">MEANING</td>
|
|
<td align="left">16-bit<br>EVENT<br>DATA</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">1</td>
|
|
<td align="left"><code>TRACE_CLASSAPI_ID</code><sup>1</sup></td>
|
|
<td align="right">1</td>
|
|
<td align="left"><code>USBSER_TRACECLASSAPI_SETUP</code><sup>1</sup></td>
|
|
<td align="left">0000</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">2</td>
|
|
<td align="left"><code>TRACE_CLSERROR_ID</code><sup>1</sup></td>
|
|
<td align="right">19</td>
|
|
<td align="left"><code>USBSER_TRACEERR_SETUPNOTCONNECTED</code><sup>1</sup></td>
|
|
<td align="left">0000</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">3</td>
|
|
<td align="left"><code>TRACE_INTENTRY_ID</code><sup>1</sup></td>
|
|
<td align="right">1</td>
|
|
<td align="left"><code>LPC17_40_TRACEINTID_USB</code><sup>2</sup></td>
|
|
<td align="left">0039</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">4</td>
|
|
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
|
|
<td align="right">7</td>
|
|
<td align="left"><code>LPC17_40_TRACEINTID_DEVSTAT</code><sup>2</sup></td>
|
|
<td align="left">0019</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">5</td>
|
|
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
|
|
<td align="right">32</td>
|
|
<td align="left"><code>LPC17_40_TRACEINTID_SUSPENDCHG</code><sup>2</sup></td>
|
|
<td align="left">0019</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">6</td>
|
|
<td align="left"><code>TRACE_INTDECODE_ID</code><sup>2</sup></td>
|
|
<td align="right">6</td>
|
|
<td align="left"><code>LPC17_40_TRACEINTID_DEVRESET</code><sup>2</sup></td>
|
|
<td align="left">0019</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">7</td>
|
|
<td align="left"><code>TRACE_CLASS_ID</code><sup>1</sup></td>
|
|
<td align="right">3</td>
|
|
<td align="left"><code>(See TRACE_CLASSDISCONNECT</code><sup>1</sup>)</td>
|
|
<td align="left">0000</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">8</td>
|
|
<td align="left"><code>TRACE_DEV_ID</code><sup>1</sup></td>
|
|
<td align="right">6</td>
|
|
<td align="left"><code>(See TRACE_DEVPULLUP</code><sup>1</sup>)</td>
|
|
<td align="left">0001</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center">9</td>
|
|
<td align="left"><code>TRACE_INTEXIT_ID</code><sup>1</sup></td>
|
|
<td align="right">1</td>
|
|
<td align="left"><code>LPC17_40_TRACEINTID_USB</code><sup>2</sup></td>
|
|
<td align="left">0000</td>
|
|
</tr>
|
|
</table>
|
|
<p><small><b>NOTES</b>:<br>
|
|
<sup>1</sup>See <code>include/nuttx/usb/usbdev_trace.h</code><br>
|
|
<sup>2</sup><code>See arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c</code>
|
|
</small></p>
|
|
</ul>
|
|
<p>
|
|
In the above example you can see that:
|
|
</p>
|
|
<ul>
|
|
<li><b>1</b>.
|
|
The serial class USB setup method was called for the USB serial class.
|
|
This is the corresponds to the following logic in <code>drivers/usbdev/pl2303.c</code>:
|
|
<ul><pre>
|
|
static int pl2303_setup(FAR struct uart_dev_s *dev)
|
|
{
|
|
...
|
|
usbtrace(PL2303_CLASSAPI_SETUP, 0);
|
|
...
|
|
</pre></ul>
|
|
</li>
|
|
<li><b>2</b>.
|
|
An error occurred while processing the setup command because no configuration has yet been selected by the host.
|
|
This corresponds to the following logic in <code>drivers/usbdev/pl2303.c</code>:
|
|
<ul><pre>
|
|
static int pl2303_setup(FAR struct uart_dev_s *dev)
|
|
{
|
|
...
|
|
/* Check if we have been configured */
|
|
|
|
if (priv->config == PL2303_CONFIGIDNONE)
|
|
{
|
|
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SETUPNOTCONNECTED), 0);
|
|
return -ENOTCONN;
|
|
}
|
|
...
|
|
</pre></ul>
|
|
<li><b>3-6</b>.
|
|
Here is a USB interrupt that suspends and resets the device.
|
|
</li>
|
|
<li><b>7-8</b>.
|
|
During the interrupt processing the serial class is disconnected
|
|
</li>
|
|
<li><b>9</b>.
|
|
And the interrupt returns
|
|
</li>
|
|
</ul>
|
|
<p><b>USB Monitor</b>.
|
|
The <i>USB monitor</i> is an application in the <code>apps/system/usbmonitor</code> that provides a convenient way to get debug trace output.
|
|
If tracing is enabled, the USB device will save encoded trace output in in-memory buffer;
|
|
if the USB monitor is also enabled, that trace buffer will be periodically emptied and dumped to the
|
|
system logging device (the serial console in most configurations).
|
|
The following are some of the relevant configuration options:
|
|
</p>
|
|
<ul>
|
|
<table width="100%">
|
|
<tr>
|
|
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
|
|
<i>Device Drivers -> USB Device Driver Support</i>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBDEV_TRACE=y</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Enable USB trace feature
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBDEV_TRACE_NRECORDS=<i>nnnn</i></code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Buffer <i>nnnn</i> records in memory.
|
|
If you lose trace data, then you will need to increase the size of this buffer
|
|
(or increase the rate at which the trace buffer is emptied).
|
|
</td>
|
|
</tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBDEV_TRACE_STRINGS=y</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Optionally, convert trace ID numbers to strings.
|
|
This feature may not be supported by all drivers.
|
|
</td>
|
|
<tr>
|
|
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
|
|
<i>Application Configuration -> NSH LIbrary</i>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_NSH_USBDEV_TRACE=n</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Make sure that any built-in tracing from NSH is disabled.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_NSH_ARCHINIT=y</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Enable this option <i>only</i> if your board-specific logic has logic to automatically start the USB monitor.
|
|
Otherwise the USB monitor can be started or stopped with the <code>usbmon_start</code> and <code>usbmon_stop</code> commands from the NSH console.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2" align="left" valign="top" bgcolor="#e4e4e4">
|
|
<i>Application Configuration -> System NSH Add-Ons</i>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBMONITOR=y</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Enable the USB monitor daemon
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBMONITOR_STACKSIZE=<i>nnnn</i></code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Sets the USB monitor daemon stack size to <i>nnnn</i>.
|
|
The default is 2KiB.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBMONITOR_PRIORITY=50</code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Sets the USB monitor daemon priority to <i>nnnn</i>.
|
|
This priority should be low so that it does not interfere with other operations, but not so low that you cannot dump the buffered USB data sufficiently rapidly.
|
|
The default is 50.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBMONITOR_INTERVAL=<i>nnnn</i></code>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Dump the buffered USB data every <i>nnnn</i> seconds.
|
|
If you lose buffered USB trace data, then dropping this value will help by increasing the rate at which the USB trace buffer is emptied.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="30%" align="left" valign="top">
|
|
<code>CONFIG_USBMONITOR_TRACEINIT=y</code><br>
|
|
<code>CONFIG_USBMONITOR_TRACECLASS=y</code><br>
|
|
<code>CONFIG_USBMONITOR_TRACETRANSFERS=y</code><br>
|
|
<code>CONFIG_USBMONITOR_TRACECONTROLLER=y</code><br>
|
|
<code>CONFIG_USBMONITOR_TRACEINTERRUPTS=y</code><br>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
Selects which USB event(s) that you want to be traced.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</ul>
|
|
<p>
|
|
NOTE: If USB debug output is also enabled, both outputs will appear on the serial console.
|
|
However, the debug output will be asynchronous with the trace output and, hence, difficult to interpret.
|
|
</p>
|
|
</body>
|
|
</html>
|