Reply by chris June 2, 20132013-06-02
On 05/30/13 21:59, pozz wrote:

> > Other suggestions?
I wrote code for a project (Traffic led signs) that used rs485, half duplex at 9600 bauds. The protocol had been designed years ago, used stx / etx frame delimiters and had a crc included to detect errors. It too was master slave and comms was only ever initiated by the master. It was fully interrupt driven with fifo buffers for both tx and rx. Each slave has a unique address, but there was also a broadcast facility, with no reply, for things like clear display, usually followed by round robin status enquiry to check all that all the slaves had received the broadcast. The low level code was classic lower half interrupt handler, with upper half called from the application code and fifo buffers in between. For portability, the lower layers were designed to be transparent to data. That is, everything received went into the fifo and the protocol decode handled by the layers above. There is a module with a set of functions to control the uarts and another module to do protocol decode etc, which is just a simple state machine. The top level calls functions in the fifo module that search for frame delimiters and if found, the frame is handed over to the protocol handler. There was no real time exec on this project, and the mainloop is a state machine that scans the two rs485 interfaces for traffic, then calls a command processor when a valid frame is received. While there is quite a bit of traffic on the interfaces, the frames are short and quite small buffers (512 bytes rx, less for tx) were found to be more than enough. There are up to 12 slave nodes in a system, so 11 out of 12 frames may be discarded by any slave, but the system had more than enough performance, even when output of display data was via software. Modern micros are very fast :-)... Regards, Chris
Reply by Grant Edwards May 31, 20132013-05-31
On 2013-05-30, pozz <pozzugno@gmail.com> wrote:
> Il 29/05/2013 09:02, upsidedown@downunder.com ha scritto: > > > > [...] > > >> If the slave address is corrupted producing an (incorrect) address >> match, the whole message will be processed, but any higher level >> routine would reject the message due to CRC error. > > Do you think it's better to discard a packet with a bad CRC or to answer > with a "bad CRC" message to the master? In the latter scenario, the > retransmission is speeded up (the master will not wait for the timeout), > but I'm in doubt if it is correct to answer to a corrupted packet (even > the destination address could be wrong).
If the CRC is bad, you don't know the address is valid. If you don't know the address is valid, how do you know which unit should respond? -- Grant Edwards grant.b.edwards Yow! Thousands of days of at civilians ... have produced gmail.com a ... feeling for the aesthetic modules --
Reply by May 31, 20132013-05-31
On Thu, 30 May 2013 23:59:38 +0200, pozz <pozzugno@gmail.com> wrote:

>I have just one problem with this implementation: there are some >messages or destionation addresses (broadcast addresses) that doesn't >want any answer from the slaves. >The master could send a new packet just after a broadcast packet: >there's no need to wait for some time if no answer will be received. > >In this case my implementation doesn't work, because I stop receiving at >the end of the first packet until the CPU will process it. There's a >concrete risk some bytes of the second packet will be lost. > >One solution is to delay the transmission of a packet after one packet >that doesn't want an answer. I don't like this solution, the delay >depends on the speed of the slaves (if they are supercomputers or >smallish 8-bit microcontrollers).
What do you intend to use those broadcasts ? Of course it is nice for clock synchronization, but what else in practice ? For clock setting/synchronization, the master should cease communication for a while, in order to any buffered traffic has died out, then generate the time message from master clock. This message will then go immediately for transmission and can be handled immediately by the slaves at the frame (no messages in the FIFO), thus, there is a well defined time difference between the master and slave clocks and hence easily correctable. Sending an unspecified broadcast messages back to back is a bad idea, since even a device with large buffers but slow responses might overflow. For this reason, silent gaps should be added around broadcast frames. if you insist to use broadcasts with both fast and slow devices, instead of one broadcast address, Why not use several multicast addresses for slaves with small buffers, but fast processing time, one for small buffers with long processing time and one for huge buffers slow processing time etc. Anyway, I do not see the point of using the same protocol for short messages with short response times and big computer with large transfer requirements on the same RS-485 bus. It might be a better idea to let the big slaves communicate directly over ethernet and install some eth/RS485 converters for the smaller devices.
Reply by Stef May 31, 20132013-05-31
In comp.arch.embedded,
pozz <pozzugno@gmail.com> wrote:
> > I have just one problem with this implementation: there are some > messages or destionation addresses (broadcast addresses) that doesn't > want any answer from the slaves. > The master could send a new packet just after a broadcast packet: > there's no need to wait for some time if no answer will be received. > > In this case my implementation doesn't work, because I stop receiving at > the end of the first packet until the CPU will process it. There's a > concrete risk some bytes of the second packet will be lost. > > One solution is to delay the transmission of a packet after one packet > that doesn't want an answer. I don't like this solution, the delay > depends on the speed of the slaves (if they are supercomputers or > smallish 8-bit microcontrollers). > > So I'm thinking to change my implementation and move from a simple > buffer/array to a more complex FIFO/array, without stopping anymore the > rx interrupt at the end of a packet for us (a second packet could appear > immediately after). However, this new approach brings other problems > with it. > > Now the packets are pushed in the FIFO one after the other, so I loose > the separation between them (remember that SLIP decoding is performed in > the ISR, because I have to check the destination address to discard > packets that are for other slaves). In other words, I loose the packet > length info. > One solution is to add a new byte at the beginning of the packet that is > the packet length in bytes. I don't like it, because I'm solving a > problem related to the physical layer modifying the upper MAC layer. > But it's just a philosophical argument. > > With this FIFO/array implementation, a single packet could be stored in > part at the end and in part at the beginning of the FIFO/array. So I > need a new array where to copy all the bytes of the packet in order, > starting from the first. The memory/RAM requirements increase respect > the buffer/array implementation. > > > Other suggestions?
Instead of inserting a length character in the buffer, you can build a FIFO of receive buffers, each with it's length and other info. If the processing is guaranteed to be shorter than the transmission time of the next message, a simple 'flip buffer' will work. Just have two receive buffers with an RxCount and 'ready' status. On reception of a complete and OK message, set the lenght, mark 'ready' and start filling the next buffer while your application processes the just received message. -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) To generalize is to be an idiot. -- William Blake
Reply by srl100 May 31, 20132013-05-31
>Il 29/05/2013 09:02, upsidedown@downunder.com ha scritto: >My implementation uses an array buf[] to store the packet, starting from >buf[0]. The SLIP decoding is performed inside the ISR thanks to a >simple state machine. If the first byte of the packet (destination >address) matches the slave address, the remaining bytes of the packet >are saved in the buffer, otherwise they are discarded and the buffer >pointer reset. > >When the END character is received during reception of a packet for us, >the rx interrupt is disabled to let the CPU process it. After >transmitting the answer, the interrupt is enabled again and buffer >pointer reset. > >I have just one problem with this implementation: there are some >messages or destionation addresses (broadcast addresses) that doesn't >want any answer from the slaves. >The master could send a new packet just after a broadcast packet: >there's no need to wait for some time if no answer will be received. > >In this case my implementation doesn't work, because I stop receiving at >the end of the first packet until the CPU will process it. There's a >concrete risk some bytes of the second packet will be lost. > >One solution is to delay the transmission of a packet after one packet >that doesn't want an answer. I don't like this solution, the delay >depends on the speed of the slaves (if they are supercomputers or >smallish 8-bit microcontrollers). > >So I'm thinking to change my implementation and move from a simple >buffer/array to a more complex FIFO/array, without stopping anymore the >rx interrupt at the end of a packet for us (a second packet could appear >immediately after). However, this new approach brings other problems >with it. > >Now the packets are pushed in the FIFO one after the other, so I loose >the separation between them (remember that SLIP decoding is performed in >the ISR, because I have to check the destination address to discard >packets that are for other slaves). In other words, I loose the packet >length info. >One solution is to add a new byte at the beginning of the packet that is >the packet length in bytes. I don't like it, because I'm solving a >problem related to the physical layer modifying the upper MAC layer. >But it's just a philosophical argument.
How about using a ring buffer to store the decoded packet data (what you are calling your FIFO) but have a separate FIFO to carry the details for each received message - i.e. at the end of your RX ISR you push the last byte of the message into the 'data' ring buffer and then push {pointer, length} onto the 'control' FIFO. Of course, you will have to protect the ring buffer from overflow. --------------------------------------- Posted through http://www.EmbeddedRelated.com
Reply by May 31, 20132013-05-31
On Thu, 30 May 2013 23:59:38 +0200, pozz <pozzugno@gmail.com> wrote:

>Il 29/05/2013 09:02, upsidedown@downunder.com ha scritto: > > > > [...] > > >> If the slave address is corrupted producing an (incorrect) address >> match, the whole message will be processed, but any higher level >> routine would reject the message due to CRC error. > >Do you think it's better to discard a packet with a bad CRC or to answer >with a "bad CRC" message to the master? In the latter scenario, the >retransmission is speeded up (the master will not wait for the timeout), >but I'm in doubt if it is correct to answer to a corrupted packet (even >the destination address could be wrong). >
Unless you have a separate CRC for the header, responding to a message with overall CRC, could cause quite a lot of problems. If the master and slave(s) are out of synch for some reason, having a timeout is a good thing, during the silent period every device will end into a known state.
Reply by hamilton May 30, 20132013-05-30
On 5/30/2013 3:59 PM, pozz wrote:
> Il 29/05/2013 09:02, upsidedown@downunder.com ha scritto: > > > > [...] > > >> If the slave address is corrupted producing an (incorrect) address >> match, the whole message will be processed, but any higher level >> routine would reject the message due to CRC error. > > Do you think it's better to discard a packet with a bad CRC or to answer > with a "bad CRC" message to the master?
If you have three slaves and one master. Which of the three slaves should answer "bad CRC" ? If you have a bad address but a good CRC who should answer ? Any COMM error is just left on the floor, ignore it. In the latter scenario, the
> retransmission is speeded up (the master will not wait for the timeout), > but I'm in doubt if it is correct to answer to a corrupted packet (even > the destination address could be wrong). > > >> However, if the message was addressed to you, but slave address >> corruption cause the message to be skipped, the master will not get a >> response and after timeout resends the request. > > Ok, I was trying to implement this kind of protocol. > > Every packet is encapsulated in a SLIP frame (RFC1055). The last byte > 0xC0 marks the END of the frame. If END character appears inside the > packet, it is escaped with the 2-bytes sequence ESC (0xDB) ESC_END > (0xDC). Of course, even ESC character in the payload is escaped with > the 2-bytes sequence ESC (0xDB) ESC_ESC (0xDD). To improve reliability, > END character is transmitted as the first byte of the frame too (see RFC). > In this way, the length of the packet is intrinsic in the frame > transmission and there's no need to put this info inside the packet data. > > The packet syntax is: > DD SS dd ... dd CC > where DD is the destination address, SS is the source address, dd is the > variable-length field of data and CC is the checksum. > > My implementation uses an array buf[] to store the packet, starting from > buf[0]. The SLIP decoding is performed inside the ISR thanks to a > simple state machine. If the first byte of the packet (destination > address) matches the slave address, the remaining bytes of the packet > are saved in the buffer, otherwise they are discarded and the buffer > pointer reset. > > When the END character is received during reception of a packet for us, > the rx interrupt is disabled to let the CPU process it. After > transmitting the answer, the interrupt is enabled again and buffer > pointer reset. > > I have just one problem with this implementation: there are some > messages or destionation addresses (broadcast addresses) that doesn't > want any answer from the slaves. > The master could send a new packet just after a broadcast packet: > there's no need to wait for some time if no answer will be received. > > In this case my implementation doesn't work, because I stop receiving at > the end of the first packet until the CPU will process it. There's a > concrete risk some bytes of the second packet will be lost. > > One solution is to delay the transmission of a packet after one packet > that doesn't want an answer. I don't like this solution, the delay > depends on the speed of the slaves (if they are supercomputers or > smallish 8-bit microcontrollers). > > So I'm thinking to change my implementation and move from a simple > buffer/array to a more complex FIFO/array, without stopping anymore the > rx interrupt at the end of a packet for us (a second packet could appear > immediately after). However, this new approach brings other problems > with it. > > Now the packets are pushed in the FIFO one after the other, so I loose > the separation between them (remember that SLIP decoding is performed in > the ISR, because I have to check the destination address to discard > packets that are for other slaves). In other words, I loose the packet > length info. > One solution is to add a new byte at the beginning of the packet that is > the packet length in bytes. I don't like it, because I'm solving a > problem related to the physical layer modifying the upper MAC layer. But > it's just a philosophical argument. > > With this FIFO/array implementation, a single packet could be stored in > part at the end and in part at the beginning of the FIFO/array. So I > need a new array where to copy all the bytes of the packet in order, > starting from the first. The memory/RAM requirements increase respect > the buffer/array implementation. > > > Other suggestions?
Reply by pozz May 30, 20132013-05-30
Il 29/05/2013 09:02, upsidedown@downunder.com ha scritto:
 >
 > [...]
 >
> If the slave address is corrupted producing an (incorrect) address > match, the whole message will be processed, but any higher level > routine would reject the message due to CRC error.
Do you think it's better to discard a packet with a bad CRC or to answer with a "bad CRC" message to the master? In the latter scenario, the retransmission is speeded up (the master will not wait for the timeout), but I'm in doubt if it is correct to answer to a corrupted packet (even the destination address could be wrong).
> However, if the message was addressed to you, but slave address > corruption cause the message to be skipped, the master will not get a > response and after timeout resends the request.
Ok, I was trying to implement this kind of protocol. Every packet is encapsulated in a SLIP frame (RFC1055). The last byte 0xC0 marks the END of the frame. If END character appears inside the packet, it is escaped with the 2-bytes sequence ESC (0xDB) ESC_END (0xDC). Of course, even ESC character in the payload is escaped with the 2-bytes sequence ESC (0xDB) ESC_ESC (0xDD). To improve reliability, END character is transmitted as the first byte of the frame too (see RFC). In this way, the length of the packet is intrinsic in the frame transmission and there's no need to put this info inside the packet data. The packet syntax is: DD SS dd ... dd CC where DD is the destination address, SS is the source address, dd is the variable-length field of data and CC is the checksum. My implementation uses an array buf[] to store the packet, starting from buf[0]. The SLIP decoding is performed inside the ISR thanks to a simple state machine. If the first byte of the packet (destination address) matches the slave address, the remaining bytes of the packet are saved in the buffer, otherwise they are discarded and the buffer pointer reset. When the END character is received during reception of a packet for us, the rx interrupt is disabled to let the CPU process it. After transmitting the answer, the interrupt is enabled again and buffer pointer reset. I have just one problem with this implementation: there are some messages or destionation addresses (broadcast addresses) that doesn't want any answer from the slaves. The master could send a new packet just after a broadcast packet: there's no need to wait for some time if no answer will be received. In this case my implementation doesn't work, because I stop receiving at the end of the first packet until the CPU will process it. There's a concrete risk some bytes of the second packet will be lost. One solution is to delay the transmission of a packet after one packet that doesn't want an answer. I don't like this solution, the delay depends on the speed of the slaves (if they are supercomputers or smallish 8-bit microcontrollers). So I'm thinking to change my implementation and move from a simple buffer/array to a more complex FIFO/array, without stopping anymore the rx interrupt at the end of a packet for us (a second packet could appear immediately after). However, this new approach brings other problems with it. Now the packets are pushed in the FIFO one after the other, so I loose the separation between them (remember that SLIP decoding is performed in the ISR, because I have to check the destination address to discard packets that are for other slaves). In other words, I loose the packet length info. One solution is to add a new byte at the beginning of the packet that is the packet length in bytes. I don't like it, because I'm solving a problem related to the physical layer modifying the upper MAC layer. But it's just a philosophical argument. With this FIFO/array implementation, a single packet could be stored in part at the end and in part at the beginning of the FIFO/array. So I need a new array where to copy all the bytes of the packet in order, starting from the first. The memory/RAM requirements increase respect the buffer/array implementation. Other suggestions?
Reply by hamilton May 29, 20132013-05-29
On 5/29/2013 12:32 AM, pozz wrote:
> Il 29/05/2013 07:50, upsidedown@downunder.com ha scritto: >> On Tue, 28 May 2013 16:19:04 +0200, pozz <pozzugno@gmail.com> wrote: >> >>> Typically the bytes received are stored in a fifo buffer inside the ISR. >>> During main loop, the FIFO is spooled for a new complete packet to >>> decode and process. What is the size of the buffer to avoid missing >>> packets? I can't answer. >> >> Put some more intelligence into the ISR, i.e. a state machine. >> >> As long as the slave address is near the beginning of the address, do >> not put anything into the FIFO until the slave address is received and >> compared. If the message is not for you, enter skip-until-end-of-frame >> state, so all the next received characters in the ISR are ignored, >> until the end-of-frame character is received. >> >> If the message header contains a byte count field, store the count and >> decrement for each received character. When the count drops to zero, >> resume listening for next frame header. >> >> The ISR will require 1-3 bytes statically allocated memory for the >> state machine current state and/or remaining byte count. > > Thank you all for your suggestions. They are very good. > > I have just one problem in this approach. The packets are usually > protected against communication error with a checksum (CRC or similar) > at the end. How could I inspect and process the first bytes of the > packets if I have to receive the CRC yet to convalidate the packet?
If the address is not for me OR the checksum is bad, I will ignore this message. As this is a simplex system, waiting for the last byte to come in is not going to delay anything. At the point of the last byte, you can throw away the packet and start looking for the next. Also, the amount of time processing that last packet, turn on the RS-485 driver, sending the response, with all the other boards in the system is just waiting for the next packet, is dead time for all by the working node. What is the "timeout" time for the correctly addressed node that does not respond ?
> > Should I add a second CRC just for the header that contains address info? >
Reply by Reinhardt Behm May 29, 20132013-05-29
On Wednesday 29 May 2013 08:32 pozz wrote:

> Il 29/05/2013 07:50, upsidedown@downunder.com ha scritto: >> On Tue, 28 May 2013 16:19:04 +0200, pozz <pozzugno@gmail.com> wrote: >> >>> Typically the bytes received are stored in a fifo buffer inside the ISR. >>> During main loop, the FIFO is spooled for a new complete packet to >>> decode and process. What is the size of the buffer to avoid missing >>> packets? I can't answer. >> >> Put some more intelligence into the ISR, i.e. a state machine. >> >> As long as the slave address is near the beginning of the address, do >> not put anything into the FIFO until the slave address is received and >> compared. If the message is not for you, enter skip-until-end-of-frame >> state, so all the next received characters in the ISR are ignored, >> until the end-of-frame character is received. >> >> If the message header contains a byte count field, store the count and >> decrement for each received character. When the count drops to zero, >> resume listening for next frame header. >> >> The ISR will require 1-3 bytes statically allocated memory for the >> state machine current state and/or remaining byte count. > > Thank you all for your suggestions. They are very good. > > I have just one problem in this approach. The packets are usually > protected against communication error with a checksum (CRC or similar) > at the end. How could I inspect and process the first bytes of the > packets if I have to receive the CRC yet to convalidate the packet? > > Should I add a second CRC just for the header that contains address info?
That is not necessary. The only case a receiving error would break that scheme is when the address gets changed and looks like the correct one for this device. You can than continue to "receive" the message and put it into your buffer. If it exceeds the max length you know something must be wrong. Then skip- until-end-of-frame state and proceed as if it is not for you. -- Reinhardt Behm