当前位置: 首页 > 科技观察

HDF驱动框架探路:Linux总线机制imx6ull驱动sr501红外传感器

时间:2023-03-17 19:36:45 科技观察

更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com老规矩最终还是希望用完效果会被释放。如下:HDF驱动框架之Pathfinder6:前言上篇文章在操作LED灯的硬件时,直接看原理图,操作寄存器。这是我们在大多数情况下会做的。操作,本章我们的核心重点是使用总线机制,即通过修改设备树来操作硬件。本章框架图总线框架图中涉及的概念介绍1.总线的概念总线是处理器与一个或多个设备之间的通道。在设备模型中,所有设备都通过总线连接。甚至那些内部虚拟“平台”总线。总线可以相互插入,例如USB控制器通常是PCI设备。设备模型显示总线和它们控制的设备之间的连接。Driver1.1首先调用使用总线的逻辑。为了向内核正确注册,所有平台驱动程序必须创建的主要结构是structplatform_driver结构。该结构由许多向平台描述平台驱动程序的回调函数和变量组成。所以我们需要写一个structplatform_driver结构体。然后是两个比较重要的回调函数:probe和removeint(*probe)(...)指向平台驱动中的probe函数的指针。当平台核心有一个它认为驱动程序需要控制的结构platform_device时调用此函数。所以我们会在这个函数中编写驱动程序的逻辑。int(*remove)(…)指向移除函数的指针,当从系统中移除structplatform_device时,或者当从内核中卸载平台驱动程序时,平台核心将调用该移除函数。为了将structplatform_driver注册到平台核心中,需要以structplatform_driver作为参数调用platform_driver_register函数。这种工程通常在平台驱动程序的模块化代码中完成。当即将卸载平台驱动程序时,需要从内核中注销structplatform_driver。这是通过调用platform_driver_unregister来完成的。1.2完整实现代码#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includestaticintmajor;staticstructclass*sr501_class;staticstructgpio_desc*sr501_gpio;staticintirq;staticintsr501_data=0;staticwait_queue_head_tsr501_wq;/*实现相应的open/read/write函数,填写file_operations结构体*/staticssize_tsr501_drv_read(structfile*file,char__user*buf,size_tsize,loff_t*offset){#if0intval;intlen=(size<4)?大小:4;val=gpiod_get_value(sr501_gpio);copy_to_user(buf,&val,len);returnlen;#elseintval;intlen=(size<4)?size:4;/*1。copy_to_uesr*//*2如果有数据.sleep没有数据:放入链表*/wait_event_interruptible(sr501_wq,sr501_data);copy_to_user(buf,&sr501_data,len);sr501_data=0;returnlen;#endif}staticunsignedintsr501_drv_poll(structfile*fp,poll_table*wait){return;}/*定义自己的file_operations结构*/staticstructfile_operationssr501_fops={.owner=THIS_MODULE,.read=sr501_drv_read,.poll=sr501_drv_poll,};staticirqreturn_tsr501_isr(intirq,void*dev_id){printk("%s%sline%d\n",__FILE__,__FUNCTION__,__LINE__);/*1.记录数据*/sr501_data=1;/*2.唤醒APP:去同一个链表唤醒APP*/wake_up(&sr501_wq);returnIRQ_HANDLED;}/*1.GetGPIO*2fromplatform_device.gpio=>irq*3.request_irq*/staticintsr501_probe(structplatform_device*pdev){/*1。获取硬件信息*/sr501_gpio=gpiod_get(&pdev->dev,NULL,0);gpiod_direction_input(sr501_gpio);irq=gpiod_to_irq(sr501_gpio);request_irq(irq,sr501_isr,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"sr501_gpio",NULL操作);/major=register_chrdev(0,"sr501",&sr501_fops);sr501_class=class_create(THIS_MODULE,"sr501_class");if(IS_ERR(sr501_class)){printk("%s%sline%d\n",__FILE__,__FUNCTION__,__LINE__);unregister_chrdev(major,"sr501");returnPTR_ERR(sr501_class);}/*2.device_create*/device_create(sr501_class,NULL,MKDEV(major,0),NULL,"sr501");return0;}staticintsr501_remove(structplatform_device*pdev){device_destroy(sr501_class,MKDEV(major,0));class_destroy(sr501_class);unregister_chrdev(major,"sr501");}staticconststructof_device_idqzk_sr501[]={{.compatible="qzk,sr501"},{},};/*1.定义platform_driver*/staticstructplatform_driversr501s_driver={.probe=sr501_probe,.remove=sr501_remove,.driver={.name="qzk_sr501",.of_match_table=qzk_sr501,},};/*2.在入口函数中注册platform_driver*/staticint__initsr501_init(void){interr;printk("%s%sline%d\n",__FILE__,__FUNCTION__,__LINE__);init_waitqueue_head(&sr501_wq);err=platform_driver_register(&sr501s_driver);returnerr;}/*3。如果有入口函数,就应该有出口函数:当驱动被卸载时,这个出口函数会被调用*uninstallplatform_driver*/staticvoid__exitsr501_exit(void){printk("%s%sline%d\n",__FILE__,__FUNCTION__,__LINE__);platform_driver_unregister(&sr501s_driver);}/*7.其他改进:提供设备信息,自动创建设备节点*/module_init(sr501_init);module_exit(sr501_exit);MODULE_LICENSE("GPL");2.修改设备树2.1修改思路在上面的驱动中,of_device_id结构中的.compatible="qzk,sr501",所以我们需要在设备树中添加一个这样的设备节点2.2修改代码如下:Linux-4.9.88/arch/arm/boot/dts/100ask_imx6ull-14x14.dts3.应用端测试程序3.1测试程序逻辑测试程序只需要不断的读取,等到接收到中断时返回,就会得到返回3.2测试程序完成实现代码#include#include#include#include#include#include<细绳。h>intmain(intargc,char**argv){intfd;intval;fd=open("/dev/sr501",O_RDWR);if(fd==-1){printf("cannotopenfile%s\n",argv[1]);return-1;}while(1){read(fd,&val,4);if(val==0x1){printf("detectpeople\n");}}close(fd);return0;}4。编译4.1配置交叉编译工具链回到源码根目录执行sourceenv.sh配置编译工具链4.2重新生成内核设备树进入源码目录下的Linux-4.9.88文件夹并执行makedtbs重新生成设备树4.3将重新生成的设备树放入开发板的boot目录下cp100ask_imx6ull-14x14.dtb/boot4.4make编译驱动KERN_DIR=~/imx6ullpro/Linux-4.9.88#The开发板使用的内核源代码目录all:make-C$(KERN_DIR)M=`pwd`modules$(CROSS_COMPILE)gcc-osr501_testsr501_test.cclean:make-C$(KERN_DIR)M=`pwd`modulescleanrm-rfmodules.orderobj-m+=sr501_drv.o直接执行make脚本执行上面的Makefile生成测试程序和驱动ko文件4.5加载驱动insmodsr501_drv.ko4.6执行测试程序./sr501_test更多信息请访问:https://harmonyos.51cto,鸿蒙科技社区y与华为共同打造。com