2

我对处理器寄存器的概念有一些误解。有一个地址寄存器,比方说,0x0345678。这个寄存器是 32 位宽/长(现在没关系,哪个字是正确的)。正如手册中所写,有某种表/数组:

职位价值
 0 111111...10b
 1 111111...11b
 2 7A
 .....................
 7 3F7C

我必须访问位置 2 的值。我所做的第一件事是:

#define REG 0x0345678

void somereadfunction()
{
   volatile unsigned int *pval = (volatile unsigned int *)REG;
   printf("%x", *(pval | 0x02));
}

正如您已经猜到的那样,这是错误的假设。

另一项尝试是:

    for(unsigned int i = 0; i < 3; i++)
    {
        printf("i: %d, res: 0x%08X", i, *((volatile unsigned int *)REG));
    } 

它有效。所以,我的问题是,为什么以及如何?处理器是否只是使用其他开发人员编写的内部某种魔术算法来切换寄存器值?我对此有点困惑。我知道如何使用一些简单的逐位操作来访问寄存器的第三位,但我不明白,如何通过调用寄存器的 3 次来获得正确的值?

预先感谢您的回答。

添加:处理器是 ARM 7。使用了 i2c 设备。

4

3 回答 3

3

为什么

因为构建您的硬件设备(连接到您的 ARM 处理器)的人可能只声明了一些“属于”设备的地址。然后,他们注意到硬件中的数据比寄存器多,并且更改手册为时已晚,因此他们决定让一些寄存器保存多个值。

怎么样

硬件有一个内部计数器,用于计算来自处理器的读取命令。每次处理器想要从寄存器中读取时,硬件都会向它发送另一条数据,由不可见的内部计数器索引,并增加计数器。计数器是 3 位的,所以它计数 0, 1, ..., 7, 0, 1, ... 等等。

因此,如果要读取索引为 2 的数据,还必须读取所有其他数据元素(3、4、5、6 和 7)以重置不可见计数器。

于 2012-06-12T16:59:54.353 回答
3

内存映射 I/O 寄存器根据对它们的读取和写入更改其内容。他们描述它的方式有点奇怪,通常会向控制寄存器写入一个值,以告诉设备要访问哪个内部寄存器,然后从另一个位置读取该值。

于 2012-06-12T16:42:55.993 回答
2

*(pval | 0x02)*(pval + 0x2)如果您试图索引到该数组中的第二个位置,应该是真的。

您还可以通过在强制转换REG + 0x8之前获取位置 2 处的第三个 32 位值来将 REG 设置为正确的地址。

如果此架构使用字节寻址,则这是正确的,这意味着每个地址都指向一个数据字节。因此,您可以从 0x345678、0x345678+1、0x345678+2 等处读取一个字节的数据。现在,如果您使用的是 32 位架构,则每次只需关注 4 个字节。所以 0x345678 是位置 0,0x345682 是位置 1,依此类推。

您还必须考虑内存对齐,因为您无法进行未对齐的访问。它通常在 32 位架构中的 4 字节边界对齐。

于 2012-06-12T16:50:50.963 回答