Data got by calling the k_fifo_get() less than the data received by the UART RX

Dear Support Team

I test the peripheral_uart sample from NCS(V2.4.0), I found that the data got by calling the k_fifo_get() less than the data received by the UART RX. For example, I sent 208 Bytes to the UART RX but it just printed 200 Bytes by calling the LOG_HEXDUMP_INF()  macro as the screenshots below showing, and UART baud rate I set is 921600.

Below screenshot below shows I send 208 Bytes to the RX. This packet starts with 2c and ends with 2c.

Below screenshot shows the data printed by calling the LOG_HEXDUMP_INF()  macro. It starts with 2c but ends with 77, so there was still 8 bytes haven't been printed.

Why it would loss printing the 8 bytes? How could I print all of the any size of data packet without end with \r or \n received by the UART RX?  Many thanks.

Parents Reply
  • I'm having a similar problem.  Either the buffer has to fill up or the timeout has to occur.  If I send a shorter amount of bytes even with \r\n I still have to wait for the timeout.  As a workaround I significantly decreased the timeout CONFIG_BT_NUS_UART_RX_WAIT_TIME  which is a huge improvement but its not the optimal solution.  Race conditions and other nasty things can occur if not careful.  Ideally the data will show up immediately after the \r\n or something.  The way I'm seeing it the data only shows up with either all the data is sent or the timeout.  If that's not correct please let me know.  I think the original post I think maybe Tom Fu has a valid complaint and just reducing the timeout although is a big help its more of a bandage to me and a good solution should come forward.

Children
  • Hi,

    Unless you know the exact size of the string before \r\n arrives, it is not possible to get the data before a timeout. The HW does not have any way to know when these characters are received, and it can therefor not inform the application before a timeout occurs. The other alternative is to use only 1 byte buffers for all UART transfers and check each received byte in SW, but this will cause heavy load on the CPU and is not feasible with high throughput on the UART. This will be a tradeoff that the designer makes in the application (frequency of interrupts vs. latency from transfer end until application interrupt).

    Best regards,
    Jørgen

  • Excellent, thanks for straightening me out on this!  I didn't mean to commandeer Tom Fu's post but it's all related.  If Tom needs any additional help maybe we can get him going or he might have it all figured out by now.  I will need to do some testing and so on now to consider the byte by byte transfer.  My background is embedded with bare metal so with a good context switch byte by byte back in the day wasn't that big of a deal.  It might be with such an involved operating system?  Would it be possible to hook this kind of "uart" up to the DMA?  Any other ideas?  Thanks.

  • Ramulous said:
    with a good context switch byte by byte back in the day wasn't that big of a deal.  It might be with such an involved operating system?

    I guess this will depend on the baudrate and throughput. Even with bare metal, I think you will struggle to handle constant data streams byte by byte with higher baudrates (921600/1M). To receive short commands byte by byte once in a while would likely not cause any issues.

    Ramulous said:
    Would it be possible to hook this kind of "uart" up to the DMA?  Any other ideas?

    There is no way to hook up a byte by byte UART to DMA, the nRF52 chips comes with two configurations: legacy UART without EasyDMA and UARTE with EasyDMA. The legacy UART needs to update data pointer for each byte, UARTE will transfer bytes to/from RAM until it reaches the MAXCNT buffer size, but it is possible to count the number of received bytes using a TIMER, and use timeouts to determine when a transfer have stopped/paused.

Related