uint8_t volatile *tx_tail;
/* blah blah */
Declare the pointer volatile, not the value it is pointing to
The principle is right, the details are wrong. You want:
uint8_t * volatile tx_tail;
These things are so very easy to get wrong that I always use typedefs:
typedef uint8_t * pUint8_t;
volatile pUint8_t tx_tail;
That way there is no room for confusion or error.
And I presume it is only tx_tail that could be changing in interrupts,
otherwise tx_head must also be declared volatile.
As a general point, it is a bad idea to use a 16-bit value as the
"volatile" variable modified in the interrupt routine and checked by the
main code. The problem is that you cannot access the whole 16 bits
atomically (without added interrupt disables or other code). It doesn't
matter for a simple check, but if the main code can change the value of
tx_tail, or needs to make use of the value (other than for a simple
comparison), while the interrupt is enabled, then there's going to be
trouble. It would be much better to store tx_tail (and tx_head) as an
8-bit index into tx_buffer - 8-bit data can be handled atomically.
Pink Boy wrote:
I recently run into an issue with a struct with some volatile members
and was wondering is this is a problem with me or gcc, ar avr-gcc.
I have a structure used to define a buffer for a serial port somewhat
volatile uint8_t *tx_tail;
/* blah blah */
In my main loop I have a code that waits to see if the buffer is full.
while(dbg_serial_port.tx_head == dbg_serial_port.txtail)
And of course with compiler flags set to optimize for size -Os it hangs
and waits forever.
The only way to get it to work is to declare the whole structure and
tx_tail as volatile. I'd be just annoyed, but if I do that I get a whole
bunch of compiler warnings on stuff like
uint8_t *temp = dbg_serial_port.tx_head;
I can fix those with a cast but doing that is like going after a fly
with a hammer.
Is this a bug with gcc's handling of volatile or just me?
PS: Using the WinAvr 20090313.
AVR-GCC-list mailing list