[chbot] AVR external interrupt and Makefile example
Charles Manning
manningc2 at actrix.gen.nz
Sun Nov 15 23:04:13 GMT 2009
sei()/cli() is not necessarily non-portable because you generally use a macro
that you can redefine whereever it is needed.
What is important though is to guard against reenabling interrupts when not
intended.
For example consider:
void clear_counter(void)
{
cli();
temp = counter;
sti()
return temp;
}
int a_n_other(void)
{
cli();
...A...
clear_counter()
...B...
sti()
}
or
main()
{
/* initialisation at start with interrupts off */
...C..
clear_counter();
...D...
/* Everything set up OK, now turn on interrupts */
sei();
...
}
At first glance that looks like the code section ..B.. in a_b_other is
protected by the cli()/sti(). Nope. The sti() in clear_counter() reenabled
interrupts.
Same with using clear_counter() during start up. It would have turned on
interrupts too soon!
ATOMIC_BLOCK can help, but there is a way to do this manually too by
remembering if interrupts were on or off.
eg
void clear_counter(void)
{
uint8_t istate = interrupt_GetAndDisable()
temp = counter;
interrupt_Enable(istate);
return temp;
}
Have a look at http://github.com/cdhmanning/avrprojects
for examples.
-- Charles
On Sunday 15 November 2009 10:11:58 Richard Jones wrote:
> Many thanks Col,
>
> You located the 'bug' I referred to in my original post.
> 11 improvement opportunities to go!
> However I was unaware of the ATOMIC_BLOCK c99 feature and have to confess
> its portability is a real benefit compared to adding sei and cli
> instructions.
>
> Richard
>
> On Thu, 12 Nov 2009 17:40:15 +1300, Col <colp at paradise.net.nz> wrote:
> > Hi Richard
> >
> > In the interest of the group I would like to point out your supplied
> > code contains a race condition.
> >
> > Basically the count4ms is 16 bit variable on an eight bit micro. If an
> > interrupt occurs 1/2 way through reading the variable you could get
> > unexpected results.
> >
> > My suggestion is something like
> >
> >
> > #include <util/atomic.h>
> >
> > ATOMIC_BLOCK( ATOMIC_FORCEON )
> > {
> > temp = count4ms;
> > }
> > if ( temp >= 305 ) {
> >
> >
> > This is outlined in the libc user manual.
> > http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html
> >
> >
> > Cheers
> > Col.
> >
> > _______________________________________________
> > Chchrobotics mailing list Chchrobotics at lists.linuxnut.co.nz
> > http://lists.ourshack.com/mailman/listinfo/chchrobotics
> > Mail Archives: http://lists.ourshack.com/pipermail/chchrobotics/
> > Web site: http://kiwibots.org
> > Meeting Dates:
> > Tue 15 December 2009 6.30pm
> > Tue 16 February 2010 6.30pm
> > When replying, please edit your Subject line to reflect new content.
>
> _______________________________________________
> Chchrobotics mailing list Chchrobotics at lists.linuxnut.co.nz
> http://lists.ourshack.com/mailman/listinfo/chchrobotics
> Mail Archives: http://lists.ourshack.com/pipermail/chchrobotics/
> Web site: http://kiwibots.org
> Meeting Dates:
> Tue 15 December 2009 6.30pm
> Tue 16 February 2010 6.30pm
> When replying, please edit your Subject line to reflect new content.
More information about the Chchrobotics
mailing list