本帖最后由 liuyu-419812 于 2015-10-10 18:01 编辑
内容和代码参考:http://blog.csdn.net/junllee/article/details/8900372
Linux驱动编写对于我这种小白来说,还是有难度的,还是先从应用出发学习Linux,把FirePrime给玩起来。 FirePrime开发板上预留了很多的接口,如果不用岂不可惜了,先从简单的GPIO开始。Linux内核中GPIO是最简单,最常用的资源驱动程序,应用程序都能够通过相应的接口使用GPIO,GPIO使用0~MAX_INT之间的整数标识,不能使用负数。用户空间访问GPIO,即通过sysfs接口访问GPIO,下面是/sys/class/gpio目录下的三种文件: export/unexport文件 gpioN文件:指代具体的gpio引脚 gpio_chipN文件:指代gpio控制器 必须知道以上接口没有标准device文件和它们的链接。 1.export/unexport文件接口: /sys/class/gpio/export,该接口只能写不能读。 用户程序通过写入GPIO的编号来向内核申请将某个GPIO的控制权导出到用户空间,当然前提是没有内核代码申请这个GPIO端口。如果想申请开发板上的GPIO1_B4这个端口,它的GPIO号为32+8+4=44,例如: 上述操作会为44号GPIO创建一个节点gpio44,此时/sys/class/gpio目录下边生成一个gpio44的目录。 /sys/class/gpio/unexport和导出的效果相反。例如 上述操作将会移除gpio44这个节点。 2./sys/class/gpio/gpioN 指代某个具体的GPIO端口,主要用到如下属性文件: (1)direction:表示GPIO端口的方向,读取结果是in或out。该文件也可以写,写入out 时该GPIO设为输出同时电平默认为低。 (2)value :表示GPIO引脚的电平,如果GPIO被配置为输出,这个值是可写的,记住任何非零的值都将输出高电平。 (3)edge:表示中断的触发方式,edge文件有如下四个值:"none", "rising", "falling","both"。 none表示引脚为输入,不是中断引脚 rising表示引脚为中断输入,上升沿触发 falling表示引脚为中断输入,下降沿触发 both表示引脚为中断输入,边沿触发 这个文件节点只有在引脚被配置为输入引脚的时候才存在。当值是none时可以通过如下方法将变为中断引脚。 对于是both,falling还是rising依赖具体硬件的中断的触发方式。此方法即用户态GPIO转换为中断引脚的方式。 3./sys/class/gpio/gpiochipN gpiochipN表示的就是一个gpio_chip,用来管理和控制一组GPIO端口的控制器。 在程序里,主要通过open()函数和write()函数来实现GPIO控制。为了使用这两个函数你需要包含以下头文件: #include<fcntl.h> #include <unistd.h> 在程序里会控制GPIO_B4这个端口输出高低电平。我们在程序里先打开export文件,然后向export文件写入相应控制的GPIO号,使得该GPIO的操作接口从内核空间暴露到用户空间。然后向该GPIO下的direction文件写入out,变为输出接口。最后向该gpio下的value文件写入数值,控制输出的电平。 程序代码如下: - #include<stdio.h>
- #include<unistd.h>
- #include<fcntl.h>
- #include<string.h>
- void tdelay(int d)
- {
- volatile int j;
- for(j = 0; j<d*1000000;j++);
- }
- int main(int argc,char **argv)
- {
- int gpio_fd = -1;
- int ret;
- char gpio[] = "44";
- char dir[] = "out";
- gpio_fd = open("/sys/class/gpio/export",O_WRONLY);
- if(gpio_fd<0)
- {
- printf("open gpio/export1 failed\n");
- return -1;
- }
- ret = write(gpio_fd,gpio,strlen(gpio));
- if(ret < 0)
- {
- printf("Write to gpio/failed\n");
- return -1;
- }
- close(gpio_fd);
- gpio_fd = open("/sys/class/gpio/gpio44/direction",O_RDWR);
- if(gpio_fd < 0)
- {
- printf("open gpio44/direction failed\n");
- return -1;
- }
- ret = write(gpio_fd,dir,strlen(dir));
- if(ret < 0)
- {
- printf("write to gpio44/direction failed\n");
- return -1;
- }
- close(gpio_fd);
- gpio_fd = open("/sys/class/gpio/gpio44/value",O_RDWR);
- if(gpio_fd < 0)
- {
- printf("open gpio44/value failed\n");
- return -1;
- }
- int i;
- char off[] = "1";
- char on[] = "0";
- for(i = 0; i<10;i++)
- {
- printf("led off\n");
- ret = write(gpio_fd,off,strlen(off));
- if(ret < 0 )
- {
- printf("write to gpio44/value failed\n");
- return -1;
- }
- tdelay(30);
- printf("led on\n");
- ret = write(gpio_fd,on,strlen(on));
- if(ret < 0 )
- {
- printf("write to gpio44/value failed\n");
- return -1;
- }
- tdelay(10);
- }
- close(gpio_fd);
- gpio_fd = open("/sys/class/gpio/unexport",O_WRONLY);
- if(gpio_fd<0)
- {
- printf("open gpio/unexport1 failed\n");
- return -1;
- }
- ret = write(gpio_fd,gpio,strlen(gpio));
- if(ret < 0)
- {
- printf("Write to gpio/unexport failed\n");
- return -1;
- }
- close(gpio_fd);
- printf("Hello World");
- return 0;
- }
复制代码 打开一个终端,定位到程序所在的文件夹,编译,执行。gpio_out.c为我的源文件。 - gcc gpio_out.c -o gpio
- sudo ./gpio
复制代码
|