强制GCC使用文字访问结构 [英] Force GCC to access structs with words

查看:406
本文介绍了强制GCC使用文字访问结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ARM处理器(HT32F1655)上,寄存器的特定部分需要字访问。请注意,AHB总线中的所有外设寄存器都只支持字访问。
$ b / blockquote>

但gcc正在生成一些 ldrb (加载字节)并且 strb (存储字节)指令打包结构。结构如下所示:

  typedef union {
struct {
uint32_t CKOUTSRC:3; //<!; CKOUT时钟源选择
uint32_t:5;
uint32_t PLLSRC:1; //<!; PLL时钟源选择
uint32_t:2;
uint32_t CKREFPRE:5; //<!; CK_REF时钟预分频器选择
uint32_t:4;
uint32_t URPRE:2; //<!; USART时钟预分频器选择
uint32_t USBPRE:2; //<!; USB时钟预分频器选择
uint32_t:5;
uint32_t LPMOD:3; //<!;低功耗模式状态
__attribute __((packed))__attribute__((aligned(4)));
uint32_t word;
} reg;

示例用法:

 (*(volatile uint32_t *)0x40088000) - > CKOUTSRC = 1; 

产生类似于:

  ldrb r2,[r1] 
orr r2,r2,#1
strb r2,[r1]

当我需要时:

  ldr r2,[r1] 
orr r2,r2,#1
str r2,[r1]

有什么办法强制gcc只生成访问整个单词的指令?有些选项( -mno-unaligned-access )会让gcc产生字访问,但只有当字节不是4字对齐时才是。



有一个 -mslow-bytes 应该做正确的事情,但是看起来这个选项对于arm-none-eabi-gcc不存在。



理想情况下,只会在受影响的结构中强制执行此操作。



请不要不要使用位域的答案。我知道这些缺点,但我有能力在这里控制使用的编译器,所以我不担心可移植性。

解决方案

您正在寻找的是GCC的 -fstrict-volatile-bitfields 选项:


如果访问易失性位字段(或其他结构字段,尽管编译器通常会尊重这些类型),则应该使用此选项应该使用字段类型的宽度的单个访问,对齐到自然对齐if可能。例如,具有内存映射外设寄存器的目标可能要求所有这些访问都是16位宽;使用此标志,您可以将所有外设位字段声明为无符号短符号(假设这些目标中的16位短),以强制GCC使用16位访问,而不是更高效的32位访问。



如果禁用此选项,编译器将使用最高效的指令。在前面的例子中,这可能是一个32位的加载指令,即使它访问的字节不包含位域的任何部分,或者存储器映射的寄存器与正在更新的寄存器无关。



在某些情况下,例如将压缩属性应用于结构字段时,可能无法通过为目标机器正确对齐的单个读取或写入来访问该字段。在这种情况下,GCC会重新生成多次访问,而不是在运行时会错误或截断结果的代码。

注意:由于C / C ++的限制, +11内存模型,写入访问不允许触摸非位域成员。因此,建议将字段类型的所有位定义为位字段成员。



此选项的默认值由目标处理器的应用程序二进制接口确定。

以及使用 volatile 关键字。请参阅: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options。 HTML


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.

解决方案

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

这篇关于强制GCC使用文字访问结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆