驱动学习之静态映射和动态映射

1:静态映射方法的特点:

内核移植时以代码的形式硬编码,如果要更改必须改源代码后重新编译内核在内核启动时建立静态映射表,到内核关机时销毁,中间一直有效对于移植好的内核,你用不用他都在那里

2:动态映射方法的特点:

驱动程序根据需要随时动态的建立映射、使用、销毁映射映射是短期临时的

3:如何选择虚拟地址映射方法

(1)2种映射并不排他,可以同时使用

(2)静态映射类似于C语言中全局变量,动态方式类似于C语言中malloc堆内存

(3)静态映射的好处是执行效率高,坏处是始终占用虚拟地址空间;动态映射的 好处是按需使用虚拟地址空间,坏处是每次使用前后都需要代码去建立映射&销毁映射(还得学会使用那些内核函数的使用)

4:三星版本内核(内核版本2.6.35.7)中的静态映射表

不同版本的内核,其静态映射表的文件名以及文件路径不一定相同,但是一般都在arch/arm/xxx/map_xx.h文件中

(1)主映射表位于:arch/arm/plat-s5p/include/plat/map-s5p.h

CPU在安排寄存器地址时不是随意乱序分布的,而是按照模块去区分的。每一个模块内部的很多个寄存器的地址是连续的。所以内核在定义寄存器地址时都是先找到基地址,然后再用基地址+偏移量来寻找具体的一个寄存器。这个文件夹下面的虚拟地址基地址是不全的,原因是三星在移植的时候只是移植了自己需要的部分,将来我们需要添加其他基地址的时候直接添加就行了。

map-s5p.h中定义的就是要用到的几个模块的寄存器基地址(虚拟地址)。

(2)虚拟地址基地址定义在:arch/arm/plat-samsung/include/plat/map-base.h

#define S3C_ADDR_BASE (0xFD000000) // 三星移植时确定的静态映射表的基地址,表中的所有虚拟地址都是以这个地址+偏移量来指定的

(3)GPIO相关的主映射表位于:arch/arm/machs5pv210/include/mach/regs-gpio.h

表中是GPIO的各个端口的基地址的定义

(4)GPIO的具体寄存器定义位于:arch/arm/mach-s5pv210/include/mach/gpio-bank.h

5:实驱动LED灯

通过驱动代码去操作LED灯和裸机操作LED灯的方法是一样的,都是操作相应的寄存器地址,不同之处在于驱动代码操作的是虚拟地址,而裸机操作的LED灯对应的物理地址。一个物理地址可以对应多个虚拟地址,原因在于虚拟地址最终指向的也是物理地址,(相当于一个房间(物理地址)有多个入口(虚拟地址)一样)但是一个虚拟地址只能对应一个物理地址。

虚拟地址寄存器(查看mach/gpio-bank.h)

#define GPJ0CONS5PV210_GPJ0CON    //0xFD050240
#define GPJ0DATS5PV210_GPJ0DAT    //0xFD050244
#define rGPJ0CON*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT*((volatile unsigned int *)GPJ0DAT)
rGPJ0CON = 0x11111111;     //设置寄存器的相应位
rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));  // 亮
rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));  // 灭

6:动态映射操作LED

6.1:如何建立动态映射

(1)request_mem_region:向内核申请(报告)需要映射的内存资源。

request_mem_region(GPJ0CON_PA, 8, "GPJ0CON"))

参数说明:

GPJ0CON_PA:需要进行虚拟映射的物理地址

8:映射的长度为8字节

"GPJ0CON":描述这个动态映射的名字

(2)ioremap:真正用来实现映射,传给他物理地址他返回给你一个虚拟地址

pGPJ0CON = ioremap(GPJ0CON_PA, 8);

参数:

GPJ0CON_PA:需要进行虚拟映射的物理地址

8:映射的长度为8字节

返回值:成功返回一个虚拟地址(或者是一段虚拟地址的首地址,具体取决于我们需要映射的字节长度),失败返回0

6.2:如何销毁动态映射

(1)iounmap:解除映射

(2)release_mem_region:释放映射

    //使用动态映射来操作LED
    //发出虚拟地址申请请求
if (!request_mem_region(GPJ0CON_PA, 8, "GPJ0CON"))
return -EINVAL;
  //申请虚拟地址
pGPJ0CON = ioremap(GPJ0CON_PA, 8);
      //if (!request_mem_region(GPJ0DAT_PA, 4, "GPJ0DAT"))
     //return -EINVAL;
    //申请虚拟地址
   //pGPJ0DAT = ioremap(GPJ0DAT_PA, 4);
   //使用申请得到的虚拟地址
*pGPJ0CON = 0x11111111;
*(pGPJ0CON+1) = ((0<<3) | (0<<4) | (0<<5));
    //pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
*(pGPJ0CON+1) = ((1<<3) | (1<<4) | (1<<5));
    //释放申请的虚拟地址
    //解除映射
iounmap(pGPJ0CON);
    //iounmap(pGPJ0DAT);
    //释放申请的虚拟地址
   //release_mem_region(GPJ0CON_PA, 8);
release_mem_region(GPJ0DAT_PA, 4);

注:因为这里GPJ0CON(0xe0200240) 和GPJ0DAT(0xe0200244)是两个连续的物理地址,所以我们可以只映射0xe0200240这个物理地址,映射的字节数为8,那么(GPJ0CON+1)就是我们GPJ0DAT对应的虚拟地址。

时间: 2024-10-10 09:18:53

驱动学习之静态映射和动态映射的相关文章

Bottle?中的基本映射和动态映射

这篇Bottle 教程是比较基础的,主要讲解Bottle?的基本映射和动态映射. 基本映射 映射使用在根据不同 URLs 请求来产生相对应的返回内容. Bottle 使用 route() 修饰器来实现映射. from bottle import route, [email protected]('/hello')def hello(): return "Hello World!" run() # This starts the HTTP server 运行这个程序,访问 http://

linux学习 建立静态库,动态库,写简单的makefile

建立静态库 建立四个文件 bin(可执行文件),lib(库),include(头文件),src(放源文件) 这里的起的库明为add 在src文件中执行 1)gcc -c add.c //编译add.c源文件生成add.o目标文件 2)ar crsv ../lib/ libadd.a add.o //对目标文件*.o进行归档,生成lib*.a, 把这个生成文件放在lib里 3)gcc -o main main.c -L(大些的爱偶,放库的路径)../lib   –l(小写的爱偶,库名为add) a

JAVA学习篇--静态代理VS动态代理

本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者的区别是什么呢? 2,通过学习动态代理了解到动态代理是一种符合AOP设计思想的技术,那么什么又是AOP? 下面是我对它们的理解! 代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对

Java设计模式学习06——静态代理与动态代理(转)

原地址:http://blog.csdn.net/xu__cg/article/details/52970885 一.代理模式 为某个对象提供一个代理,从而控制这个代理的访问.代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代.代理类负责请求的预处理.过滤.将请求分配给委托类处理.以及委托类处理完请求的后续处理. 二.代理模式结构 UML类图: 由上图代理模式的结构为: 抽象角色: 真实对象和代理对象的共同接口. 代理角色: 代理对象角色内部含有对真实对

学习笔记-静态SQL和动态SQL

一:静态SQL 在编写pl/sql程序的时候,sql语句已经编写好了(编译时确定) ddl和会话控制语句不能在pl/sql中直接使用 二:动态SQL 在编写pl/sql程序的时候,sql语句还不确定 不编译,执行时动态确定 需要根据用户输入参数动态确定SQL语句 解决pl/sql中不支持ddl语句的问题 动态SQL语法: EXECUTE  IMMEDIATE  ‘DDL,DML语句’  ---sql语句是字符串的形式,sql语句中若有参数,可以:参数名使用 [INTO 〈变量序列〉]      

RT-Thread学习之——静态线程和动态线程

RT-Thread中支持静态和动态两种定义方式. 用线程来举例的话,rt_thread_init对应静态定义方式,rt_thread_create对应动态定义方式. 使用静态定义方式时,必须先定义静态的线程控制块,并且定义好堆栈空间,然后调用rt_thread_init来完成线程的初始化工作.采用这种方式,线程控制块和堆栈占用的内存会放在RW段,这段空间在编译时就已经确定,它不是可以动态分配的,所以不能被释放.而只能使用rt_thread_detach函数将该线程控制块从对象管理器中脱离. 使用

【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理

这篇博文,我们主要以类图和代码的形式来对照学习一下静态代理和动态代理.重点解析各自的优缺点. 定义 代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用. 代理模式不会改变原来的接口和行为,仅仅是转由代理干某件事,代理能够控制原来的目标,比如:代理商,代理商仅仅会买东西,但并不会改变行为.不会制造东西. 让我们通过以下的代码好好理解一下这句话. 分类 静态代理和动态代理 静态代理 静态代理类图 代码演示样例 接口 pac

学习领域驱动设计(二)之上下文映射图及架构

前一篇文章 :"学习领域驱动设计开篇"给大家主要了解了下领域驱动设计是什么!这篇文章主要介绍下上下文映射图及架构相关方面的知识. 1.上下文映射图 1.1上下文映射图为何如此重要 当项目中开始采用DDD时,首先你应该为当前的项目绘制一个上下文映射图,该图主要描述当前项目中的限界上下文之间的集成关系!而上下文映射图的作用就是帮助我们从解决方案空间的角度来看待问题.(限界上下文已在上篇文章中介绍了) U表示上游(Upstream).D表示下游(Downstream) 1.2绘制上下文映射图

NAT地址转换详解(静态NAT,端口映射,动态NAT,PAT)

NAT地址转换概述图 这一章我们将学习并实践,静态NAT地址转换,动态NAT地址转换, 端口映射,PAT端口多路复用 一.了解NAT的优缺点 二.NAT的工作原理 静态转换 (Static Translation)动态转换(Dynamic Translation)端口多路复用(Port Address Translation) 三.NAT的术语于转换表 NAT地址转换一种伪装,确保了地址的安全 如图: PC1第一件事情发出请求,先查询路由表,然后才会根据NAT表转换成公网地址,去访问外部网.源I