• Linux地址映射那些事,堪称初学者的噩梦!


    Linux地址映射那些事,堪称初学者的噩梦!

    在设备驱动程序的开发过程中,我们通常需要跟硬件地址打交道。在不带操作系统的嵌入式平台上(如51单片机,STM32等),我们是可以直接操作的是硬件物理地址。

    但是在基于Linux的嵌入式平台上,我们想要直接控制硬件的地址基本是不可能的。操作系统操作的是虚拟地址,因此我们只有将物理地址映射成为虚拟地址才能对硬件进行操作。


    我使用的硬件平台是树莓派Raspberry Pi 2 Model B,处理器芯片是BCM2836。我想用树莓派直接控制引脚电平高低(简单的GPIO操作)。官方没有提供BCM2837芯片手册,但是提供了BCM2835芯片手册。BCM2837架构是在BCM2835上做了改变,但是基本不变。BCM2835下载地址

    我们从芯片手册中可以看出三个地址,分别是总线地址、ARM虚拟地址、ARM物理地址。我们下面对这三个地址进行一 一介绍。

    总线地址

    总线地址,顾名思义,是与总线相关的,就是总线的地址线或在地址周期上产生的信号, 外设使用的是总线地址。

    物理地址与总线地址之间的关系是由系统的设计决定的。在x86平台上,物理地址与PCI总线地址是相同的。 在其他平台上,也许会有某种转换,通常是线性的转换。

    物理地址

    在存储器里以字节位单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址(Physical Address),又叫实际地址或绝对地址。

    我们在对Linux系统中是无法直接对物理地址进行操作的,我们操作的都是虚拟地址,而虚拟地址和物理地址之间存在映射关系,具体如下图所示:
    在这里插入图片描述

    物理内存只有 512MB,虚拟内存有 4GB,那么肯定存在多个虚拟地址映射到同一个物理地址上去,虚拟地址范围比物理地址范围大的问题处理器自会处理。

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

    在Linux中,虚拟地址和虚拟地址之间的映射是通过ioremapiounmap 函数实现的。

    虚拟地址

    虚拟地址又称为逻辑地址,基于算法实现的软件层面的地址,物理地址通过MMU(分页管理系统)映射后得到的就是虚拟地址,虚拟地址也是我们在编写程序时使用最多的地址。

    地址映射

    我们通过上面的概念可以了解到虚拟地址向物理地址的映射是通过ioremapiounmap 这两个函数实现的。

    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));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ioremap 是个宏,有两个参数:cookiesize,真正起作用的是函数__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)
    
    • 1

    iounmap 只有一个参数 addr,此参数就是要取消映射的虚拟地址空间首地址。

    关于Linux地址映射的应用大家可以看我另一篇文章:树莓派编写GPIO驱动程序(详细教程)

    👇点击下方公众号卡片获取资料👇
  • 相关阅读:
    Maya arnold 前台渲染没反应
    苹果签名应用掉签频繁原因排查,以及如何避免
    CSS 动画特效运用目录
    【Linux练习生】Linux多线程
    2024-02-26(Spark,kafka)
    面向OLAP的列式存储DBMS-13-[ClickHouse]的MergeTree表引擎原理解析
    优化类问题概述
    以antd为例 React+Typescript 引入第三方UI库
    excel常用函数
    【QT+JS】QT和JS 中的正则表达式 、QT跑JS语言
  • 原文地址:https://blog.csdn.net/qq_45172832/article/details/125867030