Arranging data packet between micros for optimal speed

Started by mik3ca 6 years ago5 replieslatest reply 6 years ago78 views

Ok, I managed to get the microcontrollers (AT89LP52 and AT89S52) to execute code, but now I need a way to optimize my data flow.

I have one controller setup as a server, and I currently have one client but this will expand to 24 clients.

Currently the server sends out fixed-size data over a half-duplex wireless network to each client at 56kbps in the following format:

Byte 1: Recipient
Byte 2: Sender
Bytes 3-10: Data
Byte 11: Checksum value of all of the above

Each client is assigned a fixed number from 1 to 24 and is setup to ignore full packets not belonging to it.

For example, if server sends the following (assume 77h is the valid checksum value):

01h 21h 00h 00h 00h 00h 11h 11h 11h 11h 77h

Then clients 2 to 23 must ignore the packet. since the first byte represents client 1.

But all clients must know at minimum who the next packet being sent out belongs to. Now if I wasn't interested in any data validation, then I would not send or detect checksum values, plus I could make my microcontroller shut off its receiver for the remaining bytes in the packet, but I can't because the checksum needs to be validated to determine the packet is legit (even if part of it is of interest) and that someone isn't messing with the network.

I can't crunch down the 8-byte data space in the packet if the server sends the packet to the client that expects to receive it. Also, the client makes a response of the same data length.

The point I'm getting at with all of this is that I want to reduce the number of times the serial interrupt is unnecessarily accessed.

Only thing I could think of is adding an extra checksum field right after the second packet byte (before data begins) but wouldn't that be overkill? a wasted byte just for an empty-ish packet?

Any suggestions on what I can do?

[ - ]
Reply by Bob11January 12, 2019

With an 8-bit (byte) protocol there's really no robust way to get around needing to service every byte in the interrupt routine. Of course you don't have to pass the bytes on to the rest of the code, but you still need to scan for the start and end of message blocks to ensure you remain in / recapture sync.

The traditional UART way to avoid having to service messages not intended for a particular client is to use 9-bit data framing. Many UARTs support that mode. In 9-bit framing a ninth bit in the packet accompanies an 8-bit client address. If that bit is set and the client address doesn't match, the remaining byte transfers (those with the ninth bit cleared) can be ignored. Hardware that supports 9-bit data framing almost always includes a way to tell the UART to discard data bytes and only interrupt when an address packet arrives. I believe the processors you mention support that mode. You may want to look into it.

[ - ]
Reply by mik3caJanuary 12, 2019

I have, but the problem is I'm doing wireless transfer through UART with an HM-TRP radio module and it only supports the 8-N-1 data format

[ - ]
Reply by matthewbarrJanuary 12, 2019

It sounds like your protocol really only needs one address, the client address. You would need sender and recipient if you wanted to support client-to-client communications, which it sounds like you don't. Five bits is sufficient to hold the client address. The server could send a request with bit 7 clear and the client address in bits 4:0. The client could respond with bit 7 set and its address again in bits 4:0. You can now distinguish a request from the server vs. a response from one of the clients, and you always know the addressed or responding client. This address byte replaces your recipient and sender bytes. Bits 6:5 are unused, reserved for future use. Your packet is down to 10 bytes with just two bytes beyond the data payload, one for address and one for checksum.

Having address 0 invalid by definition allows the client to reject any packet whose first byte does not have bit 7 clear and does not contain a valid non-zero slave address in the range 1-24. Likewise in the master, except bit 7 must be set. This rules out accidentally trying to make a message out of an all 0's or all 1's first byte. If you think you are highly unlikely to change this protocol, you could further harden first byte error detection by having the server send 010 in address bits 7:5, and the client respond with 101. Now there is one and only one 8 bit pattern that each client would recognize as a valid address byte. Likewise for the server, assuming it is looking for a response from a specific client.

With a binary data payload and checksum there is always the possibility that the first byte of a valid message appears elsewhere in the packet. Without something like COBS or a 9th bit to uniquely identify start/end of message, you're pretty much stuck with a scheme like detecting gaps in transmission ala MODBUS to reject false start of packet in error situations. Absence of a gap and "not my packet" could be your criteria for dumping RX bytes and quickly exiting the interrupt. A gap tells you to start looking for the first byte of a new packet.

Revisiting your nomenclature...

Normally a request is made from a client to a server, a typical web server has many clients making requests to it. A client initiates communication, the server responds, exactly opposite of your "server" and "client" nomenclature.

At the risk of upsetting the PC crowd and social justice warriors everywhere, the tried and true master/slave nomenclature as defined in the MODBUS model is probably more appropriate for your system. Messages contain a slave address, the master always initiates communication (request) and the addressed slave responds.

[ - ]
Reply by BVRameshJanuary 12, 2019

Dear Mik,

You can club first two bytes as follows:

1 byte low 5 bits: Present Recipient
1 byte high 3 bits & 2 byte low 2 bits: Next Recipient, (0 if nobody)
2 byte high 5 bits Sender.

With this you can use the highest bit of second byte o indicate some thing logiclaly.

This is the best I can think off.

In the receiver side you can decipher first two bytes and then wait for present packet if it is yours, ignore and if next packet is yours wait for next packet, and keep quite if none of them is yours.

Best Regards,

BV Ramesh.

[ - ]
Reply by msimunicJanuary 12, 2019

Hi mik3ca,

Which type of physical layer is used in your network? ie. RS-485, UART serial, CAN, etc.

It's is some kind of multi-drop network. I can assume it's RS-485. In that case microcontroller is communicating using UART (USART) interface.

1) If physical layer interface (ie. UART) doesn't support addressing in hardware or better say addressing in physical layer then you must receive whole data package (or frame) and decide in software what to do whit it.

1.a.) I think that it's possible to temporarily disable physical layer interface or disable interrupts from that interface but (could be) dangerous (In means of loosing data and synchronicity).

1.b.) Interrupt service routine should be as short as possible. Just receive one byte, store it to the buffer and set a flag to notice byte received. Update byte count in a frame. In ISR you can check if it's first byte and if recipient address is your address. set flag if that frame is yours or not. If not, ignore rest of received bytes in that frame - but you MUST enter in ISR for each byte.

1.c.) May be using DMA would be useful to speed things up, but maybe it wouldn't. It depends on architecture of AT89xxxx, which I'm not familiar.

1. d.) For that mater It would help to have some kind of start/end package (frame) notifiers ie. high nibble in first byte or better first byte with defined value, some special character. Try to find character aout of your data range - if possible.

In order to achieve correct operation you should combine all of a), b,) c), d) and maybe something more.

2)  Use physical bus which supports addressing in physical layer ie. CAN