0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux下驱动开发

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-09-20 09:00 次阅读

Linux下驱动开发

1.简介

驱动,是指驱动计算机里软件的程序。驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。驱动程序是操作系统与硬件连接的桥梁。
设备驱动最通俗的解释就是“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮询、中断处理、DMA通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。

2.驱动分类

Linux驱动分类:
字符设备、块设备、网络设备。
网络设备: 有线网卡、无线网卡、其它与网络相关的设备。
块设备: U盘、SD卡、硬盘、光盘等。
字符设备: 除了块设备和网络设备,其它都归结于字符设备。
字符设备中分类: 杂项设备、输入设备(键盘、鼠标、触摸屏)、帧缓冲(显示类设备)、RTC设备、串口设备等。

3.杂项设备

pYYBAGMoThuAXtjZAACGh6k1cfM063.png#pic_center

驱动程序是应用层和硬件层的连接桥梁,应用层只管完成应用逻辑开发和界面设计,驱动层则处理硬件配置,实现应用层相关接口函数。
杂项设备:字符设备类的一种,是除了上述输入设备、帧缓冲设备、RTC设备后的其它设备,例LED设备,由于不好归结于上述分类,则可将LED设备按杂项设备类进行注册。杂项设备主设备号为10。
在生成的设备节点中,主设备号用来区分设备类。如字符设备中杂项设备主设备号为10,帧缓冲设备主设备号为29;次设备号用来区分这个类中的具体硬件。

4.驱动注册框架

4.1开发平台

开发平台:Ubuntu18.04
编译器:arm-linux-gcc
硬件平台:tiny4412基于Cortex-A9 4核1.5GHZ
开发板内核:Linux3.5

poYBAGMoThyAFONuAAhfvDjkbsA493.png#pic_center

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 硬件接口

pYYBAGMoThyAcqAWAAB785gbBRc774.png#pic_center

  蜂鸣接口:BP1 – GPD0_0 高电平驱动。

poYBAGMoTh2ALh5zAAFIVeaUTtI355.png#pic_center

   GPD0_CON:0x1140 0000+0x00A0 --配置寄存器

pYYBAGMoTh2AHTkFAADx1i9W8rc801.png#pic_center

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位。

审核编辑:汤梓红


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1362

    浏览量

    40224
  • Linux
    +关注

    关注

    87

    文章

    11222

    浏览量

    208896
  • 驱动开发
    +关注

    关注

    0

    文章

    130

    浏览量

    12062
收藏 人收藏

    评论

    相关推荐

    自学买什么开发板比较好,求推荐

    有比较长的linux基础,也有单片机的开发经验。现在想自学 arm 和linux驱动开发,内
    发表于 05-09 22:05

    【NanoPi2申请】简单人脸识别

    这是很好的发展方向。我现在正在学习linux的一些基本操作,打算做linux驱动开发,本来
    发表于 12-18 14:37

    嵌入式Linux设备驱动开发

    嵌入式Linux设备驱动开发 Linux 设备驱动的基本概念Linux 设备
    发表于 09-10 13:10 82次下载
    嵌入式<b class='flag-5'>Linux</b>设备<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>

    Linux基于I2C协议的RTC驱动开发

    首先研究了Linux环境字符设备驱动程序框架,然后介绍12C协议,在此基础上开发基于12C协议的RTC字符设备驱动程序。砷于
    发表于 03-02 16:15 48次下载
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b>基于I2C协议的RTC<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>

    嵌入式LinuxARM_DSP通信接口设计及驱动开发

    嵌入式LinuxARM_DSP通信接口设计及驱动开发
    发表于 05-19 11:17 0次下载

    基于嵌入式LinuxARM_DSP通信接口设计及驱动开发

    基于嵌入式LinuxARM_DSP通信接口设计及驱动开发
    发表于 10-19 10:38 12次下载
    基于嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>下</b>ARM_DSP通信接口设计及<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>

    如何编写Linux Nand Flash驱动

    如何编写Linux Nand Flash驱动
    发表于 10-30 08:36 15次下载
    如何编写<b class='flag-5'>Linux</b> <b class='flag-5'>下</b>Nand Flash<b class='flag-5'>驱动</b>

    基于Linux的LCD驱动程序实现

    基于Linux的LCD驱动程序实现
    发表于 10-30 16:45 12次下载
    基于<b class='flag-5'>Linux</b><b class='flag-5'>下</b>的LCD<b class='flag-5'>驱动</b>程序实现

    LinuxPCI设备驱动程序开发

    PCI是一种广泛采用的总线标准,它提供了许多优于其它总线标准(如EISA)的新特性,目前已经成为计算机系统中应用最为广泛,并且最为通用的总线标准。Linux的内核能较好地支持PCI总线,本文以Intel 386体系结构为主,探讨了在Linux
    发表于 04-26 17:00 1032次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b>PCI设备<b class='flag-5'>驱动</b>程序<b class='flag-5'>开发</b>

    ARM11嵌入式系统LinuxLCD的驱动的设计

    ARM11嵌入式系统LinuxLCD的驱动的设计(嵌入式开发啥意思)-ARM11嵌入式系统Linux
    发表于 07-30 14:53 24次下载
    ARM11嵌入式系统<b class='flag-5'>Linux</b><b class='flag-5'>下</b>LCD的<b class='flag-5'>驱动</b>的设计

    嵌入式linux报警,嵌入式LinuxLED报警灯驱动设计及编程.doc

    设计及编程一.实验目的理解驱动本质,掌握嵌入式Linux系统驱动开发相关知识,包括端口寄存器访问、接口函数编写、和文件系统挂接、注册及相关
    发表于 11-01 17:21 5次下载
    嵌入式<b class='flag-5'>linux</b>报警,嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>下</b>LED报警灯<b class='flag-5'>驱动</b>设计及编程.doc

    Linux设备驱动开发详解

    Linux设备驱动开发详解
    发表于 10-28 11:03 50次下载

    如何驱动Linux开发板LED灯

    Linux的任何外设驱动,最终都是要配置相应的硬件寄存器。前面的文章中介绍了新旧字符设备的驱动开发框架,也介绍了IMX6ULL处理器GPI
    的头像 发表于 04-14 11:41 930次阅读
    如何<b class='flag-5'>驱动</b><b class='flag-5'>Linux</b><b class='flag-5'>开发</b>板LED灯

    如何学习Linux驱动开发

    困惑,面对复杂的Linux内核有一种无从下手的感觉。今天就和大家分享一,让刚刚步入驱动开发的同学少走一些弯路。01要知道将来要做什么学习,都是有目的性的,要么是兴
    的头像 发表于 01-06 16:34 884次阅读
    如何学习<b class='flag-5'>Linux</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>?

    Linux 驱动开发与应用开发,你知道多少?

    一、Linux驱动开发与应用开发的区别开发层次不同:Linux
    的头像 发表于 08-30 12:16 592次阅读
    <b class='flag-5'>Linux</b> <b class='flag-5'>驱动</b><b class='flag-5'>开发</b>与应用<b class='flag-5'>开发</b>,你知道多少?