Linux下驱动开发

linux下驱动开发  
1.简介        驱动,是指驱动计算机里软件的程序。驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。驱动程序是操作系统与硬件连接的桥梁。
       设备驱动最通俗的解释就是“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮询、中断处理、dma通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。
2.驱动分类 linux驱动分类:
 字符设备、块设备、网络设备。
 网络设备: 有线网卡、无线网卡、其它与网络相关的设备。
 块设备: u盘、sd卡、硬盘、光盘等。
 字符设备: 除了块设备和网络设备,其它都归结于字符设备。
 字符设备中分类: 杂项设备、输入设备(键盘、鼠标、触摸屏)、帧缓冲(显示类设备)、rtc设备、串口设备等。
3.杂项设备       驱动程序是应用层和硬件层的连接桥梁,应用层只管完成应用逻辑开发和界面设计,驱动层则处理硬件配置,实现应用层相关接口函数。
      杂项设备:字符设备类的一种,是除了上述输入设备、帧缓冲设备、rtc设备后的其它设备,例led设备,由于不好归结于上述分类,则可将led设备按杂项设备类进行注册。杂项设备主设备号为10。
      在生成的设备节点中,主设备号用来区分设备类。如字符设备中杂项设备主设备号为10,帧缓冲设备主设备号为29;次设备号用来区分这个类中的具体硬件。
4.驱动注册框架 4.1开发平台 开发平台:ubuntu18.04
编译器:arm-linux-gcc
硬件平台:tiny4412基于cortex-a9 4核1.5ghz
开发板内核:linux3.5 4.2 驱动模板#include #include /*驱动初始化*/static int __init wbyq_hello_module_init(void){ printk(驱动入口,驱动注册成功n); return 0;}/*驱动释放*/static void __exit wbyq_hello_module_cleanup(void){ printk(驱动出口,驱动注销成功n);}module_init(wbyq_hello_module_init);//驱动入口函数module_exit(wbyq_hello_module_cleanup);//驱动出口函数module_license(gpl);//驱动注册协议module_author(it_ashui);module_description(exynos4 hello driver); 4.3 驱动编译ker_add=/home/wbyq/src_pack/linux-3.5 #linux3.5内核的makefile位置all: make -c $(ker_add) m=`pwd` modules #通过调用linux3.5内核的makefile文件进行编译 cp ./*.ko /home/wbyq/src_pack/rootfs/code #将驱动文件拷贝到code目录下 make -c $(ker_add) m=`pwd` modules clean #清空文件obj-m +=hello_drv.o #添加依赖文件 4.4 驱动安装[root@wbyq code]# insmod hello_drv.ko #安装驱动[ 4684.795000] 驱动入口,驱动注册成功[root@wbyq code]# modinfo hello_drv.ko #查看驱动详细信息modinfo: can't open '/lib/modules/3.5.0-friendlyarm/modules.dep': no such file or directory[root@wbyq code]# mkdir /lib/modules/3.5.0-friendlyarm/ -p[root@wbyq code]# touch /lib/modules/3.5.0-friendlyarm/modules.dep[root@wbyq code]# lsmod #查看动态安装的驱动hello_drv 612 0 - live 0xbf000000 (o)[root@wbyq code]# rmmod hello_drv.ko #注销驱动[ 5610.635000] 驱动出口,驱动注销成功 5 编写蜂鸣器驱动 5.1 硬件接口   蜂鸣接口:bp1 – gpd0_0 高电平驱动。
   gpd0_con:0x1140 0000+0x00a0 --配置寄存器
5.2 蜂鸣器驱动层    1.调用驱动注册和注销函数,在驱动入口函数中实现beep硬件接口配置。在驱动出口函数中完成硬件资源释放。
   2.通调用杂项设备驱动框架完成杂项设备注册,注册成功后在/dev生成beep的设备节点。完成应用层相关接口函数编写。
#include #include #include #include #include /*驱动初始化*/unsigned int *gpdo_con;unsigned int *gpdo_dat;int beep_open(struct inode *inode, struct file *file)/*对应应用层open函数*/{ printk(open函数调用成功n); return 0;}int beep_release(struct inode *inode, struct file *file) /*对应应用层close*/{ printk(releasse函数调用成功n); *gpdo_dat&=~(1<<0); return 0;}ssize_t beep_read(struct file *file, char __user * data, size_t size, loff_t *offset)/*对应应用层read*/{ int *p=(int *)data; *p=123; printk(read函数调用成功n); return 4;}ssize_t beep_write(struct file *file, const char __user *data, size_t size, loff_t *offset)/*对应应用层write*/{ char buff[20]; memcpy(buff,data,size); buff[size]=''; printk(buff=%sn,buff); if(strcmp(buff,beep_on)==0)//开蜂鸣器 { *gpdo_dat|=1<<0; } else if(strcmp(buff,beep_off)==0)//关蜂鸣器 { *gpdo_dat&=~(1<<0); } return size;//返回写入成功的字节数}/*文件操作集合结构体*/static struct file_operations beep_fops={ .owner = this_module,/*当前模块*/ .open = beep_open, .release = beep_release, .read =beep_read, .write =beep_write};/*杂项设备结构体*/static struct miscdevice tiny4412_beep = { .minor = misc_dynamic_minor,//次设备号,255表示由系统自动分配 .name = beep, /*在/dev生成的设备节点名字*/ .fops = &beep_fops,};static int __init wbyq_beep_init(void){ printk(驱动入口,驱动注册成功n); /*蜂鸣器配置*/ gpdo_con=ioremap(0x114000a0, 4);//将gpdo_con物理地址转换虚拟地址 gpdo_dat=ioremap(0x114000a4, 4);//将gpdo_dat物理地址转换虚拟地址 /*蜂鸣器*/ *gpdo_con&=0xfffffff0;//清除当前gpd0_0的配置 *gpdo_con|=0x00000001;//设置为输出模式 /*注册杂项设备:在/dev下生成设备节点,实现应用层接口函数*/ misc_register(&tiny4412_beep); return 0;}/*驱动释放*/static void __exit wbyq_beep_cleanup(void){ printk(驱动出口,驱动注销成功n); /*注销杂项设备*/ misc_deregister(&tiny4412_beep); iounmap(gpdo_con); iounmap(gpdo_dat);}module_init(wbyq_beep_init);//驱动入口函数module_exit(wbyq_beep_cleanup);//驱动出口函数module_license(gpl);//驱动注册协议module_author(it_ashui);module_description(exynos4 beep driver);    杂项设备主设备为10,次设备可填值为0~254;当次设备号填255时表示有系统分配。
5.3 蜂鸣器应用层    linux下一切皆文件,操作设备就和操作文件一样。只需要open打开设备、读写设备、操作完成关闭设备即可。
#include #include #include #include #include #include int main(){ /*1.打开设备*/ int fd=open(/dev/beep,2); if(fd<0) { printf(/dev/beep 设备打开失败n); return 0; } int data=0; int size; /*读写文件*/ size=read(fd,&data,4); printf(size=%d,data=%dn,size,data); while(1) { write(fd,beep_on,strlen(beep_on));//开蜂鸣器 sleep(1); write(fd,beep_off,strlen(beep_off));//关蜂鸣器 sleep(1); } close(fd);//关闭文件}   在linux内核中,设备节点的访问是通过主设备+次设备号的组合来完成的,占32位,主设备号是20 ~ 31位。次设备号是0 ~ 19位。


2020年生物识别市场的四大热门趋势及应用
通信协议的基础知识
突发!字节跳动高层展开新一轮人事调整
共享经济还能共享什么?共享音箱来了
分级金手指工艺研发浅谈
Linux下驱动开发
游泳耳机哪个好,游泳效果最好的蓝牙耳机推荐
广汽集团与华为共同开发L4级自动驾驶车辆 360公司官宣正式造车
中国AOPA第六期梦天计划无人机辅导师培训班(深圳站)圆满结束
diy移动电源制作教程
在轻载情况下非同步降压转换器的效率性能分析与比较
今日传感财经:车用传感器概念报跌;检测仪器概念报涨;MEMS传感器概念报跌
专注科学系列 新品分享—Maleon飞秒激光双光子聚合3D打印系统
采用蓝牙技术的车辆监控系统电路设计
拼接处理器:优化视频质量的先进技术
沁恒股份U盘和SD卡高速文件管理控制芯片CH378概述
DIY制作强大的射频放电电路
卖到缺货,高端触觉驱动器性能有多优秀?
中航光电推新型VMP水密连接器,满足海洋装备的连接需求
模拟电子技术的十年新发展计划