C 结构体,其中元素跨越字节边界并放置在下一个字节中

标签 c struct embedded xilinx cortex-a

我有以下 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/

相关文章:

基于for循环增量的函数指针的C宏扩展

无法打印 C 中的用户定义函数

C++ 在函数参数中正确使用结构

linux - 在嵌入式系统上,您将内核控制台发送到哪里?

image-processing - 如何将单色图像转换为热敏打印机的按位格式

c++ - 从0还是1开始循环?哪一个,为什么?

c - 返回数组 C 的指针时出现指针段错误

c - SO_SNDBUF 小时阻塞 0.04 秒

c - 从动态结构数组中删除元素时出现未定义的行为

c - 重新定义;不同的基本类型(typedef 结构)