Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #18575 > unrolled thread
| Started by | pozzugno <pozzugno@gmail.com> |
|---|---|
| First post | 2014-10-13 13:58 +0200 |
| Last post | 2014-10-14 20:44 +0200 |
| Articles | 20 on this page of 66 — 16 participants |
Back to article view | Back to comp.arch.embedded
Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-13 13:58 +0200
Re: Two-wires RS485 and the driver enable problem Wouter van Ooijen <wouter@voti.nl> - 2014-10-13 14:29 +0200
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-13 14:38 +0200
Re: Two-wires RS485 and the driver enable problem Wouter van Ooijen <wouter@voti.nl> - 2014-10-13 15:28 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 07:21 -0700
Re: Two-wires RS485 and the driver enable problem Wouter van Ooijen <wouter@voti.nl> - 2014-10-13 16:46 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 08:02 -0700
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-13 16:59 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 08:08 -0700
Re: Two-wires RS485 and the driver enable problem pozz <pozzugno@gmail.com> - 2014-10-14 07:48 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 23:28 -0700
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-14 09:20 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-14 06:09 -0700
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-14 10:36 +0200
Re: Two-wires RS485 and the driver enable problem Wouter van Ooijen <wouter@voti.nl> - 2014-10-13 18:14 +0200
Re: Two-wires RS485 and the driver enable problem Tim Wescott <seemywebsite@myfooter.really> - 2014-10-13 16:30 -0500
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-13 14:47 +0200
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-13 14:56 +0200
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-13 16:13 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 08:06 -0700
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-14 08:50 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-14 14:34 -0700
Re: Two-wires RS485 and the driver enable problem Richard Damon <Richard@Damon-Family.org> - 2014-10-13 09:11 -0400
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-13 10:53 -0400
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-13 17:03 +0200
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-13 15:20 +0000
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-16 09:01 +0200
Re: Two-wires RS485 and the driver enable problem Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2014-10-16 10:19 +0300
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-16 05:02 -0400
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 08:17 -0700
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 08:19 -0700
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-14 09:28 +0200
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-14 06:09 -0700
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-14 14:28 -0400
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-14 04:36 -0400
Re: Two-wires RS485 and the driver enable problem Les Cargill <lcargill99@comcast.com> - 2014-10-13 12:35 -0500
Re: Two-wires RS485 and the driver enable problem langwadt@fonz.dk - 2014-10-13 15:02 -0700
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 17:36 -0700
Re: Two-wires RS485 and the driver enable problem Les Cargill <lcargill99@comcast.com> - 2014-10-13 21:53 -0500
Re: Two-wires RS485 and the driver enable problem Don Y <this@is.not.me.com> - 2014-10-13 20:24 -0700
Re: Two-wires RS485 and the driver enable problem upsidedown@downunder.com - 2014-10-13 22:02 +0300
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-13 19:09 +0000
Re: Two-wires RS485 and the driver enable problem glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-10-13 20:58 +0000
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-13 21:08 +0000
Re: Two-wires RS485 and the driver enable problem langwadt@fonz.dk - 2014-10-13 14:40 -0700
Re: Two-wires RS485 and the driver enable problem Dave Nadler <drn@nadler.com> - 2014-10-14 09:58 -0700
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-14 14:20 -0400
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-14 23:35 +0200
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-15 02:00 -0400
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-15 09:47 +0200
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-16 01:30 -0400
Re: Two-wires RS485 and the driver enable problem David Brown <david.brown@hesbynett.no> - 2014-10-16 20:46 +0200
Re: Two-wires RS485 and the driver enable problem Dave Nadler <drn@nadler.com> - 2014-10-16 12:00 -0700
Re: Two-wires RS485 and the driver enable problem upsidedown@downunder.com - 2014-10-15 11:01 +0300
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-15 14:24 +0000
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-16 01:17 -0400
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-16 08:36 +0200
Re: Two-wires RS485 and the driver enable problem rickman <gnuarm@gmail.com> - 2014-10-16 05:05 -0400
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-16 12:54 +0200
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-16 14:16 +0000
Re: Two-wires RS485 and the driver enable problem upsidedown@downunder.com - 2014-10-15 09:09 +0300
Re: Two-wires RS485 and the driver enable problem Grant Edwards <invalid@invalid.invalid> - 2014-10-15 14:26 +0000
Re: Two-wires RS485 and the driver enable problem glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-10-13 20:55 +0000
Re: Two-wires RS485 and the driver enable problem Tim Wescott <seemywebsite@myfooter.really> - 2014-10-13 16:37 -0500
Re: Two-wires RS485 and the driver enable problem pozzugno <pozzugno@gmail.com> - 2014-10-14 09:37 +0200
Re: Two-wires RS485 and the driver enable problem Arlet Ottens <usenet+5@c-scape.nl> - 2014-10-14 20:44 +0200
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | pozzugno <pozzugno@gmail.com> |
|---|---|
| Date | 2014-10-14 08:50 +0200 |
| Message-ID | <m1ih3a$l3i$1@dont-email.me> |
| In reply to | #18589 |
Il 13/10/2014 17:06, Don Y ha scritto: > On 10/13/2014 5:56 AM, pozzugno wrote: >> Il 13/10/2014 14:47, David Brown ha scritto: >>> or if you do, re-enable global interrupts first. Then it >>> makes little difference if an interrupt function is running when the >>> "transmission complete" triggers because the function will be complete >>> in a few microseconds. >> >> Someone considers the practice to enable interrupts inside an ISR as >> The Devil :-) >> >> http://betterembsw.blogspot.it/2014/01/do-not-re-enable-interrupts-in-isr.html >> > > No, what you are most concerned with is ensuring every ISR manages to > terminate > before it can be reinvoked. > > So, ISR1 can be interrupted by ISR3 which can be interrupted by ISR7 > which can be interrupted by ISR2, etc. AS LONG AS ISR1 can't reassert > itself while ANY instance of ISR1 is still "active". > > (Ditto for every ISR in the system) > > Even this "rule" can be bent -- if you know the worst case nesting of ISR's > on themselves (and ensure you have adequate stack to cover that level of > penetration) IMHO it's a critical approach. In order to let the immediate "transmit complete" ISR (TXC), I have to re-enable interrupts inside all the other ISRs. So ISR A could be interrupted by ISR B even if I don't interested in this, just because ISR A must be interrupted by ISR TXC.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-14 14:34 -0700 |
| Message-ID | <m1k4t9$4gt$1@speranza.aioe.org> |
| In reply to | #18614 |
On 10/13/2014 11:50 PM, pozzugno wrote:
> Il 13/10/2014 17:06, Don Y ha scritto:
>> No, what you are most concerned with is ensuring every ISR manages to
>> terminate before it can be reinvoked.
>>
>> So, ISR1 can be interrupted by ISR3 which can be interrupted by ISR7
>> which can be interrupted by ISR2, etc. AS LONG AS ISR1 can't reassert
>> itself while ANY instance of ISR1 is still "active".
>>
>> (Ditto for every ISR in the system)
>>
>> Even this "rule" can be bent -- if you know the worst case nesting of ISR's
>> on themselves (and ensure you have adequate stack to cover that level of
>> penetration)
>
> IMHO it's a critical approach. In order to let the immediate "transmit
> complete" ISR (TXC), I have to re-enable interrupts inside all the other ISRs.
>
> So ISR A could be interrupted by ISR B even if I don't interested in this, just
> because ISR A must be interrupted by ISR TXC.
You're stuck with this problem because you are forcing processing and
timeliness constraints into the ISR's. An ISR should *only* do what it
ABSOLUTELY MUST. "In and out", lickity split!
Your description SUGGESTS that you are implementing your comms system
in a state machine something at the RxIRQ level like (pseudocode):
GetCharacter:
retrieve character from comms hardware
note error flags associated with this reception
if any error, do some sort of error recovery/logging
(or, do state specific error recovery, as appropriate)
ret
AwaitSoH:
header = GetCharacter()
if (header != Start_of_Header)
diagnostic("SoH not received when anticipated")
// leave RxIRQ as is; remain in the state awaiting SoH
else
set_RxIRQ(SoHReceived)
return from interrupt
// the above assumes SoH doesn't occur in a message body. If it
// does, then you revisit this state occasionally as you sync up to
// the data stream
SoHReceived:
address = GetCharacter()
if (address != MyAddress)
diagnostic("message APPARENTLY not intended for me")
set_RxIRQ(AwaitSoH) // a simplification, for illustration
else
message_length = 0 // prepare for payload to follow
InitializeChecksum(address)
set_RxIRQ(AccumulateMessage)
return from interrupt
AccumulateMessage:
datum = GetCharacter()
buffer[message_length++] = datum
UpdateChecksum(datum)
if (message_length > MESSAGE_LENGTH)
set_RxIRQ(AwaitChecksum)
return from interrupt
AwaitChecksum:
checksum = GetCharacter()
if (Checksum != computedChecksum)
diagnostic("message failed integrity check")
error
else
parse message (unless you've been doing this incrementally)
act on message
prepare result
wait until master has turned off its bus driver
turn on your bus driver and transmitter
(or, have the scheduler do so)
schedule your reply for transmission
set_RxIRQ(AwaitSoH)
return from interrupt
[Note that you may, instead, have folded all of this into one static RxIRQ
by conditionally examining a "state variable" (byte counter?) and acting
accordingly:
if (byte_count == 1)
check if correct header
else if (byte_count == 2)
check if correct address
else if (byte_count ...
I manipulate the interrupt vector instead as each little ISR "knows"
what the next ISR should be so why introduce a bunch of conditionals?]
And, your TxIRQ (once the reply has been scheduled):
TxIRQ:
SendCharacter(buffer[message_length++])
if (message_length > MESSAGE_LENGTH)
set_TxIRQ(ShutdownTx)
return from interrupt
ShutdownTx:
wait until last character cleared transmitter (NOT holding reg)!
wait until line has stabilized (bus driver)
turn off bus driver
set_TxIRQ(none)
return from interrupt
[Of course, message lengths can vary between Tx and Rx, etc]
So, all of your IRQ's are lightweight. EXCEPT the "AwaitChecksum"
state. There, you have to do a fair bit of processing ON THE HEELS OF
the final character in the master's transmission (you could add an
additional "trailer" but that's just more characters to receive and
process and doesn't fundamentally change the algorithm).
The delays ("wait until...") are all relatively short. Yet, not
necessarily "opcode timing" short. So, you sort of have to sit around
twiddling your thumbs until you think you've met the required delays
(you can't make any *observations* to tell you when the time is right...
when the master has turned off its bus driver, etc.)
Or, throw some hardware resource at the problem (small interval timing)
All of that waiting wants to be done OUTSIDE the ISR. Yet, you can't
afford for it to be unbounded -- because your master no doubt expects a
reply in *some* time period else a dropped message would hang all comms!
(and it probably uses a lack of reply to indicate a failure of your node)
I.e., there are LOWER and UPPER bounds on when you can start your reply.
Too soon and you collide with the the tail end of the master's transmission;
too late and you risk the end of your reply running into the master's
*next* transmission.
[Or, you can add a timer to the master so that it doesn't start its next
transmission until it is *sure* you are finished transmitting]
Likewise, all of the *processing* that isn't time critical (or, SHOULDN'T
be!) wants to happen outside the ISR.
If, instead, you could note the time at which a "request" from the master
was sent and use that as a reference point from which to determine
when you would have a CHANCE to deliver a reply ("timeslot"), then
you can do all of this processing AND waiting outside of the IRQ.
[If you force that time to be JUST the duration of the master's message,
then you don't have any real leeway -- you have to act promptly! You're
stuck with your present dilemma.]
For example, assume you have a 1ms periodic interrupt (change to
suit your needs). Assume you are delivering data at 9600 baud
(change to suit your needs). Assume messages from the master are
M characters long.
[I've chosen numbers that make the math relatively easy so you don't
have to dig out a calculator. Changing the values just changes the
math. I.e., characters are arriving roughly at the same rate as your
periodic interrupt -- though they aren't guaranteed to be in
a particular phase relationship with it. (this is not a requirement
of this approach, just a coincidence for the numbers I have chosen)]
On a particular node, you notice a "SoH" received sometime between
periodic interrupt S-1 and S (because you modify your AwaitingSoH
ISR to signal an event that you can then examine -- or, let it
capture the "periodic counter" *in* the ISR and post that time value
as the "event").
You KNOW the master's message will not be complete until at least
(S-1)+M but definitely before S+M -- because you have *designed* to
this goal!
Furthermore, you know that your timeslot is offset X ms from the
StartOfHeader in the master's message (i.e., time ~S). You KNOW
that you can't safely turn on your bus driver until S+X (because those
are the rules of the protocol) but you *do* know that the master
will have turned his bus driver off by then (because it is following
the same rules!)
So, you schedule a job that turns on your bus driver at S+X and
pushes *a* reply onto the bus.
*A* reply.
This need not be *the* reply to the message from the master sent
at time S! It may, instead, be a reply to the message sent by
the master at the *previous* "time S". Or, the one before that!
Instead of tail-gating the master's message and trying to reply
as soon as the last character in its message has cleared the medium
(or, some epsilon later), you decouple your replies from the master's
requests.
With the timeslot, you *know* you can send a reply EVEN IF THE MESSAGE
FROM THE MASTER IS NOT FOR YOU! I.e., you dont have to check the address,
decode the message, act on it AND compose your reply *now*. Likewise,
other nodes know that they can send THEIR replies even when the current
message is for *you* and not them!
You just support some number of outstanding messages to each node
(perhaps just "1" but bigger numbers are better) and tag them with
a (small) sequence number -- so the master can pair replies to
outstanding requests AND so you can see when the master has given
up on an "old" request that you perhaps forgot to acknowledge.
[E.g., you can conceivably reply to message 2 before replying to message
1 -- if that makes sense in your current execution environment. If
not, then Reply2 has to wait to be scheduled until Reply1 has been sent.
You are free to arrange those criteria as fits your processing capabilities.
You don't HAVE TO reply to the message *now*.]
Note that this can be scaled by supporting a smaller number of
timeslots than there are physical nodes in the system -- the
master can allow nodes (1 - Q) to use the Q timeslots following
*this* message (before it issues the NEXT message) and the (Q+1 - 2Q)
nodes to use the Q timeslots following the NEXT message.
The point is, each node knows AHEAD OF TIME when it can reply (when
it can turn on its bus driver) instead of having "very little notice"
and having to react promptly.
It also allows the nodes to know that communications are "fair"
and "deterministic". Any node knows how long it must wait before
it is *guaranteed* a chance to access the medium. (if there was
no guarantee, then nodes wouldn't have been able to PREDICT when
they should acquire the medium and place their messages on it)
You've moved the:
parse message (unless you've been doing this incrementally)
act on message
prepare result
steps from the ISR into a lower priority task where you, presumably,
have more leeway in addressing those needs (than you would in an
ISR that wants to be short!). *All* of your ISRs are now short
(because they just empty the receiver or stuff the transmitter
and don't do any *decoding*, processing, etc.)
RxIRQ:
datum = GetCharacter()
FIFO <- (datum,timestamp)
return from interrupt
Something else watches the FIFO to try to identify messages
within. When it does, it knows when the message began (because
of the timestamp on that datum) so it can figure out when a reply
*should* be scheduled -- even though the reply might not be the
reply for this message.
Instead of having to deliver a response *NOW*, your protocol moves
the time that you are granted to fabricate a response out of the
low level "driver". You could conceivably allow different timeouts
for different types of messages, etc.
And, because you know when to expect a message from the master
(even if it is not for you!) -- because the protocol has the master
sending a message followed by Q reply timeslots -- and when, relative
to that, to present your reply, the timing of the bus arbitration is
decoupled from the immediacy of a particular "Rx IRQ". You're not
trying to accurately time/delay "character times", "bit times" or smaller.
You, instead, rely on a timebase that you already have in place.
Making timing decisions in a more tolerant environment (including,
potentially, the enabling and disabling of the bus driver)
If you look at higher performance "packet protocols", you will tend
to see this same pattern repeated. I.e., you don't send an ethernet
message and expect the receiving interrupt on the destination node
to prepare and deliver a reply! Nor do you expect the sending node
to twiddle its thumbs awaiting that reply; nor the reply to message 1
before it sends message 2 (to you *or* some other node).
You just have to agree, ahead of time (i.e., protocol specification!)
how long you are willing to wait for old acknowledgements and how
many you are willing to let remain outstanding at any given time.
This defines the time you have to "handle" a particular message; NOT
some artifically tight constraint IN an ISR.
Then, "do the math" for your particular periodic interrupt rate
and data rates (and message lengths, node counts, etc.) so you can
ensure each node gets serviced in a timely fashion. The point isn't
to maximize throughput but, rather, to be able to provide *guarantees*
without overspecifying hardware or needlessly tightening constraints
on the software.
This turns a hard real-time approach (where missing a deadline means
you simply abandon the action that you were attempting) into a softer
one with more flexible deadlines (where missing a deadline doesn't
render the effort "wasted" but, rather, salvageable at some possibly
reduced "value", at a later time).
Otherwise, you "must" reply to this message now. And, if you can't,
what makes you think you will be able to the *next* time it is
sent to you (i.e., as a "retry")? Your implementation is "more brittle".
(what happens if some node needs an ISR for some other capability
and that ISR interferes with your TIMELY processing of "this" message?)
[I currently use a variation of this "over ethernet" (where it isn't
necessary) in anticipation of porting the design to a wireless
implementation (where folks can't all "talk at once" yet deterministic
delivery is required). I.e., "bus driver" in my case is "RF transmitter"]
*Think* about this sort of implementation... what it means/costs in your
hardware. Put ballpark numbers on how much time it allows slaves to
handle messages, etc. Decide what the impact on the devices (master?)
making those requests might be: e.g., if they BLOCK until they get a
request (and no other processing CAN occur on that node), then you
would want to favor more prompt responses.
OTOH, if you can do meaningful work while awaiting a reply, then the
impact of a delayed reply is minimized.
I reviewed a colleague's implementation of a product a few weeks back
that had several CAN nodes collaborating on the services provided.
Every message request he sent out, I asked:
"What happens if you NEVER get a reply to this?
What happens if the reply is delayed?
Is this node effectively *stuck* in that get_reply() for the duration?"
And, eventually:
"Ahhhh... so that's why you are doing all this work in your ISRs that
one would more safely do elsewhere -- less precious! Can't risk things
catching fire while you're waiting for a reply!"
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2014-10-13 09:11 -0400 |
| Message-ID | <1cQ_v.381586$_k.123237@fx16.iad> |
| In reply to | #18575 |
On 10/13/14, 7:58 AM, pozzugno wrote: > I have a multi-drop two-wires RS485 bus. One node is the master and all > the others are slaves. The master is the only node that is authorized > to initiate a transmission, addressing one slave. The addressed slave > usually answers to the master. > > The bus is half-duplex, so every node disables the driver. Only THE > node that transmits data on the bus enables the driver and disables it > as soon as it can, just after the last byte. An interrupt (transmit > complete) usually triggers when the last byte is totally shifted out, so > the driver can be disabled immediately. > > Of course, other interrupts can be triggered. What happens when > interrupt X (whatever) triggers just before the "transmit complete" > interrupt? The result is the ISR X is called, postponing the execution > of "transmit complete" ISR. The RS485 driver will be disabled with a > certain amount of delay. In the worst case, the driver could be > disabled with a delay that is the sum of the duration of all ISRs that > could trigger. > [In this scenario, I think of ISRs that can't be interrupted by a higher > priority interrupt.] > > 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. This interval > could be in the range of 100 microseconds and should be calibrated on > the sum of duration of *all* ISRs of *all* nodes on the bus. It isn't a > simple calculation. > > Moreover, implementing a short "software" delay in the range of some > microseconds isn't a simple task. An empty loop on a decreasing > volatile variable is a solution, but the final delay isn't simple to > calculate at the design time, and it could depend on the compiler, > compiler settings, clock frequency and so on. Use an hw timer only for > this pause? > > How do you solve this problem? > > [I know there are some microcontrollers that automatically (at the > hw-level) toggle an output pin when the last byte is totally shifted > out, but I'm not using one of the them and they aren't so common.] Yes, the best solution is to make it happen in hardware, but I understand it isn't always available. As you commented, the key is to define the maximum period after transmission is complete that a unit is allowed to drive the line, and thus the minimum time another unit must wait to respond. By defining a maximum time that a unit can drive the bus, you have now introduced a "Hard Real Time" requirement to the system. That normally means that you need to be careful what is done in interrupt routines, so no interrupt can mask off other interrupts for an extended time. A second question is how much data is being sent and how fast do responses need to be. It may be possible to define the minimum reply delay long enough that you don't really need to worry about "small" delays in the transmitter. A third question is can the protocol be made "fail-safe" so that if on an occasional unlucky combination of delays, and the beginning of the response is garbled by a slow disable, that the system can detect this and cause a retransmission (This is often good to handle other types of errors too), or otherwise tolerate an occasional missing response. In this case you just need to make sure that the responding unit takes long enough to build its response (maybe with an added delay to make sure) for the transmitter to normally get off the bus. Unless you have vastly differing speed of units, this often will just happen to be true as the receiving unit, especially if set to verify the "stop bit", won't begin to parse the message which is normally a longer task than the sending units "shut off the driver" operation.
[toc] | [prev] | [next] | [standalone]
| From | rickman <gnuarm@gmail.com> |
|---|---|
| Date | 2014-10-13 10:53 -0400 |
| Message-ID | <m1gp1s$h27$1@dont-email.me> |
| In reply to | #18575 |
On 10/13/2014 7:58 AM, pozzugno wrote:
> I have a multi-drop two-wires RS485 bus. One node is the master and all
> the others are slaves. The master is the only node that is authorized
> to initiate a transmission, addressing one slave. The addressed slave
> usually answers to the master.
>
> The bus is half-duplex, so every node disables the driver. Only THE
> node that transmits data on the bus enables the driver and disables it
> as soon as it can, just after the last byte. An interrupt (transmit
> complete) usually triggers when the last byte is totally shifted out, so
> the driver can be disabled immediately.
>
> Of course, other interrupts can be triggered. What happens when
> interrupt X (whatever) triggers just before the "transmit complete"
> interrupt? The result is the ISR X is called, postponing the execution
> of "transmit complete" ISR. The RS485 driver will be disabled with a
> certain amount of delay. In the worst case, the driver could be
> disabled with a delay that is the sum of the duration of all ISRs that
> could trigger.
> [In this scenario, I think of ISRs that can't be interrupted by a higher
> priority interrupt.]
>
> 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. This interval
> could be in the range of 100 microseconds and should be calibrated on
> the sum of duration of *all* ISRs of *all* nodes on the bus. It isn't a
> simple calculation.
>
> Moreover, implementing a short "software" delay in the range of some
> microseconds isn't a simple task. An empty loop on a decreasing
> volatile variable is a solution, but the final delay isn't simple to
> calculate at the design time, and it could depend on the compiler,
> compiler settings, clock frequency and so on. Use an hw timer only for
> this pause?
>
> How do you solve this problem?
>
> [I know there are some microcontrollers that automatically (at the
> hw-level) toggle an output pin when the last byte is totally shifted
> out, but I'm not using one of the them and they aren't so common.]
If you can't use hardware to control the driver enable signal, then
perhaps you can use hardware to control your time out. Rather than
worry about software reading timers and messing with your interrupt
priorities, etc... use the UART as a timer to delay the first enabled
character being transmitted.
Before a device transmits on the bus, send a character to the UART
without enabling the RS-485 driver. Wait for the transmitter shift
register to be empty ("transmit complete" by your terminology). Then
enable the bus driver and start sending the packet data. This will
provide 1 character transmission time delay.
You still need to calculate the worst case delay needed. If it turns
out to be longer than 1 character transmission time then you may need to
pad with more than 1 dummy character.
--
Rick
[toc] | [prev] | [next] | [standalone]
| From | pozzugno <pozzugno@gmail.com> |
|---|---|
| Date | 2014-10-13 17:03 +0200 |
| Message-ID | <m1gpjl$i0p$2@dont-email.me> |
| In reply to | #18585 |
Il 13/10/2014 16:53, rickman ha scritto:
> Before a device transmits on the bus, send a character to the UART
> without enabling the RS-485 driver. Wait for the transmitter shift
> register to be empty ("transmit complete" by your terminology). Then
> enable the bus driver and start sending the packet data. This will
> provide 1 character transmission time delay.
Good suggestion to avoid using another hardware peripheral for
implementing the delay. Thank you.
[toc] | [prev] | [next] | [standalone]
| From | Grant Edwards <invalid@invalid.invalid> |
|---|---|
| Date | 2014-10-13 15:20 +0000 |
| Message-ID | <m1gqjd$ojj$1@reader1.panix.com> |
| In reply to | #18575 |
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.
--
Grant Edwards grant.b.edwards Yow! Here I am in the
at POSTERIOR OLFACTORY LOBULE
gmail.com but I don't see CARL SAGAN
anywhere!!
[toc] | [prev] | [next] | [standalone]
| From | pozzugno <pozzugno@gmail.com> |
|---|---|
| Date | 2014-10-16 09:01 +0200 |
| Message-ID | <m1nqeq$s6q$1@dont-email.me> |
| In reply to | #18591 |
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?
[toc] | [prev] | [next] | [standalone]
| From | Tauno Voipio <tauno.voipio@notused.fi.invalid> |
|---|---|
| Date | 2014-10-16 10:19 +0300 |
| Message-ID | <m1nrhd$v4p$1@dont-email.me> |
| In reply to | #18676 |
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
[toc] | [prev] | [next] | [standalone]
| From | rickman <gnuarm@gmail.com> |
|---|---|
| Date | 2014-10-16 05:02 -0400 |
| Message-ID | <m1o1k0$i65$1@dont-email.me> |
| In reply to | #18676 |
On 10/16/2014 3:01 AM, pozzugno wrote: > > 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 block start and end bytes are important, but if they are not unique you have to escape them in your data which implies a message handling layer in your software. Or you can use a UART that recognizes the start characters. If you use sync data transmission rather than async this is common. > 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. How is N sync bytes equivalent to a bunch of empty frames? Is your sync byte unique? > 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? I'm not sure I see a problem. UARTs typically see the falling edge as the start of the start bit, but check at least once in the middle of the bit to see if it was just noise. Too short a pulse and it is discarded. Long enough and it will be seen as a start bit. Since the UART starts looking for a new start bit in the middle of the stop bit (approximately) such a start bit timing discrepancy will not create a problem although this leaves no room for timing variation between the two ends. As long as point B is in the first preamble char and not the last it should be ok. But if you can be sure the driver disable will be at worst case no later than C, why can't the slave just hold of sending the start of frame for another char? Your approach will work, but it is no better than sending chars without enabling the slave's driver in the first place. In fact, if you know when the master driver will be off the bus, you can get your message out once character more quickly by not sending the last preamble byte. -- Rick
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-13 08:17 -0700 |
| Message-ID | <m1gqn4$fvt$1@speranza.aioe.org> |
| In reply to | #18575 |
On 10/13/2014 4:58 AM, pozzugno wrote: [bus acquisition in the face of possible contention] > 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. This interval could be in the range of > 100 microseconds and should be calibrated on the sum of duration of *all* ISRs > of *all* nodes on the bus. It isn't a simple calculation. > > How do you solve this problem? First, you need to *know* that it is *you* that has been granted access to the bus/resource. If this requires you to perform some analysis of the ENTIRE MESSAGE (to verify that the "address field" is, in fact, intact!), then you probably DON'T want to try to ride the coat-tails of the message, directly. As the front end of a message (including yours) is more likely to be corrupted (by a collision on the bus -- someone jabbering too long or too soon), you might consider designing a packet format that has one checksum on the address field "early" in the packet (before the payload) and another that handles the balance of the message. This allows you to capture the address information and it's closely following checksum, verify that it is *you* that are being addressed and prepare for your acquisition of the bus before the message has completely arrived. You can also arrange to access the bus in "timeslots" referenced to some easily recognizable event (e.g., a beacon sent by the master). So, you do all of your timing off of that single event (see "some special point" in the beacon, start timer, wait to transmit until "your slot"). Note this also works if you just assume the "next slot" after the master's message is the slot you should use (you just limit the length of the master's message so it fits in that fixed delay). Similarly, the master can "know" that your reply will never exceed a fixed duration so it won't issue another beacon/request until that has expired. Hopefully, this makes sense. Sorry, I'm off for a pro bono day so no time here... :-/
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-13 08:19 -0700 |
| Message-ID | <m1gqrb$fvt$2@speranza.aioe.org> |
| In reply to | #18592 |
On 10/13/2014 8:17 AM, Don Y wrote: > As the front end of a message (including yours) is more likely to be corrupted > (by a collision on the bus -- someone jabbering too long or too soon), you > might consider designing a packet format that has one checksum on the > address field "early" in the packet (before the payload) and another that > handles the balance of the message. > > This allows you to capture the address information and it's closely following > checksum, verify that it is *you* that are being addressed and prepare for your > acquisition of the bus before the message has completely arrived. ... so that you don't erroneously acquire the bus only to discover that it was intended for someone else (and you've just made things worse)
[toc] | [prev] | [next] | [standalone]
| From | pozzugno <pozzugno@gmail.com> |
|---|---|
| Date | 2014-10-14 09:28 +0200 |
| Message-ID | <m1ijai$que$1@dont-email.me> |
| In reply to | #18592 |
Il 13/10/2014 17:17, Don Y ha scritto: > On 10/13/2014 4:58 AM, pozzugno wrote: > First, you need to *know* that it is *you* that has been granted access to > the bus/resource. If this requires you to perform some analysis of the > ENTIRE MESSAGE (to verify that the "address field" is, in fact, intact!), > then you probably DON'T want to try to ride the coat-tails of the message, > directly. > > As the front end of a message (including yours) is more likely to be > corrupted > (by a collision on the bus -- someone jabbering too long or too soon), you > might consider designing a packet format that has one checksum on the > address field "early" in the packet (before the payload) and another that > handles the balance of the message. > > This allows you to capture the address information and it's closely > following > checksum, verify that it is *you* that are being addressed and prepare > for your > acquisition of the bus before the message has completely arrived. I have just one checksum at the end of the message, but the address field is at the beginning. Anyway I look at the address field as it arrives to decide if it's a frame for me. I know the address field could be corrupted, but IMHO it's not important. If the address field is corrupted and appear for me, but the master wanted to talk to another node, I store the message till the end, but the checksum will be wrong, so the frame will be discarded. If the address field is corrupted and it doesn't appear for me, but the master really wanted to talk with me, I discard early the message. IMHO, adding a new checksum at the beginning of the frame, only to protect the address field, doesn't add more robustness to the final performance. > You can also arrange to access the bus in "timeslots" referenced to some > easily recognizable event (e.g., a beacon sent by the master). So, > you do all of your timing off of that single event (see "some special > point" in the beacon, start timer, wait to transmit until "your slot"). > > Note this also works if you just assume the "next slot" after the master's > message is the slot you should use (you just limit the length of the > master's > message so it fits in that fixed delay). Similarly, the master can "know" > that your reply will never exceed a fixed duration so it won't issue > another > beacon/request until that has expired. > > Hopefully, this makes sense. Sorry, I'm off for a pro bono day so no time > here... :-/ I think I'll have to think more deeply about this beacon approach. Any useful info on the Internet?
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-14 06:09 -0700 |
| Message-ID | <m1j7jj$kbp$1@speranza.aioe.org> |
| In reply to | #18616 |
On 10/14/2014 12:28 AM, pozzugno wrote: > Il 13/10/2014 17:17, Don Y ha scritto: >> On 10/13/2014 4:58 AM, pozzugno wrote: > >> First, you need to *know* that it is *you* that has been granted access to >> the bus/resource. If this requires you to perform some analysis of the >> ENTIRE MESSAGE (to verify that the "address field" is, in fact, intact!), >> then you probably DON'T want to try to ride the coat-tails of the message, >> directly. >> >> As the front end of a message (including yours) is more likely to be >> corrupted >> (by a collision on the bus -- someone jabbering too long or too soon), you >> might consider designing a packet format that has one checksum on the >> address field "early" in the packet (before the payload) and another that >> handles the balance of the message. > > > > This allows you to capture the address information and it's closely > > following > > checksum, verify that it is *you* that are being addressed and prepare > > for your > > acquisition of the bus before the message has completely arrived. > > I have just one checksum at the end of the message, but the address field is at > the beginning. Anyway I look at the address field as it arrives to decide if > it's a frame for me. Correct. > I know the address field could be corrupted, but IMHO it's not important. If > the address field is corrupted and appear for me, but the master wanted to talk > to another node, I store the message till the end, but the checksum will be > wrong, so the frame will be discarded. If the address field is corrupted and > it doesn't appear for me, but the master really wanted to talk with me, I > discard early the message. Also correct. > IMHO, adding a new checksum at the beginning of the frame, only to protect the > address field, doesn't add more robustness to the final performance. You haven't indicated how big the payload is. Or, the effort required to create the reply. In your scheme, you MUST deliver a reply as soon as the message from the master is complete (you are free to define "soon"). Verifying the address (as yours AND "intact") lets you know whether or not you have to deal with the payload AT ALL. >> You can also arrange to access the bus in "timeslots" referenced to some >> easily recognizable event (e.g., a beacon sent by the master). So, >> you do all of your timing off of that single event (see "some special >> point" in the beacon, start timer, wait to transmit until "your slot"). >> >> Note this also works if you just assume the "next slot" after the master's >> message is the slot you should use (you just limit the length of the >> master's >> message so it fits in that fixed delay). Similarly, the master can "know" >> that your reply will never exceed a fixed duration so it won't issue >> another >> beacon/request until that has expired. >> >> Hopefully, this makes sense. Sorry, I'm off for a pro bono day so no time >> here... :-/ > > I think I'll have to think more deeply about this beacon approach. Any useful > info on the Internet? <shrug> Probably. But, I've not gone looking for it. You might look at some of the token passing algorithms to see (Arcnet?) what they have to say by way of example. The key advantage is that it lets you set up the time at which your reply will be "required" instead of having to "watch carefully" for the end of the immediately preceding transmission (from the master). This lets you deal with bigger time intervals instead of bit-level timing. I.e., recognize the start of the beacon -- because that is usually a more repeatable "event" -- (and it's content) and then IGNORE the serial line until you know it is your timeslot to reply (you don't care what the data on the bus happens to be from the other nodes -- why even receive it?). [Unless you also want to use this scheme to allow the other nodes to be bus masters and directly deliver their messages to other nodes, instead of via the master. I.e., in time slot N, node N can send a message to ANY node (which may be a REPLY to a message sent from that other node, earlier). The master's significance is just to coordinate the timeslots. Note this is far more involved than anything discussed so far] Note that you also know when your timeslot *ends* and the next begins. So, you can turn on the driver for the entire duration REGARDLESS of how long your message is -- subject to the constraint that you know it must fit in the time allotted. And, even before you are ready to transmit! If you are sluggish getting onto the bus... <shrug> No problem. As long as you hit *your* timeslot. I.e., you can be sluggish if you know your reply is short enough to still get out in the time remaining. In other words, you can trade processing time for response time. If you have to digest a complex message from the master, just make sure your expected reply is SHORT: ACK vs. NAK instead of detailed. If you need to deliver a detailed reply, then modify your protocol so that you can get some forewarning of its impending need. E.g., a message that effectively says, "prepare the detailed reply for me" to which you acknowledge (or NOT!) your understanding of the request AND your ability to deliver it (which might require scheduling resources that aren't normally available for that). Then, later, expect to get a message asking for the actual details (that you have presumably "staged" in anticipation of this). [You can also modify the protocol so the master does this in three steps: "Prepare the details" "ACK/NAK" "Are you ready yet?" "ACK/NAK" "OK, give them to me!"] It's just another way to get stuff out of ISR's and into lower priority processing. It also lets you modify the protocol to give everyone a slot (if you have a small number of nodes) instead of having the master constantly prompting everyone (which wastes bandwidth as well as increasing the number of instances where the bus has to be handed off "per unit message exchange") Finally, it allows the master to routinely distribute information that may be pertinent to all nodes (e.g., current system time). I have no idea what your actual communications needs are (you haven't indicated an application, etc.). I offer it as an alternative approach to consider instead of the more obvious "ping-pong" of command-response that you appear to be pursuing. Only you can tell if it has merit in your case. If messages pass between nodes (via the master?) infrequently, then this wastes a lot of time on the bus -- because most timeslots will contain no information (though the corresponding node can be REQUIRED to deliver an acknowledgement if it is important for you to use that as a keepalive/verification that the node is still "up"). Of course, if the master is cyclicly *polling* each of these nodes, then even MORE time is wasted (the time for the individual solicitations and the negative acknowledgements). I use a similar scheme with Ethernet to manage multiple (~120) co-operating hosts and ensure all have "system data" that needs to be delivered periodically (the beacon is a "periodic token") as well as ensuring that the required nodes are "up". [Of course, my nodes can all chat as necessary so it isn't used to arbitrate access to the medium]
[toc] | [prev] | [next] | [standalone]
| From | rickman <gnuarm@gmail.com> |
|---|---|
| Date | 2014-10-14 14:28 -0400 |
| Message-ID | <m1jq0n$vh$1@dont-email.me> |
| In reply to | #18624 |
On 10/14/2014 9:09 AM, Don Y wrote: > On 10/14/2014 12:28 AM, pozzugno wrote: > >> IMHO, adding a new checksum at the beginning of the frame, only to >> protect the >> address field, doesn't add more robustness to the final performance. > > You haven't indicated how big the payload is. Or, the effort required to > create the reply. > > In your scheme, you MUST deliver a reply as soon as the message from the > master is complete (you are free to define "soon"). Really? "MUST"??? All the respondent is required to do is respond before the master times out thinking the respondent is not replying. This timeout should be set as required by system level requirements such as throughput, etc. Don't make this as complex as the things you design. > Verifying the address (as yours AND "intact") lets you know whether or not > you have to deal with the payload AT ALL. Who cares? >> I think I'll have to think more deeply about this beacon approach. >> Any useful >> info on the Internet? The "beacon" is pointless, don't waste your time with it. It has no advantage over a simple poll/response protocol and in fact is just the same thing with more complication and no added benefit. One point you should be aware of is that your start and end characters can be compromised and the protocol has to deal with that. So consider what happens when they are munged and not recognized. Make sure your protocol is robust to those problems. -- Rick
[toc] | [prev] | [next] | [standalone]
| From | rickman <gnuarm@gmail.com> |
|---|---|
| Date | 2014-10-14 04:36 -0400 |
| Message-ID | <m1inc6$7jc$1@dont-email.me> |
| In reply to | #18592 |
On 10/13/2014 11:17 AM, Don Y wrote: > > First, you need to *know* that it is *you* that has been granted access to > the bus/resource. If this requires you to perform some analysis of the > ENTIRE MESSAGE (to verify that the "address field" is, in fact, intact!), > then you probably DON'T want to try to ride the coat-tails of the message, > directly. It's called a checksum and can be done after the entire message is received and before a reply needs to be sent. > As the front end of a message (including yours) is more likely to be > corrupted > (by a collision on the bus -- someone jabbering too long or too soon), you > might consider designing a packet format that has one checksum on the > address field "early" in the packet (before the payload) and another that > handles the balance of the message. > > This allows you to capture the address information and it's closely > following > checksum, verify that it is *you* that are being addressed and prepare > for your > acquisition of the bus before the message has completely arrived. As the OP has pointed out this is of no value whatsoever. No one is trying to minimize dead time or maximize throughput. The question is about turning off the driver at the end of a transmission. > You can also arrange to access the bus in "timeslots" referenced to some > easily recognizable event (e.g., a beacon sent by the master). So, > you do all of your timing off of that single event (see "some special > point" in the beacon, start timer, wait to transmit until "your slot"). This is not only not a solution to the problem, it is entirely pointless. The protocol is that the master sends a message to a peripheral device. When the peripheral device receives a message it responds. When the master receives a response it can send the next message. > Note this also works if you just assume the "next slot" after the master's > message is the slot you should use (you just limit the length of the > master's > message so it fits in that fixed delay). Similarly, the master can "know" > that your reply will never exceed a fixed duration so it won't issue > another > beacon/request until that has expired. Or the master can wait to send another message until the reply from the peripheral is complete. > Hopefully, this makes sense. Sorry, I'm off for a pro bono day so no time > here... :-/ Actually this is poorly thought out. The problem is not with the protocol. The problem is a basic hardware limitation which makes it hard to control the driver enable at the time it is needed. Either you have no understanding of the problem or you just couldn't be bothered to actually respond about the problem at hand. -- Rick
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2014-10-13 12:35 -0500 |
| Message-ID | <m1h2gb$m44$1@dont-email.me> |
| In reply to | #18575 |
pozzugno wrote: > I have a multi-drop two-wires RS485 bus. One node is the master and all > the others are slaves. The master is the only node that is authorized > to initiate a transmission, addressing one slave. The addressed slave > usually answers to the master. > > The bus is half-duplex, so every node disables the driver. Only THE > node that transmits data on the bus enables the driver and disables it > as soon as it can, just after the last byte. An interrupt (transmit > complete) usually triggers when the last byte is totally shifted out, so > the driver can be disabled immediately. > > Of course, other interrupts can be triggered. What happens when > interrupt X (whatever) triggers just before the "transmit complete" > interrupt? The result is the ISR X is called, postponing the execution > of "transmit complete" ISR. The RS485 driver will be disabled with a > certain amount of delay. In the worst case, the driver could be > disabled with a delay that is the sum of the duration of all ISRs that > could trigger. > [In this scenario, I think of ISRs that can't be interrupted by a higher > priority interrupt.] > > 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. This interval > could be in the range of 100 microseconds and should be calibrated on > the sum of duration of *all* ISRs of *all* nodes on the bus. It isn't a > simple calculation. > > Moreover, implementing a short "software" delay in the range of some > microseconds isn't a simple task. An empty loop on a decreasing > volatile variable is a solution, but the final delay isn't simple to > calculate at the design time, and it could depend on the compiler, > compiler settings, clock frequency and so on. Use an hw timer only for > this pause? > > How do you solve this problem? > MODBUS RTU specifies 3.5 character times "settle time" after the last byte was sent. That's on the order of .9 msec for 38,400 baud. But that's a *minimum*. > [I know there are some microcontrollers that automatically (at the > hw-level) toggle an output pin when the last byte is totally shifted > out, but I'm not using one of the them and they aren't so common.] You have to know the worst-case timing. If you can't control the slave nodes, then you'll have retransmissions due to collisions if the ISR is sufficiently nondeterministic. Since it's half-duplex, I'm wondering why you get an interrupt other than TX-complete in that state. You simply have to trade speed for determinism in this case. And there will be collisions. If nothing else, add counters of bad CRC events and no-response events and tune a delay. 485 isn't a good protocol these days. The kids get Ethernet on RasPi class machines for class projects; it's not unreasonable to use a real comms stack. -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | langwadt@fonz.dk |
|---|---|
| Date | 2014-10-13 15:02 -0700 |
| Message-ID | <7d53d708-b579-4349-984a-59e05b39f485@googlegroups.com> |
| In reply to | #18595 |
Den mandag den 13. oktober 2014 19.35.45 UTC+2 skrev Les Cargill: > pozzugno wrote: > > > I have a multi-drop two-wires RS485 bus. One node is the master and all > > > the others are slaves. The master is the only node that is authorized > > > to initiate a transmission, addressing one slave. The addressed slave > > > usually answers to the master. > > > > > > The bus is half-duplex, so every node disables the driver. Only THE > > > node that transmits data on the bus enables the driver and disables it > > > as soon as it can, just after the last byte. An interrupt (transmit > > > complete) usually triggers when the last byte is totally shifted out, so > > > the driver can be disabled immediately. > > > > > > Of course, other interrupts can be triggered. What happens when > > > interrupt X (whatever) triggers just before the "transmit complete" > > > interrupt? The result is the ISR X is called, postponing the execution > > > of "transmit complete" ISR. The RS485 driver will be disabled with a > > > certain amount of delay. In the worst case, the driver could be > > > disabled with a delay that is the sum of the duration of all ISRs that > > > could trigger. > > > [In this scenario, I think of ISRs that can't be interrupted by a higher > > > priority interrupt.] > > > > > > 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. This interval > > > could be in the range of 100 microseconds and should be calibrated on > > > the sum of duration of *all* ISRs of *all* nodes on the bus. It isn't a > > > simple calculation. > > > > > > Moreover, implementing a short "software" delay in the range of some > > > microseconds isn't a simple task. An empty loop on a decreasing > > > volatile variable is a solution, but the final delay isn't simple to > > > calculate at the design time, and it could depend on the compiler, > > > compiler settings, clock frequency and so on. Use an hw timer only for > > > this pause? > > > > > > How do you solve this problem? > > > > > > > MODBUS RTU specifies 3.5 character times "settle time" after > > the last byte was sent. That's on the order of .9 msec for 38,400 > > baud. > > > > But that's a *minimum*. > > > > > [I know there are some microcontrollers that automatically (at the > > > hw-level) toggle an output pin when the last byte is totally shifted > > > out, but I'm not using one of the them and they aren't so common.] > > > > > > You have to know the worst-case timing. If you can't control the slave > > nodes, then you'll have retransmissions due to collisions if the ISR > > is sufficiently nondeterministic. > > > > Since it's half-duplex, I'm wondering why you get an interrupt > > other than TX-complete in that state. > > > > You simply have to trade speed for determinism in this case. And there > > will be collisions. If nothing else, add counters of bad CRC events > > and no-response events and tune a delay. > > > > 485 isn't a good protocol these days. The kids get Ethernet on RasPi > > class machines for class projects; it's not unreasonable to > > use a real comms stack. > but Ethernet need hubs or switches, that gets messy if you have a lot of nodes -Lasse
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-13 17:36 -0700 |
| Message-ID | <m1hrg6$jc1$1@speranza.aioe.org> |
| In reply to | #18608 |
On 10/13/2014 3:02 PM, langwadt@fonz.dk wrote: > Den mandag den 13. oktober 2014 19.35.45 UTC+2 skrev Les Cargill: >> 485 isn't a good protocol these days. The kids get Ethernet on RasPi >> class machines for class projects; it's not unreasonable to >> use a real comms stack. > > but Ethernet need hubs or switches, that gets messy if you have a lot of nodes In the past, I've had good luck with 10Base2 implementations. But, you have to "fix" the cabling instead of relying on the flakey T's, etc. [Do they even make 10Base2 kit anymore?]
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2014-10-13 21:53 -0500 |
| Message-ID | <m1i36a$kh5$1@dont-email.me> |
| In reply to | #18609 |
Don Y wrote: > On 10/13/2014 3:02 PM, langwadt@fonz.dk wrote: >> Den mandag den 13. oktober 2014 19.35.45 UTC+2 skrev Les Cargill: > >>> 485 isn't a good protocol these days. The kids get Ethernet on RasPi >>> class machines for class projects; it's not unreasonable to >>> use a real comms stack. >> >> but Ethernet need hubs or switches, that gets messy if you have a lot >> of nodes > > In the past, I've had good luck with 10Base2 implementations. > But, you have to "fix" the cabling instead of relying on the > flakey T's, etc. > POR QUE??? :) > [Do they even make 10Base2 kit anymore?] I haven't seen any since the '90s. -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-13 20:24 -0700 |
| Message-ID | <m1i5b4$52j$1@speranza.aioe.org> |
| In reply to | #18610 |
On 10/13/2014 7:53 PM, Les Cargill wrote: > Don Y wrote: >>> but Ethernet need hubs or switches, that gets messy if you have a lot >>> of nodes >> >> In the past, I've had good luck with 10Base2 implementations. >> But, you have to "fix" the cabling instead of relying on the >> flakey T's, etc. > > POR QUE??? :) Device sat in a hard-to-access location and had pretty extreme environmental conditions (heat, vibration, etc.). The traditional T's (or F's if you preferred that orientation) just weren't very good at long term reliability. So, the physical connections were "adjusted" to more appropriately address those needs. >> [Do they even make 10Base2 kit anymore?] > > I haven't seen any since the '90s. I'd assume you could still hack together a suitable PHY. (?) Not sure how *economical* it would be, though...
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.arch.embedded
csiph-web