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.

TMDX654IDKEVM: Issue with receiving a complete string via UART

Part Number: TMDX654IDKEVM

Hi there,

We are experiencing a issue with receiving a complete string via UART. Some bytes are just missing on occasion. UART settings are set up as follow: Baud 19200, 8 Data bits, 1 stop bit, zero parity.

Within our application, our uart receive functionality is implemented as follow:

- Task thread created for receiving

- Within while loop, call UART_read(........, ........., 1U), which continuously reads one byte of data on the uart specified.

- This character is then stored on a buffer, and the while loop should starts over again.

However with this implementation, when multiple bytes are sent to the board, some bytes are just missing. When sending the bytes one by one, the receive function works perfectly. Do you have any suggestions what the issue might be? I have also tried using different terminal prorgams, but the issue is still the same. Here is an example when trying to transmit '0xA3 0xBC 0x02 0xBC 0x02' from RealTerm to the board:

In the above image it is clear that the final bytes is missing. Other times, some bytes in the middle are missing. However, when transmitting the bytes indivudually, as '0xA3' then '0xBC' then ...... '0x02', the bytes are received successfully and placed on the buffer :

A suspicion I have, is that the UART_read API is called too late sometimes when transmitting complete strings, which might cause a byte to go missing? How would you then suggest to change the code in order to immediately store a character on the buffer when an intterupt is received, without having to call the uart_read API?

Do you perhaps have other suggestions what the cause of the issue might be? I look forward to hearing a reply

Kind regards,

Johnny 

  • Hi,

    What software/version are you using?
    Is the UART_read the driver API or your own implementation?

    Regards,
    Prasad

  • Hi Prasad,

    Thanks for your reply.

    Software is processor_sdk_rtos_am65xx_6_00_00_07 and pdk_am65xx_1_0_5.

    The UART_Read API is also the standard driver API, and not my own implementation.

    Kind regards,

    Johnny

  • Hi,

    Is there anyone who can provide advise/update on this issue?

    This is quite urgent!

    Kind regards,

    Johnny 

  • Hi,

    What is going on with TI support lately? Could anyone please provide some feedback? These support forums used to be excellent and assistance plentiful.

    As stated, I am experiencing issues with continuously reading from UART using the UART read function.

    Some documentation suggests a solution were you should call the UART_read API within the callback function of the UART_read API. However, it is also stated in other documentation that this should not be done in order to prevent stackoverflow? This is contradicting?

    Is there any advise that anyone can give in order to successfully read continously from the UART?

    Regards,

    Johnny

  • Part Number: TMDX654IDKEVM

    Hi,

    I refer to the below thread I created a week ago, on which I do not receive any replies.

    https://e2e.ti.com/support/processors/f/791/t/883948

    Could anyone please provide some assistance?

    We need to receive data continuously on the UART, but data gets missing when transmitting strings to the the EVM. Our application currently calls the UART_read API (Driver API and not my own implementation) within a task thread, and stores the received byte in a global buffer. This is an a while loop so that it will continuously wait on a byte, and if a byte is received, store it and repeat.

    However, as you can see in the thread link that I posted above, data gets missing when I send a complete string to the EVM. When sending the data byte by byte, everything works fine.

    Is there any advise you can give as to how I can continously read data from the UART byte by byte?

    Please refer to the above thread link for more detail.

    Kind regards,

    Johnny

  • Hi,

    What is the deal with TI support? We need a answer/advice to this issue!

    We have tried multiple approaches for the UART in blocking mode and callback mode, but still no success!

    Please assist!

    Kind regards,

    Johnny Smith 

  • Hi Johnny,

    I am very sorry for the late reply. I was just aware that I was assigned for this E2E thread.

    From your description, I assume you use the default UART SoC configuration (interrupt enabled, blocking mode), UART_read() API will enable the read buffer status interrupt first and wait until it receives one char and disable the read buffer status interrupt.

    In you test scenario, it could be possible that one of the chars comes in when the UART_read() API just finishes receiving the previous interrupt and disables the read interupt, and that char will be missing, that also explains that your code works if you send one char at a time, please refer to below the UART driver code: 

    https://git.ti.com/cgit/processor-sdk/pdk/tree/packages/ti/drv/uart/src/v1/UART_v1.c#n1378

    To resolve this problem, and if you have to send multiple chars at a time:

    1. if you know the # of chars you read, call UART_read (uartHandle, rxBufPtr, <# of bytes>) instead of calling UART_read (uartHandle, rxBufPtr, 1) 

    2. if you don't know the # of chars you read, try to disable the interrupt and use polling mode by calling UART_readPolling(), but that will block your other tasks running

    Best,

    Hao

  • Hello Hao,

    Thanks finally for the reply!

    I also believe it is a timing issue. Currently however, the amount of chars to be read is unknown, which is why we have to continously read 1 char from UART. The system we have currently (we are upgrading this), continously reads 1 char from UART by storing the received char into a buffer when the intterupt is triggered. The application can then access the data in the buffer. The amount of chars to read can range anything from 1-25, depending on the first byte received (the first char is like a instruction, the following chars are like parameters to that instruction). Thus after the first char is received, the amount of chars that will follow is known, and that amount of chars can be accessed in the receive buffer.

    We are trying the implement the same functionality on the TMDX654IDKEVM now using the uart driver, but we receive this error where bytes go missing. Pollingmode is not really desired. We have also tested the following:

    1. UART_read in callback mode, posting a SWI to trigger a new UART_read. This also gives the same error with missing chars.

    2. UART_read in callback mode, calling UART_read in the callback function. This works, however this is not recommended according to the manuals and this will thus not be used.

    Another consideration might be to use UART_read with a timeout (but this is also some kind of polling mode I think)...

    Thus when considering the above information, what other suggestions might you have to use the uart driver for the above functionality? Is there a way of storing the received char directly into a buffer when the rx interrupt is triggered, instead of having to call the uart_read?

    I hope the above clearly describes our restrictions and I look forward to hearing further advice.

    Regards,

    Johnny

  • Hi Johnny,

    Thanks for providing the detailed description of your application use case.

    I think you can call UART_read (uartHandle, rxBufPtr, 25) in callback mode. This API will call back to your application after it receives all the 25 chars or times out. Each char received in the UART RX FIFO will be read out by the ISR and saved to your rxBuf after a UART CHAR_TIMEOUT. Your application code can check the data received in your rxBuf and call UART_readCancel(uartHandle) API to cancel the previous read after you have received all the data:

    https://git.ti.com/cgit/processor-sdk/pdk/tree/packages/ti/drv/uart/src/v1/UART_v1.c#n456

    Please let me if that works for your application.

    Best,

    Hao

  • Hi Hao,

    Thanks for the above suggestion.

    Is it possible for you to give some example code of the timeout in callback mode, with the uart_readCancel() function? I am not too sure how this will be implemented for the callback mode...

    I have implemented the above suggestion in blocking mode with a timeout. As soon as all 25 chars are received, or the timeout is reached (whichever occurs first), the UART_read() API will return the number of bytes that has been received. The ISR also then would have read out the data in the UART RX FIFO into the specified buffer. This works, however is still some kind of polling mode I think, as the task wherein the UART_read function call is made, will get executed every time the timeout is reached. This is unnecesarry, as there might be extended periods of time where no chars are sent to the system via UART...

    It would thus be great if we could store the data received over uart in a buffer EVERY time a char is sent to the system (whether it is sent as an individual char OR a string of chars). Thus, store a byte in the buffer each time the RX interrupt is trigger. Is this functionality possible?

    I look forward to hearing from you.

    Kind regards,

    Johnny

  • uint8_t           rxBuf[25];
    
    void UART_callback(UART_Handle handle, void *buf, size_t count)
    {
        
    }
    
    bool checkRxData(uint8_t *rxBuf, uint32_t *rxBytes)
    {
        /* 
         * add your own function to check received data in rxBuf
         * rxBytes used as the index of rxBuf to check new received bytes
         * rxBytes is incremented in checkRxData if new chars are received
         */
    }
    
    void UART_test_callback()
    {
        UART_Handle       uart = NULL;
        UART_Params       uartParams;
        uint32_t          uartTestInstance = 0;
        uint32_t          rxBytes = 0;
        bool              receivedAllChars = false;
    
        UART_Params_init(&uartParams);
        uartParams.readCallback = UART_callback;
        uartParams.readMode = UART_MODE_CALLBACK;
    
        uart = UART_open(uartTestInstance, &uartParams);
        UART_read(uart, (void *)(uintptr_t)rxBuf, 25);
        
        while (!receivedAllChars)
        {
            /* 
             * add your own function to check received data in rxBuf
             * rxBytes used as the index of rxBuf to check new received bytes
             * rxBytes is incremented in checkRxData if new chars are received
             */
            receivedAllChars = checkRxData(rxBuf, &rxBytes);
            if (receivedAllChars)
            {
                /* check if received all the bytes */
                if (rxBytes < 25)
                {
                    UART_readCancel(uart);
                }
            }
            else
            {
                Osal_delay(1);  /* This will suspend current task and sleep for 1 tick time */
            }
            
            
        }
        
        UART_close(uart);
    }

  • Hi Johnny,

    Please try the attached test code, and let me know if that works?

    Best,

    Hao

    uint8_t           rxBuf[25];
    
    void UART_callback(UART_Handle handle, void *buf, size_t count)
    {
        
    }
    
    bool checkRxData(uint8_t *rxBuf, uint32_t *rxBytes)
    {
        /* 
         * add your own function to check received data in rxBuf
         * rxBytes used as the index of rxBuf to check new received bytes
         * rxBytes is incremented in checkRxData if new chars are received
         */
    }
    
    void UART_test_callback()
    {
        UART_Handle       uart = NULL;
        UART_Params       uartParams;
        uint32_t          uartTestInstance = 0;
        uint32_t          rxBytes = 0;
        bool              receivedAllChars = false;
    
        UART_Params_init(&uartParams);
        uartParams.readCallback = UART_callback;
        uartParams.readMode = UART_MODE_CALLBACK;
    
        uart = UART_open(uartTestInstance, &uartParams);
        UART_read(uart, (void *)(uintptr_t)rxBuf, 25);
        
        while (!receivedAllChars)
        {
            /* 
             * add your own function to check received data in rxBuf
             * rxBytes used as the index of rxBuf to check new received bytes
             * rxBytes is incremented in checkRxData if new chars are received
             */
            receivedAllChars = checkRxData(rxBuf, &rxBytes);
            if (receivedAllChars)
            {
                /* check if received all the bytes */
                if (rxBytes < 25)
                {
                    UART_readCancel(uart);
                }
            }
            else
            {
                Osal_delay(1);  /* This will suspend current task and sleep for 1 tick time */
            }
            
            
        }
        
        UART_close(uart);
    }

  • Hi Hao,

    Thanks for this information - this is exremely helpful. I have tested this in our current setup, and this seems as if this is an approach that will work! I do however still have the following to simple questions

    1. I cannot seem to figure out/understand when exactly the data from the UART RX FIFO will be cleared and stored in the receive buffer? Could you please provide some information on this?

    2. This may be a very stupid question, but how would you suggest to go about incrementing the rxBytes counter? What I mean is that how is it possible - by looking only at the content of the RxBuffer, to know how many chars were received and increment it accordingly?

    Lets say for example, all the content of the rxBuf is initialized to zeroes (0x00 for each index). Now I receive the following data (0xA3 0xBC 0x00 0xBC 0x00 - which is a possibility in our application). A simple function like this would not work, because it will miss the 0x00 bytes received:

    bool checkRxData(char *rxBuf, uint32_t *rxBytes)
    {
       if(rxBuf[*rxBytes] != 0x00)
       {
           *rxBytes++;
       }
    
       if(*rxBytes >= bytesToReceive)
       {
           return true;
       }
       else
       {
           return false;
       }
    }

    The concern is thus how to know the number of bytes received... do you have suggestions here.

    However, thank you for this information and after you have answered the above, I am confident we will be able to finally move on with this part of the project, and we deeply appreciate your advice.

    Kind regards,

    Johnny

  • Hi Johnny,

    1. The data from the UART RX FIFO will be cleared and stored in the receive buffer in the ISR when there is a CHAR_TIMEOUT interrupt generated by the HW. Please refer to the TRM I2C peripheral spec and code below:

    12.1.5.4.8.1.3.10 Time-Out Counter
    An RX idle condition is detected when the receiver line (RX) is high for a time that equals 4x the
    programmed word length + 12 bits or manually configured amount of baud clocks, if a value other zero is
    set in the timeout register. RX is sampled midway through each bit.

    https://git.ti.com/cgit/processor-sdk/pdk/tree/packages/ti/drv/uart/src/v1/UART_v1.c#n456

    2. There are two ways you can check the rxBytes counter;

    • Use object->readCount

    UART_V1_Object *object;

    object = (UART_V1_Object*)handle->object;

    • Initialize the data in rxBuf[] to any value that is not valid (e.g. 0xff) 

    Best,

    Hao

  • Hi Hao,

    Thank you for the above information! It is very helpful!

    I will let you know if the above approach is not successful, however when considering the information as well as initial tests done, I am quite sure this approach will work! Otherwise, I will just close the thread and mark it as resolved if successful!

    Thanks for your assistance once again, and I hope you keep safe during these global uncertain times!

    Kind regards,

    Johnny

  • Hi Johnny,

    Thanks for your kind reminder, we are now working home, hope you keep safe as well!

    You can close the thread once you verify if this solution works for your application.

    Best,

    Hao

  • Hi Hao,

    I hope you are still looking at this thread, as I have marked it as resolved already. However, we are still experiencing issues.

    A summary of our implementation can be seen in below (this is only some kind of pseudo code to illustrate our implementation/ due to company policy cannot share the actual code):

    uint8_t           rxBuf[30000];
    
    void UART_callback(UART_Handle handle, void *buf, size_t count)
    {
        
    }
    
    void UART_RxTask(UArg arg0, UArg arg1)
    {
        UART_Handle       uart = NULL;
        UART_Params       uartParams;
        uint32_t          uartTestInstance = 0;
        uint32_t          rxBytes = 0;
        bool              receivedChars = false;
    
        UART_Params_init(&uartParams);
        uartParams.readCallback = UART_callback;
        uartParams.readMode = UART_MODE_CALLBACK;
    
        uart = UART_open(uartTestInstance, &uartParams);
        
        
        while (1)
        {
    		UART_read(uart, (void *)(uintptr_t)rxBuf, 30000);
    
    		while(!receivedChars)
    		{
    			
    			//Get how many chars have been received
                rxBytes = object->readCount;
    			
    			if(rxBytes > 0)
    			{
    				
    				//Data received so cancel the read (if rxBytes < 30000)
    				UART_readCancel(uart);
    				
    				//Set variable that data has been received
    				receivedChars = true;
    				
    				for(i = 0; i < rxBytes; i++)
    				{
    					//Copy data in rxBytes to a buffer accessible by application layer
    				}
    
    				rxBytes = 0;				
    			}
    			else
    			{
    				Task_sleep(1U);
    			}
    		}        
        }
    }

    This implementation works perfectly when the the uart_rxtask runs on its own. Howewer, when running with other tasks (for example with the UART_txtask), reading is unsuccessful with a byte being lost every now and then. What would be the reason that this does not work with other tasks running (all lower priority)?

    For example, when running the rxtask on its own, and sending a string of 25 characters to the system (content 0x00 0x01 0x02 0x03...........0x23 0x24), all bytes are received successfully. When running it with other tasks, the 0x08 byte gets lost.

    From your previous suggestion, as well as referring to the TRM:

    12.1.5.4.8.1.3.10 Time-Out Counter
    An RX idle condition is detected when the receiver line (RX) is high for a time that equals 4x the
    programmed word length + 12 bits or manually configured amount of baud clocks.

    Is there a way of extending this time a bit? Setting a timeout in uart_params I believe will not work, because that is associated with the time elapsed since the call of uart_read, rather than the time the RX Line stays high, if my understanding is correct?

    Any other advise would still be appreciated.

    Kind regards,

    Johnny

     

  • Hi Johnny,

    Sorry for getting back to you late, I was not ware that you had a new post.

    From your test code, it looks the rxTask() calls UART_readCancel() when it receives at least one characters (rxBytes > 0), does it wait until all the expected chars are received before cancelling the read?

    You can set a breakpoint at UART_readCancel() check the rx buffer to see if the lost char is related to UART_readCancel(). The cancel API may flush the char in the RX FIFO.

    Best,

    Hao

    if(rxBytes > 0)
    {

    //Data received so cancel the read (if rxBytes < 30000)
    UART_readCancel(uart);

    //Set variable that data has been received
    receivedChars = true;

    for(i = 0; i < rxBytes; i++)
    {
    //Copy data in rxBytes to a buffer accessible by application layer
    }

    rxBytes = 0;
    }
    else
    {
    Task_sleep(1U);
    }