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全灭。
这就是我们使用静态寄存器的过程。但是一般不用静态映射。
上面是寄存器提供的读写函数。
上面只是顺利的操作,其实在运行程序的时候,有一个问题:
这是访问地址越界的样子。等待搞懂......