UART - problem reading data without losing any bytes if message length is unknown or variable

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

UART - problem reading data without losing any bytes if message length is unknown or variable

3,155 Views
nbouchon
Contributor I

Hi,

I am working off the MPC5744P UART Echo model with very minor changes to the UART config - see attached model (Matlab 2020a, NXP MBDToolbox MPC57XX version 3.2.0), as well as modifications per this thread here to define an 8 byte rx buffer.  I am testing this on the MPC5744P development board, rev E, and communicating over UART0 via a serial terminal interface (Termite).

This model works fine but only if incoming UART messages are exactly 8 bytes long; the same 8 bytes will then be echoed back.  If the incoming message is longer than 8 bytes, all bytes received after the 8th byte are lost.  Similarly, if incoming messages are shorter than 8 bytes, all of these bytes are lost, even if multiple messages (each < 8 bytes long) are sent such that the sum of bytes sent is equal or greater than 8.

I have tried changing the UART ISR to trigger on both rx transfer end as well as rx buffer full, but with the exact same behavior.  This was also confirmed by looking at the generated c code.

I'd appreciate any help you can offer to get a full functioning UART echo model, where all data bytes sent are echoed back, regardless of how many bytes are transmitted at a time.

Thank you,

Nick

0 Kudos
5 Replies

2,344 Views
Botsford
Contributor I

Receive an unknown length of data from a UART Interrupt serial communication. I have initialized an array, to store the data. Now, when I receive the data and store it byte by byte until the user enters \n, the data should be stored, and not overwritten when a new set of data comes in. For this, I thought of initializing a counter, whenever there is data received.

0 Kudos

3,121 Views
mariuslucianand
NXP Employee
NXP Employee

Hello @nbouchon,

In this case, I would try the following approach.

Since the string to be sent has a variable size, I would define a terminator; let's say '\r' or '\n' to mark the string end.

In the Simulink model, I would set the RX interrupt to be triggered for each character. I would store all the characters received, one by one in a Data Store Memory variable, defined as an array of max string size, let's say 128 characters. If the character that arrived is the terminator I've set, then I would change a flag defined as a (Data Store Memory variable too). So in the main model, when this flag has been changed, then the entire string has arrived and I can do whatever I need to do with it. After that, I would reset the flag.

Hope this helps,

Marius

 

0 Kudos

3,084 Views
nbouchon
Contributor I

Hi Marius,

Thanks for your answer and sorry for the delay in my reply. I agree with you that implementation of a communication protocol is what will eventually be needed. However, I was struggling with the basics.

To have a full functioning UART for my application, I need the following capabilities:

1. Receive all incoming bytes, independent of how many are sent at a time and make them available to the application without losing any bytes, and without undue delay.

2. Be able to send a variable number of bytes.

I was struggling with part 1 which is what prompted this ticket. The UART echo example provided by NXP as part of the model based toolbox does not work properly, as it can only echo a byte at a time. If one tries to send 2 or more bytes at a time, only the first byte is echoed. The rest go missing. I suspect that the issue is the the interrupt is triggered after the whole packet is read, but as the example only reads one byte, the rest are discarded. To try to resolve this, I had bumped up the rx buffer size to 8 bytes, and I would receive everything, but of course only if the interrupt was triggered, i.e. if a full 8 byte packet was transferred. If I transferred a 3 byte packet, followed by a 5 byte packet, all of those 8 bytes were lost. I suspected this to be due to the UART rx block being triggered by the time step, vs being fully interrupt driven.

I was able to get around this restriction by moving the UART rx block to the rx ISR, reading 1 byte at a time, and ensuring all bytes are captured in a circular buffer. I created a block that then outputs a fixed size rx buffer containing the new bytes at index 0-num_bytes where num_bytes is an output variable which lets the application time step know how many bytes were received. See attached model. This works well to satisfy condition 1.

Now for part 2 - sending or echoing variable size packets. I applied the same principle to send a single byte at a time by loading an interrupt driven tx block one byte at a time from a tx circular buffer. The idea is to send the next byte whenever the previous transfer is done so as not to overwhelm the uart module. This also works well.

So problem solved. We have a fully functioning UART echo that also makes the received bytes available to the timestep. Hope the attached model can help others in the community.

One last note to help others, the NXP blockset does not seem to respect execution order. If a Simulink block feeds into a UART Tx block for example, there is no guarantee that the Simulink block will execute first. That is dangerous IMO, leading to unexpected behavior and frustration. The work around is to set priorities in the blocks, but that is not ideal and should ideally be addressed by NXP in future releases.

Thanks,
Nick

0 Kudos

2,677 Views
ranulf
Contributor IV

The attached file is a Simulink cache file, so it is not helpful. I am interested in looking at your approach. Can you please attach the appropriate file?

0 Kudos

2,565 Views
nbouchon
Contributor I

Hi Ranulf,

My bad, sorry about that.  Here is the actual file.

Hope this helps,

Nick

0 Kudos