This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/PROCESSOR-SDK-OMAPL138: possible race condition in PDK 1.0.5 bulk usb device driver

Part Number: PROCESSOR-SDK-OMAPL138
Other Parts Discussed in Thread: OMAPL138

Tool/software: TI-RTOS

Working with PDK 1.0.5 on an OMAP L138, using the USB bulk example, we found the driver would some times lock up, waiting for readSem to be signalled.

The patch below fixed this for us.  We're hoping someone at TI can verify that this is a problem, and that our fix is correct.

diff -uprN pdk_omapl138_1_0_5-original/packages/ti/drv/usb/src/usb_func/device/usbdbulk.c pdk_omapl138_1_0_5/packages/ti/drv/usb/src/usb_func/device/usbdbulk.c
--- pdk_omapl138_1_0_5-original/packages/ti/drv/usb/src/usb_func/device/usbdbulk.c      2018-07-26 19:35:01.000000000 -0700
+++ pdk_omapl138_1_0_5/packages/ti/drv/usb/src/usb_func/device/usbdbulk.c       2018-10-15 13:50:10.643378800 -0700
@@ -918,6 +918,7 @@ int32_t USBD_bulkWrite(USB_Handle handle
     {
         if ((dataSize <= DATA_IN_EP_MAX_SIZE) && (dataSize > 0))
         {
+            psInst->eBulkTxState = BULK_STATE_WAIT_DATA;
             usbSetupEpReq(pGadgetObj,
                     psInst->ucINEndpoint,   /* IN EP # */
                     (uint32_t*)buffer,
@@ -925,7 +926,6 @@ int32_t USBD_bulkWrite(USB_Handle handle
                     dataSize,
                     USB_TRANSFER_TYPE_BULK);

-            psInst->eBulkTxState = BULK_STATE_WAIT_DATA;
             usb_osalPendLock(psInst->writeSem, SemaphoreP_WAIT_FOREVER);

             retSize = psInst->usLastTxSize;
@@ -972,6 +972,9 @@ int32_t USBD_bulkRead(USB_Handle handle,
         /* prepare for incoming bulk connection from host */
         *dataSize = psInst->usLastRxSize = 0;

+        /* set state to waiting */
+        psInst->eBulkRxState = BULK_STATE_WAIT_DATA;
+
         /* Setup request for the lower layer to be ready for OUT transfer */
         usbSetupEpReq(pGadgetObj,
                 psInst->ucOUTEndpoint,
@@ -980,9 +983,6 @@ int32_t USBD_bulkRead(USB_Handle handle,
                 DATA_OUT_EP_MAX_SIZE,
                 USB_TRANSFER_TYPE_BULK);

-        /* set state to waiting */
-        psInst->eBulkRxState = BULK_STATE_WAIT_DATA;
-
         usb_osalPendLock(psInst->readSem, SemaphoreP_WAIT_FOREVER);
         *dataSize = psInst->usLastRxSize;


  • There may be other race conditions in this driver; by repeatedly starting and stopping a program on the host that just does bulk writes & bulk reads, I can eventually get in a state in cppi41dma.c dmaTxCompletion() where completed_bd == NULL. Subsequent read/write operations from the host all fail, and I cannot figure out how to recover from this state. =(
  • Hello Adam,

    I'm working on getting this setup on my end. If there are any specific steps needed to reproduce the race condition please let me know.

  • to expose the race condition that the patch addresses, we simple wrote and read bulk small bulk packets (about 20 bytes data) as fast as we could using libusb on a Windows PC.

    The other problem (probably unrelated) I'm currently seeing is that If I do about 14 writes from the Host, WITHOUT DOING ANY READS, then the OMAP stops responding to USB packets.
  • I'm also getting stuck in usb_wrapper.c near line 385

    while(musbPtr->dmaStatus & CPDMA_RX_PENDING)
    {
    usbMusbDcdEpEvntHandler((void *)musbPtr);
    musbPtr->dmaStatus = CppiDmaGetPendStatus(musbPtr->controllerId);
    }

    It seems this flag doesn't get cleared. I can't seem to find any documentation on the underlying register
    HWREG(USB_OTGBASE + CPDMA_PEND_0_REGISTER);
  • Hi Adam,

    I couldn't reproduce this issue using the Python script "usb_dev_bulk_host_application.py" found under pdk_omapl138_1_0_6\packages\ti\drv\usb\example\usb_dev\bulk.

    Can you provide the program or list the steps needed to reproduce this with libusb?
  • Two things I can think of that might help you reproduce this.

    We were running the OMAP at top speed, 456MHz.

    The libUSB code was a very tight loop of

    rc = libusb_bulk_transfer(devh, OUT_EP, out, out_size, &transferred, 2);
    rc = libusb_bulk_transfer(devh, IN_EP, in, in_size, &in_size, 2);
  • I am still seeing this issue. Snooping with a protocol analyzer, the device responds to OUT with NYET, and responds to IN with NAK. In the ROV, my USB task is blocked in USBD_bulkRead waiting for a semaphore to clear.
  • I'm using 1.0.5, which does not have this script. Where can I find 1.0.6 ???
  • a'ight, I found software-dl.ti.com/.../index_FDS.html which has PROCESSOR-SDK-RTOS-OMAPL138 05_01_00_11 which has PDK 1.0.6

    but I note your wiki has references to PDKs 1.08.00, 1.09.00, and 1.10.00 (were those typos?)
    processors.wiki.ti.com/.../PDK_Patches

    Is 1.0.6 the very latest? If not, where can I find the very latest?
  • Apologies, it took me a while to set things up.

    Here's my setup:

    Brand new fresh out of the box lcdk

    pdk 1.0.6 (unmodified)

    CCSv7

    usb bulk example built as described in processors.wiki.ti.com/index.php/Rebuilding_The_PDK#PDK_Example_and_Test_Project_Creation

    I'm on windows, so I run Linux (ubuntu 18.04, freshly installed VM) in order to "python usb_dev_bulk_host_application.py"

    Here's what it does for me:

    USB generic bulk host application

    Send string to usb bulk device and wait for reverse case string echo back

    and check to make sure the returned data is matched with what we expect

    usb_dev_bulk_host_application.py [single] to send 1 packet

    Found device with following usb info:

    ('Bus:        ', 1)

    ('Address:    ', 4)

    ('Vendor Id:  ', '0x1cbe')

    ('Product Id: ', '0x0003')

    Sending test string of length 5200 bytes... in chunk of 512 bytes

    Traceback (most recent call last):

     File "usb_dev_bulk_host_application.py", line 160, in <module>

       for letter in ep2.read(len(substring)):

     File "/usr/local/lib/python2.7/dist-packages/usb/core.py", line 402, in read

       return self.device.read(self, size_or_buffer, timeout)

     File "/usr/local/lib/python2.7/dist-packages/usb/core.py", line 988, in read

       self.__get_timeout(timeout))

     File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 833, in bulk_read

       timeout)

     File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 936, in __read

       _check(retval)

     File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _check

       raise USBError(_strerror(ret), ret, _libusb_errno[ret])

    usb.core.USBError: [Errno 110] Operation timed out

    I also have a hardware USB protocol analyzer between the LCDK and the PC (Beagle USB 480 by Total Phase) so I could watch packets fly by.

    I've included (below) a CSV of what it caught during this test. (Index 0 through 1407 is all the initial string descriptor stuff with the Windows OS.  Index 1432 is where I "connected" it to the Linux VM.  Index 7225 is where I ran the python script you suggested)

    Note this may NOT be the deadlock I was seeing; this may be a different problem another developer here is seeing:  Once the LCDK starts, any subsequent Control transfers will cause it to lock up.

    # Total Phase Data Center(tm) v6.73
    # (c) 2005-2017 Total Phase, Inc.
    # www.totalphase.com
    #
    #
    #
    # Level,Sp,Index,m:s.ms.us,Dur,Len,Err,Dev,Ep,Record,Summary
    0,,0,0:00.000.000,,,,,,Capture started (Aggregate),[11/28/18 15:15:13]
    0,,1,0:00.000.000,,,,,,<Host connected>,
    0,FS,2,0:30.257.569,,,,,,<Full-speed>,
    0,FS,3,0:30.260.569,97.726.666 ms,,,,,<Suspend>,
    0,FS,4,0:30.358.296,5.650 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,FS,5,0:30.358.301,1.097.500 ms,,,,,<Chirp K>,
    0,FS,6,0:30.359.399,26.033 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,FS,7,0:30.359.425,53.723.600 ms,,,,,[548 Chirp K-J pairs] ,
    0,FS,1105,0:30.413.149,297.883 us,,,,,<Reset>,
    0,HS,1106,0:30.413.446,,,,,,<High-speed>,
    0,HS,1107,0:30.413.446,32.129.850 ms,,,,,[258 SOF],[Frames: 231.x - 263.3]
    0,HS,1108,0:30.445.595,28.250 us,18 B,,00,00,Get Device Descriptor,Index=0 Length=64
    0,HS,1122,0:30.445.701,83 ns,,,,,[1 SOF],[Frame: 263.4]
    0,HS,1123,0:30.445.690,23.200 us,0 B,,00,00,Set Address,Address=56
    0,HS,1133,0:30.445.826,10.251.600 ms,,,,,[83 SOF],[Frames: 263.5 - 273.7]
    0,HS,1134,0:30.456.163,34.033 us,18 B,,56,00,Get Device Descriptor,Index=0 Length=18
    0,HS,1148,0:30.456.203,1.000.216 ms,,,,,[9 SOF],[Frames: 274.0 - 275.0]
    0,HS,1149,0:30.457.240,28.650 us,32 B,,56,00,Get Configuration Descriptor,Index=0 Length=255
    0,HS,1163,0:30.457.293,28.450 us,18 B,,56,00,Get String Descriptor,Index=3 Length=255
    0,HS,1177,0:30.457.328,66 ns,,,,,[1 SOF],[Frame: 275.1]
    0,HS,1178,0:30.457.336,30.516 us,4 B,,56,00,Get String Descriptor,Index=0 Length=255
    0,HS,1192,0:30.457.382,28.333 us,40 B,,56,00,Get String Descriptor,Index=2 Length=255
    0,HS,1206,0:30.457.453,16.877.583 ms,,,,,[136 SOF],[Frames: 275.2 - 292.1]
    0,HS,1207,0:30.474.404,34.416 us,18 B,,56,00,Get Device Descriptor,Index=0 Length=18
    0,HS,1221,0:30.474.455,83 ns,,,,,[1 SOF],[Frame: 292.2]
    0,HS,1222,0:30.474.508,16.633 us,4 B,,56,00,Get String Descriptor,Index=0 Length=255
    0,HS,1235,0:30.474.580,83 ns,,,,,[1 SOF],[Frame: 292.3]
    0,HS,1236,0:30.474.598,30.300 us,18 B,,56,00,Get String Descriptor,Index=3 Length=255
    0,HS,1250,0:30.474.705,83 ns,,,,,[1 SOF],[Frame: 292.4]
    0,HS,1251,0:30.474.698,12.766 us,36 B,,56,00,Get String Descriptor,Index=1 Length=255
    0,HS,1264,0:30.474.793,29.600 us,40 B,,56,00,Get String Descriptor,Index=2 Length=255
    0,HS,1278,0:30.474.831,2.250.400 ms,,,,,[19 SOF],[Frames: 292.5 - 294.7]
    0,HS,1279,0:30.477.135,28.183 us,18 B,,56,00,Get Device Descriptor,Index=0 Length=18
    0,HS,1293,0:30.477.206,66 ns,,,,,[1 SOF],[Frame: 295.0]
    0,HS,1294,0:30.477.187,28.183 us,9 B,,56,00,Get Configuration Descriptor,Index=0 Length=9
    0,HS,1308,0:30.477.241,34.416 us,32 B,,56,00,Get Configuration Descriptor,Index=0 Length=32
    0,HS,1322,0:30.477.290,28.283 us,2 B,,56,00,Get Device Status,
    0,HS,1336,0:30.477.331,66 ns,,,,,[1 SOF],[Frame: 295.1]
    0,HS,1337,0:30.477.362,26.216 us,0 B,,56,00,Set Configuration,Configuration=1
    0,HS,1347,0:30.477.456,605.339.850 ms,,,,,[4843 SOF],[Frames: 295.2 - 900.4]
    0,HS,1348,0:31.082.839,41.433 us,4 B,,56,00,Get String Descriptor,Index=0 Length=255
    0,HS,1362,0:31.082.921,66 ns,,,,,[1 SOF],[Frame: 900.5]
    0,HS,1363,0:31.082.911,29.533 us,36 B,,56,00,Get String Descriptor,Index=1 Length=255
    0,HS,1377,0:31.082.958,33.850 us,40 B,,56,00,Get String Descriptor,Index=2 Length=255
    0,HS,1391,0:31.083.046,66 ns,,,,,[1 SOF],[Frame: 900.6]
    0,HS,1392,0:31.083.052,47.900 us,48 B,,56,00,Get String Descriptor,Index=5 Length=255
    0,HS,1406,0:31.083.171,66 ns,,,,,[1 SOF],[Frame: 900.7]
    0,HS,1407,0:31.083.162,43.200 us,40 B,,56,00,Get String Descriptor,Index=4 Length=255
    0,HS,1421,0:31.083.296,1.999.921.683 s,,,,,[15998 SOF],[Frames: 901.0 - 852.5] [Periodic Timeout]
    0,HS,1422,0:33.083.342,1.999.921.700 s,,,,,[15998 SOF],[Frames: 852.6 - 804.3] [Periodic Timeout]
    0,HS,1423,0:35.083.389,1.999.921.700 s,,,,,[15998 SOF],[Frames: 804.4 - 756.1] [Periodic Timeout]
    0,HS,1424,0:37.083.436,1.999.921.700 s,,,,,[15998 SOF],[Frames: 756.2 - 707.7] [Periodic Timeout]
    0,HS,1425,0:39.083.482,1.999.921.700 s,,,,,[15998 SOF],[Frames: 708.0 - 659.5] [Periodic Timeout]
    0,HS,1426,0:41.083.529,1.999.921.683 s,,,,,[15998 SOF],[Frames: 659.6 - 611.3] [Periodic Timeout]
    0,HS,1427,0:43.083.576,1.999.921.683 s,,,,,[15998 SOF],[Frames: 611.4 - 563.1] [Periodic Timeout]
    0,HS,1428,0:45.083.622,1.999.921.666 s,,,,,[15998 SOF],[Frames: 563.2 - 514.7] [Periodic Timeout]
    0,HS,1429,0:47.083.669,1.999.921.666 s,,,,,[15998 SOF],[Frames: 515.0 - 466.5] [Periodic Timeout]
    0,HS,1430,0:49.083.715,1.999.921.666 s,,,,,[15998 SOF],[Frames: 466.6 - 418.3] [Periodic Timeout]
    0,HS,1431,0:51.083.762,144.521.500 ms,,,,,[1157 SOF],[Frames: 418.4 - 563.0]
    0,HS,1432,0:51.231.285,5.510.383 ms,,,,,<Suspend>,
    0,HS,1433,0:51.236.795,5.933 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,1434,0:51.236.801,1.097.166 ms,,,,,<Chirp K>,
    0,HS,1435,0:51.237.898,25.750 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,1436,0:51.237.924,53.704.800 ms,,,,,[548 Chirp K-J pairs] ,
    0,HS,2534,0:51.291.629,289.333 us,,,,,<Reset>,
    0,HS,2535,0:51.291.918,,,,,,<High-speed>,
    0,HS,2536,0:51.291.918,32.754.933 ms,,,,,[263 SOF],[Frames: 626.x - 659.3]
    0,HS,2537,0:51.324.697,28.266 us,18 B,,00,00,Get Device Descriptor,Index=0 Length=64
    0,HS,2551,0:51.324.798,66 ns,,,,,[1 SOF],[Frame: 659.4]
    0,HS,2552,0:51.324.839,22.783 us,0 B,,00,00,Set Address,Address=57
    0,HS,2562,0:51.324.923,10.001.550 ms,,,,,[81 SOF],[Frames: 659.5 - 669.5]
    0,HS,2563,0:51.334.928,28.150 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,2577,0:51.335.049,500.150 us,,,,,[5 SOF],[Frames: 669.6 - 670.2]
    0,HS,2578,0:51.335.523,32.216 us,32 B,,57,00,Get Configuration Descriptor,Index=0 Length=255
    0,HS,2592,0:51.335.620,28.650 us,18 B,,57,00,Get String Descriptor,Index=3 Length=255
    0,HS,2606,0:51.335.674,83 ns,,,,,[1 SOF],[Frame: 670.3]
    0,HS,2607,0:51.335.720,28.366 us,4 B,,57,00,Get String Descriptor,Index=0 Length=255
    0,HS,2621,0:51.335.799,83 ns,,,,,[1 SOF],[Frame: 670.4]
    0,HS,2622,0:51.335.808,28.216 us,40 B,,57,00,Get String Descriptor,Index=2 Length=255
    0,HS,2636,0:51.335.924,7.251.150 ms,,,,,[59 SOF],[Frames: 670.5 - 677.7]
    0,HS,2637,0:51.343.143,38.466 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,2651,0:51.343.258,16.483 us,4 B,,57,00,Get String Descriptor,Index=0 Length=255
    0,HS,2664,0:51.343.301,83 ns,,,,,[1 SOF],[Frame: 678.0]
    0,HS,2665,0:51.343.361,15.666 us,18 B,,57,00,Get String Descriptor,Index=3 Length=255
    0,HS,2678,0:51.343.426,83 ns,,,,,[1 SOF],[Frame: 678.1]
    0,HS,2679,0:51.343.506,28.766 us,36 B,,57,00,Get String Descriptor,Index=1 Length=255
    0,HS,2693,0:51.343.551,83 ns,,,,,[1 SOF],[Frame: 678.2]
    0,HS,2694,0:51.343.586,29.650 us,40 B,,57,00,Get String Descriptor,Index=2 Length=255
    0,HS,2708,0:51.343.676,582.586.466 ms,,,,,[4661 SOF],[Frames: 678.3 - 1260.7]
    0,HS,2709,0:51.926.317,29.316 us,4 B,,57,00,Get String Descriptor,Index=0 Length=255
    0,HS,2723,0:51.926.387,66 ns,,,,,[1 SOF],[Frame: 1261.0]
    0,HS,2724,0:51.926.404,28.250 us,36 B,,57,00,Get String Descriptor,Index=1 Length=255
    0,HS,2738,0:51.926.512,66 ns,,,,,[1 SOF],[Frame: 1261.1]
    0,HS,2739,0:51.926.524,29.933 us,40 B,,57,00,Get String Descriptor,Index=2 Length=255
    0,HS,2753,0:51.926.592,28.483 us,48 B,,57,00,Get String Descriptor,Index=5 Length=255
    0,HS,2767,0:51.926.637,66 ns,,,,,[1 SOF],[Frame: 1261.2]
    0,HS,2768,0:51.926.705,28.416 us,40 B,,57,00,Get String Descriptor,Index=4 Length=255
    0,HS,2782,0:51.926.762,1.250.266 ms,,,,,[11 SOF],[Frames: 1261.3 - 1262.5]
    0,HS,2783,0:51.927.985,33.433 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,2797,0:51.928.086,27.416 us,9 B,,57,00,Get Configuration Descriptor,Index=0 Length=9
    0,HS,2811,0:51.928.137,83 ns,,,,,[1 SOF],[Frame: 1262.6]
    0,HS,2812,0:51.928.174,27.783 us,32 B,,57,00,Get Configuration Descriptor,Index=0 Length=32
    0,HS,2826,0:51.928.262,83 ns,,,,,[1 SOF],[Frame: 1262.7]
    0,HS,2827,0:51.928.243,29.383 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,2841,0:51.928.387,66 ns,,,,,[1 SOF],[Frame: 1263.0]
    0,HS,2842,0:51.928.356,35.433 us,9 B,,57,00,Get Configuration Descriptor,Index=0 Length=9
    0,HS,2856,0:51.928.512,100.514.983 ms,,,,,[805 SOF],[Frames: 1263.1 - 1363.5]
    0,HS,2857,0:52.029.060,29.733 us,32 B,,57,00,Get Configuration Descriptor,Index=0 Length=32
    0,HS,2871,0:52.029.152,186.402.716 ms,,,,,[1492 SOF],[Frames: 1363.6 - 1550.1]
    0,HS,2872,0:52.215.555,3.000.666 ms,,,,,<Reset> / <Target disconnected>,
    0,HS,2873,0:52.218.556,103.166 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,2874,0:52.218.659,1.097.166 ms,,,,,<Chirp K>,
    0,HS,2875,0:52.219.756,25.250 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,2876,0:52.219.781,50.666.383 ms,,,,,[517 Chirp K-J pairs] ,
    0,HS,3912,0:52.270.448,240.483 us,,,,,<Reset>,
    0,HS,3913,0:52.270.688,,,,,,<High-speed>,
    0,HS,3914,0:52.270.688,32.379.866 ms,,,,,[260 SOF],[Frames: 1605.x - 1637.5]
    0,HS,3915,0:52.303.058,37.333 us,18 B,,00,00,Get Device Descriptor,Index=0 Length=64
    0,HS,3929,0:52.303.193,66 ns,,,,,[1 SOF],[Frame: 1637.6]
    0,HS,3930,0:52.303.193,3.000.583 ms,,,,,<Reset> / <Target disconnected>,
    0,HS,3931,0:52.306.194,102.850 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,3932,0:52.306.296,1.097.500 ms,,,,,<Chirp K>,
    0,HS,3933,0:52.307.394,25.383 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,3934,0:52.307.419,50.571.066 ms,,,,,[516 Chirp K-J pairs] ,
    0,HS,4968,0:52.357.990,335.716 us,,,,,<Reset>,
    0,HS,4969,0:52.358.326,,,,,,<High-speed>,
    0,HS,4970,0:52.358.326,32.379.883 ms,,,,,[260 SOF],[Frames: 1692.x - 1725.2]
    0,HS,4971,0:52.390.706,23.016 us,0 B,,00,00,Set Address,Address=57
    0,HS,4981,0:52.390.831,10.251.583 ms,,,,,[83 SOF],[Frames: 1725.3 - 1735.5]
    0,HS,4982,0:52.401.162,28.050 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,4996,0:52.401.207,303.795.133 ms,,,,,[2431 SOF],[Frames: 1735.6 - 2039.4]
    0,HS,4997,0:52.705.003,3.000.633 ms,,,,,<Reset> / <Target disconnected>,
    0,HS,4998,0:52.708.003,103.316 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,4999,0:52.708.107,1.097.033 ms,,,,,<Chirp K>,
    0,HS,5000,0:52.709.204,25.916 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,5001,0:52.709.229,50.557.533 ms,,,,,[516 Chirp K-J pairs] ,
    0,HS,6035,0:52.759.787,348.666 us,,,,,<Reset>,
    0,HS,6036,0:52.760.136,,,,,,<High-speed>,
    0,HS,6037,0:52.760.136,32.629.916 ms,,,,,[262 SOF],[Frames: 46.x - 79.2]
    0,HS,6038,0:52.792.790,27.766 us,18 B,,00,00,Get Device Descriptor,Index=0 Length=64
    0,HS,6052,0:52.792.818,3.000.550 ms,,,,,<Reset> / <Target disconnected>,
    0,HS,6053,0:52.795.819,103.116 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,6054,0:52.795.922,1.097.233 ms,,,,,<Chirp K>,
    0,HS,6055,0:52.797.019,26.150 us,,,,,<Reset> / <Chirp J> / <Tiny J>,
    0,HS,6056,0:52.797.045,50.571.050 ms,,,,,[516 Chirp K-J pairs] ,
    0,HS,7090,0:52.847.616,282.516 us,,,,,<Reset>,
    0,HS,7091,0:52.847.899,,,,,,<High-speed>,
    0,HS,7092,0:52.847.899,32.379.866 ms,,,,,[260 SOF],[Frames: 134.x - 166.6]
    0,HS,7093,0:52.880.326,22.850 us,0 B,,00,00,Set Address,Address=57
    0,HS,7103,0:52.880.403,10.126.583 ms,,,,,[82 SOF],[Frames: 166.7 - 177.0]
    0,HS,7104,0:52.890.557,28.300 us,18 B,,57,00,Get Device Descriptor,Index=0 Length=18
    0,HS,7118,0:52.890.655,469.069.650 ms,,,,,[3753 SOF],[Frames: 177.1 - 646.1]
    0,HS,7119,0:53.359.794,28.366 us,4 B,,57,00,Get String Descriptor,Index=0 Length=255
    0,HS,7133,0:53.359.850,5.750.933 ms,,,,,[47 SOF],[Frames: 646.2 - 652.0]
    0,HS,7134,0:53.365.686,27.983 us,40 B,,57,00,Get String Descriptor,Index=2 Length=255
    0,HS,7148,0:53.365.725,6.876.083 ms,,,,,[56 SOF],[Frames: 652.1 - 659.0]
    0,HS,7149,0:53.372.638,30.083 us,36 B,,57,00,Get String Descriptor,Index=1 Length=255
    0,HS,7163,0:53.372.727,5.875.950 ms,,,,,[48 SOF],[Frames: 659.1 - 665.0]
    0,HS,7164,0:53.378.655,28.583 us,18 B,,57,00,Get String Descriptor,Index=3 Length=255
    0,HS,7178,0:53.378.727,8.126.283 ms,,,,,[66 SOF],[Frames: 665.1 - 673.2]
    0,HS,7179,0:53.386.890,24.666 us,0 B,,57,00,Set Configuration,Configuration=1
    0,HS,7189,0:53.386.979,3.625.616 ms,,,,,[30 SOF],[Frames: 673.3 - 677.0]
    0,HS,7190,0:53.390.674,28.716 us,48 B,,57,00,Get String Descriptor,Index=5 Length=255
    0,HS,7204,0:53.390.729,6.626.066 ms,,,,,[54 SOF],[Frames: 677.1 - 683.6]
    0,HS,7205,0:53.397.437,36.900 us,40 B,,57,00,Get String Descriptor,Index=4 Length=255
    0,HS,7219,0:53.397.480,1.999.921.683 s,,,,,[15998 SOF],[Frames: 683.7 - 635.4] [Periodic Timeout]
    0,HS,7220,0:55.397.527,1.999.921.683 s,,,,,[15998 SOF],[Frames: 635.5 - 587.2] [Periodic Timeout]
    0,HS,7221,0:57.397.573,1.999.921.683 s,,,,,[15998 SOF],[Frames: 587.3 - 539.0] [Periodic Timeout]
    0,HS,7222,0:59.397.620,1.999.921.683 s,,,,,[15998 SOF],[Frames: 539.1 - 490.6] [Periodic Timeout]
    0,HS,7223,1:01.397.667,1.999.921.683 s,,,,,[15998 SOF],[Frames: 490.7 - 442.4] [Periodic Timeout]
    0,HS,7224,1:03.397.713,956.892.000 ms,,,,,[7655 SOF],[Frames: 442.5 - 1399.3]
    0,HS,7225,1:04.354.632,9.300 us,512 B,,57,02,OUT txn (NYET),61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78…
    0,HS,7229,1:04.354.730,10.626.650 ms,,,,,[86 SOF],[Frames: 1399.4 - 1410.1]
    0,HS,7230,1:04.365.451,9.433 us,512 B,,57,01,IN txn,41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58…
    0,HS,7234,1:04.365.482,2.875.500 ms,,,,,[24 SOF],[Frames: 1410.2 - 1413.1]
    0,HS,7235,1:04.368.443,11.650 us,512 B,,57,02,OUT txn (NYET),53 54 55 56 57 58 59 5A 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70…
    0,HS,7242,1:04.368.482,1.999.921.683 s,,,,,[15998 SOF],[Frames: 1413.2 - 1364.7] [Periodic Timeout]
    0,HS,7243,1:04.372.080,1.001.367.983 s,,,57,01,[40086 IN-NAK],[Periodic Timeout]
    0,HS,7244,1:06.368.529,1.999.921.700 s,,,,,[15998 SOF],[Frames: 1365.0 - 1316.5] [Periodic Timeout]
    0,HS,7245,1:08.368.576,1.999.921.716 s,,,,,[15998 SOF],[Frames: 1316.6 - 1268.3] [Periodic Timeout]
    0,HS,7246,1:10.368.622,1.999.921.716 s,,,,,[15998 SOF],[Frames: 1268.4 - 1220.1] [Periodic Timeout]
    0,HS,7247,1:12.368.669,1.999.921.716 s,,,,,[15998 SOF],[Frames: 1220.2 - 1171.7] [Periodic Timeout]
    0,HS,7248,1:14.368.716,1.999.921.700 s,,,,,[15998 SOF],[Frames: 1172.0 - 1123.5] [Periodic Timeout]
    0,HS,7249,1:16.368.762,1.999.921.716 s,,,,,[15998 SOF],[Frames: 1123.6 - 1075.3] [Periodic Timeout]
    0,HS,7250,1:18.368.809,1.999.921.700 s,,,,,[15998 SOF],[Frames: 1075.4 - 1027.1] [Periodic Timeout]
    0,HS,7251,1:20.368.855,1.999.921.700 s,,,,,[15998 SOF],[Frames: 1027.2 - 978.7] [Periodic Timeout]
    0,HS,7252,1:22.368.902,1.999.921.700 s,,,,,[15998 SOF],[Frames: 979.0 - 930.5] [Periodic Timeout]
    0,HS,7253,1:24.368.949,1.999.921.700 s,,,,,[15998 SOF],[Frames: 930.6 - 882.3] [Periodic Timeout]
    0,HS,7254,1:26.368.995,1.999.921.700 s,,,,,[15998 SOF],[Frames: 882.4 - 834.1] [Periodic Timeout]
    0,HS,7255,1:28.369.042,1.296.317.350 s,,,,,[10370 SOF],[Frames: 834.2 - 82.3]
    0,,7256,1:29.665.359,,,,,,Capture stopped,[11/28/18 15:16:43]

  • More information: If I add
    usb_osalDelayMs(9000);
    in dev_bulk_main.c line 234, that gives me enough time to connect the device to the VM before the while loop starts.

    Under those conditions, the usb_dev_bulk_host_application.py runs to completion and prints "Test passes!"

  • Hi Adam

    Thank you for contacting us and showing us the patch.

    We will need to investigate as of why we see such kind of race condition. If there is a race condition somewhere, moving the line code that setups the eBulkTxState or eBulkRxState to before the function usbSetupEpReq() would make difference since the function usbSetupEpReq() is a non-blocking function.  I'm not certain how it helps with your tests.

    As for the second problem that you mentioned that you were writing 14 OUT packets without any reads, could you please clarify if the read is from the OMAP or from the host PC? If the host PC doesn't do USB read, the USB_write from the OMAP will get stalled (USB device cannot send unsolicited data to USB host without USB host asking for it) and then result in the stalled USB write from host PC. The bulk example anticipates the both USB device and host working together.

    We need to start the bulk transfer only after the controlled transfer on EP 0 has completed.  The USB bulk example relies on the "Set Configuration" command to figure out when the EP0 has done its setup.   It sets up a 500ms delay after the Set Configuration arrives to deal with this.   In your logic analyzer capture with Linux running under VM, there are 2 "Set Configuration" commands.  This could be the reason why you see it works after you increase the delay to 9 second. Do you see "Host disconnect" event showing up in the UART console of the OMAP when you mount the USB bulk device to the VM machine?

    As for the NYET, we also see that with OMAP and AM3. We will address it in the future release.

  • Bottom line, your usb bulk driver, as written, is too fragile.  Activity should be able to occur on any endpoint regardless of what is happening on the other endpoints.

    This should be easy to do with just a little buffering.

    Host sends a read request and you have no data for them?  Tell them you have no data.

    Host sends a read request and there is data in the buffer?  Give it to them.

    Host sends a write request? accept it, buffer the data, and hold it until a Task asks for it.

    Task wants to read and there's no data?  Tell the task there's no data.

    Task wants to read and there is data? Give the Task the data.

    Task wants to write?  Take the data, put it in a buffer, and keep it until the HOST sends an IN.

    OUT is, by definition a transfer FROM the HOST (i.e. a write).  See sdphca.ucsd.edu/Lab_Equip_Manuals/usb_20.pdf page 33, "Endpoint Direction"

    Your arbitrary 500ms delay is insufficient for all use cases, and would not be necessary at all if you treated the endpoints independently.  It is completely possible you may receive any number of CONTROL packets before receiving an IN or an OUT.  The test case I gave you is a perfect example of this.

  • Hi Adam

    What you've suggested about what to do with host send read / write requests or if task want to read / write data are really application level functions, IMHO.  You're free to implement your application that way.  The driver is just providing the read/write functions on top of the hardware.  The bulk example that comes with the USB driver is just a simple example and definitely won't fit all use cases. 

    Take a look at USB Mass Storage Class implementation for example:

    Set configuration comes and done

    Host sends a class request for get LUN on EP0. The device application then starts preparing for the MSC application.

    The device then starts preparing for the bulk transfer anticipating the first bulk OUT from the host.

    Host then sends a SCSI command to tell the device what to do (to read or to write from or to storage or reading capacity, etc.)

    The device then does what host wants it to do

    Then device then waits for another SCSI command (Bulk out) from host.

    As for the delay, the bulk endpoint transfer can only happen after the bulk endpoints have been configured.  This configuration is done  when the "Set Configuration" command comes from the host.  Ideally the host application should send out a class request for the bulk application (similar to the get LUN with the MSC implementation) so that the bulk application knows when it's ready to do bulk read.  The bulk example application doesn't have this command as a mark so it relies on the delay.  We will look at how to get rid of this delay in future release.

    The delay doesn't work with the VM like in your setup where it should have. I see multiple reset / disconnects coming to the OMAP in your logic analyzer capture. The demo application should have changed its state and restarted the timer accordingly.  Do you see the log on the UART console of the OMAP reporting multiple disconnect/connect as well?

    Regards

  • "What you've suggested about what to do with host send read / write requests or if task want to read / write data are really application level functions, IMHO. You're free to implement your application that way. The driver is just providing the read/write functions on top of the hardware. The bulk example that comes with the USB driver is just a simple example and definitely won't fit all use cases. "

    A'ight, it's clear I'm not making any headway here.

    I don't know a lot about this USB peripheral, documentation is scarce or incomplete, I don't know a ton about USB, and I'm not super familiar with the PDK.

    I'd like some sort of generic driver where I can provide callbacks to be called when the USB hardware interrupt happens.

    Are there any other drivers in the PDK that behave like this? Can you point me in a direction so I can make some progress?
  • Hi Adam

    I'm not sure which other drivers in PDK that have generic call back when hardware interrupt happens. Most of them would try to hide the hardware interrupt or complexity away from user application.

    I can tell you more about the USB drivers / and its interrupts though, but you probably have seen them in the USB example codes already. In the USB dev bulk example (example/bios/dev_bulk_main.c) there is function usbdbulkEventCallback(). This callback function is called when the driver receives USB event like device connect, disconnect, or sending or receiving completion. It's registered to the driver by the table inside usb_bulk_structs.c. Would this work for you? If you need some other events that are not already mentioned in this callback function please let us know and we will look at how to add them.

    The USB interrupt handler is usbCoreIntrHandler(). This handler is called with every USB hardware interrupt. Some of these interrupts result in the calls to the callback function mentioned above. So you are probably not really interested in looking at this interrupt.

    Regards
    Thanh
  • ok, so say I'm in usbdbulkEventCallaback, and ulEvent is USB_EVENT_RX_AVAILABLE.
    How do I get that data?

    If is ulEvent is USB_EVENT_TX_COMPLETE, how do I send more data (without blocking)?
  • Hi Adam

    The incoming buffer that is associated with the call back are the g_bulkRxBuffer in file example/usb_dev/bulk/usb_bulk_structs.c

    const tUSBDBulkDevice g_sBulkDevice =
    {
        USB_VID_STELLARIS,
        USB_PID_BULK,
        500,
        USB_CONF_ATTR_SELF_PWR,
        usbdbulkEventCallback,        /* pfnRxCallback */
        (void *)g_bulkRxBuffer,       /* pvRxCBData */    
        usbdbulkEventCallback,        /* pfnTxCallback */
        (void *)g_bulkTxBuffer,       /* pvTxCBData */
        g_pStringDescriptors,         /* ppStringDescriptors */
        NUM_STRING_DESCRIPTORS,       /* ulNumStringDescriptors */
        &g_sBulkInstance              /* psPrivateBulkData */
    };

    You can replace the buffer in this structure with any buffer of your choice. Keep in mind that data will be written to it by DMA engine, so the buffer needs to be cache size aligned.

    To send data from USB device (BULK IN) without blocking, you need to create a new function. It's basically a copy of the function

    int32_t USBD_bulkWrite(USB_Handle handle, uint8_t* buffer, uint32_t dataSize)

    But you would need to remove the function

    usb_osalPendLock(psInst->writeSem, SemaphoreP_WAIT_FOREVER);

    Then you will have to wait for the call back to tell you that it's finished sending.

    Please let us know if this works for you or not.

    Best regards

    Thanh

  • Thanks Thanh.  I'd reached most of the same conclusions about the same time you sent this message.

    This resolves my issue, although i do still think your example code should be more robust.

  • Thanh,

    This is working great for normal cases. However, if something goes wrong on the workstation (ctrl-C of my application), my device can be left in an odd state. I tried to handle this with expanding usbdbulkEventCallback:

    case USB_EVENT_ERROR:
    {
    // TODO FIX take specific action based on endpoint
    // for now, just reset everything
    ok_to_read = true;
    ok_to_write = true;
    last_read_size = 0;
    break;
    }

    and this helps in some, but not all cases.

    I'd like to catch the events where the device is sending NAK to an OUT request from the host. And also, I expect I might want to do the same for NAK on IN. How would I do this? I tried hooking the default case in usbdbulkEventCallback, but that never got hit, so I'm thinking some lower level may be handling that. How would I catch these events?
  • Hi Adam

    It's great to hear that you made some great progress.

    As for the NAK question, I'm still waiting for response from an expert on the hardware. 

    My understanding of the USB hardware in OMAP138 is that it does not give the software any visibility of whenever it sends a NAK to an OUT request.

    For IN request, the USB block would retry on its own without letting the CPU involved when it sees a NAK.

    If I receive any information that says it is possible to do so, I'll update you here.

    Regards

    Thanh

  • I've tried changing usbdbulk.c HandleEndpoints() to also include USB_GENERIC_EVENT_DATA_OUT_NAK (as well as OUT_PARTIAL, IN_NAK, and IN_PARTIAL) but breakpoints set for OUT_NAK never get hit, even though I clearly see OUT NAK in the protocol analyzer output.
    =(
  • Hi Adam

    I got confirmation from multiple sources that the hardware will not generate any interrupt on NAK response (if it does, host CPU could be overwhelm with unnecessary interruptions from the USB block and could slow everything down). That explains why you didn't see any interrupt for NAK.

    We probably need to look closely at how we get to the condition that the USB device keeps sending NAK to USB host so we can avoid that.

    Regards
  • *ugh* I've also just tried this in my task, which I was *CERTAIN* would work... but it doesn't, it just causes everything to be NAK'd

    if (((usbMusbDcdDevice_t *)usb_handle->usbParams->drvData)->outEpReq.status <= 0) {
    ok_to_read = true;
    }
    if (((usbMusbDcdDevice_t *)usb_handle->usbParams->drvData)->inEpReq.status <= 0) {
    ok_to_write = true;
    }

    if (ok_to_read) {
    ok_to_read = false;
    if (last_read_size) {
    usbqPush(&incoming_queue, read_buffer, last_read_size);
    last_read_size = 0;
    }
    USBD_bulkRead(usb_handle, read_buffer, &rxBytes, false);
    }

    if (ok_to_write) {
    if (!usbqEmpty(&outgoing_queue)) {
    ok_to_write = false;
    txBytes = usbqPull(&outgoing_queue, g_bulkTxBuffer, SLOT_SIZE);
    if (txBytes) {
    USBD_bulkWrite(usb_handle, g_bulkTxBuffer, txBytes, false);
    }
    else {
    ok_to_write = true;
    }
    }
    }
  • I'm seeing PING-NAK right before my OUT-NAK. What conditions can cause a PING-NAK ? What conditions can cause an OUT-NAK?
    both
    ((usbMusbDcdDevice_t *)usb_handle->usbParams->drvData)->inEpReq.status
    and
    ((usbMusbDcdDevice_t *)usb_handle->usbParams->drvData)->outEpReq.status
    are == 1, indicating a request is pending on both endpoints.

    Why is the ARM doing NAK for PING and OUT ???
  • Still trying to figure out why I'm seeing PING-NAK and OUT-NAK
    Do these register values tell us anything?

    DEVCTL 0x99 OTG Device Control [Memory Mapped]
    TXFIFOSZ 0x00 TRANSMIT ENDPOINT FIFO SIZE (INDEXED) [Memory Mapped]
    RXFIFOSZ 0x00 RECEIVE ENDPOINT FIFO SIZE (INDEXED) [Memory Mapped]
    TXFIFOADDR 0x0000 TRANSMIT ENDPOINT FIFO ADDRESS - IN UNITS OF 8 BYTES (INDEXED) [Memory Mapped]
    RXFIFOADDR 0x0000 RECEIVE ENDPOINT FIFO ADDRESS - IN UNITS OF 8 BYTES (INDEXED) [Memory Mapped]
    HWVERS 0x0720 VERSION OF USB CONTROLLER CORE [Memory Mapped]
    HOST_PERI_CSR0 0x0000 Control Status Register for Endpoint 0 (Host or Peripheral modes) [Memory Mapped]
    COUNT0 0x0000 Number of Received Bytes in Endpoint 0 FIFO [Memory Mapped]
    HOST_TYPE0 0x00 Defines the Speed of Endpoint 0 [Memory Mapped]
    HOST_NAKLIMIT0 0x00 Sets the NAK Response Timeout on Endpoint 0 [Memory Mapped]
    CONFIGDATA 0x06 Returns details of core configuration for Endpoint 0 [Memory Mapped]
    DMA_SCHED_CTRL 0x80000003 Receive DMA Host Packet Configuration Register B Endpoint 4 [Memory Mapped]
    QMGRREVID 0x00521200 Queue Manager Revision Register [Memory Mapped]
    DIVERSION 0x00000000 Queue Manager Diversion Register [Memory Mapped]
    FDBSC0 0x00003700 Queue Manager Free Descriptor/Buffer Starvation Count Register 0 [Memory Mapped]
    FDBSC1 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 1 [Memory Mapped]
    FDBSC2 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 2 [Memory Mapped]
    FDBSC3 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 3 [Memory Mapped]
    LRAM0BASE 0xC0065A40 Linking RAM Region 0 Base Address [Memory Mapped]
    LRAM0SIZE 0x00001000 Linking RAM Region 0 Size [Memory Mapped]
    LRAM1BASE 0x00000000 Linking RAM 1 Base Address [Memory Mapped]
    PEND0 0x00000002 Queue Manager Queue Pending Register 0 [Memory Mapped]
    PEND1 0x00000000 Queue Manager Queue Pending Register 1 [Memory Mapped]
    PEND2 0x00000000 Queue Manager Queue Pending Register 2 [Memory Mapped]
  • oops, here's all of them:
    REVID 0x4EA11003 Revision Register [Memory Mapped]
    CTRLR 0x00000002 Control Register [Memory Mapped]
    STATR 0x00000000 Status Register [Memory Mapped]
    EMUR 0x00000003 Emulation Register [Memory Mapped]
    MODE 0x00000000 RNDIS MODE REGISTER [Memory Mapped]
    AUTOREQ 0x00000000 Auto Request Register [Memory Mapped]
    SRPFIXTIME 0x0280DE80 SRP Fix Time Register [Memory Mapped]
    TEARDOWN 0x00000000 Teardown Register [Memory Mapped]
    INTSRCR 0x00080000 USB Interrupt Source Register [Memory Mapped]
    INTSETR 0x00080000 USB Interrupt Source Set Register [Memory Mapped]
    INTCLRR 0x00080000 USB Interrupt Source Clear Register [Memory Mapped]
    INTMSKR 0x01FF1E1F USB Interrupt Mask Register [Memory Mapped]
    INTMSKSETR 0x01FF1E1F USB Interruppt Mask Set Register [Memory Mapped]
    INTMSKCLRR 0x01FF1E1F USB Interruppt Mask Clear Register [Memory Mapped]
    INTMASKEDR 0x00080000 USB Interrupt Source Masked Register [Memory Mapped]
    EOIR 0x00000000 USB End Of Interrupt [Memory Mapped]
    INTVECTR 0x00000000 USB Interrupt Vector [Memory Mapped]
    FADDR 0x18 Function Address [Memory Mapped]
    POWER 0x70 Power Management Register [Memory Mapped]
    INTRTX 0x0000 Transmit Endpoint Interrupt Register [Memory Mapped]
    INTRRX 0x0000 Transmit Endpoint Interrupt Register [Memory Mapped]
    INTRTXE 0x001F Transmit Endpoint Interrupt Enable Register [Memory Mapped]
    INTRRXE 0x001E Transmit Endpoint Interrupt Enable Register [Memory Mapped]
    INTRUSB 0x00 USB Bus Interrupts [Memory Mapped]
    INTRUSBE 0x2F USB Interrupt Enable Register [Memory Mapped]
    FRAME 0x027A Frame Number of Last Received Frame [Memory Mapped]
    INDEX 0x00 Selects Endpoint accessed through index register [Memory Mapped]
    TESTMODE 0x00 Test Mode Register [Memory Mapped]
    TXMAXP 0x0000 Max Packet Size for Transmit Packet [Memory Mapped]
    PERI_CSR0 0x0000 TRANSMIT / ENDPOINT 0 CONTROL AND STATUS IN PERIPHERAL MODE [Memory Mapped]
    HOST_CSR0 0x0000 TRANSMIT / ENDPOINT 0 CONTROL AND STATUS IN HOST MODE [Memory Mapped]
    HOST_TXCSR 0x0000 CSR REGISTER FOR TRANSMIT ENDPOINT (INDEXED) - HOST MODE [Memory Mapped]
    PERI_TXCSR 0x0000 CSR REGISTER FOR TRANSMIT ENDPOINT (INDEXED) - PERIPHERAL MODE [Memory Mapped]
    RXMAXP 0x0000 RX ENDPOINT MAX PACKET SIZE [Memory Mapped]
    PERI_RXCSR 0x0000 Receive Control/Status Register Peripheral Mode [Memory Mapped]
    HOST_RXCSR 0x0000 Receive Control/Status Register Host Mode [Memory Mapped]
    COUNT0 0x0000 Count0 is a 7 bit read only register that indicates the number of received data bytes in the Endpoint 0 FIFO. The value returned changes as the contents of the FIFO change and is only valid while RXPKTRDY is set. [Memory Mapped]
    RXCOUNT 0x0000 RX Count is a 13-bit read only register that holds the number of received dtata bytes in the packet currently in line to be read from the RX FIFO. If the packet was transmitted as multiple bulk packets, the number given will be for the combined packet. [Memory Mapped]
    HOST_TYPE0 0x00 TYPE0 FOR ENDPOINT 0 [Memory Mapped]
    HOST_TXTYPE 0x00 TXTYPE FOR ENDPOINT1,2,3,4 [Memory Mapped]
    HOST_NAKLIMIT0 0x00 NAKLIMIT0 FOR ENDPOINT 0 [Memory Mapped]
    HOST_TXINTERVAL 0x00 TXINTERVAL FOR ENDPOINT1,2,3,4 [Memory Mapped]
    HOST_RXTYPE 0x00 RXTYPE FOR ENDPOINT1,2,3,4 [Memory Mapped]
    HOST_RXINTERVAL 0x00 RXINTERVAL FOR ENDPOINT1,2,3,4 [Memory Mapped]
    CONFIGDATA 0x06 Returns details of core configuration for Endpoint 0 [Memory Mapped]
    FIFO0 0x00010900 FIFO0 [Memory Mapped]
    FIFO1 0x0004095E FIFO1 [Memory Mapped]
    FIFO2 0xC3004000 FIFO2 [Memory Mapped]
    FIFO3 0x0004095E FIFO3 [Memory Mapped]
    FIFO4 0x0004095E FIFO4 [Memory Mapped]
    DEVCTL 0x99 OTG Device Control [Memory Mapped]
    TXFIFOSZ 0x00 TRANSMIT ENDPOINT FIFO SIZE (INDEXED) [Memory Mapped]
    RXFIFOSZ 0x00 RECEIVE ENDPOINT FIFO SIZE (INDEXED) [Memory Mapped]
    TXFIFOADDR 0x0000 TRANSMIT ENDPOINT FIFO ADDRESS - IN UNITS OF 8 BYTES (INDEXED) [Memory Mapped]
    RXFIFOADDR 0x0000 RECEIVE ENDPOINT FIFO ADDRESS - IN UNITS OF 8 BYTES (INDEXED) [Memory Mapped]
    HWVERS 0x0720 VERSION OF USB CONTROLLER CORE [Memory Mapped]
    HOST_PERI_CSR0 0x0000 Control Status Register for Endpoint 0 (Host or Peripheral modes) [Memory Mapped]
    COUNT0 0x0000 Number of Received Bytes in Endpoint 0 FIFO [Memory Mapped]
    HOST_TYPE0 0x00 Defines the Speed of Endpoint 0 [Memory Mapped]
    HOST_NAKLIMIT0 0x00 Sets the NAK Response Timeout on Endpoint 0 [Memory Mapped]
    CONFIGDATA 0x06 Returns details of core configuration for Endpoint 0 [Memory Mapped]
    DMA_SCHED_CTRL 0x80000003 Receive DMA Host Packet Configuration Register B Endpoint 4 [Memory Mapped]
    QMGRREVID 0x00521200 Queue Manager Revision Register [Memory Mapped]
    DIVERSION 0x00000000 Queue Manager Diversion Register [Memory Mapped]
    FDBSC0 0x0000FF00 Queue Manager Free Descriptor/Buffer Starvation Count Register 0 [Memory Mapped]
    FDBSC1 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 1 [Memory Mapped]
    FDBSC2 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 2 [Memory Mapped]
    FDBSC3 0x00000000 Queue Manager Free Descriptor/Buffer Starvation Count Register 3 [Memory Mapped]
    LRAM0BASE 0xC0065A40 Linking RAM Region 0 Base Address [Memory Mapped]
    LRAM0SIZE 0x00001000 Linking RAM Region 0 Size [Memory Mapped]
    LRAM1BASE 0x00000000 Linking RAM 1 Base Address [Memory Mapped]
    PEND0 0x00000002 Queue Manager Queue Pending Register 0 [Memory Mapped]
    PEND1 0x00000000 Queue Manager Queue Pending Register 1 [Memory Mapped]
    PEND2 0x00000000 Queue Manager Queue Pending Register 2 [Memory Mapped]
  • Hi Adam

    The USB core sends out NAK for OUT or PING when it cannot accept any more data. This could be because the USB's FIFO is full. Either the ARM or DMA has not read and emptied the USB's FIFO in this case.   Could you read the endpoint status by calling the function USBEndpointStatus or by reading the register associated with OUT endpoint or IN endpoint and see what their value is.

  • USBEndpointStatus seems to always return 0

    uint32_t tmp;

    tmp = USBEndpointStatus(g_USBInstance[0].uiBaseAddr, USB_EP_0);
    if (tmp) epstatus[0] = tmp;
    tmp = USBEndpointStatus(g_USBInstance[0].uiBaseAddr, USB_EP_1);
    if (tmp) epstatus[1] = tmp;
    tmp = USBEndpointStatus(g_USBInstance[0].uiBaseAddr, USB_EP_2);
    if (tmp) epstatus[2] = tmp;

    my epstatus[] is always {0,0,0}
  • Which register, specifically, should I be looking at? (remember, I'm no expert on this.)
  • do you mean USB0ARM.EPCSR ???

    [0].TXMAP=0x200
    [0].HOST_PERI_TXCSR=0x1403
    [0].RXCOUNT=0x1FFC
    (all others in [0] == 0)

    [1].RXMAXP=0x0200
    [1].HOST_PERI_RXCSR=0x2003
    [1].RXCOUNT=0x180
    (all others in [1] == 0)

    [2] and [3] are all == 0
  • Hi Adam

    That would be
    USB_O_TXCSRL1 / USB_O_RXCSRL1 for EP1,
    USB_O_TXCSRL2 / USB_O_RXCSRL2 for EP2

    from the base address of the USB0 which is at 0x01E00000.

    When you called the function USBEndpointStatus(g_USBInstance[0].uiBaseAddr, USB_EP_2), where and when do you call it? after the code / system already get into bad state?

    If the above function called in proper place, it would go to same place to read the USB_O_RXCSRL2 for EP2 and USB_O_TXCSRL1 for EP1.

    In my test, if I call this function inside USBMusbDcdEpReq() where it's about to do the DMA request (doDmaRxTransfer) I see the value is not zero.

    Regards
  • I'm calling USBEndpointStatus continuously in my Task while(1) loop, and storing any nonzero values; it is *always* 0, good state and bad.

    Looking in the Registers tab in CCSv7, I don't see any registers named USB_O_RXCSRL2. However,
    ./packages/ti/drv/usb/soc/omapl138/hw_usb.h:#define USB_O_RXCSRL2 0x00000126 /* USB Receive Control and Status
    ./packages/ti/drv/usb/soc/omapl137/hw_usb.h:#define USB0_BASE SOC_USB0_BASE
    ./packages/ti/drv/usb/soc/omapl137/hw_soc.h:#define SOC_USB0_BASE USB_0_OTGBASE + 0x400
    ./packages/ti/drv/usb/soc/omapl138/hw_soc.h:#define USB_0_OTGBASE CSL_USB_0_REGS
    packages/ti/csl/soc/omapl138/src/cslr_soc_baseaddress.h:#define CSL_USB_0_REGS (0x01E00000u)

    So I think you're asking about 0x01E00000+0x400+0x126 == 0x01E00526, which is the same as the USB0ARM.EPCSR[1].HOST_PERI_RXCSR I gave you in my last comment. The value is 0x2003, which indeed indicates the FIFO is full.

    I have not yet figured out how to safely recover from this condition.

    How do we recover from this? It seems like there will be times under normal operation where the FIFO will be full. Where does this normally get cleared?
  • Hi Adam

    Under normal operation, the FIFO would get cleared when the ARM reads the FIFO (in FIFO mode) or when the DMA unloads the FIFO (DMA mode - which is what the PDK ships with).

    I think your setup might have gotten into some bad state in which the DMA doesn't unload the FIFO.

    When it gets stuck, does it recover if you unplug the USB cable then plug it back?

    I've not tried this before but you can also try to write 1 to bit 6 or try manually clearing bit 0 of USB_O_RXCSRL2 to see if it could clear the FIFO and your next transaction would go?

    I can't suggest much since I don't know the nature of the problem or how it gets to that situation.

    Regards
    Thanh