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.

TM4C USB Device - Read and Write data to host

Hello! 

I have modified the usb_dev_bulk example a bit, I can read the data which is coming from the host (PC) but I can't send my "status codes" back. Only the very firs letter which is '1' goes back to the host.

static uint32_t
EchoNewDataToHost(tUSBDBulkDevice *psDevice, uint8_t *pui8Data,
                  uint32_t ui32NumBytes)
{
    uint32_t ui32Loop, ui32Space, ui32Count;
    uint32_t ui32ReadIndex;
    uint32_t ui32WriteIndex;
    uint32_t valueL;
    uint32_t valueR;
    uint32_t valueC;
    tUSBRingBufObject sTxRing;

    //
    // Get the current buffer information to allow us to write directly to
    // the transmit buffer (we already have enough information from the
    // parameters to access the receive buffer directly).
    //
    USBBufferInfoGet(&g_sTxBuffer, &sTxRing);

    //
    // How much space is there in the transmit buffer?
    //
    ui32Space = USBBufferSpaceAvailable(&g_sTxBuffer);

    //
    // How many characters can we process this time round?
    //
    ui32Loop = (ui32Space < ui32NumBytes) ? ui32Space : ui32NumBytes;
    ui32Count = ui32Loop;

    //
    // Update our receive counter.
    //
    g_ui32RxCount += ui32NumBytes;

    //
    // Dump a debug message.
    //
    DEBUG_PRINT("Received %d bytes\n", ui32NumBytes);

    //
    // Set up to process the characters by directly accessing the USB buffers.
    //
    ui32ReadIndex = (uint32_t)(pui8Data - g_pui8USBRxBuffer);
    ui32WriteIndex = sTxRing.ui32WriteIndex;

    while(ui32Loop)
    {
    	UARTprintf("\n" );

        //
        // LEFT SIDE USB MSG
        //
        if((g_pui8USBRxBuffer[ui32ReadIndex] == 'L'))
        {
            ui32ReadIndex++;
            ui32ReadIndex = (ui32ReadIndex == BULK_BUFFER_SIZE) ?
                            0 : ui32ReadIndex;
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
            UARTprintf("LEFT" );
            char buffer[3];
            uint32_t i;
            for(i = 0; i<3; i++){
            	buffer[i] = g_pui8USBRxBuffer[ui32ReadIndex];
                ui32ReadIndex++;
                ui32ReadIndex = (ui32ReadIndex == BULK_BUFFER_SIZE) ?
                                0 : ui32ReadIndex;
            }
            valueL = atoi((char *)buffer);
            UARTprintf("\n %i", valueL);
            sprintf(g_pui8USBTxBuffer, "100");



        }

        //
        // RGITH SIDE USB MSG
        //
        else if((g_pui8USBRxBuffer[ui32ReadIndex] == 'R'))
        {
            ui32ReadIndex++;
            ui32ReadIndex = (ui32ReadIndex == BULK_BUFFER_SIZE) ?
                            0 : ui32ReadIndex;
            UARTprintf(" RIGHT " );
            char buffer[3];
            uint32_t i;
            for(i = 0; i<3; i++){
            	buffer[i] = g_pui8USBRxBuffer[ui32ReadIndex];
                ui32ReadIndex++;
                ui32ReadIndex = (ui32ReadIndex == BULK_BUFFER_SIZE) ?
                                0 : ui32ReadIndex;
            }
            valueR = atoi((char *)buffer);
            UARTprintf("\n %i", valueR);
    		sprintf(g_pui8USBTxBuffer, "100");

        }



        ui32Loop--;
    }


    //
    // We've processed the data in place so now send the processed data
    // back to the host.
    //
    USBBufferDataWritten(&g_sTxBuffer, sizeof(g_pui8USBTxBuffer[BULK_BUFFER_SIZE]));

    DEBUG_PRINT("Wrote %d bytes\n", ui32Count);

    //
    // We processed as much data as we can directly from the receive buffer so
    // we need to return the number of bytes to allow the lower layer to
    // update its read pointer appropriately.
    //
    return(ui32Count);
}

I you could tell me what's wrong that would be really nice, I have never used USB communication before, I have always used UART. So in the next step I would like to get help with creating a function like "UARTPrintln" which can be called with a simple parameter which would be the message itself.  

  • Hello Zoltan,

    USBBufferDataWritten(&g_sTxBuffer, sizeof(g_pui8USBTxBuffer[BULK_BUFFER_SIZE]));

    This line doesn't make sense... you are asking the API for sizeof to assess the size of g_pui8USBTxBuffer[BULK_BUFFER_SIZE] - that is just going to be singular array result at array location BULK_BUFFER_SIZE. So it will always be a size of 1, would it not? And that would explain why only the first value is sent back?

    There's a reason in the original code we used a ui32Count variable instead. You need to track the number of bytes you are planning to send out.

  • Hello Ralph!


    Yeah I know it does not makes any sense, but I am literraly clueless. The original code processes the incoming characters one-by-one. So if I am not doing a mistake here. The problem is I only write to the first 3 bytes of the g_pui8USBTxBuffer. As a result for the first time I recieve 100 but nothing after that. (The dev_bulk_example.exe says I have recieved 4 bytes, but as they are empty it only shows the "" signs.

    I have been starring at the original EchoNewDataToHost() for the last 20 minutes but I can't see the forest for the trees.
  • Hello Zoltan,

    The API needs to know how many bytes to send out, so if every time you are sending out only 3 bytes, then to start just hard code the 3 to see if you can get a positive result (though making that value adaptive in the future may be key depending on your application).

    So far the problem you described is you can't send your status code back, but instead only the first letter - and what I see if you only send 1 byte back each time.

    The original example was an echo example right? If so it expects a keystroke from the user, reads it in, and outputs it back out. No need to send more than 1 byte in that case as a human can't out type the MCU's processing speed in that specific application. That is the essence of echo examples.

    For your application, it sounds like you need to receive data (possibly more than 1 byte) and then send data back (sounds very much like more than one byte) - so you if you are using the echo example as a basis you need to remove the aspect which are just RX 1 byte, TX 1 byte and replace them with RX x bytes and TX x bytes, where x is your expected packet size for RX and TX (which may well need to be dynamic).
  • Hi Zoltan,

    I am also looking for the similar requirement.

    I want my TM4C to be a device and I want to send and receive data via USB to my host which is PIC32 mc.

    This will be helpful for me to communicate both.
  • Hello Ralph,

    Sorry for not keeping you updated, but I had to solve the issue the other way (we have temporarly stoped workig on the usb part), but now I am back on track.

    So could you please explain this go to 1 byte to X bytes thing in more detail?

    Thanks,

    Zoltan
  • Hello!

    Have you managed to get this working?

    Zoltan
  • Hello Zoltan,

    USBBufferDataWritten requires the second parameter to be the number of bytes sent.

    For your code, you have this listed:

    USBBufferDataWritten(&g_sTxBuffer, sizeof(g_pui8USBTxBuffer[BULK_BUFFER_SIZE]));

    However, 

    sizeof(g_pui8USBTxBuffer[BULK_BUFFER_SIZE])

    That will ALWAYS return a value of 1.

    That is because you are not checking the size of the whole buffer, but rather the size of a singular entry for the buffer. Thus the result will always equal 1.

    What you should have instead is a counter to track how many bytes you are loading into g_pui8USBTxBuffer, and then use the counter for the USBBufferDataWritten API.

    For now though, if you know you will always send 3 bytes, you can just hard code that like for initial tests to make sure that solves your problem:

    USBBufferDataWritten(&g_sTxBuffer, 3);

  • Dear Ralph!

    I have managed to get status code sent back every time, but with 3 digits there was a problem related to buffer size. After a couple messages I have started receiving '010'-s due to the 256 byte size there was an issue. So I have decided to go with '1000' as it wont cause any issues with the buffer.

    The solution was:

        sprintf(g_pui8USBTxBuffer + strlen(g_pui8USBTxBuffer),"1000");
    
        USBBufferDataWritten(&g_sTxBuffer, 4);
    

    The problem with this Is CCS is flagging sprintf:

    Multiple markers at this line
    - #169-D argument of type "uint8_t *" is incompatible with parameter of type "const char *"
    - #169-D argument of type "uint8_t *" is incompatible with parameter of type "char *"
    - #1532-D (ULP 5.3) Detected sprintf() operation(s). Recommend moving them to RAM during run time
    or not using as these are processing/power intensive
    - usb_dev_bulk.c, line 309 ($C$L19) [S/W BP]

    It works so I am not sure if there is a workaround for this to get rid of the warnings or not.

    However the application has developed some new symptons.

    After succesfuly recieving 1200 bytes it just hangs. It does not matter how fast or slow the data is being entered it just hangs. While in debug mode I cannot see any issues maybe I am looking at the wrong numbers?

    Any idea about this?

  • Hello Zoltan,

    It looks like the issue it is complaining about is that a char parameter is being used in there, perhaps it is because of how strlen returns - see if strlen function returns as a char type, if so, then just typecast to uint8_t to resolve that issue.
  • Unless strlen is non-standard it should return a size_t.

    size_t is a compiler specific type but is for practical purposes consistent across compilers.

    Robert