cancel
Showing results for 
Search instead for 
Did you mean: 

How to write a parser for UART 'control packets'?

TGilc.1
Associate II

Hi all

I've just jumped on the STM32 bandwagon so apologies if this post isn't in the right place. Just let me know and I'll go annoy the right people 🙂

I've done some work with the ATMega AVR range, both via Arduino and native so I'm not a complete newbie. However I'm not an experienced MCU programmer.

I've started a project where I need to communicate with an existing product via UART. The existing product uses a fairly simple 'control packet' format i.e. each update is in the form

0xEE 0x?? 0x?? 0x00 0x00

i.e. header, data byte, data byte, terminator, terminator and expects an ACK of 0xF5.

Obviously it wouldn't be hard to write a basic routine to

  • read the first byte received
  • if it is 0xEE read the next four bytes and ensure the last two are 0x00 then deal with the payload bytes
  • if the first byte is 0xF5 treat it as an ACK and continue

However, that'll clearly only work well if nothing goes wrong and things don't get out of sequence or data corrupted, etc. I'm wondering how to deal with errors such as only receiving two bytes and not locking up the interface waiting for the rest of the message, etc.

I'm guessing this is a fairly standard requirement and there are tried and tested methods of dealing with it but I'm having trouble finding any resources. The main difficulty is probably terminology, I'm not sure what I'm looking for. Searching for UART and 'control packets' leads to any number of articles about how the async serial protocol works.

My requirement isn't high bandwidth, the existing device is configured for 115,200 baud and a couple of control packets per second would be a busy period (although they do tend to come in batches of three or four).

If anyone could point me towards the right terminology and / or resources I'd greatly appreciate it.

Tommy

6 REPLIES 6

So perhaps state machines, and resync of serial data stream.

Self synchronizing packet formats or codes.

Syncword.

If you buffer the data you can look for the pattern later in the stream without discarding too much data as you attempt to resynchronize.

You can use timeouts, or data symbols to determine an error or loss of sync has occurred.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
prain
Senior III

you can make use of uart idle line detection interrupt to synch with transmitter. enable idle line detection interrupt, in ISR reset the receive state machine to beginning of new packet.

TGilc.1
Associate II

Thanks both, that's really helped me make progress.

State machine plus idle line detection seems to be the way to go.

One question about idle line detection though, I've started looking at MaJerle's git repository for examples of how to do this as it seems to be the go-to reference for this sort of thing. However, it mentions that not all STM32s have idle line detection functionality.

How can I check which models have this capability? I've checked multiple datasheets but none seem to list it as a feature although I'm undoubtedly looking for either the wrong thing or in the wrong place.

Tommy

Not clear which STM32 you're using or plan to use.

Avoid the F1, it is very old, and many of the lessons learned from that were applied to later models. L1, F2, F3, F4 all rather old designs.

Depends a lot on the horse power you need, but the L4, G4 and L0 would be better entries.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Usart peripheral have different features in each family. check the reference manual of intended MCU, under usart section there is a subsection named features. check there.

Jack Peacock_2
Senior III

For a more formal view of your question you might look at the RTU protocol for Modbus. It has the same general type of model, how to reliably transmit a binary message in a potentially noisy environment.

Conceptually you need to "frame" your message with some type of identifiable pattern that doesn't depend on just a prefix character, since your data payload may also include the same character. Modbus RTU handles this by specifying a minimum inter-message gap time, and a maximum inter-character gap time within the message (obviously less than inter-message gap time).

Later models of the STM32 incorporate a programmable idle timer in the USART for just this purpose. The idle timeout signals the inter-message gap timing has been met so the start of a new message occurs when the first character arrives. In this case you can reliably check the message prefix for an ACK/NACK or start of a data payload. The double 0x00 bytes at the end of the fixed length message act as end of frame, where the RX idle timer interrupt is restarted.

If the received data contains any type of error (parity, overflow, framing) then assume the entire frame is unreliable and treat it as a NACK, followed by waiting on a new start of message gap. Your protocol must be robust in that it handles automatic retry if no ACK/NACK is received, otherwise you have no way to recover message sequencing if data is lost.

Older STM32s can use a programmable timer in place of the RX idle timeout.

Jack Peacock