我有以下 C 结构体,代表外部芯片中的寄存器
typedef union {
// Individual Fields
struct {
uint8_t ELEM_1 : 4 ; // Bits 0-3
uint8_t ELEM_2 : 3 ; // Bits 4-6
uint8_t ELEM_3 : 2 ; // Bits 7-8
} field;
// Complete Value
uint32_t value;
} ELEMENTS_t;
如您所见,ELEM_1 和 ELEM_2 可以毫无问题地放入一个字节中,并且在访问时,汇编代码如下所示
ELEMENTS.field.ELEM_2 = 0x7;
101488: e55b3028 ldrb r3, [fp, #-40] ; 0xffffffd8
10148c: e3833070 orr r3, r3, #112 ; 0x70
101490: e54b3028 strb r3, [fp, #-40] ; 0xffffffd8
ELEMENTS.field.ELEM_1 = 0xf;
101494: e55b3028 ldrb r3, [fp, #-40] ; 0xffffffd8
101498: e383300f orr r3, r3, #15
10149c: e54b3028 strb r3, [fp, #-40] ; 0xffffffd8
它们都以正确的位顺序写入同一字节中。
问题出在我们到达 ELEM_3 时。该元素跨越字节边界,因为它应该放置在位 [8:7] 中,并且为了避免多次内存访问(可能),编译器将其放置在完全独立的字节中,所以当我尝试访问它时,它看起来像这个
ELEMENTS.field.ELEM_3 = 0x3;
10147c: e55b3027 ldrb r3, [fp, #-39] ; 0xffffffd9
101480: e3833003 orr r3, r3, #3
101484: e54b3027 strb r3, [fp, #-39] ; 0xffffffd9
在逐个字段访问这些元素时,这不会导致问题,但在尝试将数据刷新到外部芯片时就会出现问题。
有人知道如何告诉编译器将所有位打包在一起吗?这是使用针对 Zynq SoC 中嵌入的 ARM Cortex-A9 处理器的 Xilinx SDK。
最佳答案
你不能将 9 位打包成一个字节。所以它跨越了字节边界。如果寄存器是单字节,则它只能访问位 0 到 7。
如果您需要同时设置多个位,则可能会出现其他问题。
关于C 结构体,其中元素跨越字节边界并放置在下一个字节中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53550330/