> The volatile attribute must be used on any variable that may be modified
> by a means that cannot be anticipated by the compiler given the code that it
> can see. Examples include:
> - variables representing hardware registers
> - variables in multi-port memory
> - variables modified by an interrupt handler
I agree with those.
> - variables modified by another thread/task/process that may run at any
> time
Don't agree with that one. Volatile is never the solution to a
problem with threads.
Either proper locks, or message passing, needs to be used.
> You may safely omit the volatile attribute (or cast it away)
I'd think really hard about casting it away as well.
> It should be further noted that use of the volatile attribute does *not*
> guarantee atomic access.
Hence my comment above.
>This is an important consideration when working
> with variables wider than the data path (for 8-bit AVRs, multi-byte
> variables) and also for read-modify-write operations.
Here is a real example for Tim:
Three different methods to read a 32-bit value changed inside
an interrupt on an 8-bit part.
/* Running on 8-Bit AVR: */
#include <avr/interrupt.h> /*
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
*/
#include <atomic.h> /*
http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html
*/
static uint32_t volatile system_ticks_u32;
static uint32_t miss_match_count_u32;
ISR( some_timer )
{
++system_ticks_u32;
}
/*
* In this example the 8-bit AVR changes the 32-bit system_tick variable
* inside the interrupt, a bad value will be returned if
* system_tick_get_BAD() called simultaneously.
*/
uint32_t system_ticks_get_BAD( void );
uint32_t system_ticks_get_BAD( void )
{
return( system_ticks_u32 );
}
/* Interrupts are disabled for the shortest possible time: */
uint32_t system_ticks_get_GOOD( void );
uint32_t system_ticks_get_GOOD( void )
{
uint32_t current_ticks_u32;
/*
* Interrupts turned off while copying 32-bit
* value 8-bits at a time:
*/
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
current_ticks_u32 = system_ticks_u32;
}
return( current_ticks_u32 );
}
/* Never turns the interrupts off: */
uint32_t system_ticks_get_BETTER( void );
uint32_t system_ticks_get_BETTER( void )
{
uint32_t t1_u32, t2_u32;
do{
t1_u32 = system_ticks_u32;
t2_u32 = system_ticks_u32;
if( t1_u32 != t2_u32 )
{
++miss_match_count_u32;
}
}while( t1_u32 != t2_u32 );
return( t2_u32 );
}
Running on a real project of mine, using a XMega128A1 at 4.0 MHz,
miss_match_count_u32 is incremented about every twenty minutes, generally
in clusters of three each. Not shown here is an other counter that
counts if the do{}while() ever repeats the loop more than once, which
has yet to happen.
--
http://blog.softwaresafety.net/
http://www.designer-iii.com/
http://www.wearablesmartsensors.com/Message
Re: [AVR-Chat] Re: gcc compiler bad behaviour
2012-04-14 by Bob Paddock
Attachments
- No local attachments were found for this message.