AnsweredAssumed Answered

UART_DRV_ReadDataBlocking seems to allow FIFO data to be lost

Question asked by dave408 on Sep 18, 2015
Latest reply on Sep 20, 2015 by dave408

I'm not 100% sure about this.  However, I have been running my code that is expecting a 17 byte Modbus RTU packet, and it very rarely works.


I have a MQX Lite task running the following Modbus FSM:



In each the Reception and Control and Waiting states, I read in data using UART_DRV_ReadDataBlocking and pass 1ms for the timeout.  I'm using 1ms as a rough estimate of the 750us interbyte delay required by the Modbus spec for baud rates > 19200 (I am currently using 38400).


If I send a command that is <= 8 bytes, the command is handled properly the majority of the time.  However, when I send a command that is 18 bytes, it almost never works.  My code always detects the interpacket delay (1750us) after receiving 8 bytes.


Just as an extra test, I have kept reading the RX buffer with UART_DRV_ReadDataBlocking, and the remaining 10 bytes that I am expecting are never read out of the FIFO.  The end result is that my modbus receive buffer has all 0s after the 8th byte and then the CRC check fails.


I'm wondering if I have missed something or am misusing the function.  I know that I have been told that UART_DRV_SendDataBlocking is poorly named and doesn't actually block until the data goes out of the UART TX pin.  I don't see anything in UART_DRV_ReadDataBlocking that suggests the same.


I went ahead and modified my FSM to do the following: keep trying to read bytes and stuff them into a buffer when successful:


case Receiving: {     while( true) {         int ret = UART_DRV_ReceiveDataBlocking( _rs485_instance, &rx, 1, INTERBYTE_DELAY); // INTERBYTE_DELAY is 1         if( kStatus_UART_Success == ret) {             rxbuff[index++] = rx;         }         if( index == 17) {             int i = 0;             i += 2;         }     } ...


Two observations when I run this:

1.  I never hit my breakpoint inside of if(index==18), because I never read enough data from the RX FIFO

2.  I checked rxbuff and it only has 8 bytes of data (indicated by the variable "index")


I then changed up the code a little and in the Receiving state, rather than reading in one byte at a time, I read in the remaining 16 bytes since I knew they were coming.  When I did this, I was able to read in all of the data sent by the host:


case Receiving: {     while( true) {         // read in the next 16 bytes since we know they are coming         int ret = UART_DRV_ReceiveDataBlocking( _rs485_instance, &rxbuff[1], 16, 1000);         if( kStatus_UART_Success == ret) {             int j = 0;         }     }     ...


I'd love to hear any suggestions as to what might cause this behavior!