ARM是对内存空间和IO空间统一编址的,所以,通过读写SFR来控制硬件也就变成了通过读写相应的SFR地址来控制硬件。这部分地址也被称为I/O内存。x86中对I/O地址和内存地址是分开编址的,这样的IO地址被称为I/O端口。本文只讨论IO内存的访问

IO内存访问流程

我们知道,为了管理最重要的系统资源并让物理地址对进程透明,Linux使用了内存映射机制,就是一个进程如果想访问一个物理内存地址(eg.SFR地址),那么首先就是将其映射成虚拟地址。

IO内存申请/归还

Linux提供一组函数用于申请和释放IO内存的范围,这两个API在访问IO内存的时候并不是必须的,但是建议使用,他们可以检查申请的资源是否可用,增加IO访问的安全性,如果可用则申请成功,并标志为已用,其他驱动想在这个进程归还资源前申请就会失败。

request_mem_region()宏函数向内存申请n个内存地址,这些地址从first开始,len长,name表示设备的名称,成功返回非NULL失败返回NULL。

/**
* request_mem_region - create a new busy resource region
* @start: resource start address
* @n: resource region size
* @name: reserving caller's ID string
*/ struct resource * request_mem_region(resource_size_t start, resource_size_t n,const char *name)

release_mem_region()宏函数顾名思义就是将request_mem_region()申请的IO内存资源归还给内核以便其他进程也可以访问该IO内存。

/**
* release_mem_region - release a previously reserved resource region
* @start: resource start address
* @n: resource region size
*/
void release_mem_region(resource_size_t start, resource_size_t n,const char *name)

IO内存映射/去映射

申请了IO资源,接下来就是进行物理地址到虚拟地址的映射。内核提供的API如下

static inline void __iomem *ioremap(unsigned long port, unsigned long size)
static inline void iounmap(volatile void __iomem *addr)

IO内存访问API

ARM的SFR是32bit的,我们在经过了ioremap之后其实就可以直接通过强制类型转换来读取获取的虚拟地址,但是这种方法不够安全,一不小心就会读错位,为此,内核同样提供的标准的API来读写IO内存,不但代码的安全性更高,可读性也得到了改善。

读IO

unsigned int ioread8(void *addr)
unsigned int ioread16(void *addr)
unsigned int ioread32(void *addr)

写IO

void iowrite8(u8 val,void *addr)
void iowrite16(u8 val,void *addr)
void iowrite32(u8 val,void *addr)

读一串IO内存

void ioread8_rep(void *addr,void *buf,unsigned long len)
void ioread16_rep(void *addr,void *buf,unsigned long len)
void ioread32_rep(void *addr,void *buf,unsigned long len)

写一串IO内存

void iowrite8_rep(void *addr,const void *buf,unsigned long len)
void iowrite16_rep(void *addr,const void *buf,unsigned long len)
void iowrite32_rep(void *addr,const void *buf,unsigned long len)

复制IO内存

void memcpy_fromio(void *dest,void *source,unsigned long len)
void memcpy_toio(void *dest,void *source,unsigned long len)

设置IO内存

void memset_io(void *addr,u8 value,unsigned int len)

Linux驱动技术(二) _访问I/O内存的更多相关文章

  1. Linux驱动技术(一) _内存申请

    先上基础,下图是Linux的内存映射模型,其中体现了Linux内存映射的几个特点: 每一个进程都有自己的进程空间,进程空间的0-3G是用户空间,3G-4G是内核空间 每个进程的用户空间不在同一个物理内 ...

  2. Linux驱动技术(八) _并发控制技术

    为了实现对临界资源的有效管理,应用层的程序有原子变量,条件变量,信号量来控制并发,同样的问题也存在与驱动开发中,比如一个驱动同时被多个应用层程序调用,此时驱动中的全局变量会同时属于多个应用层进程的进程 ...

  3. Linux驱动技术(五) _设备阻塞/非阻塞读写

    等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节点都是一个PCB(进程控制块),内核会将PCB挂在等待队列中的所有进程都调度为睡眠状态,直到某个唤醒的条件发生 ...

  4. Linux驱动技术(七) _内核定时器与延迟工作

    内核定时器 软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行.实际上,时钟中断处理程 ...

  5. Linux驱动技术(五) _设备阻塞/非阻塞读写【转】

    转自:http://www.cnblogs.com/xiaojiang1025/p/6377925.html 等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节 ...

  6. Linux驱动技术(四) _异步通知技术

    异步通知的全称是"信号驱动的异步IO",通过"信号"的方式,放期望获取的资源可用时,驱动会主动通知指定的应用程序,和应用层的"信号"相对应, ...

  7. Linux驱动技术(六) _内核中断

    在硬件上,中断源可以通过中断控制器向CPU提交中断,进而引发中断处理程序的执行,不过这种硬件中断体系每一种CPU都不一样,而Linux作为操作系统,需要同时支持这些中断体系,如此一来,Linux中就提 ...

  8. Linux驱动技术(四) _异步通知技术【转】

    转自:https://www.cnblogs.com/xiaojiang1025/p/6376561.html 异步通知的全称是"信号驱动的异步IO",通过"信号&quo ...

  9. 如何编写一个简单的Linux驱动(二)——完善设备驱动

    前期知识 1.如何编写一个简单的Linux驱动(一)——驱动的基本框架 2.如何编写一个简单的Linux驱动(二)——设备操作集file_operations 前言 在上一篇文章中,我们编写设备驱动遇 ...

随机推荐

  1. c++内存管理的一些资料

      C++内存分配方式详解--堆.栈.自由存储区.全局/静态存储区和常量存储区 如何动态调用DLL中的导出类 在dll中导出类,并结合继承带来的问题 如何更好的架构一个界面库,欢迎大家一起讨论 pim ...

  2. Unity3D MonoBehaviour的生命周期(lifecycle)

    官方的事件函数的执行顺序中有详解(Link:Execution Order of Event Functions) (图片来源:http://whatiseeinit.blogspot.com/201 ...

  3. windows多线程同步--事件

    推荐参考博客:秒杀多线程第六篇 经典线程同步 事件Event   事件是内核对象,多用于线程间通信,可以跨进程同步 事件主要用到三个函数:CreateEvent,OpenEvent,SetEvent, ...

  4. Duplicate复制数据库并创建物理StandBy(pfile版本)

    1设定环境如下: Primary数据库 IP 172.17.22.16 SID orcl Standby数据库 IP 172.17.22.17 SID orcl 设置提示,以区分操作的位置 prima ...

  5. nginx https 配置样例

    站点nginx https 配置模板 第一章 nginx 支持https 配置样例 其他 相关链接地址 第一章 nginx 支持https 配置样例 说明:https 段配置参数说明 Server 段 ...

  6. Golang select

    Golang下select的功能和Linux IO复用中的select, poll, epoll相似,是监听 channel 操作,当 channel 操作发生时,触发相应的动作. package m ...

  7. Keepalived源码安装

    1.编译.安装 # tar -xvf keepalived-1.3.9.tar.gz # cd keepalived-1.3.9/ # ./configure -prefix=/usr/local/k ...

  8. PCA主成份分析学习记要

    前言 主成份分析,简写为PCA(Principle Component Analysis).用于提取矩阵中的最主要成分,剔除冗余数据,同时降低数据纬度.现实世界中的数据可能是多种因数叠加的结果,如果这 ...

  9. 译:3.消费一个RESTful Web Service

    这节课我们根据官网教程学习如何去消费(调用)一个 RESTful Web Service . 原文链接 https://spring.io/guides/gs/consuming-rest/ 本指南将 ...

  10. linux每日命令(5):mkdir命令

    linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录名或路径名 2. ...