On an ARM processor (HT32F1655), a specific section of registers requires word accesses. From the user manual:
Note that all peripheral registers in the AHB bus support only word access.
But gcc is generating some ldrb (load byte) and strb (store byte) instructions on packed structs. The structs look something like this:
typedef union {
struct {
uint32_t CKOUTSRC : 3; //!< CKOUT Clock Source Selection
uint32_t : 5;
uint32_t PLLSRC : 1; //!< PLL Clock Source Selection
uint32_t : 2;
uint32_t CKREFPRE : 5; //!< CK_REF Clock Prescaler Selection
uint32_t : 4;
uint32_t URPRE : 2; //!< USART Clock Prescaler Selection
uint32_t USBPRE : 2; //!< USB Clock Prescaler Selection
uint32_t : 5;
uint32_t LPMOD : 3; //!< Lower Power Mode Status
} __attribute__((packed)) __attribute__ ((aligned(4)));
uint32_t word;
} reg;
Example usage:
(*(volatile uint32_t*)0x40088000)->CKOUTSRC = 1;
Produces something similar to:
ldrb r2, [r1]
orr r2, r2, #1
strb r2, [r1]
When I need:
ldr r2, [r1]
orr r2, r2, #1
str r2, [r1]
Is there any way to force gcc to only generate instructions that access the whole word? Some options (-mno-unaligned-access) make gcc generate word accesses, but only when the byte is not 4-word aligned.
There is a -mslow-bytes which should do the right thing, however it seems that option does not exist for arm-none-eabi-gcc.
Ideally, there would be a way to force this only on the affected structs.
Please, no "don't use bitfields" answers. I know the drawbacks, but I have the ability here to control the compiler(s) used, so I am not worried about portability.