[En-Nut-Discussion] Hardware Register Access Using Volatile Pointer
Harald Kipp
harald.kipp at egnite.de
Tue Apr 26 09:27:50 CEST 2011
Hi Bernd,
On 4/25/2011 10:45 PM, Bernd Walter wrote:
> On Mon, Apr 25, 2011 at 07:51:25PM +0200, Harald Kipp wrote:
>> #define inr(_reg) (*((volatile unsigned int *)(_reg)))
> The Atmel ARM include has something like this:
> typedef volatile unsigned int AT91_REG;// Hardware register definition typedef struct
> _AT91S_SYS {
> AT91_REG AIC_SMR[32]; // Source Mode Register
> AT91_REG AIC_SVR[32]; // Source Vector Register
IMHO, that's even worse. inr() and outr() offer much more flexibility.
>> The problem is, that the compiler will not guarantee, that the
>> sequence of statements is kept. To force this, a memory barrier
>> can be used
> Which statements can be reordered?
Any, as long as this doesn't break the logic of statements.
The order of accesses to volatile memory is kept. But when mixing
volatile and non-volatile accesses, the optimizer may re-order the
statements, which may introduce unexpected side effects.
I vaguely remember such a case, but cannot remember where that happened
exactly. Let me try to construct a lousy example. Let's assume, we have
an interrupt routine running in two modes, controlled by a global variable.
/* Set mode used by IRQ function. */
imode = 0;
/* Enable interrupts. */
outr(EIR, 1);
The compiler may decide to execute
outr(EIR, 1);
imode = 0;
Of course we could declare imode as volatile too to force the compiler
to execute the statements in right order. BUT:
1. imode is not volatile per definition, because its content will not
change out of the scope of the compiler.
2. Each time imode is used at other places, the compiler will generate
less optimal code.
> A memory barrier usually is more than just a compiler thing, since
> it pushed things out to the coherence point for other CPUs or DMA.
I know, but when implemented as
asm volatile("": : :"memory");
it is just a compiler thing. It simply tells GCC to write out all values
which are temporarily kept in registers. This will have the effect, that
outr() and inr() are working correctly even if the pointers are not
declared as pointers to volatiles.
> - IMHO the compiler shouldn't reorder things around volatile
> variables.
Is this documented (guaranteed) anywhere?
> With the original volatile it must read, since it is volatile. In
> your cae with the barrier I'm not sure, since it's not reading from
> a volatile memory anymore it might be optimized away.
That's the point. I assume too, that the suggested approach will remove
inr(). Further, I'm not sure, that an access to volatile memory will be
kept, if the result is not used in the code. I wasn't able to find any
document on this either.
Regards,
Harald
More information about the En-Nut-Discussion
mailing list