a .应用程序通过阻塞的io模型来读取number变量的值
b.number是内核驱动中的一个变量
c .number的值随着按键按下而改变(按键中断)例如number=0按下按键number=1 ,再次按下按键number=0
d .在按下按键的时候需要同时将led1的状态取反
e.驱动中需要编写字符设备驱动
f.驱动中需要自动创建设备节点
g.这个驱动需要的所有设备信息放在设备树的同一个节点中
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- int ret;
- struct device_node *node;
- struct resource *res;
- int irqno;
- struct gpio_desc *desc;
- unsigned int number=0;
-
- //中断处理函数
- irqreturn_t irq_handler(int irq,void *dev)
- {
- if(number==0)
- {
- number=1;
- //点亮led1
- gpiod_set_value(desc,1);
- }else if(number==1)
- {
- number=0;
- //熄灭led1
- gpiod_set_value(desc,0);
- }
- printk("%d\n",number);
- return IRQ_HANDLED;
- }
-
-
- int pdrv_probe(struct platform_device* pdr)
- {
- printk("%s,%d\n",__FILE__,__LINE__);
-
-
- //解析设备树节点
- node=of_find_node_by_name(NULL,"myplatform");
- if (node==NULL)
- {
- printk("解析设备树节点失败\n");
- return EAGAIN;
- }
- printk("解析设备树节点成功\n");
- //获取软中断号
- irqno=irq_of_parse_and_map(node,0);
- if(irqno==0)
- {
- printk("获取软中断号失败\n");
- return EINVAL;
- }
- printk("获取软中断号成功\n");
- //注册中断号
- ret=request_irq(irqno,irq_handler,IRQF_TRIGGER_FALLING,"key1_inte",NULL);
- if(ret)
- {
- printk("注册中断失败\n");
- return ret;
- }
- printk("注册中断成功\n");
-
- //获取设备信息
- res=platform_get_resource(pdr,IORESOURCE_MEM,0);
- if (res==NULL)
- {
- printk("资源获取失败\n");
- return -ENODATA;
- }
- irqno=platform_get_irq(pdr,0);
- if (irqno<0)
- {
- printk("资源获取失败\n");
- return irqno;
- }
- printk("%#x %d\n",res->start,irqno);
-
- //获取GPIO编号
- desc=gpiod_get_from_of_node(pdr->dev.of_node,"led1",0,GPIOD_OUT_LOW,NULL);
- if(IS_ERR(desc))
- {
- printk("获取GPIO编号失败");
- return PTR_ERR(desc);
- }
-
- return 0;
- }
- int pdrv_remove(struct platform_device* pdr)
- {
- printk("%s,%d\n",__FILE__,__LINE__);
- return 0;
- }
-
- //定义compatible表
- struct of_device_id oftable[]={
- {.compatible="hqyj,platform"},
- {},
- };
- MODULE_DEVICE_TABLE(of,oftable);
-
- struct platform_driver pdrv={
- .probe=pdrv_probe,
- .remove=pdrv_remove,
- .driver={
- .name="test",
- .of_match_table=oftable, //设备树匹配
- },
- };
-
- //对应的是open()
- int mycdev_open(struct inode *inode, struct file *file)
- {
- printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
- return 0;
- }
- //read()
- ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff)
- {
-
- //size参数是用户期待读到的字节长度
- int ret;
- ret=copy_to_user(ubuf,&number,size);
- if(ret)
- {
- printk("数据从内核向用户拷贝失败\n");
- return -EIO;
- }
-
- return size;
- }
- //write()
- ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
- {
- return size;
- }
- //close()
- int mycdev_close(struct inode *inode, struct file *file)
- {
-
- printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
- return 0;
- }
- //操作方法结构体的初始化
- struct file_operations fops=
- {
- .open=mycdev_open,
- .read=mycdev_read,
- .write=mycdev_write,
- .release=mycdev_close,
- };
-
- static int __init mycdev_init(void)
- {
- //注册对象
- platform_driver_register(&pdrv);
- return 0;
- }
- static void __exit mycdev_exit(void)
- {
- //注销中断
- free_irq(irqno,NULL);
- //释放GPIO编号
- gpiod_direction_output(desc,0);
- gpiod_put(desc);
- //注销
- platform_driver_unregister(&pdrv);
- }
- module_init(mycdev_init);
- module_exit(mycdev_exit);
- MODULE_LICENSE("GPL");