我正在编写一个与 VHDL 中定义的许多寄存器接口的应用程序。寄存器为 32 位宽并分配到组中。我得到了组的基地址和组中每个成员的 32 位偏移量。这是一个组的示例,组内的寄存器以及寄存器的结构。
目前 I/O 使用以下位域结构处理,
typedef struct
{
uint32_t data0 : 12;
uint32_t data1 : 1;
...
}volatile data_port;
并使用指向地址的指针修改字段,
data_port *const p_data = (data_port *)0xc006380;
虽然这可能适用于这个平台,但使用当前的编译器,我担心可移植性。我想知道在被迫使用这些非常规数据类型时是否有更好的方法来处理硬件接口?
我能想到的另一种选择是在硬件和寄存器结构之间创建另一个层,一个易失的无符号整数指针,并在应用层中使用位域结构。问题是,数据仍然必须从位域(可能在另一个平台上以不同方式对齐)复制到 int,这可能是另一个主题。
编辑:
我认为我真正想要的是一种消除位域使用的方法。将具有位域成员的结构映射到硬件似乎确实是一种不好的方法。因此,为了消除这种情况,我将使用以下内容之一作为指向易失性内存地址的指针,
#define PeripheralBase ((uint32_t volatile *)BASE)
或者
uint32_t volatile *const peripheral_base = (uint32_t *) BASE;
希望一旦我达到这一点,一切都会在 32 位内很好地对齐。我正在考虑的一种方法是创建相同的 data_port 结构,但删除位打包,然后为每个寄存器专门设置一个函数以将位转换为无符号整数,然后可以将其传递给寄存器使用易失性指针。
就像是,
static inline uint32_t struct_to_uint(data_port *data)
{
return data->data0
+ ((uint32_t)data->data1 << 12)
+ ((uint32_t)data->data2 << 13)
+ .....;
}
我不确定语法是否正确,但想法是在不必担心编译器或平台的情况下将值移入。这是从那时起吗?这种方法是否存在可移植性问题?