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/TM4C1294NCPDT: USBHCDPipeWrite Bug

Part Number: TM4C1294NCPDT

Tool/software: TI-RTOS

There is a following piece of code in USBHCDPipeWrite(uint32_t ui32Pipe, uint8_t *pui8Data, uint32_t ui32Size) function in usbhostenum.c file (revision 2.1.1.71 of the Tiva USB Library):

 

            //

            // Only send 64 bytes at a time if not using DMA.

            //

            if(ui32ByteToSend > 64)

            {

                ui32ByteToSend = 64;

            }

            else

            {

                //

                // Send the requested number of bytes.

                //

                ui32ByteToSend = ui32RemainingBytes;

            }

 

            //

            // Start a write request.

            //

            g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriting;

 

            //

            // Disable uDMA on the USB endpoint

            //

            MAP_USBEndpointDMADisable(USB0_BASE, ui32Endpoint,

                                      USB_EP_HOST_OUT);

 

            //

            // Put the data in the buffer.

            //

            MAP_USBEndpointDataPut(USB0_BASE, ui32Endpoint, pui8Data,

                                   ui32ByteToSend);

 

The code runs in a loop. Let’s assume the function is called with ui32Size = 200. In the first pass, ui32ByteToSend is set to 64. In the second pass, because ui32ByteToSend is NOT greater than 64, it’s set to ui32RemainingBytes, that is 136 in our example. The write of more than 64 bytes fails but the function returns a ui32Size number of bytes scheduled for sending. This is a severe bug that prevents sending more than 128 bytes. From searching e2e.ti.com, I see that this bug was reported as early as October 2013 (https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/296947/1035641#1035641, https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/468291/1681349,

https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/491095/1799245).

 

There was an attempt to fix it as mentioned in the Release Notes:

TivaWare for C Series SW-TM4C-RLN-2.1.4.178 Release Notes Literature Number: SPMU299E May 2015–Revised February 2017

5 Release Notes for Version 2.1.0 (February 7, 2014)

5.9.1 USBHCDPipeWrite() Hangs With Certain Data Sizes If USBHCDPipeWrite() is called with a data size that is greater than 64 and not a multiple of 64 and the USB pipe is not using DMA then the call incorrectly attempted to send the full number of bytes requested. This also caused the call to USBHCDPipeWrite() to hang waiting for more bytes than can be sent. The call now correctly sends only the remaining bytes and returns correctly.

 

But change from:

                ui32ByteToSend = ui32Size;

to:

                ui32ByteToSend = ui32RemainingBytes;

 

that was done for TivaWare release 2.1.0.12573 did not do the job.

 

A simple fix might be to replace:

if(ui32ByteToSend > 64)

with:

if(ui32ByteToSend >= 64)

But test it please.

 

Thanks,

Ed

  • Hi Ed,
    Perhaps I'm reading the usbhostenum.c in the TivaWare 2.1.2.156, I'm not very clear on the statement you wrote "In the second pass, because ui32ByteToSend is NOT greater than 64, it’s set to ui32RemainingBytes, that is 136 in our example.". In the second pass, shouldn't the ByteToSend starts with 64 again?

    After the first 64 bytes are transferred the ui32RemainingBytes becomes 136 and since it is larger than 64 the ui32ByteToSend becomes 64 again.
  • Hi Charles,
     
    With a breakpoint set at the line:
     
    //
          // Put the data in the buffer.
          //
          MAP_USBEndpointDataPut(USB0_BASE, ui32Endpoint, pui8Data,
                                 ui32ByteToSend);
     
     
    It should be:
    Pass
    ui32RemainingBytes
    ui32ByteToSend
    1
    200
    64
    2
    136
    64
    3
    72
    64
    4
    8
    8
     
     
    It is:
    Pass
    ui32RemainingBytes
    ui32ByteToSend
    1
    200
    64
    2
    136
    136
     
    This is because the piece of code below is incorrect:
     
    //
          // Only send 64 bytes at a time if not using DMA.
          //
          if(ui32ByteToSend > 64)
          {
             ui32ByteToSend = 64;
          }
          else
          {
              //
              // Send the requested number of bytes.
              //
              ui32ByteToSend = ui32RemainingBytes;
          }
     
    Regards,
    Ed
     
  • Hi Ed,
    Sorry for the trouble. I see what you saying now. Looks like it is still an unresolved issue. I can't guarantee there will be another TivaWare release coming. In the meantime if your hack works, please continue with it. I will need to discuss internally on the matter.