c - 使用 void * 写入硬件寄存器

标签 c embedded

我正在 Altera 软处理器上编写应用程序。 API 提供对 VHDL 中定义的寄存器的访问,如下所示。

#define __IO_CALC_ADDRESS_DYNAMIC(BASE, OFFSET) \
((void *)(((alt_u8*)BASE) + (OFFSET)))

#define IOWR_32DIRECT(BASE, OFFSET, DATA) \
__builtin_stwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))

基于我所学到的有关编写与硬件接口(interface)或直接注册的代码的所有知识,我编写了这样的代码,

typedef uint8_t volatile reg;    /* special type to access registers */

typedef struct reg_one           /* access to base and offsets */
{
    reg data_0;    /* first 8 bits */
    reg data_1;    /* second 8 bits */
    .
    .
} reg_one;

static reg_one *const reg_ptr = (reg_one *)SOME_BASE_ADDRESS;

uint32_t data;

data = 0;

__builtin_stwio(&(reg_ptr->data_0), data);

但是,地址被强制转换为 void * 并且 volatile 和 const 限定符立即被丢弃。是否有解决此问题的方法,或者我只是缺少一些简单的东西?

我知道使用宏来定义指针是一种选择,

#define reg_ptr ((reg_one *)SOME_ADDRESS)

但我更愿意为范围和类型使用常量对象。

提前感谢您的帮助!

最佳答案

我认为使用结构来定义一个设备寄存器接口(interface)的更合适的方法是用普通类型声明结构,然后用关键字 volatile限定结构的类型,当定义指向寄存器基地址的指针,因此:

typedef struct reg_one  /* access to base and offsets */
{
    uint8_t data_0;     /* first 8 bits */
    uint8_t data_1;     /* second 8 bits */
    /* ... */
} reg_one;

/*   key addition: volatile applied to the struct's type, reg_one   */
static volatile reg_one* const reg_ptr = (reg_one*)SOME_BASE_ADDRESS;

这会将通过指针 reg_ptr 对该结构的成员进行的所有访问标记为 volatile 。这对于确保诸如

reg_ptr->data_0 = (uint8_t)data;
/* reg_ptr         has type volatile reg_one*, so 
   reg_ptr->data_0 has type volatile uint8_t      */

不会被优化编译器删除或重新排序。

但您似乎没有通过 C 语言赋值、递增/递减或其他方式访问这些成员。相反,您使用看起来像 GCC 内置的 __builtin_stwio 。根据 http://www.johnloomis.org/altera/nios2/gnutools/binutils/gcc/Altera-Nios-II-Built-in-Functions.html ,内置 __builtin_stwio 定义为

void __builtin_stwio (volatile void *, int)

当您开始使用编译器内置函数时,所有关于它们真实行为的赌注都会落空,因为编译器会给予它们任何它想要的特殊待遇。就是说,我敢打赌您的 GCC 变体将尊重原型(prototype)所暗示的内容。您的编译器很可能既不会删除也不会重新排序对此内置函数的调用,因此它的使用将遵循 volatile 语义。

关于c - 使用 void * 写入硬件寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20385500/

相关文章:

c - stdint.h 和 inttypes.h 丢失

c - 如何使用 Rembedded 解析因子/数据帧

c++ - 类型转换与类型消歧

c++ - 嵌入式 C++,有什么技巧可以避免仅用于返回堆栈上的值的局部变量吗?

c - 没有字符串数组的输出

python - 如何将自定义类及其变量/方法添加到 Visual Studio Intellisense?

c - Chan的FAT FILE SYSTEM MODULE写入字节数有限制吗?

c - dsPIC33EP512MU810 ADC channel 到引脚的映射

c - 嵌入式C函数宏问题

c - MISRA-C适用于Linux应用吗