c - 如何计算 devmem2/mmap 的 MMIO GPIO 地址

标签 c embedded intel mmap gpio

我正在尝试访问一些 MMIO GPIO 地址以进行 LED 控制和电池监控。但我不知道如何计算正确的地址。

文档说明如下:

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

Documentation

我的问题是北部和西北社区端口 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

任何帮助将不胜感激。

最佳答案

我不明白他们是怎么得到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 寄存器,那么它们并不罕见。通常的方法是要么不读取它们,要么在内存中维护您认为它们应该是什么的副本,然后抽象对象,以便您从寄存器的私有(private)值“读取”并“写入”到实际的 GPIO 引脚并更新您的私有(private)值。

关于c - 如何计算 devmem2/mmap 的 MMIO GPIO 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57635659/

相关文章:

c - Eclipse J-Link ATMEL ARM ATSAME70Q21。当代码的起始地址不同于 0x00400000 时进行调试

c - Intel Intrinsics 代码优化

c++ - 非常适合 Xeon-phi 众核架构的应用程序

linux - 如何实现 ABA 解决方案?

c - 使用 stat 查找文件长度时的错误检查

c - 三个条件排列的最快算法是什么?

c++ - ARM 中的图像处理(埃)

c - pic32中的文件处理

c - 获取recv函数返回的错误号

c - 为什么这个程序会无限循环?