1

假设有一个 32 位寄存器定义为内存 (DDRAM) 中的TIMER32 位地址TIMER_ADDR

uint32_t TIMER_ADDR; // 32 bits address declared as uint32_t

TIMER的布局定义为:

struct timer {
    uint32_t start:1;
    uint32_t mode: 3;
    uint32_t init: 4;
    uint32_t value:24
}

后来我将本地 var loc_timer 定义为:

struct timer loc_timer;

如何将此寄存器读取到程序中的本地寄存器,以便修改内容

loc_timer.mode = 4;
loc_timer.init = 10;

并将其写回寄存器TIMER

就像是

(*(uint32_t *))&loc_timer = (*((uint32_t *)(TIMER_ADDR))); // read
(*((uint32_t *)(TIMER_ADDR))) = (*(uint32_t *))&loc_timer; // write

但它不起作用:-(

4

3 回答 3

3

像这样:

struct timer loc_timer = *(struct timer *)TIMER_ADDR; // read register
loc_timer.mode = 4;                                   // modify fields
loc_timer.init = 10;
*(struct timer *)TIMER_ADDR = loc_timer;              // write register back again

请注意,由于这是一个内存映射寄存器,您应该将其视为volatile,例如

volatile struct_timer * const timer = (struct timer *)TIMER_ADDR;
struct timer loc_timer = *timer;                      // read register
loc_timer.mode = 4;                                   // modify fields
loc_timer.init = 10;
*timer = loc_timer;                                   // write register back again
于 2013-12-20T09:56:24.893 回答
1

问题 1:寄存器未声明为易失性,因此读取或写入将不起作用。编译器可能会决定将读取优化为与预期不同的值,将其推迟到稍后,或者完全跳过它。

问题2:寄存器是一个名为“TIMER_ADDR”的32位变量。它是否包含地址,如果有,为什么不将其声明为指针?无法告诉读者。

问题 3:由于多种原因,您不能将位域用于硬件寄存器的位映射。看到这个

问题 4:不能使用结构或位域来映射硬件寄存器,不能保证没有启用填充。您需要特定于编译器的编译指示或编译时静态检查来防止这种情况。


如果我们忽略上述内容并猜测 TIMER_ADDR 确实是一个变量而不是一个变量的地址,那么解决方案将是:

struct timer loc_timer = *(struct timer*) &TIMER_ADDR;
// and the other way around:
TIMER_ADDR = *(uint32_t*) &loc_timer;

形式上,这样的强制转换是未定义的行为,编译器可能会警告它们。在实践中,只要我们确定没有对齐或填充问题,它就会起作用。

于 2013-12-20T10:51:11.937 回答
0

经过一些调查,事实是,PROGRAMMER 知道 TIMER_ADDR 指向的数据类型(即结构计时器),因此他/她应该能够正确取消引用它。否则这个练习毫无意义,会打印垃圾!!!

所以在我们的例子中:

struct timer loc_timer;  
loc_timer = *(struct timer *)TIMER_ADDR;  

// Modify some struct members  

// Copy back loc_timer to register  
*(struct timer *)TIMER_ADDR = local_timer;  

// Print new content of TIMER register  
printf("new value  = %08x\n", *(struct timer *)TIMER_ADDR);   
于 2013-12-26T15:59:40.500 回答