我想将通用寄存器分成三个独立的寄存器;两个8位寄存器&一个16位寄存器。这是我正在使用的方法,但我认为这可能是错误的。
typedef struct {
volatile uint8_t reg_0;
volatile uint8_t reg_1;
volatile uint16_t reg_2;
} reg_split;
#define REG_BASE (0xA040000C)
#define REG ((reg_split *)REG_BASE)
这就是我访问寄存器的方式:
REG->reg_0 = 0xFF;
这是错误的做法还是更清洁的解决方案?
答案 0 :(得分:3)
对于所有类型的内存映射,最重要的是验证C代码是否产生预期结果。你必须考虑填充和对齐。
您的例子中有一些小问题:
0xA040000C
是签名类型,很可能是unsigned int
。如果你使用像0x5040000C
这样的字面值,它将是(带符号)int
类型。在大多数系统上,签名地址没有意义。 “草率类型”可能会导致各种微妙的错误,特别是与各种形式的整数提升相结合时。考虑到上述评论,您的代码可以重写为:
typedef struct {
uint8_t reg_0;
uint8_t reg_1;
uint16_t reg_2;
} reg_split;
#define REG_BASE (0xA040000Cu)
#define REG (*(volatile reg_split *)REG_BASE)
_Static_assert(sizeof(reg_split) == 4, "Unwanted padding detected");
...
REG.reg_0 = 0xFF;