For avr 8 bit micro controller a single bit ( flag ) must be set or cleared in some 8 bit integer variable. This set/clear function can be called from normal context ( main ) and also from interrupt handler ( Isr() ). As this, the variable must be made volatile
to prevent it from reordering or keeping it somewhere in registers. std::atomic
is not a valid option here, as there is no underlying OS nor a multi cpu core nor caches so some kind of memory fences are not needed. Even std::atomic
is not part of any avr c++ library.
The operation to set a flag is something like: some_flags|= new_set_flags
.
But with c++20
I get the warning: warning: compound assignment with 'volatile'-qualified left operand is deprecated [-Wvolatile]
.
It is no problem to rewrite the functions by using a temporary variable, but it feels that this is not the intend of making the volatile keyword deprecated in this situation.
BTW: As the variable is stored in RAM, the cpu is not able to set a bit in the memory in a single assembler instruction. As this, the whole operation must be atomic. For that use case the avr-lib has ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
which simply disables interrupts.
#include <util/atomic.h>
volatile uint8_t some_flags;
void SetFlag( uint8_t new_set_flags )
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
uint8_t tmp = some_flags;
tmp |= new_set_flags;
some_flags = tmp;
... vs ...
some_flags|= new_set_flags; // main.cpp:65:19: warning: compound assignment with 'volatile'-qualified left operand is deprecated [-Wvolatile]
}
}
void SomeIsr()
{
SetFlag( 0x02 );
}
int main()
{
SetFlag( 0x01);
}
Question: What is the "correct" way of setting a flag to a int variable if this flags/variable is used in different context on a bare metal controller with a single core without OS nor MMU.
It becomes very curious if you want to set a bit on a IO register, which is on AVR something like PORTA|=0x01;
and the compiler can take that action within a single assembler instruction.
#include <avr/io.h>
int main()
{
PORTA|=0x01; // main.cpp:57:10: warning: compound assignment with 'volatile'-qualified left operand is deprecated [-Wvolatile]
}
0000006c <main>:
6c: d8 9a sbi 0x1b, 0 ; 27
6e: 90 e0 ldi r25, 0x00 ; 0
70: 80 e0 ldi r24, 0x00 ; 0
72: 08 95 ret