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.

Simple PC <> Launchpad USB link fails

I'm experimenting with a single direction, USB bulk transfer link between a TI Stellaris Launchpad and a (linux) PC. Below is the relevant code on the PC and on the Launchpad. The sender (Launchpad) sends 10 (ten) 64-byte packets to the PC.

The problem: There is only a data transfer during the first cycle. The following cycles, libusb (on the PC side) reports error -7 ("Other error")

On the PC side (using synchronous transfer, libusb-1.0):

      for (r = 0; r < 10; r++) {
        res = libusb_bulk_transfer(dev_handle, EP_IN, bff, 64, &recd, 1200);
        total += recd;
        if (res == 0)
          printf("Received: %d\n", recd);
        else
          printf("Receive error (%d: %s)\n", res, libusb_strerror(r));
      }

On the Launchpad:

    USBDBulkPacketWrite(pDevice, USBTxBuffer_A, 64, true);
    // USBBufferDataWritten(&g_sTxBuffer, ulCount);

I've tried both `USBDBulkPacketWrite` (where the data is written by the function call) and `USBBufferDataWritten` (where data is written directly into the TxBuffers, as in the `usb-dev-bulk` demo.

The receiver confirms reception of 64 bytes only once.

As far as I know, no 'ending' packets are needed, as the transfer length is exactly the size of the packet. Running the `libusb` receiver with debug level 5, does print an error, which I can't really identify the cause of. This is the debug output of the first of the ten tries:

    libusb: debug [libusb_alloc_transfer] transfer 0xc4c9f8
    libusb: debug [libusb_submit_transfer] transfer 0xc4c9f8
    libusb: debug [add_to_flying_list] arm timerfd for timeout in 1200ms (first in line)
    libusb: debug [submit_bulk_transfer] need 1 urbs for new transfer with length 62
    libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
    libusb: debug [handle_events] poll fds modified, reallocating
    libusb: debug [handle_events] poll() 3 fds with timeout in 60000ms
    libusb: debug [handle_events] poll() returned 1
    libusb: debug [handle_events] timerfd triggered
    libusb: debug [libusb_cancel_transfer] transfer 0xc4c9f8
    libusb: debug [disarm_timerfd]
    libusb: debug [handle_events] poll() 3 fds with timeout in 0ms
    libusb: debug [handle_events] poll() returned 1
    libusb: debug [reap_for_handle] urb type=3 status=-2 transferred=0
    libusb: debug [handle_bulk_completion] handling completion status -2 of bulk urb 1/1
    libusb: debug [handle_bulk_completion] abnormal reap: urb status -2
    libusb: debug [handle_bulk_completion] abnormal reap: last URB handled, reporting
    libusb: debug [usbi_handle_transfer_cancellation] detected timeout cancellation
    libusb: debug [disarm_timerfd]
    libusb: debug [usbi_handle_transfer_completion] transfer 0xc4c9f8 has callback 0x7f7ea23ac6d0
    libusb: debug [sync_transfer_cb] actual_length=0
    libusb: debug [libusb_free_transfer] transfer 0xc4c9f8

The only difference with the following output is the reallocation of the fds.

  • Hello John,

    I have forwarded the post to my colleague who can help you better.

    Thanks,
    Sai
  • Hello John,

    I have some questions:
    1. Do you have a USB trace on the bus? What I am trying to see what is the communication on the bus
    2. Did you check on the uC side if the next 64 byte packet is written and the USB controller is waiting for it to be transmitted?

    Regards
    Amit
  • I've determined that the controller dies in this library function (usbringbuf.c)
    because the value of ulSize is 0. Maybe there should be an ASSERT to verify
    this on entry?

    I followed this to USBRingBufRead, but I have to leave for the university now.
    Will investigate further this evening. I was quite sure I called all the right
    _inits though.

    //
    // Correct for wrap. We use a loop here since we don't want to use a
    // modulus operation with interrupts off but we don't want to fail in
    // case ulDelta is greater than ulSize (which is extremely unlikely but...)
    //
    while(*pulVal >= ulSize)
    {
    *pulVal -= ulSize;
    }
    
    

    These are the first few packets on the bus (taken from the usbmon system):

    ffff880094176b40 1023713490 S Bi:6:046:1 -115 64 <
    ffff880094176b40 1023713612 C Bi:6:046:1 0 64 = 00010203 04050607 08090a0b 0c0d0e0f 10111213 14151617 18191a1b 1c1d1e1f
    ffff880094176b40 1023713754 S Bi:6:046:1 -115 64 <
    ffff880094176b40 1024914144 C Bi:6:046:1 -2 0
    ffff88020c840e40 1024914158 S Co:6:002:0 s 23 08 92e1 0001 0000 0
    ffff88020d639300 1024914229 S Bi:6:046:1 -115 64 <
    ffff88020c840e40 1024914442 C Co:6:002:0 0 0
    ffff88020d639300 1026114542 C Bi:6:046:1 -2 0
    ffff88010684d180 1026114573 S Co:6:002:0 s 23 08 92e1 0001 0000 0
    ffff88020dbb5780 1026114669 S Bi:6:046:1 -115 64 <
    

  • Hello John,

    OK. Please keep us posted. In case that is the issue we can file a bug against the software to fix the issue.

    Regards
    Amit
  • It's a slow process. Usually, I quite like Code Composer, but sometimes it does get a little frustrating. For some reason, I could set a breakpoint at the function I mentioned above, but CCS refuses to set a breakpoint at USBRingBufRead, which is in the same source file, getting the message:

    No code is associated with "C:\Driverlib/build/Driverlib.test/usblib/usbringbuf.c" ...

    Note that:

    - The slashes are as typed above: C:\ and then continuing with the unix-like '/'
    - I am on Linux, so I've no idea where the C:\ keeps coming from. All path are defined correctly, else the code wouldn't compile.
    - When I wanted to trace the ulSize problem the first time, a dialog asked me to give the path to the usbringbuf.c file, and that worked. It seems the association then got lost.
    - The breakpoint gets set, but is disabled immediately with the above message.

    I can't find if I can edit this path somewhere. The project 'Properties' doesn't seem to show it.

  • Hello John,

    Import usblib as a project into CCS and compile it. Use the output of the usblib locally recompiled instead of the precompiled library. Then you should be able to set breakpoints.

    Regards
    Amit
  • Apologies for the inactivity.

    I've been able to follow the issue with lots of patience. I found out that the USB library actually uses an interrupt internally. On entering the interrupt service routine, it calls the routine I mentioned above. I have been trying to check the structure it uses in the interrupt routine, but the interesting parts (the addresses of the callback functions) are not accessible (debugger shows an error text about nos being to access non-primary values?).

    As far as I can see, I do initialize everything. Is there some other step necessary to initialize the USB lib?

    I wanted to play with yet another copy of the usb_dev_bulk project, to try and make it work with ping-pong buffers, but could not find any mention about ping-pong buffers (in the entire Stellaris or Tiva USB library docs). Is it not possible to do this with the USB library, and do I have to fall back to the standard peripheral library USB functions?

    The docs mention "No calls may be made to any other USB layer while the device class driver API is in use", so I have to rewrite BulkInit() etc. too?
  • Hello John,

    Are you referring to the double buffering the USB controller or the Ping Pong of the DMA?

    Regards
    Amit
  • Hi Amit.

    It seems that many of my problems were due to a hardware problem. In those cases the PC-side program reported the lauchpad to be unavailable (not enumerating). Though I thought there were problems in the software, in fact it was a port of the hub that stopped working. Today, I found a program which can selectively reset the hub's ports. Each time I hit a problem, a reset solved the problem. For anyone interested, this post describes a solution. It's a small C program which send a reset to the file corresponding to the hub's port (Linux only!).

    I searched again through the USB library doc, and think that DMA is not available for the Bulk Device driver. I only found a reference to DMA use when in the Host mode, and then only for Audio. (It's also mentioned in Mass Storage, but with a warning about silicon errata) Is that correct (no DMA for USB Device Bulk mode using the USB library)?

    John

  • Hello John,

    But isn't it interesting to know why the port on the hub stops working in the first place. Is this related to the PC in use or any other PC also has the same issue.

    The errata on TM4C123x for the UDMA is only when using multiple channel maps.

    Regards
    Amit
  • >But isn't it interesting to know why the port on the hub stops working in the first place. Is this related to the PC in use or any other PC also has the same issue.

    The problem is on the launchpad side, but probably due to errors in my code. The fact that the hub hangs makes debugging complicated. Before the reset program I was (un)plugging the launchpad (or later, the hub), but the frequent connections at times caused problems in the computer.

    > The errata on TM4C123x for the uDMA is only when using multiple channel maps.

    The errata was for Mass Storage, so that actually doesn't touch me. But I can't find documentation on how to enable uDMA on Bulk Transfers. From the Peripheral Library manual:

    "When configuring the endpoint, there are additional DMA settings required"

    How do I do that with the USB Library functions?

    Can I use the low-level functions to connect uDMA to the USB controller (which is programmed with the high level library)? In the USB Library manual, there's a statement that Low level access shouldn't be used simultaneously.

    BTW, I am using the launchpad to test a design for a low-cost data collection terminal for a research project, which possibly would be shared by several universities.

  • Hello John,

    There is a little or no documentation on the USB DMA usage. I have this code under development for USB DMA with bulk class device, that I should be able to share once I complete testing.

    You can use low level functions to connect the uDMA to the USB controller, but then it would throw the usblib out of sync.

    Regards
    Amit