19、硬件访问技术

硬件访问技术

 

我们前面点亮led就是使用动态的虚拟地址:

看了动态映射,接下来就是静态映射:

该结构有四个成员:第一个参数是我们的虚拟地址,第二个参数才是我们实际的物理地址,只不过我们现在使用页桢号来表示。假如物理地址是50008000,一页的大小为4K,用物理地址除以4K,就得到页桢号了。它现在是一个宏,是通过下面两步实现的:

我们知道一个页的大小了4K,除以4K就是物理地址右移12位。如上代码。除以2就是向右移动一位。第三是映射区域的长度,第四是区域的类型。

注意:当你有n个地址空间需要映射,就得创建n个上面的结构。

接下来就是看系统是如何完成这种映射关系的。

搜索:s3c_iodesc

我们搜索的结果如上,可以看出这是个数组,这个数组的元素是结构struct map_desc。前面知道一个这样的结果对应的是内存的一片映射区域。

我们来看GPIO的一片区域:

S3c6410芯片手册:

我们查看芯片手册知道,0x7f008000是GPIO这片区域的起始物理地址。

然后这片区域会被映射到下面的虚拟地址:

S3C64XX_VA_GPIO:

接着找后面的S3C_ADDR_CPU:

接着找后面的S3C_ADDR:

接着找S3C_ADDR_BASE和一个偏移量x

找到的是上面的S3C_ADDR_BASE 0XF4000000加上偏移量x,就是S3C_ADDR的地址。

有了这样的地址,当我们的内核要去使用这表的的时候:

我们知道,当我们的6410启动的时候,会去找这样的一张表来完成映射。

这就是内核启动的时候完成的静态映射。

接下来,我们使用静态映射来改写我们的led程序。

我们来搜索S3C64XX_GPKCON.

上面拿到的就是我们的虚拟地址。

S3C64XX_GPK_BASE:

我们可以看到,我们又回到了前面静态映射的物理地址:

所以S3C64XX_GPKCON的地址就是我们的虚拟地址,我们可以直接使用。

修改前面的led.c部分为:

Make编译后:

把生成的led.ko拷贝到开发板运行:

Cat /proc/devices查看主设备号:

创建设备文件:

运行了led_app 1程序后,看到开发板的led全亮。

运行了led_app 0程序后,led全灭。

这就是我们使用静态寄存器的过程。但是一般不用静态映射。

上面是寄存器提供的读写函数。

上面只是顺利的操作,其实在运行程序的时候,有一个问题:

这是访问地址越界的样子。等待搞懂......

原文地址:https://www.cnblogs.com/FORFISH/p/5188469.html