struct中的硬件保留寄存器的占位符

时间:2015-09-30 12:52:11

标签: c hardware

我有一个表示一组硬件寄存器的结构。这里有些部分是保留的,既不能写也不能读。是否有占位符或类似的东西,而不是使用明显的变量命名?

typedef volatile struct RegisterStruct
{
  uint8 BDH;
  uint8 BDL;
  ...
  uint8 IR;
  uint8 RESERVED0; // this area should not be accessed
  ...
}

3 个答案:

答案 0 :(得分:3)

明显的命名是正确的选择,因为C中没有“保留”功能。

您可以使用字节大小的整数数组正确填充到正确的长度:

typedef volatile struct RegisterStruct
{
  uint8_t BDH;
  uint8_t BDL;
  uint8_t IR;
  uint8_t __RESERVED[num_of_reserved_bytes]; // this area should not be accessed
  uint8_t NEXT_REGISTER_NAME;
};

答案 1 :(得分:2)

通常使用结构体进行寄存器映射(或类似地,对于数据通信协议映射)的问题是结构可能在任何地方都包含填充字节。

如果您为此目的使用结构(或联合),则必须通过添加一行来确保禁用填充,例如

_Static_assert(sizeof(RegisterStruct) == sizeof(uint8_t)*4, "Padding detected");

这样可以防止填充错误,因为它会阻塞带有填充的结构。

不幸的是,你不能以可移植的方式禁用struct padding;大多数情况下,你想要禁用它,因为它会使程序运行速度最慢,在最坏的情况下,你会得到未对齐访问的硬件异常,所有这些都取决于CPU。

禁用填充的最常见非标准扩展名是#pragma pack(1),但它是非标准且不可移植的。

在我看来,避免所有这些问题的最好方法是完全避免结构用于实际映射。相反,只需将所有内容声明为普通的volatile变量。 (或者通过使用宏,遗憾的是,您可以将某些内容映射到标准C中的特定内存位置)。

当你走得那么远时,没有必要使用任何“保留”的占位符。只是不要将任何内容映射到那些保留的内存位置。

实际上,为什么你想在结构中拥有许多硬件寄存器实际上没有合理的理由,即使由于某些原因在嵌入式编译器中这样做很受欢迎。你会发现为这些编译器编写的寄存器映射是不可读的,而且非常不标准。

对于通信协议,使结构更有意义,但是通常会编写序列化/反序列化例程来填充结构。

答案 2 :(得分:1)

C中没有任何东西可以在结构中声明一个没有名称的占位符/空洞或者名称不可读的东西(const可以帮助但只有写保护)。而且我在gcc的扩展中看不到任何可以帮助的内容。

但是你可以通过使用预处理器来加扰名称,例如:

#define GLUE(X,Y,Z) X ## Y ## Z
#ifdef __GNUC__
#define SCRAMBLE(X) GLUE(X,_,__COUNTER__)
#else
#define SCRAMBLE(X) GLUE(X,_,__LINE__)
#endif

typedef volatile struct
{
  uint8 BDH;
  uint8 BDL;
//  ...
  uint8 IR;
  uint8 SCRAMBLE(RESERVED0);
//  ...
} RegisterStruct;