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.

Problem to send data with USBHCDPipeWrite when its longer than 64 bytes

Other Parts Discussed in Thread: TM4C123GH6PM

Hi everyone,

I'm trying to manage a printer with a tm4c. I succeed to write host class printer and I can now communicate with the printer as long as the data length to not exceed 64 bytes.

I'v already read that it was a known issue : e2e.ti.com/.../296947

I actually encounter the same problem.

While using USBHCDPipeWrite(), I'm stuck in a while statement (line 1685) as my g_sUSBHCD.psUSBOUTPIpes[0].iState is stuck in ePipeWriteDMAWait state...

Trying to solve that, I think it may come from the USBHostIntHandlerInternal():

Line 4123, u132Status get a value but never the value that will allow the program to enter in the if statement (line 4317) that check the status of transmit(OUT) pipes and would change the state ePipeWriteDMAWait to another one. Alas, I can't figure out why...

My revision of TivaWare is 2.1.2.111

My function to send data to the printer

int32_t
USBHPRNBlockWrite(tUSBHPRNInstance *psPRNInstance, uint8_t *pui8Data, uint32_t ui32Size)
{
    //
    // If there is no device present then return an error.
    //
    if(psPRNInstance->psDevice == 0)
    {
        return(-1);
    }

    //
    // Perform the write command.
    //
    return(USBHCDPipeWrite(psPRNInstance->ui32BulkOutPipe, pui8Data,ui32Size));
}

The part of main where I send my commands :

USBHPRNBlockWrite(g_psPRNInstance, g_init, 2);
USBHPRNBlockWrite(g_psPRNInstance, g_status, 3);
USBHPRNBlockRead(g_psPRNInstance, g_ans, 64);
USBHPRNBlockWrite(g_psPRNInstance, g_control, 13);
USBHPRNBlockWrite(g_psPRNInstance, g_cut, 4);
USBHPRNBlockWrite(g_psPRNInstance, g_margin, 5);
USBHPRNBlockWrite(g_psPRNInstance, g_status, 3);
USBHPRNBlockWrite(g_psPRNInstance, g_msg, 93); //<-- All work fine until here

Thank you to anyone who will read that.

Regards,

Quentin

  • Hello Quentin,

    I have forwarded this post to one of my colleague who is more knowledgeable about this topic. He should reply pretty soon.

    Thanks,
    Sai
  • Hello Quentin,

    Are you using the DMA or the CPU Write?

    Regards
    Amit
  • Hi Amit,

    I'm using DMA for my transfers. Just for you to know, I'm using USB0HostIntHandler() in my vector table as well.

    Regards,

    Quentin.

  • Hi,

    I investigate a bit more to understand what's going on :

    When I want to send data, I call this function (I only show the lines I need for my explanation

    //usbhostenum.c
    uint32_t
    USBHCDPipeWrite(uint32_t ui32Pipe, uint8_t *pui8Data, uint32_t ui32Size)
    {
        ui32RemainingBytes = ui32Size;
        
        bUseDMA = false;
        
        
        while(ui32RemainingBytes != 0)
        {
            //I enter here as I'm using uDMA
            if(ui32Pipe & EP_PIPE_USE_UDMA)
            {
                OS_INT_DISABLE(g_sUSBHCD.ui32IntNum);
    
    	    //USBLibDMATransfer() return :
    	    //0 if ui32RemainingBytes < 64 or ui32RemainingBytes if it's greater
                if(USBLibDMATransfer(g_sUSBHCD.psDMAInstance, g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].ui8DMAChannel,pui8Data, ui32RemainingBytes) != 0)
                {
    	        //...
    	        //I came here only when I send data greater than 64 bytes and in my case (93 bytes), it makes this
                    g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriteDMASend;
    
    	        //and this
                    bUseDMA = true;
                }
    
                //I enter here only if my data is lesser than 64 bytes
                if(bUseDMA == false)
                {
                    //It makes this
    	        g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriting;
                }
    
            //The statement wait that g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState changes
            //This is where I'm stuck when I send data greater than 64 bytes
            while(1)
            {
                //I need the iState = ePipeDataSent to move on
                else if(g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState == ePipeDataSent)
                {
                    
                }
            }
        }
    }
    

    At this point I have to possibilities for my iState : ePipeWriting if my data < 64 bytes or ePipeWriteDMASend if my data >= 64 bytes.

    Now we'll take a look to the USB host interrupt handler (again I only keep the part we have interested in):

    usbhostenum.c
    void USBHostIntHandlerInternal(uint32_t ui32Index, uint32_t ui32Status)
    {
        //Lot of cases
        //Here my part
        ui32DMAIntStatus = USBLibDMAIntStatus(g_sUSBHCD.psDMAInstance);
    
        //I enter here
        if(ui32DMAIntStatus)
        {
            USBLibDMAIntHandler(g_sUSBHCD.psDMAInstance, ui32DMAIntStatus);
    
            for(ui32Idx = 0; ui32Idx < MAX_NUM_PIPES; ui32Idx++)
            {
                //If my data >= 64 bytes I enter here...
                else if(g_sUSBHCD.psUSBOUTPipes[ui32Idx].iState == ePipeWriteDMASend)
                {
                    if(USBLibDMAChannelStatus(g_sUSBHCD.psDMAInstance,g_sUSBHCD.psUSBOUTPipes[ui32Idx].ui8DMAChannel) & USBLIBSTATUS_DMA_COMPLETE)
                    {
                        MAP_USBEndpointDataSend(USB0_BASE,IndexToUSBEP(ui32Idx + 1),USB_TRANS_OUT);
    
    	            //Here we go, the iState change
                        g_sUSBHCD.psUSBOUTPipes[ui32Idx].iState = ePipeWriteDMAWait;
                     }
                 }
                
             }
        }
    }
    

    Our 2 possibilities for iState now : still ePipeWritting if data <64 bytes and ePipeWriteDMAWait id data >= 64 bytes

    Have a look at what happens just after, still in the same function :

        //This part of code takes place just after the previous part
        //This function return a value that shows in what endpoint there are a interrupt for RX/TX transmission
        ui32Status = MAP_USBIntStatusEndpoint(USB0_BASE);
    
        if(ui32Status & USB_INTEP_0)
        {
            g_sUSBHCD.ui32IntEvents |= INT_EVENT_ENUM;
        }
    
        for(ui32Idx = 0; ui32Idx < MAX_NUM_PIPES; ui32Idx++)
        {
    
            ui32Status >>= 1;
    
            if(ui32Status == 0)
            {
                break;
            }
    
            // Check the status of the receive(IN) pipes.
            if(ui32Status & 0x10000)
            {
                //I don't care this part since I send
            }
    
            //Check the status of the transmit(OUT) pipes.
            //The part I should enter in
            if(ui32Status & 1)
            {
    
                ui32EPStatus = MAP_USBEndpointStatus(USB0_BASE, IndexToUSBEP(ui32Idx + 1));
    
    	    //Here we go
                else if((g_sUSBHCD.psUSBOUTPipes[ui32Idx].iState == ePipeWriting) ||
                        (g_sUSBHCD.psUSBOUTPipes[ui32Idx].iState == ePipeWriteDMAWait))
                {
                    //My iState change, everyone is happy, I can exit the infinite while in USBHCDPipeWrite()
                    g_sUSBHCD.psUSBOUTPipes[ui32Idx].iState = ePipeDataSent;
    	    }
            }
    }
    

    For some reason I never go in the statement that checks the status of transmit(OUT) pipes when I send data >= 64 bytes but I do when data < 64 bytes. I try to debug to see if my ui32Status takes a wrong value with data >= 64 bytes but it looks like not (it's 0x00000008 by the way).

    Any idea about it or how can I figure out what's wrong ?

    Regards,

    Quentin

  • Hello Quentin,

    I would need to know, what is the USB Endpoint FIFO size configured as, the ARBSIZE for the uDMA channel and the XFERSIZE of the uDMA
    channel

    Regards
    Amit
  • Hi Amit,

    I've some problems to find the value of ArbSize and xFerSize of the uDma.

    When USBLibDMAInit() is called (usbdma.c), I have the correct function pointer that is attributed :

    //
    // Initialize the function pointers
    //
    g_psUSBDMAInst[0].pfnArbSizeSet = uDMAUSArbSizeSet;

    Nevertheless, when I put a breakpoint into uDMAUSArbSIzeSet() in order to know my ArbSizeSet, I never stop into it. I try to put a breakpoint into iDMAUSBArbSIzeSet() just in case but same results.

    If I take a closer look to my tUSBDMAInstance when I send data for example I have this :

     Or the address of uDMAUSBArbSIzeGet() seems to be 0x0000260A so I don't know if this difference between those two addresses are linked to the fact I don't stop into uDMAUSBArbSIzeGet() when I put a breakpoint...

    Any Idea about that ?

    Regards,

    Quentin

  • Ok, I think I have all the values you'vs asked for :

    USB FIFO ENdpoint Size = 0x03

    ArbSize = 64 (0x00018000)

    XFerSize = 16 368 (0x00003FF0), not quite sure about this one.

    Regards, Quentin

  • Hi,

    Just a little update to say I have not been able to get trough this yet.

    Regards, Quentin.

  • Hello Quentin

    No, it has not dropped out my radar. Since I do not have a setup as yours, I am trying to do the same with a TM4C129X and a Mass Storage Class device.

    Regards
    Amit
  • Hello Quentin,

    An important question I did not ask was which TM4C12x device are you using?

    Regards
    Amit
  • Hi,

    I use tm4c123gh6pm device.

    Since I'm stuck in this project, I move on another project with the same device where I have to write file into a usb. I have succeeded thanks FatFs so I think the problem with the printer comes from my work. I am kind of noob with usb protocol, I confess.

    Maybe there is a problem with my interruption. Per example when I send my 93 bytes data, maybe the device wait for the printer to send something after the first 64 sent bytes , I don't know...

    Regards, Quentin

  • Hello Quentin

    Thanks for the information and tip.

    Regards
    Amit