eclipse 特殊变量的GCC块读-修改-写

j8ag8udp  于 2023-03-22  发布在  Eclipse
关注(0)|答案(1)|浏览(122)

目前,我正在一个项目上与ARM M4 F的arm-gcc和eclipse。
我已经在结构中声明了位域来访问IO寄存器。请参见示例:

struct abc{
   volatile U32 a:1;
   volatile U32 b:1;
   volatile U32 c:30;
}

现在,这些结构体中的一些被Map到外围设备上,这些外围设备使用一组“设置和清除”寄存器。
将1U写入设置寄存器以设置特定位,将1U写入清除寄存器以清除特定位。

但是如果设置了一个位,它也会反映为在读取的清除寄存器中设置。

所以abc_set.a = 1U;的结果是abc_clear.a == 1U
在我的代码中,如果已经写了:abc_clear.a = 1U;

这将导致arm-gcc生成:

ldr.w   r0, [r1, #128]  ; 0x80
orr.w   r0, r0, #536870912      ; 0x20000000
str.w   r0, [r1, #128]  ; 0x80

编译器强制执行读取-修改-写入方法。

但是如果其他位在abc_clear寄存器中反映为“1U”,则它们也会被写入为1U,随后也会被清除。

"我的问题是"
我怎样才能强制gcc对特定的寄存器使用“只写”方案?
我正在寻找类似的东西:

struct abc{
    #pragma "Only-Write" / or attribute((only-write))
    volatile U32 a:1;
    #pragma "R-M-W allowed"
    volatile U32 b:1;
    volatile U32 c:30;
}
zzlelutf

zzlelutf1#

我已经在结构中声明了位域来访问IO寄存器。
你不能用位域来做这件事。基本上,位域不适合这个目的。uP没有指令来写或读几个(少于8)位 *。你浪费了时间
你需要用这种传统的方式

#define REG_X_A_POS (0)
#define REG_X_A (1<<REG_X_A_POS)
#define REG_X_B_POS (1)
#define REG_X_B (1<<REG_X_B_POS)

#define REG_X   (*(volatile uint32_t *)0x44006655)

和用法:

REGX = REG_X_A

结果代码:

foo:
        ldr     r3, .L2
        movs    r2, #1
        str     r2, [r3, #1616]
.L2:
        .word   1140875264

当你需要RMW时,你只需自己做:

REG_X |= REG_X_A;

编译器会生成正确的代码

ldr     r2, .L3
        ldr     r3, [r2, #1616]
        orr     r3, r3, #1
        str     r3, [r2, #1616]
.L3:
        .word   1140875264

另一种方法是使用临时变量(不是很方便的方法)。

struct abc tempReg = abc_set;
tmpReg.a = 1;
abc_set = tempReg
  • 您可以使用(M4)bitbang区域来完成此操作,但编译器对此一无所知。

相关问题