UARTs and interrupts

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hi all,

I have been writing code for the ds80c320 and xa-g49 and need a few
questions answered that i'm unsure about.

1. Say i have timer 0 set to interrupt on overflow. If in another interrupt
routine I disable all interrupts, then timer 0 happens to overflow, and then
I enable all interrupts, while the timer 0 overflow isr then run, or was it
missed?

***

I use interrupt driven serial comms reading / writing into ring buffers.
Also timer 0 is interrupting on overflow, and an external uart is
interrupting with data as well.

2. Do i need to disable uart/all interrupts when placing characters into the
ring buffer?

3. In the transmit and receive isr's do I need to disable/enable any
interrupts in these?


I've had problems before with the internal uart stopping. I would turn of
the uart interrupt when writing to the ring buffer, and in the isr(s). This
was fixed by turning off all the interrupts at these times.. (there were
three other interrupt sources).

4. Right now I turn off all interrupts when writing to the ring buffer and
in the uart isr's. Is this necessary?

Any answers/comments/gems of information appreciated..

ROss



Re: UARTs and interrupts
Quoted text here. Click to load it

I'm not much up on 8051 variants, but in general, interrupts are not lost -
they "pend". If you have all interrupts disabled at the time that your
counter overflows, the overflow int would pend until you re-enabled
interrupts. At some point, you re-enable interrupts and the overflow int
would assert, taking you to your overflow ISR.

Quoted text here. Click to load it

that's a pretty typical setup.

Quoted text here. Click to load it

if the processor supports it, you usually want to disable only the uart
interrupt when messing with your uaart queue pointers. Leave the others
enabled for better response to those ints.

Quoted text here. Click to load it
In most MCUs that I've seen, all ints are disabled by the MCU hardware  on
int acknowlege (entry into your ISR). (they pend as needed) You have to
explicitly re-enable them during the ISR. You haven't said what language you
use - a C complier may insert the all-int-enable instructions for you at the
end of your ISR code. In assy (with a MCU that supports int priorities) you
have separate instructions for enabling ints of lower vs ints of higher
priority. (I don't know if your processor supports int priorities - probably
not so ignore that last bit)
Quoted text here. Click to load it
this stuff gets kinda tricky and if you don't know what the hardware will
do, it could be quite confusing. The datasheet should tell you. If not,
lookup the data sheet/books for the original part (intel?) that your chip is
based on. Me-too vendors tend to omit the fundamentals in their docs. The
8051 has been me-too-ed for decades, now.

Quoted text here. Click to load it
probably not. RTFM

HTH,
Bob

Quoted text here. Click to load it


Re: UARTs and interrupts
Quoted text here. Click to load it

<snipped bob's answers.>

Thanks Bob... You've confirmed what I thought... Right now I'm mainly using
the XA-G49 which has separate interrupt vectors for every source and 8
different interrupt priorities. So I've put all the uart routines on the
same priority, and timer 0 on a slightly higher priority. I turn off the
uart tx interrupt while writing to the ring buffer and thats it. Seems to be
working fine so far...



Re: UARTs and interrupts

Quoted text here. Click to load it

Maybe yes, maybe no. It depends on how you've written your ring
buffer handler.  It's fairly simple to impliment a ring buffer
for which interrupts don't need to be disabled.

Quoted text here. Click to load it

We'd have to see the code to tell you.


--
Grant Edwards                   grante             Yow!  Don't SANFORIZE me!!
                                  at              
We've slightly trimmed the long signature. Click to see the full one.
Re: UARTs and interrupts

Quoted text here. Click to load it
interrupt
and then
was it
buffers.
into the
turn of
isr(s). This
Quoted text here. Click to load it
were
buffer and


Re: UARTs and interrupts
You didn't tell us what is the priority of interrupts in your system (
timer0,serial rx/tx etc..).If all ring buffer activity is done within
the serial RX/TX interrupt , and the timer0 interrupts has higher
priority , it's needless to disable timer0 interrupt providing that you
don't access serial ring buffers in timer0 interrupt.
Also , it is important how your system uses your ring buffers. If for
example , the high level driver extracts bytes from the receive buffer
, it should disable serial RX interrupt until the pointers are updated
, otherwise confusion may happen.
In 8051 and its derivatives , the serial RX and TX interrupts are
together so you are
disabling both, but there should be no problem with this.
Yossi


Re: UARTs and interrupts


Quoted text here. Click to load it

My own experience follows the teaching of one of my mentors in that one very
rarely  (if ever)  needs to disable interrupts.  In the 8051 world, use
interrupt priority, short service routines and amenable data structures.  In all
of our 8051 communication products, I can not think of one that runs with
interrupts disabled.  Being an assembly language dinosaur helps here.





Re: UARTs and interrupts



Quoted text here. Click to load it
all
Quoted text here. Click to load it

OK so how do you do a ring buffer without disabling interrupts during RX read ,
or a
Tx write?
The Interrupt could hit during that time.  The Keil C sample disables RI during
that
time.




Re: UARTs and interrupts

Quoted text here. Click to load it
or a
Quoted text here. Click to load it
that
Quoted text here. Click to load it

The basic principle in avoiding interrupt disabling is to make sure
that only one partner updates a specific variable (unless the hardware
supports some kind of interlocked manipulate and test instructions)
and maintaining a strict rules in which order variables are updated.

One way of doing a ring buffer is to have two globally visible
pointers, one for writing and the other for reading the ring buffer.

On the insertion side, first verify that there is space for at least
one byte in the ring buffer by comparing the visible pointers. Make a
private copy (e.g. a register) of the write pointer, update it to
point to the first free location, insert the byte into that location
and finally copy the private pointer to the globally visible write
pointer. Depending on the OS, you might inform the reader about new
data e.g. by raising a signal.

On the reading side, verify that there is at least one byte in the
buffer by comparing the publicly visible pointers. Extract the byte,
make a private copy (a register) of the read pointer, update it to
point to the next position and write the updated value to the globally
visible read pointer.

When using C/C++, it is very important to declare the globally visible
pointers with the volatile attribute to prevent the compiler from
optimising the pointer references.

Paul


Re: UARTs and interrupts
On Saturday, in article
Quoted text here. Click to load it

The only issue with using pointers (or indecii) on ring buffers is the
issue of when the pointers are identical knowing whether the buffer
is full or empty. Especially on RX buffers as this is truely aysnchronous
to the system

Quoted text here. Click to load it

Better still keep all the functions related in one or two modules where
the only globally visible parts of that module are function calls and
definitions (baud rates, error codes) and the like. The module will need
access to globally defined information like I/O registers. A second module
maybe needed to handle setting of timers or other external timers for
baud rate generation depending on platforms.

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: UARTs and interrupts

Quoted text here. Click to load it
during RX read ,
Quoted text here. Click to load it
disables RI
hardware
a
globally
the
aysnchronous

For this you leave one slot empty, the empty condition is when both
pointers are equal and the full is when there is only one slot in
between.

Quoted text here. Click to load it
visible
where
need
module


Re: UARTs and interrupts
On Sat, 14 May 2005 13:22:53 +0100 (BST), paul$@pcserv.demon.co.uk

Quoted text here. Click to load it

That is only a problem, if you can not resist the temptation to use
the last free position in the ring buffer :-).

If you declare "buffer full" at N-1 elements in the buffer (instead of
at N elements), you can avoid the ambiguity.

Paul


Re: UARTs and interrupts
Quoted text here. Click to load it

Not really. Just define that when the pointers are equal, the buffer is
empty. More generally, the number of items in the buffer is the difference
between the pointers modulo the buffer length. This simplification means
that your buffer needs no other state information besides the two pointers,
and each pointer is updated by only one process, so there's no need for
critical sections at all. Sure, this means that you can't fill that last
spot in the buffer, but if you really need that, you're probably running
too close to the edge for the system to be reliable anyway.

-- Dave Tweed

Re: UARTs and interrupts

Quoted text here. Click to load it

It is a common pitfall many people get wrong, that is why it was mentioned
in the context of the description I followed up on.

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: UARTs and interrupts
Quoted text here. Click to load it

Not really, when you have uncoordinated processes accessing the
data at random times.  This will be the situation when you have,
for example, an interrupt driven process filling the buffer, and
another process emptying it.  In this case you need a critical
section, which you can implement by disabling and reenabling
interrupts.

   MAIN_PROCESS             INTERRUPT_PROCESS
   1: read input  ptr
      read output ptr
      compare ptrs
      if empty goto 1
      read output data
      increment output ptr
      write output ptr back
      other operations

                            2: read output ptr
                               read input ptr
                               compare ptrs
                               if full go to 2
                               write input data via ptr
                               advance ptr
                               write input ptr back
                               other operations

Now shuffle these two sequences around and intermix them, and you
will find that you have to make the decision sequence (up to
compare ptrs) critical sections.  The compares decide whether there
is data to be taken (not empty) or space to be filled (not full).

In some systems you can have other problems if the write actions
are not single operations, such as writing high and low bytes of
pointers, with interrupts between them.

You can interchange the roles of MAIN and INTERRUPT PROCESS, and
have the same problem.  In fact both may be interrupt driven (for
example by a background data transfer operation).  In that case the
natural inhibition of further interrupts during interrupt service
can implement the critical section function.

--
 Some informative links:
   news:news.announce.newusers
We've slightly trimmed the long signature. Click to see the full one.
Re: UARTs and interrupts


Quoted text here. Click to load it

   1: read input  ptr
                                     <--- interrupt updates input ptr
      read output ptr
      compare ptrs
      if empty goto 1

The only problem here is that you get the "empty" indication, even
though there would be a value available at the time of the compare
instruction. In a polled system like this, the pending value would be
extracted at the next cycle anyway.

Quoted text here. Click to load it

With extremely primitive processors you would have to perform the
comparison byte by byte, first compare the high bytes of the pointers
and then the low bytes of these two pointers. If the insertion "full"
check is needed on the interrupt side, then a critical section is
indeed needed.

The "empty" check on the main program side can be done by reading the
high and low bytes multiple times until the same value is returned in
two consecutive reads. Since we are interested only if in and out
pointer have the same value, a difference in either byte would
indicate that the buffer is not empty when the input pointer is
compared twice. Thus the only need for a critical section would be the
input overflow test, if such overflows can happen or the "overflow"
status is needed.
    
For complex processors allowing unaligned access, partial pointer
update would be a problem if the pointers are unaligned and thus split
into two memory words, especially at the cache line border or virtual
memory page boundary. Using aligned pointers solves this problem,
especially with packed structures, the pointers should be placed in
the beginning of structure to ensure proper alignment.

Paul
 

Re: UARTs and interrupts

snip
Quoted text here. Click to load it

Depends, if the read of each pointer is not atomic i.e. requires more than
one instruction, then it can be interrupted part way through the read, its
value altered then the read completed. This is the well known shared data
problem.

Ian

Re: UARTs and interrupts

Quoted text here. Click to load it

I certainly hope you would never recommend a potential infinite loop inside
an ISR. Your ISR code really should produce an error if the buffer is full.
Quoted text here. Click to load it

This is commonly known as the shared data problem and can occur whenever two
independent processes share data and the operations on the data are not
atomic.

Ian



Re: UARTs and interrupts
Quoted text here. Click to load it
... snip ...
Quoted text here. Click to load it

Of course not.  That was just to illustrate the cause of the
problems.  You have all sorts of mechanisms, including signal/wait,
monitors, etc. available.

--
 Some informative links:
   news:news.announce.newusers
We've slightly trimmed the long signature. Click to see the full one.
Re: UARTs and interrupts

Quoted text here. Click to load it

Or some counter is incremented each time a new item is placed in
the buffer. The sender increments the counter that the receiver
reads and stores in a local variable. On the next cycle
the receiver checks the counter against its local variable
in order to see if new items were added to the buffer.

The receiver reads the counter but never writes to it, thus it
needs not to be protected by a semaphore or the like.

The receiver then reads the data and increments another counter.
The sender will check that counter in order to verify that the
buffer is not full.

This works well if you have a periodic activation of the receiver
or if the sender activates the receiver whenever the counter is
incremented.

The counter must be incremented once the data has been put to
the buffer not before. Then if the sender is interrupted by
the receiver after the data were written but before the counter
was incremented, the receiver will not retrieve them since
the counter will be equal to the local value.


Site Timeline