avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] BUG? Comparing of words error.


From: David Brown
Subject: Re: [avr-gcc-list] BUG? Comparing of words error.
Date: Thu, 19 Jan 2006 08:46:49 +0100

There have already been a dozen answers pointing out the O/P's problem.  I
thought you might like to know, however, that there is another way to do an
atomic read of such a counter without disabling interrupts, which can be
useful in some circumstances.  If you have complicated and slow interrupt
routines, or high frequency interrupts, then it's probably not a great idea
as it is non-deterministic.

unsigned short atomic_read_short(unsigned short *addr) {
    unsigned short a, b;
    a = (volatile)(*addr);
    do {
        b = (volatile)(*addr);
        if (a == b) return a;
        a = b;
    };
}

mvh.,

David





----- Original Message -----
From: "Paulo Marques" <address@hidden>


> Flemming Steffensen (sent by Nabble.com) wrote:
> > Hi,
> >
> > This is my first post to this forum. I'm not even sure it's the right
> > place to post, but I think so.
> >
> > I'm trying this with an ATmega8, with a 500Hz oscillator connected at
> > INT0, using WinAVR (avr-gcc 3.4.3).
> >
> > I noticed the problem using this code:
> > ------------
> >
> > unsigned short RotCount;
>
> This should be "volatile unsigned short RotCount;"
>
> > SIGNAL(SIG_INTERRUPT0){
> >         RotCount++;
> > }
> >
> > void test(void){
> >         while (1){
> >                 RotCount = 0;
> >                 while (RotCount < 1000) {}
> >                 RotCount = 0;
> >                 while (RotCount < 2000) {}
> >         }
> > }
>
> Since RotCount is a multi-byte variable you need to disable interrupts
> while accessing it.
>
> My personal preference is doing something like:
>
> unsigned short atomic_read_short(unsigned short *addr)
> {
> unsigned short ret;
> cli();
> ret = (volatile)(*addr);
> sei();
> return ret;
> }
>
> void atomic_write_short(unsigned short *addr, unsigned short value)
> {
> cli();
> (volatile)(*addr) = value;
> sei();
> }
>
>
> Then in your main loop, just do:
>
> void test(void){
>          while (1){
>                  atomic_write_short(&RotCount, 0);
>                  while (atomic_read_short(&RotCount) < 1000) {}
>                  atomic_write_short(&RotCount, 0);
>                  while (atomic_read_short(&RotCount) < 2000) {}
>          }
> }
>
> I hope this helps,
>
> --
> Paulo Marques
> Software Development Department - Grupo PIE, S.A.
> Phone: +351 252 290600, Fax: +351 252 290601
> Web: www.grupopie.com
>
> Pointy-Haired Boss: I don't see anything that could stand in our way.
>             Dilbert: Sanity? Reality? The laws of physics?
>
>
> _______________________________________________
> AVR-GCC-list mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>





reply via email to

[Prev in Thread] Current Thread [Next in Thread]