基于GPIO子系统编写LED驱动
编写应用程序进行测试
设置定时器,每5秒打印一次hello world
驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/gpio.h>
/* myled{led1-gpio=<&gpioe 10 0>; led2-gpio=<&gpiof 10 0>;led3-gpio=<&gpioe 8 0>; };
*/
struct device_node *dnode;
unsigned int gpiono;
unsigned int gpiono2;
unsigned int gpiono3;
struct timer_list mytimer;
char kbuf[128]={0};
int major;//定时器处理函数void mytimer_function(struct timer_list *timer){//打印printk("hello world\n");//再次启用定时器mod_timer(timer,jiffies+5*HZ);}ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{int net = copy_from_user(kbuf, ubuf, size);if (net){printk("copy_from_user filed\n");return -EIO;}switch(kbuf[0]){case '1'://LED1if(kbuf[1]=='0')//关灯 gpio_set_value(gpiono,0);else//灯亮gpio_set_value(gpiono,1);break;case '2'://LED2if(kbuf[1]=='0')//关灯gpio_set_value(gpiono2,0);else//灯亮gpio_set_value(gpiono2,1);break;case '3'://LED3if(kbuf[1]=='0')//关灯gpio_set_value(gpiono3,0);else//灯亮gpio_set_value(gpiono3,1);break;}return 0;
}struct file_operations fops={.write=mycdev_write,
};static int __init mycdev_init(void)
{//字符设备驱动注册major=register_chrdev(0,"mychrdev",&fops);if(major<0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n",major);//解析设备树节点信息dnode=of_find_node_by_path("/myled");if(dnode==NULL){printk("解析设备树节点失败\n");return -ENXIO;}//获取LED1 GPIO编号gpiono=of_get_named_gpio(dnode,"led1-gpio",0);if(gpiono<0){printk("获取GPIO编号失败\n");return -ENXIO;}gpiono2=of_get_named_gpio(dnode,"led2-gpio",0);if(gpiono2<0){printk("获取GPIO编号失败\n");return -ENXIO;}gpiono3=of_get_named_gpio(dnode,"led3-gpio",0);if(gpiono3<0){printk("获取GPIO编号失败\n");return -ENXIO;}//申请gpio编号int ret=gpio_request(gpiono,NULL);if(ret){printk("申请GPIO编号失败\n");return -ENXIO;}printk("申请GPIO编号成功:%d\n",gpiono);//申请gpio编号int ret2=gpio_request(gpiono2,NULL);if(ret2){printk("申请GPIO编号失败\n");return -ENXIO;}printk("申请GPIO编号成功:%d\n",gpiono2);//申请gpio编号int ret3=gpio_request(gpiono3,NULL);if(ret3){printk("申请GPIO编号失败\n");return -ENXIO;}printk("申请GPIO编号成功:%d\n",gpiono3);//初始化定时器对象timer_setup(&mytimer,mytimer_function,0);mytimer.expires=jiffies+5*HZ;//定时1s;//注册定时器add_timer(&mytimer);//设置GPIO为输出ret=gpio_direction_output(gpiono,0);if(ret){printk("GPIO输出设置失败\n");return -1;}//设置GPIO为输出ret2=gpio_direction_output(gpiono2,0);if(ret2){printk("GPIO输出设置失败\n");return -1;}//设置GPIO为输出ret3=gpio_direction_output(gpiono3,0);if(ret3){printk("GPIO输出设置失败\n");return -1;}// //灯亮// gpio_set_value(gpiono,1);// //灯亮// gpio_set_value(gpiono2,1);// //灯亮// gpio_set_value(gpiono3,1);return 0;
}
static void __exit mycdev_exit(void)
{//注销定时器del_timer(&mytimer);//gpiod_set_value(gpiono,0);gpio_set_value(gpiono,0);gpio_set_value(gpiono2,0);gpio_set_value(gpiono3,0);//释放GPIO编号gpio_free(gpiono);//释放GPIO编号gpio_free(gpiono2);//释放GPIO编号gpio_free(gpiono3);//注销字符设备驱动unregister_chrdev(major,"mychrdev");}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
应用程序
#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>int main(int argc, char const *argv[])
{char buf[128]={0};int fd=open("/dev/mychrdev",O_RDWR);if(fd<0){printf("打开设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入两个字符\n");printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");printf("第二个字符:0(关灯) 1(开灯)\n");printf("请输入>");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';//向设备文件中写write(fd,buf,sizeof(buf));}return 0;
}