我有下面的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当逐个字段访问这些元素时,这不会导致问题,但当尝试将数据刷新到外部芯片时,它会导致问题。
有没有人知道如何告诉编译器把所有的代码打包在一起?它使用的是Xilinx SDK,目标是嵌入Zynq SoC中的ARM Cortex-A9处理器。
发布于 2018-11-30 10:28:56
你不能把9位压缩到一个字节中。所以它跨越了字节边界。如果寄存器为单字节,则应仅访问位0至7。
如果您需要同时设置多个位,可能还有其他问题。
发布于 2018-11-30 10:47:57
我找到了一个解决方案。如果我将所有元素设置为uint32_t而不是uint8_t,它将一次读写32位寄存器,这使得操作可以正常工作。
ELEMENTS.field.ELEM_3 = 0x3;
10147c: e15b32b8 ldrh r3, [fp, #-40] ; 0xffffffd8
101480: e3833d06 orr r3, r3, #384 ; 0x180
101484: e14b32b8 strh r3, [fp, #-40] ; 0xffffffd8
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] ; 0xffffffd8https://stackoverflow.com/questions/53550330
复制相似问题