首页 > 解决方案 > 如何计算 devmem2/mmap 的 MMIO GPIO 地址

问题描述

我正在尝试访问一些用于 LED 控制和电池监控的 MMIO GPIO 地址。但我不确定如何计算正确的地址。

该文档指出以下内容:

COMMUINTY_BASE = Bus 0 Device 0x0d Function 0 Reg. 0x10
GPIO North Community PORT ID = 0xC5
GPIO North West Community PORT ID = 0xC4
GPIO_PADBAR = COMMUNITY_BASE + PORT ID << 16 + 0x500
GPO Reg = GPIO_PADBAR + GPIO_Offset Bit [0] (LEDs)
GPI Reg = GPIO_PADBAR + GPIO_Offset Bit [1] (Battery)

Example: Reg LED_USER1_RD_N_P1V8A = 0xD0C506A0

文档

我的问题是North和North West Community Port ID有什么区别?我什么时候需要使用哪个?在遵循记录的公式时,我也未能提出示例地址。

我编写了以下 c 程序来进行计算:

int main(void) {
    u_int32_t COMMUINTY_BASE = 0x10;
    u_int32_t GPIO_NORTH_PORT = 0xC5;
    u_int32_t GPIO_WEST_PORT = 0xC4;

    u_int32_t GPIO_PADBAR =  (COMMUINTY_BASE + GPIO_NORTH_PORT) << 16 + 0x500;
    u_int32_t GPIO_REG = GPIO_PADBAR + 0x01;

    printf("0x%04x\n", GPIO_REG);
}

但输出0xd50001不是0xD0C506A0.

如果我尝试使用devmem2它读取示例地址,则会返回所有位都设置为 1 的寄存器。

sudo devmem2 0xD0C506A0 结果读取:0xFFFFFFFF

任何帮助将不胜感激。

标签: cembeddedintelmmapgpio

解决方案


我不明白他们0xD0C506A0究竟是如何得到的,但只是在某种程度上我不明白为什么它在开头的地址0xD0000000中。

您计算其他所有内容的方式有误。运算符的<<优先级高于+,因此方程应括为COMMUNITY_BASE + (PORT ID << 16) + 0x500。计算PORT_ID << 16有问题的端口产生COMMUNITY_BASE + 0xC50000 + 0x500= COMMUNITY_BASE + 0xC50500。为此,您添加红色用户 1 LED 偏移0x1A0以获取COMMUNITY_BASE + 0xC506A0.

我主要在这个级别上做 ARM 架构,所以我不明白设备 0x0D 信息是如何变成COMMUNITY_BASE存在的0xD0000000,但是你有它。

如果您查看文档,您还会看到该地址是只写的(“输出”),这解释了为什么您无法从示例地址中读取。如果您不熟悉使用只写 GPIO 寄存器,它们并不少见。通常的方法是要么不读取它们,要么维护您认为它们应该是的内存副本,然后抽象对象以便您从寄存器的私有值“读取”并“写入”到实际的 GPIO 引脚并更新您的私有值。


推荐阅读