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

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

Re: [avr-gcc-list] generic queue library for AVR GCC?


From: gouy yann
Subject: Re: [avr-gcc-list] generic queue library for AVR GCC?
Date: Fri, 12 Nov 2004 11:33:33 +0100 (CET)

to sum up, I'm a lucky "or a very very carefull" guy
because, up to now, I only have one task that writes
or reads in a fifo and they are all less than 255
chars long. :)
Furthermore, it is constructed in a way if a task
doesn't have the necessary place to put a char in the
fifo, it yields to a background task and the fifo will
be emptied during the task switch.

regards.
    Yann

 --- Paul Haas <address@hidden> a écrit : 
> On Thu, 11 Nov 2004, gouy yann wrote:
> 
> > I'm using it with a preemptible multi-tasks kernel
> of
> > my own and I've never notice any problem.
> 
> > I have taken care the tests and modifications of
> the
> > number of elements in the fifo to be done in the
> right
> > sequence, up to now it seems sufficient for
> reading
> > and writing characters from the USART or for
> > inter-tasks communication.
> 
> It would be safe if all 4 of these conditions were
> true:
>     1. only one task calls FIFO_get()
>     2. only one task calls FIFO_put()
>     3. f->nb++ in FIFO_put() is atomic
>     4. f->nb-- in FIFO_get() is atomic
> 
> I wrote a little function:
>     typedef struct {
>       short val;
>     } f;
>     void incr(f* fp) {
>       fp->val++;
>     }
> 
> and compiled it with avr-gcc -S -O3 -c incr.c
>      .global incr
>              .type   incr, @function
>      incr:
>    1.        mov r31,r25
>    2.        mov r30,r24
>    3.        ld r24,Z
>    4.        ldd r25,Z+1
>    5.        adiw r24,1
>    6.        st Z,r24
>    7.        std Z+1,r25
>    8.        ret
> 
> Imagine that I have one task called plus which calls
> incr() and another 
> task called minus that calls the matching decr()
> function.  Assume that 
> val starts at 2.
> 
> If we have the sequence of calls:
> function   fp->val
>   incr()      3
>   decr()      2
>   incr()      3
> 
> The final value is 3 and everything is cool. 
> However if incr() is 
> interrupted at line 5, right after it finishes the
> adiw, then we get the 
> sequence:
>          function         fp->val     r24,r25
> first half of  incr()     2           3
>          decr()            1 
> second half of incr()     3
>          incr()            4
> 
> Producing a final value of 4 after two calls to
> incr() and one call to 
> decr().
> 
> You may not notice a bug like this for a long time. 
> The window for 
> corruption is only 4 instructions long and the exact
> opposite kind of 
> corruption can happen on the decr() side.  If you
> are lucky, the lost 
> increments will cancel out the lost decrements.  Or
> it will look like line 
> noise or lost characters, and you'll blame the
> serial port.  Very rarely 
> will it lead to total failure.
> 
> If you're very very carefull and you know what
> you're doing, you can write 
> fifo routines that don't require critical sections
> as long as only one 
> task reads, only one task writes and the fifo has
> 255 bytes or less. 
> Critical sections make it all easier.
> 
> 
> > bye.
> >   Yann
> >
> > --- Geoffrey Wossum <address@hidden> a écrit :
> >> On Thursday 11 November 2004 1:32 pm, gouy yann
> >> wrote:
> >>
> >>> here is my implementation of a fifo.
> >>> I hope this will help you.
> >>
> >> I took a quick look at these routines.  I noticed
> >> that they lack any type of
> >> "critical section" around where the queue data
> and
> >> pointers are modified.
> >> Calling these routines as-is from an ISR context
> and
> >> from a non-ISR context
> >> might result in race conditions and odd,
> >> intermittent behavior.
> >>
> >> Here's my critical section routines.  The enter
> just
> >> pushes the global
> >> interrupt state and then disables interrupts, the
> >> exit pops the interrupt
> >> state.  Observant list readers might note an
> uncanny
> >> resemblance to NutOS's
> >> critical section code...
> >>
> >> extern inline void utos_enter_cs(void)
> >> {
> >>     asm volatile(
> >>         "in  __tmp_reg__, __SREG__" "\n\t"
> >>         "push __tmp_reg__"          "\n\t"
> >>         "cli"                       "\n\t"
> >>     );
> >> }
> >>
> >> extern inline void utos_exit_cs(void)
> >> {
> >>     asm volatile(
> >>         "pop __tmp_reg__"           "\n\t"
> >>         "out __SREG__, __tmp_reg__" "\n\t"
> >>     );
> >> }
> >>
> >> Since these routines push and pop from the stack,
> >> you have to be careful to
> >> balance them within a function.  I'll leave where
> to
> >> insert them into the
> >> code as an exercise to the reader ;)
> >>
> >> Maybe lack of critical sections is the problem
> with
> >> the original posters code?
> >>
> >> ---
> >> Geoffrey Wossum
> >> Long Range Systems - http://www.pager.net
> ---
> Paul Haas
> http://hamjudo.com 

=====



        

        
                
Vous manquez d’espace pour stocker vos mails ? 
Yahoo! Mail vous offre GRATUITEMENT 100 Mo !
Créez votre Yahoo! Mail sur http://fr.benefits.yahoo.com/

Le nouveau Yahoo! Messenger est arrivé ! Découvrez toutes les nouveautés pour 
dialoguer instantanément avec vos amis. A télécharger gratuitement sur 
http://fr.messenger.yahoo.com


reply via email to

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