1. RK3568驱动开发中的虚拟地址映射解析
第一次在RK3568上写LED驱动时,我在/proc/iomem里查到GPIO控制器的物理地址是0xFDC20010,但直接往这个地址写数据却导致系统崩溃。这个经历让我深刻认识到:在Linux驱动开发中,直接操作物理地址是条死路。内核通过虚拟地址管理所有硬件资源,我们必须掌握物理地址到虚拟地址的转换机制。
2. 物理地址与虚拟地址的本质差异
2.1 MMU的地址转换机制
现代处理器通过MMU(内存管理单元)实现虚实地址转换。当CPU发出0x7f8a2000的虚拟地址访问时,MMU会查询页表将其转换为实际的物理地址0xFDC20010。这个过程对应用层完全透明,但在驱动层我们必须主动管理。
RK3568的Cortex-A55处理器采用三级页表结构:
- 页全局目录(PGD)
- 页中间目录(PMD)
- 页表(PTE)
2.2 内核空间的地址映射特点
内核空间占用的虚拟地址范围是0xFFFFFF8000000000~0xFFFFFFFFFFFFFFFF,其中又分为:
- 直接映射区:物理地址+固定偏移直接得到虚拟地址
- vmalloc区:动态分配的虚拟地址空间
- 设备映射区:通过ioremap建立的映射
3. 驱动开发中的地址映射实践
3.1 ioremap函数深度解析
c复制void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
这个函数会将物理地址phys_addr开始的size字节空间映射到内核虚拟地址空间。以GPIO控制器为例:
c复制#define GPIO_PHYS 0xFDC20010
#define GPIO_SIZE 0x1000
static void __iomem *gpio_base;
static int __init gpio_drv_init(void)
{
gpio_base = ioremap(GPIO_PHYS, GPIO_SIZE);
if (!gpio_base) {
printk(KERN_ERR "Failed to remap GPIO region\n");
return -ENO
