基于IMX6的GPIO驱动程序
Linux内核版本:linux-3.0.35
开发板: IMX6S MY-IMX6-EK200
编译环境:Ubuntu12
主要内容:IMX6S的IO驱动程序编写(ioctl)
实现功能:通过应用层程序控制底层IO的读写
一、驱动层
1、ioctl函数
ioctl函数从应用层传递给驱动层不同的cmd参数,驱动层根据传递的cmd参数,使用switch语句判别,来进行不同的工作。
函数:static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
参数:a、file:文件描述符;
b、cmd:command参数,根据自己的设定的cmd参数,进行不同的工作;
c、arg:应用层和驱动层数据的传递。
因此要写好一个ioctl的驱动程序,首先要学会如何正确设置cmd参数。
在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域:
bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。
bit29~bit15 14位为 “数据大小” 区,表示 ioctl() 中的 arg 变量传送的内存大小。
bit20~bit08 8位为 “魔数”(也称为”幻数”)区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。
bit07~bit00 8位为 “区别序号” 区,是区分命令的命令顺序序号。
要按照Linux内核的约定方法为驱动程序选择ioctl编号,因为如果不按照这个约定进行编写,就有可能因为cmd参数冲突问题不能正确调用ioctl函数。
2、为了合理使用ioctl函数,需要学习cmd参数的设置方法,查看Linux源码可以看到一下内容。
在include/asm/ioctl.h头文件中,我们可以看到供我们使用的创建cmd参数的方法。_IOC(dir,type,nr,size)是封装好的参数设置方法,在它的上一层,又封装了_IOW()和_IOR()进行IO的写和读的cmd参数设置方法。代码截图如下:
再看一下/ioctl-number.txt文件,在这个文件里列出了已经使用的幻数。
从上面的图中可以看出,幻数’x’都没有使用,因此我们在设置cmd参数的时候,幻数的选择可以用幻数’x’。
因此,我们就可以定义自己的cmd参数。nr参数可以随意设置,范围是0~255。size参数也可以根据需求进行设置。我的cmd参数设置如下:
3、ioctl编写实例。
从下图可以看到,当cmd参数为DS_CS1_W时,通过gpio_direction_output()设置IO的方向为输出。通过__gpio_set_value()向底层写入1或0,当写入1时,IO输出高电平,当写入0时,IO输出低电平;当cmd参数为DS_CS1_R时,通过gpio_direction_input()设置IO的方向为输入。通过__gpio_get_value()读取IO引脚状态,并通过copy_to_user()将从底层读取的状态传递给应用层程序。其他引脚设置同理。
4、编译驱动程序
写好驱动层程序,使用Makefile,进行编译。编译好的**.ko文件拷贝到开发板,通过insmod指令进行加载即可。
二、应用层
1、应用层设置的cmd参数要和驱动层的cmd参数一致。
2、应用层的程序就好写多了,可以自己进行任意封装,可以使用如下的方式进行IO操作:
注意:应用层的ioctl函数的cmd参数是传递给驱动层用来区分不同操作的。arg参数是驱动层和应用层交换的数据,例如当写GPIO,arg=1时,应用层给驱动层传递1,驱动层控制GPIO为高电平;当读GPIO时,应用层通过驱动层传递过来的arg参数的值来判别GPIO的高低电平。
3、使用linux-arm-gcc交叉编译应用程序,将编译好的可执行文件拷贝到开发板即可运行。
三、测试
驱动程序和应用测试程序均已测试通过,更为详细的内容可查看源代码,源代码下载地址:点击下载
文章来源: jackcui.blog.csdn.net,作者:Jack-Cui,版权归原作者所有,如需转载,请联系作者。
原文链接:jackcui.blog.csdn.net/article/details/53907825
- 点赞
- 收藏
- 关注作者
评论(0)