当前位置:   article > 正文

Linux驱动基础知识(一)_为什么嵌入式linux要学习驱动

为什么嵌入式linux要学习驱动


前言

参考资料:Linux设备驱动开发详解 宋宝华版

从现在开始,就对Linux驱动进行学习。在进行学习前,肯定是要给自己定下目标,做好准备。怎么学?怎么学好?

相信学习一样东西的目的,是为了解决问题,而不是为了学所学!所以,在学习前我们是抱着为了解决问题的思想去学习,这样我们的心理将会得到升华。

那么学习驱动的目的是什么呢?
因为驱动开发工程师工资高呀,没错确实很大原因和这个有关。(哈哈哈)
当然,还有一个原因!
就是设想一下,在我们身边学应用层开发的同学有去关心过printf函数的实现吗?我们学单片机开发的同学有用过printf函数吗?(有些同学用的是被重构的printf,并不是真的printf)。
而我们的驱动就是解决这样一个问题的存在,即应用软件工程师不关心硬件,而硬件工程师也不用顾及软件的实现

设备驱动的作用

任何计算机系统的运转都是系统中软硬件共同努力的结果,没有硬件的软件就是空中楼阁,没有软件的硬件就是一堆废铁。硬件是基础,代码最终会落实为硬件上的组合逻辑和时序逻辑;软件则实现了具体的应用,照顾不同的业务需求,完成了用户的最终诉求。

而为了提高开发的效率,软件和硬件不应该相互渗透入对方的领域,即软件工程师不担心硬件,硬件工程师不担心软件。也就是说,驱动的作用就是为了给软件工程师打造一个没有硬件的纯粹的软件世界,让硬件透明化。

通俗的讲,驱动也叫“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备具体的工作方式,读写设备的寄存器,完成设备的轮询,中断处理,DMA通信,进行物理内存向虚拟内存地址映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。

由此可见,设备驱动充当了硬件和软件之间的纽带,应用软件时只需要调用系统的应用编程接口(API)就可以让硬件去完成要求的工作。在系统没有操作系统的情况下,工程师可以根据硬件设备自己定义接口。而在有操作系统的情况下,驱动的框架由相应的操作系统定义,驱动工程师必须按照相应的架构设计驱动这样驱动才能更好的融合在操作系统中。

无操作系统时的设备驱动

并不是任何一个计算机系统都需要操作系统,比如针对工作任务比较单一的公交车刷卡器,冰箱等。实现的功能单一,不需要操作系统的任务调度。所以往往我们对此的设计思路就是一个死循环
相信大家在对单片机进行开发的时候,就有很深刻的印象。我们的程序逻辑都是包含在一个while(1)循环当中的

int main(int argc,char *argv[]){
	while(1){
	//your's code begin
	gpio_init();
	key_init();
	....
}
//your's code end
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这样的系统中,虽然不存在操作系统,但是设备驱动则无论如何都必须存在。一般情况下,每种设备驱动都会定义为一个软件模块,包含.h头文件和.c源文件,前者定义设备驱动的数据结构并声明外部函数,后者进行驱动的具体实现。
其他模块想要使用这个设备的时候,只需要包含设备的头文件然后调用即可。

正确的设计框架:实现软件和硬件的分离。
在这里插入图片描述

有操作系统时的设备驱动

从上面的无操作系统时设备驱动我们可以看出,设备驱动的硬件操作是必不可少的。没有这一部分驱动不可能和硬件打交道。
其次,我们还需要将驱动融入到内核。为了实现这种融合,必须在所有设备的驱动中设计面向操作系统内核的接口,这样的接口由操作系统规定,对一类设备而言结构一致,独立于具体的设备。

由此可见,当系统中存在操作系统的时候,驱动就变成了连接硬件和内核的桥梁。如下:
在这里插入图片描述

操作系统的存在势必要求设备驱动附加更多的代码和功能,把单一的“驱使硬件设备行动”变成了操作系统内核与硬件交互的模块,它对外呈现操作系统API,不再给应用软件工程师直接提供接口。

操作系统通过给驱动制造麻烦来达到给上层应用提供遍历的目的。当驱动都按照操作系统给出的独立于设备的接口而设计时,那么应用程序可使用统一的系统调用接口来访问各种设备。对于类UNIX的Vxworks、Linux等操作系统而言,当应用程序通过read(),write()等函数读写文件就可以访问各种字符设备和块设备,而不论设备的具体类型和工作方式,那将是多么遍历。

Linux设备驱动

设备的分类及其特点

计算机系统的硬件主要由CPU、存储器和外设组成。随着IC制作工艺的发展,目前芯片的集成度越来越高,往往在CPU内部就集成了存储器和外设适配器。像ARM、PowerPC、MIPS等处理器都集成了UART、IIC控制器,SPI控制器、USB控制器,SDRAM控制器等。有的还集成了GPU(图形处理器)、视频编解码器等。

驱动针对的对象是存储器和外设(包括CPU内部集成的存储器和外设),而不是针对CPU内核。Linux将存储器和外设分为3个基础大类。

  • 字符设备
  • 块设备
  • 网络设备
    字符设备指那些必须以串行顺序依次访问的设备,如触摸屏,磁带驱动器、鼠标等。块设备可以按任意顺序进行访问,以块为单位进行操作,如硬盘,eMMC等。字符设备和块设备的驱动设计有很大的差异,但是对于用户而言,它们都是通过使用文件系统的操作接口open(),close(),read(),write()等进行访问。

在Linux系统中,网络设备面向数据包的接收和发送而设计,它并不倾向于对应于文件系统的节点。内核与网络设备的通信与内核和字符设备、网络设备的通信方式完全不同,网络设备主要还是使用套接字接口

Linux设备驱动与整个软硬件系统的关系

在这里插入图片描述

除网络设备外,字符设备与块设备都被映射到Linux文件系统的文件和目录,通过文件系统的系统调用接口open()、write()、read() 、close()等即可访问字符设备和块设备。所有的字符设备和块设备都统一呈现给用户。Linux的块设备有两种访问方法:一种是类似于dd命令对应的原始块设备,如“dev/sdb1”等;另一种方法是在块设备上建立FAT,EXT4,BTRFS等文件系统,然后通过文件路径的方式进行访问。
在Linux中,针对NOR、NAND等提供了独立的内存技术设备子系统,其上运行YAFFS2,JFFS2,UBIFS等具备擦除和负载均衡能力的文件系统。针对磁盘或者Flash设备的FAT,EXT4,YAFFS2,UBIFS等文件系统定义了文件和目录在存储介质上的组织。而Linux虚拟文件系统则统一对他们进行了抽象

应用程序可以使用Linux的系统调用接口编程,但也可以使用C库函数,出于代码可移植性的目的,后者更值得推荐。C库函数本身也通过系统调用接口而实现,如C库函数fopen()、fwrite()、 fread()、 fclose()分别会调用操作系统的API open(),write(),read(),close()。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/870793
推荐阅读
相关标签
  

闽ICP备14008679号