5、映射的思考

 

学习了 GPIO_newbule 之后,一血关于映射上面的问题总结。

 

1、映射方法

    实现映射的方法是通过:ioremap ,IO_ADDRESS 这两种方法,实现物理和虚拟地址的映射,它们返回的结果就是虚拟地址了,但是这两种方法的区别是:

ioremap : 动态映射,一般是在外围的控制器的地址。当 映射的时间,是当加载相对应函数的是,才完成映射的操作。

IO_ADDRESS  : 静态映射,一般是寄存器资源映射上,映射的时间是,当系统启动的时候,就完成映射的操作,

1.1、IO_ADDRESS  的映射

   物理地址 = 基址 + 偏移地址,所以使用 IO_ADDRESS   进行地址映射的时候,存在两种映射,既直接使用物理地址映射和先对基址映射之后,再加上偏移地址,这两种映射的最终地址,都是一样的。

方法一:

#define IOConfig         IO_ADDRESS(0x200f0000) //IO复用寄存器

#define HW_REG(reg) *((volatile unsigned int *)(reg))

HW_REG(IOConfig + 0x138) = 0;

    上面的代码,是实现 200f_0000 基址地址的映射之后,再加上偏移地址。

 

方法二:

writel(0, IO_ADDRESS(0x200F0138));

    实现是对物理地址做完映射之后,进行写入 0 的操作。

   两种方法,经过验证,最终得到的虚拟地址是完全一样的,本平台使用的是 海思的 HI3518平台,所以关于 IO_ADDRESS 的定义是位于

Io.h (arch\arm\mach-hi3518\include\mach)  这里,里面看到 IO_ADDRESS 定义为:

#define __io(a)        __typesafe_io(a)
#define __mem_pci(a)    (a)

#define HI3518_IOCH1_PHYS 0x10000000 /* 0x1000_0000 ~ 0x1020_0000 */
#define HI3518_IOCH2_PHYS 0x20000000 /* 0x2000_0000 ~ 0x2020_0000 */
#define HI3518_IOCH1_SIZE 0x200000
#define HI3518_IOCH2_SIZE 0x700000

#define HI3518_IOCH1_VIRT 0xFE000000
#define HI3518_IOCH2_VIRT (HI3518_IOCH1_VIRT + HI3518_IOCH1_SIZE)

/*
*         physical addr       <--->         virtual addr
* [0x1000_0000 ~ 0x1020_0000) <---> [0xFE00_0000 ~ 0xFE20_0000)
* [0x2000_0000 ~ 0x2070_0000) <---> [0xFE20_0000 ~ 0xFE90_0000)
*/
#define IO_IOCH1_OFFSET        (HI3518_IOCH1_VIRT - HI3518_IOCH1_PHYS)
#define IO_IOCH2_OFFSET        (HI3518_IOCH2_VIRT - HI3518_IOCH2_PHYS)

#define IO_ADDRESS(x) ((x) >= HI3518_IOCH2_PHYS ? (x) + IO_IOCH2_OFFSET\
                        : (x) + IO_IOCH1_OFFSET)

 

 

 

1.3、计算虚拟地址

当IO_ADDRESS(0X200F0000) = (0X200F0000) + IO_IOCH2_OFFSET
    = (0X200F0000) + (HI3518_IOCH2_VIRT - HI3518_IOCH2_PHYS)
    = (0X200F0000) + (HI3518_IOCH2_VIRT - 0x20000000)
    = (0X200F0000) + (0xFE000000 + 0x200000) - 0x20000000
    = FE2F0000  
   
所以,IO_ADDRESS(0X200F0000) + 0x138 = FE2F0138

当当IO_ADDRESS(200F0138) = (200F0138) + IO_IOCH2_OFFSET
    = 200F0138 + (HI3518_IOCH2_VIRT - HI3518_IOCH2_PHYS)
    = 200F0138 + (HI3518_IOCH1_VIRT + HI3518_IOCH1_SIZE) - 0x20000000
    = 200F0138 + 0xFE000000 + 0x200000 - 0x20000000
    = FE2F0138

   可见最终的虚拟地址,都一样的。

 

1.4、虚拟地址的操作

    对已经完成虚拟地址操作之后,需要对这个地址操作的时候,有以下方法:

void writeb(unsigned value, address);   // 8位

void writew(unsigned value, address);  // 16 位

void writel(unsigned value, address); // 32 位

    这些写入函数,完成写 value 到 address 的地址,address 地址都是已经完成映射的虚拟地址

 

unsigned readb(address);

unsigned readw(address);

unsigned readl(address);

    读出函数,是将虚拟地址 address 处,读出寄存器的值。

 

#define HW_REG(reg) *((volatile unsigned int *)(reg))

HW_REG(IOConfig + 0x138) = 0;

    通过,宏代码的方法实现寄存器的写入

 

#define GPIO0_6_DIR        IO_ADDRESS(0x20140000+ 0x400)

flag = HW_REG(GPIO0_6_DIR);

    完成寄存器数据的读出。

 

1.5、通过报错的方法寻找头文件

    笔者,想寻找关于 IO_ADDRESS 是在那个头文件定义的,经过朋友指点才找到,但是还有通过重复定义的方法,编译器会提供相关的信息,其实就可以找到。

    在函数里面,自己定义 IO_ADDRESS ,而头文件包含的地方,也是存在 IO_ADDRESS  的,所以就出现了重复定义的错误,当编译的时候,就会报错:

/home/carlos/3516C/driver/gpio_newBlue/gpio.c:168: warning: "IO_ADDRESS" redefined
arch/arm/mach-hi3518/include/mach/io.h:25: note: this is the location of the previous definition

    可见,与真正的头文件是在,arch/arm/mach-hi3518/include/mach/io.h,达到我们的目的

时间: 2024-08-06 07:55:33

5、映射的思考的相关文章

ZF框架数据对象映射模式的思考

最近学了ZF框架,对手册中DB这一节Zend_Db_Table_Row的介绍中说,使用了Zend_Db_Table::find()或::findRow()方法可以返回一个Zend_Db_Table_Row的对象,该对象自动映射到表中的这一行记录,字段和类属性完全关联在一起(字段名是下划线分隔的,属性名由首个单词小写的驼峰式命名,如自动“last_name”,则操作时属性名“lastName”),获取任何字段就直接像操作类属性一样,如: $row = $table->fetchRow('first

关于JOS 未对全部内存分页映射之前 物理地址映射问题的思考

在kern/pmap.c 里面会又以下这段代码,要知道boot_alloc只会分配线性地址,真正建立虚拟页和物理页映射关系的在后面的page_alloc. ////////////////////////////////////////////////////////////////////// // create initial page directory. kern_pgdir = (pde_t *) boot_alloc(PGSIZE); memset(kern_pgdir, 0, PG

FPGA算法映射思考

将图像处理的算法转换为FPGA系统设计的过程称为算法映射,CPU并行算法的实现与FPGA并行算法的实现是有一定区别的. 1.算法系统结构 图像处理算法主要有两种设计结构:流水线结构和并行阵列结构. 1.1 流水线结构 在我看来,流水线结构和我们之前所理解的CPU的串行结构还是有一定区别的.相反,它与处理器的流水线结构很相似,都是依照时钟来进行流水层级的同步. 1.2并行阵列结构 |--Data1--->Data1-->Data1 | InputData------Data2--->Dat

面试题思考:什么是 对象/关系 映射集成模块

所谓对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中.本质上就是将数据从一种形式转换到另外一种形式. 详细一点,是 面向对象编程中的 对象(Object) 和关系数据库的 关系(Relation) 的一个映射(Mapping). 产生的原因是因为软件开发已经是面向对象的了. 所有的值,操作都是基于对象的概念. 而数据库还是关系数据库.记录的存储还是一条一条的. 为了在逻辑上

MapReduce源码分析之Task中关于对应TaskAttempt存储Map方案的一些思考

我们知道,MapReduce有三层调度模型,即Job-->Task-->TaskAttempt,并且: 1.通常一个Job存在多个Task,这些Task总共有Map Task和Redcue Task两种大的类型(为简化描述,Map-Only作业.JobSetup Task等复杂的情况这里不做考虑): 2.每个Task可以尝试运行1-n此,而且通常很多情况下都是1次,只有当开启了推测执行原理且存在拖后腿Task,或者Task之前执行失败时,Task才执行多次. 而TaskImpl中存在一个成员变

《星际穿越》关于时间与空间的思考

看完了近期比较火的影片星际穿越,重新刷新了我对世界对宇宙的价值观,可以说这是一部较为实体化把理论把宇宙呈现在观众眼中的影片,让那些不太明白理论的人同样可以感受到宇宙的奥秘,穿梭在宇宙之间,领略着超乎自然神奇力量的世界里,真是一个心旷神怡.相信每一个看完影片的观众都会为之称赞,称赞着自然法则的规律,称赞着科学的伟大,称赞着导演的构思与想象力.影片在现在看来太超前了,也尊重科学,对于科学理论的描述还是最大限度的贴近现有的物理学,除非真的到了那种无法解释而电影又必须用到的地方,导演才展开强大的想象力.

关于数据库‘状态’字段设计的思考与实践

最近在做订单及支付相关的系统,在订单表的设计阶段,团队成员就‘订单状态’数据库字段设计有了一些分歧,网上也有不少关于这方面的思考和探讨,结合这些资料和项目的实际情况,拟对一些共性问题进行更深一层的思考,笔耕在此,和大家一起探讨. 问题综述 这里的分歧点即有团队内部的分歧点,也有网络上常见的一些分歧点,先将存在的分歧点抛出来: 1.订单表的‘订单状态’字段对应的字典值应当包含哪些状态值?对于‘已评论’.‘已退货’.’已退款’这类状态是放到‘订单状态’中?还是独立一个字段标识? 2.订单表的‘订单状

《iOS用户体验》总结与思考-改动版

假设转载此文.请注明出处:http://blog.csdn.net/paulery2012/article/details/25157347,谢谢. 前言: 本文是在阅读<ios用户体验>的过程中,记录的总结和个人的感受思考.不免有错误之处,恳请读者指正,在以下留言就可以. 第一章:ios人机界面指南概述 1.智能手机的特点:大尺寸.高分辨率.强大的计算能力 2.签名交互:滚动轮.导航键.按键和硬键盘.软键盘.触控笔.触屏.输入特性又被称为"签名交互",用户能够通过输入方式

【CV知识学习】神经网络梯度与归一化问题总结+highway network、ResNet的思考

这是一篇水货写的笔记,希望路过的大牛可以指出其中的错误,带蒟蒻飞啊~ 一.    梯度消失/梯度爆炸的问题 首先来说说梯度消失问题产生的原因吧,虽然是已经被各大牛说烂的东西.不如先看一个简单的网络结构, 可以看到,如果输出层的值仅是输入层的值与权值矩阵W的线性组合,那么最终网络最终的输出会变成输入数据的线性组合.这样很明显没有办法模拟出非线性的情况.记得神经网络是可以拟合任意函数的.好了,既然需要非线性函数,那干脆加上非线性变换就好了.一般会使用sigmoid函数,得到,这个函数会把数据压缩到开