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.

USB Bulk device: USBlib crashes when host stops requesting packets

Other Parts Discussed in Thread: EK-TM4C123GXL

System: Tiva C Launchpad

I have written a software that works as follows:

  • Timer triggers the ADC0SS0 sequencer, last step in Sequencer triggerst the ADC0SS0 ISR routing
    • in the ISR, the new samples are written to the USB tx_ringbuffer, a counter variable is updated
  • In the main application loop, it is checked whether the counter variable is greater than (or eq) 32 (meaning that there are 64 bytes to be transmitted),  if the system is in transmitting state and if there is enough tx buffer space (USBBufferSpaceAvailable >= 64) available
    The starting of the transmission is controlled by a state machine that switches into active state upon receiving a control command from the host
    • The USBRingBufDataWritten method is then called
    • The counter is then reduced by the number of written samples

I can achieve high sample rates and good USB throughput using this method. This works by my host (via libusbx) receiving packets of max size 1024.

However, very shortly after the last endpoint.read(1024) on the host, a Fault occurs -- in line 2862 of usblib/device/usbdenum.c:

    ui32DMAIntStatus = USBLibDMAIntStatus(g_psDCDInst[0].psDMAInstance);

see the backtrace:

#0  FaultISR () at usb_startup_gcc.c:327
#1  <signal handler called>
#2  0x00040000 in ?? ()
#3  0x00001cee in USBDeviceIntHandlerInternal (
    ui32Index=<optimized out>, ui32Status=0)
    at ./device/usbdenum.c:2862
#4  0xffffffe8 in ?? ()
#5  0xffffffe8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

I'm out of my wits.
USBLibDMAIntStatus is in fact only a define that calls g_psDCDInst[0].psDMAInstance->pfnIntStatus, which strangely has the suspicious address 0x40000.


But how this happens only after the host stopped requesting packets, I don't know. To me, this looks like a grave bug in USBlib, but I'm sure there are at least workarounds that you could help me find.

Greetings,
Marcus Müller

  • Hi Marcus,

    It looks like the instance data is getting corrupted.  Can you reference the project's map file to find the address for the application provided instance data?  With that, you should be able to inspect the memory after the fault and that might provide us some clues on how that is happening.

  • Hi,

    it's the same .ld file found in all the tivaware examples, identical for example to tivaware/examples/boards/ek-tm4c123gxl/interrupts/interrupts.ld :

    MEMORY
    {
        FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
        SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
    }
    
    SECTIONS
    {
        .text :
        {
            _text = .;
            KEEP(*(.isr_vector))
            *(.text*)
            *(.rodata*)
            _etext = .;
        } > FLASH
    
        .data : AT(ADDR(.text) + SIZEOF(.text))
        {
            _data = .;
            *(vtable)
            *(.data*)
            _edata = .;
        } > SRAM
    
        .bss :
        {
            _bss = .;
            *(.bss*)
            *(COMMON)
            _ebss = .;
        } > SRAM
    }

  • Hi Marcus,

    The map file I was referring to will be in build output folder. For instance, for CCS it will place it in <project name>/Debug/<project name>_ccs.map.  That will show us where the instance data variable your application is passing into the uslib API is located in memory and allow you to dump the memory from the debugger after the fault.

    You can open the file in a text editor and search for the variable name to find the address. It will be in the SRAM range (> 0x20000000).

  • I'm terribly sorry, but I'm using gcc, and don't know how to generate such a file; I will it research it as soon as I get home.

    Thank you very much,

    Marcus Müller

  • Hi Marcus,

    You can also use the 'arm-none-eabi-objdump -t' on the axf file to get similar information if that's easier for you to do.

  • Very well, finding out how to pass options using the standard tivaware Makefiles wasn't that difficult actually :)

    So, it is quite likely that you have a point there:

    ...
                    0x20000aac                g_pui8USBRxBuffer
                    0x20000cac                g_pui8USBTxBuffer
     COMMON         0x20000eac       0x4c /home/marcus/src/tivaware/usblib/gcc/libusb.a(usbdenum.o)
                    0x20000eac                g_psDCDInst
                    0x20000ef4                g_ppsDevInfo
    ...
    

    As it seems, the ill-fortuned DCDInst struct lies right behind my USB Tx Buffer.
    So, somehow, my application manages to write beyond the latter's boundaries. I will look into that, and do have a suspicion, but as I did not take my work home debugging can only happen next monday.

    Thank you very much for your advice!