离第一篇日志已经隔了蛮几天了.别说我更新的慢,不是我更新慢,是我一直都没时间看书学习的.忘了说下.我还是在校生.平时要上课,打工,去实验室弄STC单片机.所以今天我经过好长时间的准备加上下午的奋斗,我终于把LED给点亮了..现在回想起来,那真是坎坷的.为了这个灯,前几天心情不好,还跟我朋友吵架呢.
言归正传,说说我是怎么点亮这个LED的吧.
其实最烦的是写驱动,驱动部分跟我介绍的第一篇差别不大,主要是对文件的ioctl跟read write这些函数的改写.字符驱动最终都是被用户进程作为文件来操作的.
下面我就之争对主要部分进行讲解吧.最后按照规矩贴出全部代码:
首先,我为了防止多个进程对设备进行控制,依旧采用了计数的方法打开驱动设备:
接着是与open对应的释放(关闭设备)的函数代码.其实内部就是减少计数值而已:
最后一个就是控制函数的代码了,这部分代码就是关键的点亮与熄灭的重点了.先看看代码,然后分析
到这全部重点知识就差不多了.在arm-linux驱动开发中,gpio的地址都是被映射的说,在linux中对gpio进行管脚定义的.所谓的 虚拟地址对物理地址的映射.在arm体系中,外设i/o端口具有与内存相同的物理地址,这样的方式是内存映射方式,
在内存映射方式下,外设的i/o内存资源的物理地址是已知的,由硬件设计决定,但是CPU通常并没有为这些已知的外设i/o内存资源的物理地址预定义虚拟地址范围,驱动程序并不能直接通过物理地址访问i/o内存资源,而必须将它们映射到核心虚拟地
址空间内(通过页表),然后才能根据映射得到的核心虚地址范围通过方位内指令访问这些i/o内存资源.Linux在io.h头文件中声明了函数ioremap(),用来将i/o内存资源的物理地址映射到核心虚地址(3GB~4GB)中,原型:
void* ioremap(unsigned long phys_addr,unsigned long size,unsigned long flags); //物理地址映射到核心虚地址空间
void iounmap(void *addr); //取消ioremap所做的地址映射
将这些地址映射之后,理论上就可以直接通过读写这些i/o资源就可以操作了,但为了保证驱动程序的可移植性,使用linux特定的函数访问i/o内存资源.
static unsigned char __raw_readb(unsigned int ptr); //从指定地址处读取一个char static unsigned int __raw_readl(unsigned int ptr); //从指定地址处读取一个int static void __raw_writeb(unsigned char value, unsigned int ptr); //将一个char写入指定的地址 static void __raw_writel(unsigned int value, unsigned int ptr); //将一个int写入指定的地址
下面是示例代码:
下面是测试代码:
这就是我整个下午的研究成果了,希望能让跟我一样的新手么,得到帮助,少走弯路.....加油