[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] About context saving in Vectors
From: |
David Kelly |
Subject: |
Re: [avr-gcc-list] About context saving in Vectors |
Date: |
Wed, 14 Jan 2009 19:22:19 -0600 |
On Jan 14, 2009, at 5:58 PM, Daniel O'Connor wrote:
On Thursday 15 January 2009 04:15:14 Dave Hylands wrote:
And here's some code that implements such a ring buffer. As David
Kelly points out, as long as the index type is uint8_t, then nothing
special is required (which for this particular implementation means
that buffers upto 128 entries would be supported)
<http://websvn.hylands.org/filedetails.php?repname=Projects&path=%2Fcommon%2FCBUF.h&rev=0&sc=0
>
It's important that the queue be declared volatile (as myQ is in the
sample).
And I was just about to ask if someone could post some well tested
code! :)
You will notice Dave Hyland's code is C++.
This is how I did it recently for an AVR usart in plain C. Notice I
wrapped the indexes using a bitwise AND. That isn't always as
efficient as it might seem.
The indexes are named hd and tl, head and tail, as in "food goes in
the head and comes out the tail."
None of these funtions loop, so the indexes do not need to be declared
volatile.
struct {
uint8_t hd, tl;
uint8_t buf[(1<<4)]; // (1<<4) is 16, must be power of
two for wrap
} incoming;
struct {
uint8_t hd, tl;
uint8_t buf[(1<<6)]; // (1<<6) is 64, must be power of
two for wrap
} outgoing;
//
// Incoming character
//
ISR(USART0_RX_vect)
{
if ( UCSR0A & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)) ) { //
if error
UDR0; //
discard
} else {
incoming.buf[incoming.hd] = UDR0; //
reading clears IRQ
incoming.hd = (incoming.hd + 1) &
(sizeof(incoming.buf)-1);
}
}
//
// Transmit complete, ready for another.
// USART0_TX_vect says all the buffers are empty, which we don't
care.
// USART0_UDRE_vect tells us when its ready to send another.
//
ISR(USART0_UDRE_vect)
{
if( outgoing.hd == outgoing.tl ) {
UCSR0B &= ~(1<<UDRIE0); // disable this IRQ
} else {
UDR0 = outgoing.buf[outgoing.tl++];
outgoing.tl &= ~(sizeof(outgoing.buf));
if( outgoing.hd == outgoing.tl ) //
anticipate followup IRQ that just disables
UCSR0B &= ~(1<<UDRIE0); // disable
this IRQ
}
}
//
// Return a character from incoming buffer, or -1 for empty
//
int
my_getchar(void)
{
int c;
if( incoming.hd == incoming.tl )
return(-1);
c = (unsigned)incoming.buf[incoming.tl];
incoming.tl = (incoming.tl + 1) & 0x0f; // increment
and wrap
return(c);
}
//
// Put character in outgoing buffer. Enable UDRIE0 if not already.
//
// Calling routines may disable IRQ so as to prevent the data
// they are sending from changing before its sent, so we have to
// preserve the interrupt bit in SREG.
//
// UDRE0 should be set whenever there is space in the TX buffer
for more.
// Setting UDRIE0 should trigger USART0_UDRE_vect immediately.
//
// No protection provided against over filling the buffers.
//
void
my_putchar(uint8_t c)
{
uint8_t sreg;
sreg = SREG; // save IRQ status, costs almost nothing
cli(); // don't want illegal outgoing.hd during an
IRQ
// Put it in the queue/buffer
outgoing.buf[outgoing.hd++] = c;
outgoing.hd &= ~(sizeof(outgoing.buf)); // make it
legal
// UDR0 is double-buffered so 2 characters can be handled
instantly
// leaving IRQ disabled which would force this data to split
across hops.
if( radio_hop < 3 ) // (re)start now if this is
a clean hop
UCSR0B |= (1<<UDRIE0); // enable USART0_UDRE_vect
SREG = sreg; // restore prior IRQ enable/disable
}
//
// Rather than put the outgoing struct in externally visible space,
// provide a routine to compare head and tail.
// Then expand it with many other conditions. :-(
//
uint8_t
usart_tx_empty(void)
{
return( (outgoing.hd == outgoing.tl) // buffer is
empty
&& ((RF_CTS_I & (1<<RF_CTS_B)) == 0) // radio is
not asking us to stop
);
}
--
David Kelly N4HHE, address@hidden
========================================================================
Whom computers would destroy, they must first drive mad.
- RE: [avr-gcc-list] About context saving in Vectors, (continued)
- Re: [avr-gcc-list] About context saving in Vectors, dlc, 2009/01/14
- Re: [avr-gcc-list] About context saving in Vectors, David Kelly, 2009/01/14
- Re: [avr-gcc-list] About context saving in Vectors, dlc, 2009/01/14
- Re: [avr-gcc-list] About context saving in Vectors, David Kelly, 2009/01/14
- Re: [avr-gcc-list] About context saving in Vectors, Preston Wilson, 2009/01/14
Re: [avr-gcc-list] About context saving in Vectors, Dave Hylands, 2009/01/14
Re: [avr-gcc-list] About context saving in Vectors, Dave Hylands, 2009/01/14
Re: [avr-gcc-list] About context saving in Vectors, Daniel O'Connor, 2009/01/14
RE: [avr-gcc-list] About context saving in Vectors, Weddington, Eric, 2009/01/14