Method for UART variable length receive

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

Method for UART variable length receive

3,253 Views
karl_fraasch
Contributor III

I have been investigating different UART receive methods provided by LPUART driver in order to receive a variable length UART packet. The assumption is each UART packet will contain a fixed length header which specifies the length of the remaining packet.

Packet Structure

| Byte 0       | Byte 1          | Byte 2          | Byte 3  | Byte n      | Byte 3+Length-1|

| Start Byte | Length MSB | Length LSB | Data[0] | Data[n-3] | Data[Length-1]   |

Firmware Operation

1. Prepare receive of header size (3 bytes)

2. Receive interrupt, read out the length

3. Prepare a second receive using the length in header

4. Receive interrupt after full length has been received

The methods I have tried are,

Nonblocking Interrupt

Nonblocking interrupt w/ Ring buffer

Non blocking DMA

I have had success with the three above methods at 921600 baud rate. I am able to trigger an interrupt after the header is received and register the second receive in time to receive all bytes in the remaining packet.

My question is, are there any recommended methods for how best to do this? I am concerned once other interrupts and peripherals are introduced into the system, I handle the header receive interrupt before the remaining packet byte come in.

Labels (3)
0 Kudos
5 Replies

2,440 Views
igrinberg
Contributor II

Hi,

I have a very similar application.

Receiving the header and then setting the UART to receive the message body.

I'm using non blocking DMA method. The problem is, that occasionally the interrupt handler is called and there is no data on the destination buffer.

The setting of the next transfer is done from within the interrupt handler to receive both parts of the packet on time.

What can be the issue? Please advise.

0 Kudos

2,427 Views
mjbcswitzerland
Specialist V

Hi

See these videos:
https://www.youtube.com/watch?v=dNZvvouiqis
https://www.youtube.com/watch?v=GaoWE-tMRq4&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q&index=11

The uTasker project includes compatible free-running DMA support for all Kinetis and i.MX RT10xx  parts with UARTs or LPUARTs and solves this typical complication safely - can also be used with FreeRTOS to allow very high speed serial reception rates with no race states in application software.

All code can also directly work with USB-CDC (in place of UARTs) to implement the same with high speed USB rates without any protocol interface changes needed.

Regards

Mark

https://www.utasker.com/iMX/developers.html

0 Kudos

2,411 Views
igrinberg
Contributor II

Thanks @mjbcswitzerland, but switching to this method requires a massive rewrite of the implementation done so far.

I would prefer the actual issue with the current implementation before completely rewriting it.

@jorge_a_vazquez any ideas of what the issue can be? any additional info needed?

Thanks,

Irina.

0 Kudos

2,392 Views
mjbcswitzerland
Specialist V

Hi

If your environment is not suitable for hard real-time through software design (specifically DMA and buffering to relax higher level reaction requirements) you can do it for a limited number of instances by using highest priority non-maskable interrupts to handle (in your case) the DMA buffer transfer completion of the header and set the next transfer block length before following data can arrive and potentially be lost since the next transfer has not been set-up in time. (The processing time should be known and preferably operating from RAM to avoid it fluctuating due to QSPI flash access and cache misses).

Given the speed of the i.MX RT parts this is not a real problem until very high Baud rates need to be handled, apart from possible restrictions in low power mode usage (due to increased reaction times that then cause the model to become critical).

The points that still need to be ensured (partly in the interrupts) are:
- handling parity or framing errors due to interference (this needs to be handled by other interrupt otherwise the reception can stop completely).
- handling of reception corruption (due to interference, etc.) that results in the block length being set incorrectly when the length content is corrupted, plus subsequent recovery as it may leave following messages being incorrectly synchronised to (not reading the header correctly) and potential loss of multiple messages before it can be correctly re-synchronised to.

The second point is the main disadvantage and risk of double DMA transfers since such serial protocols tend to be protected by a check sum at the end of the message and if the header is handled before the complete frame is received there is no error detection in the header and it is handled as if it were correct, which can lead to follow-on errors that cause system failure or unreliability (rather than simply correcting itself when a repetition is received).*1 [see example of how it can go seriously wrong below]

Personally I would avoid DMA for this job since double fixed-length transfers (according to this principle) can be dangerous as noted above. If free-running DMA can't be used I would instead use interrupt driven reception since that allows you to correctly identify single messages and reliably detect errors due to noise and interference and not risk consequences of that failing. As noted above, the iMX RT are fast and so high Baud rates should still be no real problem.

Regards

Mark


*1 Imaging a header is received informing that 7 more bytes will be arriving, DMA transfer is set up for 7 bytes with a second interrupt when they have all arrived.
However, due to noise, the 7 is in fact a corrupted 6 (LSB is incorrect), so DMA is set up for a length greater than the data that will actually arrive.
6 bytes arrive and the interrupt doesn't fired since the DMA hasn't completed.
The other side will probably repeat after a delay since there was no ACK and the first byte of the following header is detected as the end of the first frame, which will now be processed (potentially after a long delay), found to be incorrect and ignored (or NAK sent):
Now the next header transfer is set up but will be corrupted so the next task is to work out how to synchronise to a correct header again.
It may involve idle line timers to help detect gaps between messages to help in re-synchronise reliably.
Although DMA (and highest priority interrupts) can ensure no overrun at the receiver it can greatly complicate error recovery and potentially result in system unreliability or failure (depending on how good the recovery mechanism is).
Handling messages as complete (verified) frames or handling individual interrupts can simplify ensuring product reliability.

 

2,925 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Karl Fraasch

There is not a specific recommended method for doing this, but the one that you are using is the best approach for this. If possible I would recommend to add flow control and block any other process when receiving data in the UART.

Regards

Jorge Alcala

0 Kudos