• arm处理器IO口驱动代码编写与测试(bcm2835)


    IO口空间的起始地址(物理地址

    我们在编写驱动程序的时候,IO空间的起始地址是0x3f000000,加上GPIO的偏移量0x2000000,所以GPIO的物理地址应该是从0x3f200000开始的,然后在这个基础上进行Linux系统的MMU内存虚拟化管理,映射到虚拟地址上。

    特别注意,BCM2708 和BCM2709 IO起始地址不同,BCM2708是0x20000000,BCM2709是0x3f000000,这是造成大部分人驱动出现“段错误”的原因。树莓派3B的CPU为BCM2709。


    我们需要确定GPFSEL0的物理地址,就要找出偏移量

     

      可以得到 GPFSEL0 的物理地址:0x3F00 0000+(0x7E20 0000- 0x7E00 0000)=0x3F20 0000

    同理可得

    GPSET0的地址为: 0x3F20 001C;
    GPCLR0的地址为: 0x3F20 0028;

    映射虚拟地址

    在驱动开发过程中,一般来说外设的IO内存资源的物理地址是已知的,由硬件的设计决定。但是CPU不会为这些已知的外设IO内存资源预先指定虚拟地址的值,所以驱动程序不可以直接就通过外设的物理地址访问到IO内存,而必须要将其映射到虚拟地址空间(通过页表),然后才能根据内核映射过后的虚拟地址来通过内存指令访问这些IO内存,并对其进行操作。

    在Linux内核的io.h头文件中声明了 ioremap()函数,用来将IO内存资源映射到核心虚拟地址空间(3Gb~4GB)中,当然不用了可以将其取消映射 iounmap()。

    void* ioremap(unsigned long phys_addr , unsigned long size , unsigned long flags)

    void* iounmap(void * addr);

    -------------------------------------------------------------------------------------------------------------------------
    //用map映射一个设备意味着使用户空间的一段地址关联到设备内存上,这使得只要程序在分配的地址范围内进行读取或写入,实际上就是对设备的访问。

    -------------------------------------------------------------------------------------------------------------------------

    第一个参数是映射的起始地址

    第二个参数是映射的长度

    第三个参数是要映射的IO空间和权限有关的标志

    -----------------------------

  • 相关阅读:
    【libevent】异步UDP
    visual studio 2017安装完成后,编译c++项目失败,提示E696,无法打开ctype.h errno.h float.h stdio.h
    第一个 Python 程序
    600+ 道 Java面试题及答案整理(2022最新版)
    TensorFlow 2.9的零零碎碎(二)-构建模型
    《流畅的python》阅读笔记 - 第二章:数据结构
    平面设计师要会3D吗 优漫动游
    SpringBoot项目打包部署
    【215. 数组中的第K个最大元素】
    【资损】发布环境中的兼容性控制设计
  • 原文地址:https://blog.csdn.net/weixin_42714122/article/details/127821696