租二级目录做网站,做游戏奖金不被发现网站,赵县住房和城乡建设局网站,如何让网站自适应手机一. 简介
在前面的裸机开发实验 LED灯实验中 #xff0c;其实就是操作 IMX6ULL芯片的寄存器。
Linux 驱动开发也可以操作寄存器#xff0c;但是#xff0c;Linux不能直接对寄存器物理地址进行读写操作#xff0c;例如#xff0c;寄存器 A的物理地址为 0X01010101。 裸机…一. 简介
在前面的裸机开发实验 LED灯实验中 其实就是操作 IMX6ULL芯片的寄存器。
Linux 驱动开发也可以操作寄存器但是Linux不能直接对寄存器物理地址进行读写操作例如寄存器 A的物理地址为 0X01010101。 裸机开发时可以直接对 0X01010101这个物理地址进行操作但是Linux 开发则不行。因为 Linux会使能 MMU。
MMU 全称叫做 Memory Manage Unit也就是内存管理单元。在老版本的 Linux 中要求处理器必须有 MMU但是现在 Linux 内核已经支持无 MMU 的处理器了。 二. Linux系统中的地址映射 1. MMU(即内存管理单元)
MMU也就是内存管理单元。主要完成的功能如下 ① 完成虚拟空间到物理空间的映射。 ② 内存保护设置存储器的访问权限设置虚拟存储空间的缓冲特性。 地址映射
我们重点来看一下第 ① 点也就是虚拟空间到物理空间的映射也叫做地址映射。 首先了 解两个地址概念虚拟地址 (VA,Virtual Address) 、物理地址 (PA PhyscicalAddress) 。对于 32 位 的处理器来说虚拟地址范围是 2^324GB 我所使用的开发板DDR3的容量是 256MB 这 256MB 的 内存就是物理内存经过 MMU 可以将其映射到整个 4GB 的虚拟空间。 注意不单单是 DDR外设的寄存器的地址也是物理地址 如下图 所示 物理内存只有 512MB 虚拟内存有 4GB 那么肯定存在多个虚拟地址映射到同一个物理地址上去虚拟地址范围比物理地址范围大的问题处理器自会处理这里我们不要去深究因为 MMU 是很复杂的一个东西。 2. 内存映射涉及函数 Linux 内核启动的时候会初始化 MMU 设置好内存映射设置好以后 CPU 访问的都是虚 拟 地 址 。 例如 I.MX6ULL 的 GPIO1_IO03 引 脚 的 复 用 寄 存 器 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的地址为 0X020E0068 。如果没有开启 MMU 的话 直接向 0X020E0068 这个寄存器地址写入数据就可以配置 GPIO1_IO03 的复用功能。 现在开启 了 MMU 并且设置了内存映射因此就不能直接向 0X020E0068 这个地址写入数据了。我们必 须得到 0X020E0068 这个物理地址在 Linux 系统里面对应的虚拟地址。 这里就涉及到了物理内 存和虚拟内存之间的转换需要用到两个函数 ioremap()函数 和 iounmap 函数。 ioremap 函数 ioremap 函 数 用 于 获 取 指 定 物 理 地 址 空 间 对 应 的 虚 拟 地 址 空 间 定 义 在 arch/arm/include/asm/io.h 文件中定义如下 #define ioremap(cookie,size) __arm_ioremap((cookie), (size),
MT_DEVICE)void __iomem * __arm_ioremap(phys_addr_t phys_addr, size_t size,
unsigned int mtype)
{return arch_ioremap_caller(phys_addr, size, mtype,__builtin_return_address(0));
} ioremap 是个宏有两个参数 cookie 和 size 真正起作用的是函数 __arm_ioremap 此函 数有三个参数和一个返回值这些参数和返回值的含义如下 phys_addr 要映射给的物理起始地址。 size 要映射的内存空间大小。 mtype ioremap 的类型可以选择 MT_DEVICE 、 MT_DEVICE_NONSHARED 、 MT_DEVICE_CACHED 和 MT_DEVICE_WC ioremap 函数选择 MT_DEVICE 。 返回值 __iomem 类型的指针指向映射后的虚拟空间首地址。 iounmap 函数 卸载驱动时需要使用 iounmap 函数释放掉 ioremap 函数所做的映射 iounmap 函数原 型如下 void iounmap (volatile void __iomem *addr) iounmap 只有一个参数 addr 此参数就是要取消映射的虚拟地址空间首地址。 三. 举例说明 假如我们要获取 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); 宏 SW_MUX_GPIO1_IO03_BASE 是寄存器物理地址 SW_MUX_GPIO1_IO03 是映射后 的虚拟地址。对于 I.MX6ULL 来说一个寄存器是 4 字节 (32 位 ) 的因此映射的内存长度为 4 。 映射完成以后直接对 SW_MUX_GPIO1_IO03 进行读写操作即可。 假如我们现在要取消掉 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器的地址映射使用如下代码 即可 iounmap(SW_MUX_GPIO1_IO03); 这里了解 Linux地址映射主要为 LED灯驱动开发准备。