1. 原因这里只考虑有 MMU 的芯片,Linux 为了实现进程虚拟地址空间,在启用 MMU 后,在内核中操作的都是虚拟地址,内核访问不到物理地址。
如果在驱动里直接访问物理地址,等于访问了一个非法地址,会导致内核崩溃,下面会有一个相关的小实验。
通过 ioremap() 将物理地址映射为虚拟地址后,内核就能通过 ioremap() 返回的虚拟地址,以 虚拟地址->mmu页表映射-> 物理地址 的形式正确地访问到物理地址了。
ARM Linux 引入设备树特性后,一些支持设备树的设备驱动不再使用直接 ioremap(),改用 drivers/of/address.c/of_iomap(),of_iomap() 的内部仍然会调用 ioremap(),例如:
clk-rk3288.c (drivers\clk\rockchip)
static void rk3288_clk_init(struct device_node *np) {
rk3288_cru_base = of_iomap(np, 0);
[...]
}
2. ioremap() 实验
实验环境:Linux-4.14 + Allwinner/H3。
实验代码:
#include #include #include #include
#define USE_IOREMAP
#define H3_GPIO_BASE (0x01C20800)
static volatile unsigned long *gpio_regs = NULL;
static int __init