This question came up in the thread titled "Re: Ada, was: Re: Fundamental C question about "if" statements".
I felt it deserved its own thread, because it's far off topic to what's become a very interesting, but far off topic thread.
I, for > >>> Good luck doing that in a reliable way on ARM with gcc when you are
>> accessing device registers.
>>>
>>> If you access a bitfield in the lower 8 bits of a register, the gcc
>>> optimiser can turn that into 8-bit ldrb/strb opcodes instead of 32-bit
>>> ldr/str opcodes and thereby causing the program to break if you need
>>> to access your registers in units of greater than 8 bits.
>>
>> That's a very interesting comment, because that's basically How It Is
>> Done here, and I've had several years worth of success on both ST and
>> TI/
>> Luminary devices. I'm not sure if that's because of the way I define
>> my bitfields (absolutely everything is defined as a struct of
>> bitfields, then a union of that struct and a 32-bit integer), or if
>> I've been lucky,
>> or what.
>>
>>
> Do your MCUs _require_ register access in units of 16/32 bits ?
>
> If so, you may be doing something which works for now, but may not work
> in the future.
>
> It might be worth having a quick look with objdump just to be sure.
>
> I have personally had this happen to me and it broke my code due to the
> register access size constraints no longer been true.
>
>> So it looks like:
>>
>> struct SPeriphRegisterBits {
>> unsigned int bit0 : 1; unsigned int bits1_10 : 10; unsigned
>> int bit11 : 1; unsigned int : 16; unsigned int
>> bits28_31 : 4;
>> };
>>
>> union UPerihRegister {
>> struct SPeriphRegisterBits bits;
>> unsigned int all;
>> }
>>
>> All of the various register definitions then get collected into a
>> structure for the peripheral, which gets declared as "extern const",
>> and defined in the linker command file.
>>
>>
> This is a bit more involved than what I was doing. I wonder if this is
> what is saving you for now.
Yes, my MCU's require access in units of 16 or 32 bits, at least in places -- at least, if the ST data book is to be believed that's the case.
I would REALLY like one of the compiler guys to weigh in on this, because I'm wondering if collecting all those unions into a struct and calling it volatile isn't forcing a 32-bit access. It would be nice to know if I'm just bamboozling the optimizer into doing what I want, or if I'm actually _telling_ it to do the right thing.
So, the final definitions (that I left out) is
struct SPeripheralRegs { UPeriphRegister1 REG1; UPeriphRegister2 REG2; -- etc -- };
extern volatile SPeripheralRegs THIS_PERIPHERAL;
Then I access things by
THIS_PERIPHERAL.REGISTER.bits.whatever = someth UPeriphRegister A;
A.all = static_castTHIS_PERIPHERAL.REGISTER.all;
A.bits.whatever = something;
static_castTHIS_PERIPHERAL.REGISTER.all = A.all;
I could see how it might do this by the intent of the language, but I could see that I may just be bamboozling the optimizer, rather than intelligently directing it. So -- I'm curious, in a more-than-idly sort of way.