欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux 字符设备驱动基本框架(二)

程序员文章站 2024-02-01 14:38:28
...

一、地址映射

我们知道 STM32 无法跑 Linux 系统,是由于它内部没有 MMU(内存管理单元),MMU 主要完成的功能如下:

(1)完成虚拟空间到物理空间的映射。

(2)内存保护,设置存储器的访问权限,设置虚拟存储空间的缓冲特性。

Linux 内核启动的时候会初始化 MMU,设置好内存映射,设置好以后 CPU 访问的都是虚拟地址 。

Linux 字符设备驱动基本框架(二)
如:I.MX6ULL 的 GPIO1_IO03 引脚的复用寄存器 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 地址为 0x020E0068。如果没有开启 MMU,直接向 0x020E0068 地址处写入数据即可配置复用功能。但现在开启了 MMU 并设置了内存映射,因此就不能直接向 0X020E0068 这个地址写入数据了。我们必须得到 0x020E0068 这个物理地址在 Linux 系统里面对应的虚拟地址,这里就涉及到了物理内存和虚拟内存之间的转换,需要用到两个函数:ioremap 和 iounmap。

1、ioremap 函数

用于获取指定物理地址空间对应的虚拟地址空间。

函数原型:void __iomem * ioremap(cookie,size) 			// cookie-物理起始地址  size-映射字节数
返回值:__iomem 类型的指针,指向映射后的虚拟空间首地址

我们要获取 I.MX6ULL 的 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器对应的虚拟地址,使用如下代码即可:

#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
static void __iomem* SW_MUX_GPIO1_IO03;
SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);

2、iounmap 函数

卸载驱动时需要使用 iounmap 函数释放掉 ioremap 函数所做的映射。

函数原型:void iounmap (volatile void __iomem *addr)

__iomem 是什么意思?

【答】:用来表示指针是指向一个 I/O 的内存空间,检查地址空间的有效性。

#define __iomem __attribute((noderef,address_space(2)))

attribute 用来修饰变量,这个变量必须是非解除参考(noderef),即这个变量地址必须是有效的,而且所在的地址空间必须是 2,即 I/O 存储空间。

二、 I/O 内存访问函数

可直接通过指针访问这些地址,但是 Linux 内核不建议这么做,而是推荐使用操作函数对映射后的内存进行读写操作。

1、读操作函数

u32 readl(const volatile void __iomem *addr)   // 32bit 读操作,返回值是读到的值

2、写操作函数

void writel(u32 value, volatile void __iomem *addr)   // 32bit 写操作