问题
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.
回答1:
What you're looking for is GCC's -fstrict-volatile-bitfields
option:
This option should be used if accesses to volatile bit-fields (or other structure fields, although the compiler usually honors those types anyway) should use a single access of the width of the field's type, aligned to a natural alignment if possible. For example, targets with memory-mapped peripheral registers might require all such accesses to be 16 bits wide; with this flag you can declare all peripheral bit-fields as unsigned short (assuming short is 16 bits on these targets) to force GCC to use 16-bit accesses instead of, perhaps, a more efficient 32-bit access.
If this option is disabled, the compiler uses the most efficient instruction. In the previous example, that might be a 32-bit load instruction, even though that accesses bytes that do not contain any portion of the bit-field, or memory-mapped registers unrelated to the one being updated.
In some cases, such as when the packed attribute is applied to a structure field, it may not be possible to access the field with a single read or write that is correctly aligned for the target machine. In this case GCC falls back to generating multiple accesses rather than code that will fault or truncate the result at run time.
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. It is therefore recommended to define all bits of the field's type as bit-field members.
The default value of this option is determined by the application binary interface for the target processor.
along with use of the volatile
keyword. See: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
回答2:
This is exactly what the volatile
keyword was designed for.
来源:https://stackoverflow.com/questions/42171429/force-gcc-to-access-structs-with-words