EmbeddedRelated.com
Forums

Two-wires RS485 and the driver enable problem

Started by pozzugno October 13, 2014
On Mon, 13 Oct 2014 22:02:33 +0300, upsidedown@downunder.com wrote:

>You must be quite desperate, if you intend to use 1x550 style chips on >RS-485 :-). That chip family is useless for any high speed half duplex >communication. > >You can get an interrupt when you load the last character into the Tx >shift register, but you can't get an interrupt, when the last bit of >the last character is actually shifted out of the Tx shift register. > >In real word, some high priority code will have to poll, when the last >bit of your transmission has actually sent the last stop bit of your >last byte into the line.
An other way of dealing with '550 style UARTs on RS-485 is to use a driver chip that doesn't disable the receiver during your own transmit. Thus the UART Rx pin will hear your transmission and the Rx ISR can do "echo canceling" by monitoring your own transmission. As soon as the Rx interrupt hears your complete final transmitted byte, the Rx ISR can turn off the transmit enable (RTS) and change the Rx mode from echo canceling to normal Rx mode. This makes it possible to do all things in the ISR and you don't have to do anything in normal code (with potentially bad latencies in some OS).
On 15/10/14 08:00, rickman wrote:
> On 10/14/2014 5:35 PM, David Brown wrote: >> On 14/10/14 20:20, rickman wrote: >>> On 10/14/2014 12:58 PM, Dave Nadler wrote: >>>> On Monday, October 13, 2014 9:02:33 PM UTC+2, upsid...@downunder.com >>>> wrote: >>>>> ...you can't get an interrupt, when the last bit of >>>>> the last character is actually shifted out of the Tx shift register. >>>> >>>> Sure you can, just append N dummy TX bytes where "N" is the TX FIFO >>>> depth. >>>> >>>> But check it on the scope!! >>> >>> That is a very dangerous way to control the driver enable. Most likely >>> the interrupt will happen when the start bit is sent which means the >>> output will already be sending the start bit when the driver is >>> disabled. >>> >> >> It can often work fine - at worst, the receiver sees a brief noise at >> the end of the telegram itself, and that is easily ignored. >> >> However, if you are worried that the "transmission complete" interrupt >> might be delayed too long, then clearly the same thing will apply to the >> final "transmit character" interrupt for your extra character. So it is >> a useful trick if you don't have a "transmission complete" interrupt >> signal, but not for the problem at hand here. > > Is all of this based on the idea that the transmitter empty interrupt is > not valid in some way? >
No, my point was that Dave's suggestion of sending an extra byte is not "very dangerous" as you suggest, and can be a useful trick. It is not needed here as the OP has a "transmission complete" interrupt which triggers when the final send is complete. Many other microcontrollers and UARTs don't have a suitable interrupt on the final character (or have flaws with it, such as an interrupt that triggers at the start of the stop bit - turning off the driver at that point can cause hard-to-trace problems). For such micros, sending an extra byte can be a good solution. But as far as I can remember (it's a long time since I used an AVR), the AVR's "transmission complete" interrupt works fine.
On Wed, 15 Oct 2014 02:00:20 -0400, rickman <gnuarm@gmail.com> wrote:

>On 10/14/2014 5:35 PM, David Brown wrote: >> On 14/10/14 20:20, rickman wrote: >>> On 10/14/2014 12:58 PM, Dave Nadler wrote: >>>> On Monday, October 13, 2014 9:02:33 PM UTC+2, upsid...@downunder.com >>>> wrote: >>>>> ...you can't get an interrupt, when the last bit of >>>>> the last character is actually shifted out of the Tx shift register. >>>> >>>> Sure you can, just append N dummy TX bytes where "N" is the TX FIFO >>>> depth. >>>> >>>> But check it on the scope!! >>> >>> That is a very dangerous way to control the driver enable. Most likely >>> the interrupt will happen when the start bit is sent which means the >>> output will already be sending the start bit when the driver is disabled. >>> >> >> It can often work fine - at worst, the receiver sees a brief noise at >> the end of the telegram itself, and that is easily ignored. >> >> However, if you are worried that the "transmission complete" interrupt >> might be delayed too long, then clearly the same thing will apply to the >> final "transmit character" interrupt for your extra character. So it is >> a useful trick if you don't have a "transmission complete" interrupt >> signal, but not for the problem at hand here. > >Is all of this based on the idea that the transmitter empty interrupt is >not valid in some way?
Please tell us, how to get transmitter [shift register] empty interrupt on the '550 style UARTs ? You can get last byte loaded into the transmit SR interrupt, but you need to poll some status bits to know, when the last byte has been shifted out of the SR. There has been claims that dropping the SR empty status at the end of last bit but before the stop bit(s) might be a problem, However, with standard "fail-safe" termination, the line is in the idle state during the stop bit times anyway. Turning the transmitter a few bit times too late is usually not a problem, except for extremely low line rates. A character delay can be catastrophic, if the other station responds rapidly. In practice (I have seen several examples) is the stupid implementation in many devices, in which the designer relies on the "last byte moved to the SR" interrupt and prematurely turns off the transmitter and the line floats to the idle "1" state. Since the UART sends LSB bits first, the premature Tx disable will set the MSB bit(s) to 1, so 0x0? is received as 0x8?, 0xC?, 0xE?, 0xF? of even as 0xFF. Since many protocols put BCC/CRC into the last byte, the received and calculated value differ by those high bits, which is a clear sign of premature Tx disabling. This problem becomes worse as the line speed is dropped. Some devices can't be used below 9600 bit/s rates due to this problem.
On 2014-10-15, rickman <gnuarm@gmail.com> wrote:
> On 10/14/2014 5:35 PM, David Brown wrote: > >> It can often work fine - at worst, the receiver sees a brief noise at >> the end of the telegram itself, and that is easily ignored. >> >> However, if you are worried that the "transmission complete" interrupt >> might be delayed too long, then clearly the same thing will apply to the >> final "transmit character" interrupt for your extra character. So it is >> a useful trick if you don't have a "transmission complete" interrupt >> signal, but not for the problem at hand here. > > Is all of this based on the idea that the transmitter empty interrupt is > not valid in some way?
We're talking about a 16550. There _is_no_ transmitter empty interrupt. There is a transmit holding register empty interrupt, but that happens _before_ transmission of the last byte has begun. There is a transmit shift register empty status bit (no interrupt). In my experience that status bit isn't reliable either and on some implementations goes active before the final stop bit has been sent. -- Grant Edwards grant.b.edwards Yow! Used staples are good at with SOY SAUCE! gmail.com
On 2014-10-15, upsidedown@downunder.com <upsidedown@downunder.com> wrote:

> An other way of dealing with '550 style UARTs on RS-485 is to use a > driver chip that doesn't disable the receiver during your own > transmit. Thus the UART Rx pin will hear your transmission and the Rx > ISR can do "echo canceling" by monitoring your own transmission. As > soon as the Rx interrupt hears your complete final transmitted byte, > the Rx ISR can turn off the transmit enable (RTS) and change the Rx > mode from echo canceling to normal Rx mode. > > This makes it possible to do all things in the ISR and you don't have > to do anything in normal code (with potentially bad latencies in some > OS).
That works, but you have to disable the RX FIFO so that you get notified of RX bytes immediatly. -- Grant Edwards grant.b.edwards Yow! Everybody is going at somewhere!! It's probably gmail.com a garage sale or a disaster Movie!!
On 10/15/2014 10:24 AM, Grant Edwards wrote:
> On 2014-10-15, rickman <gnuarm@gmail.com> wrote: >> On 10/14/2014 5:35 PM, David Brown wrote: >> >>> It can often work fine - at worst, the receiver sees a brief noise at >>> the end of the telegram itself, and that is easily ignored. >>> >>> However, if you are worried that the "transmission complete" interrupt >>> might be delayed too long, then clearly the same thing will apply to the >>> final "transmit character" interrupt for your extra character. So it is >>> a useful trick if you don't have a "transmission complete" interrupt >>> signal, but not for the problem at hand here. >> >> Is all of this based on the idea that the transmitter empty interrupt is >> not valid in some way? > > We're talking about a 16550. There _is_no_ transmitter empty > interrupt. There is a transmit holding register empty interrupt, but > that happens _before_ transmission of the last byte has begun.
I don't know who "we" is, but the OP never said what UART he is using. I had the impression it was a UART within an MCU from his initial post where he refers to "some microcontrollers" toggling an output. Did he say he is using a '550' type UART? -- Rick
On 10/15/2014 3:47 AM, David Brown wrote:
> On 15/10/14 08:00, rickman wrote: >> On 10/14/2014 5:35 PM, David Brown wrote: >>> On 14/10/14 20:20, rickman wrote: >>>> On 10/14/2014 12:58 PM, Dave Nadler wrote: >>>>> On Monday, October 13, 2014 9:02:33 PM UTC+2, upsid...@downunder.com >>>>> wrote: >>>>>> ...you can't get an interrupt, when the last bit of >>>>>> the last character is actually shifted out of the Tx shift register. >>>>> >>>>> Sure you can, just append N dummy TX bytes where "N" is the TX FIFO >>>>> depth. >>>>> >>>>> But check it on the scope!! >>>> >>>> That is a very dangerous way to control the driver enable. Most likely >>>> the interrupt will happen when the start bit is sent which means the >>>> output will already be sending the start bit when the driver is >>>> disabled. >>>> >>> >>> It can often work fine - at worst, the receiver sees a brief noise at >>> the end of the telegram itself, and that is easily ignored. >>> >>> However, if you are worried that the "transmission complete" interrupt >>> might be delayed too long, then clearly the same thing will apply to the >>> final "transmit character" interrupt for your extra character. So it is >>> a useful trick if you don't have a "transmission complete" interrupt >>> signal, but not for the problem at hand here. >> >> Is all of this based on the idea that the transmitter empty interrupt is >> not valid in some way? >> > > No, my point was that Dave's suggestion of sending an extra byte is not > "very dangerous" as you suggest, and can be a useful trick. It is not > needed here as the OP has a "transmission complete" interrupt which > triggers when the final send is complete. Many other microcontrollers > and UARTs don't have a suitable interrupt on the final character (or > have flaws with it, such as an interrupt that triggers at the start of > the stop bit - turning off the driver at that point can cause > hard-to-trace problems). For such micros, sending an extra byte can be > a good solution.
I just don't know that putting the glitch on the bus is a good idea. Minimizing the glitch depends on a fast response to the interrupt which is most of what this thread has been discussing. A slow response puts a larger glitch on the bus. Personally I prefer to use hardware which is designed for the job and will handle the driver enable properly. -- Rick
Il 16/10/2014 07:17, rickman ha scritto:
> On 10/15/2014 10:24 AM, Grant Edwards wrote: >> On 2014-10-15, rickman <gnuarm@gmail.com> wrote: >>> On 10/14/2014 5:35 PM, David Brown wrote: >>> >>>> It can often work fine - at worst, the receiver sees a brief noise at >>>> the end of the telegram itself, and that is easily ignored. >>>> >>>> However, if you are worried that the "transmission complete" interrupt >>>> might be delayed too long, then clearly the same thing will apply to >>>> the >>>> final "transmit character" interrupt for your extra character. So >>>> it is >>>> a useful trick if you don't have a "transmission complete" interrupt >>>> signal, but not for the problem at hand here. >>> >>> Is all of this based on the idea that the transmitter empty interrupt is >>> not valid in some way? >> >> We're talking about a 16550. There _is_no_ transmitter empty >> interrupt. There is a transmit holding register empty interrupt, but >> that happens _before_ transmission of the last byte has begun. > > I don't know who "we" is, but the OP never said what UART he is using. I > had the impression it was a UART within an MCU from his initial post > where he refers to "some microcontrollers" toggling an output. Did he > say he is using a '550' type UART?
Yes, I'm using a UART peripheral integrated in microcontrollers, like PICs from Microchip or AVRs from Atmel.
Il 13/10/2014 17:20, Grant Edwards ha scritto:
> On 2014-10-13, pozzugno <pozzugno@gmail.com> wrote: > >> If a node on the bus is very fast and starts transmitting (the master) >> or answering (one slave) immediately after receving the last byte, but >> when the previous transmitting node is executing other ISRs, the final >> result is a corrupted transmission. >> >> What is the solution? I think the only solution is to define, at the >> design time, a minimum interval between the receiving of the last byte >> from one node and the transmission of the first byte. > > Or put a some disposable preamble bytes on the front of messages. This > is pretty common when using half-duplex modems: the padding bytes give > the modems time to "turn-around" and get carrier established, PLLs > locked, etc.
I was thinking about your suggestions, but it seems to me it doesn't work well. Others suggested to send some dummy bytes, keeping the RS485 driver *disabled*. Only after those bytes are really shifted out, the driver could be enabled. In other words, you use the UART hardware also for timing, without the need to use other peripherals (such as timers/counters). Your suggestion seems better: send some sync bytes at the beginning, with the RS485 driver *enabled*. My protocol can be used with this approach, because it is inspired to HDLC. Every frame starts and ends with a sync byte. If the sync byte appears in the payload data, it is escaped (as in HDLC or SLIP protocols). The device could send N sync bytes without problems. The receiver will see N empty frames and will discard them silently. In this way it's even more simple to introduce a delay before the answer. But I think it doesn't work. Bytes are send asyncronously and the receiver must syncronize to the start bit of each byte. If the slave sends 2 sync bytes in the front of each frame, without a delay, and the master toggles direction in the middle of the two sync bytes, the master will receive one or two wrong bytes or detect frame errors, depending on the precise time and transitions pattern. Moreover, if the payload is transmitted immediately after sync bytes, as really happens, the overall frame could be corrupted. *Perhaps* this technique works well only if the preamble bytes are 0xFF, because they appears on the wire just as a single start bit (all the other bits, including stop bits, are at the idle level). --- ------------------ ------------------ -......... | | PREAMBLE | | PREAMBLE | | START OF FRAME | | 0xFF | | 0xFF | | ---- ---- ---- ^ ^ ^ A B C If the master toggles direction at time A, it will receive the two preamble bytes correctly and could discard them. The frame is received correctly. If it toggles direction at time C, it will receive only one preamble byte correctly and could discard it. The frame is received correctly. What happens it the master toggles direction at time B, in the middle of a start bit? I don't know if the UART detects a start bit on the high-to-low edge or on the low level. In the first case, I think there's no problem. In the second case, what happens?
On 16.10.14 10:01, pozzugno wrote:

> *Perhaps* this technique works well only if the preamble bytes are 0xFF, > because they appears on the wire just as a single start bit (all the > other bits, including stop bits, are at the idle level). > > --- ------------------ ------------------ -......... > | | PREAMBLE | | PREAMBLE | | START OF FRAME > | | 0xFF | | 0xFF | | > ---- ---- ---- > ^ ^ ^ > A B C
It does - I have been using it for years (20+) in several different RS-485 links. You need also a reliable way of recognizing frame boundaries, to get the framing right. I'm using an encapsulation similar to PPP (RFC1662) which also gives the possibility to exclude the preamble bytes from valid frame data. -- Tauno Voipio