Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: [AVR-Chat] Re: gcc compiler bad behaviour

2012-04-14 by Bob Paddock

> 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/

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.