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: Bruce D. Lightner
Subject: Re: [avr-gcc-list] generic queue library for AVR GCC?
Date: Mon, 15 Nov 2004 14:20:30 -0800
User-agent: Mozilla Thunderbird 0.5 (Windows/20040207)

Geoffrey Wossum wrote:

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 ;)

Below is what I use.  A bit more more efficient in most cases
and does not require matching push/pop. Your way makes me a bit
nervous in C, although, given how "avr-gcc" stack frames work
today, your approach should be OK.

Here are the AVR assembly macros that I use...

    #define begin_critical_section() ({         \
        uint8_t t;                              \
        asm volatile (                          \
                "in %0, __SREG__" "\n\t"        \
                "cli"                           \
                : "=r" (t)                      \
        );                                      \
        t;                                      \
     })

    #define end_critical_section(val)           \
        asm volatile (                          \
                "out __SREG__,%0"               \
                : /* no outputs */              \
                : "r" ((uchar)(val))            \
        )

Here's example usage...

    {
        unsigned char sreg = begin_critical_section();
        sm_qin = sm_qout = 0;   // reset queue pointers
        end_critical_section(sreg);
    }

My way also preserves the original state of the interrupt flag,
which may be essential, depending upon the circumstance.

Best regards,

Bruce

--
 Bruce D. Lightner
 Lightner Engineering
 La Jolla, California
 Voice: +1-858-551-4011
 FAX: +1-858-551-0777
 Email: address@hidden
 URL: http://www.lightner.net/lightner/bruce/


reply via email to

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