记录下对驱动程序的整体了解过程。
笔者是从算法开始接触计算机,然后学习单片机,fpga,嵌入式linux,网络编程。经过十年左右的断续学习,对计算机体系有了一个完整的概念。
从自己的经验,来介绍下我眼中的驱动。
关键词解释:
本文里MCU和单片机是一个意思,都是一个微型控制系统.包含CPU模块(中央控制器),以及所有的片上外设等。
CPU特指处理器核心,例如ARM cortex-M7,M4
第一层
从个人主机的角度来看,驱动就是驱动 底层硬件 的软件。
至于驱动程序怎么驱动底层软件?
装了驱动之后为什么其他应用程序就能用这个硬件了?
我怎么知道?(心中的猜测是,驱动程序承担着沟通硬件与应用层程序的功能,至于怎么实现的?我怎么知道?)
第二层
开始接触单片机编程了,抛弃了中间商操作系统的情况下。从硬件的角度来看,对驱动的印象是:
任何系统(单片机,soc)想驱动一个外设,都需要配置外设内部的寄存器,以此来改变外设的工作状态,使之达到我们想要的效果。
依据改变外设寄存器的方法,把外设分为两类:
片外外设:独立的外设模块,cpu无法直接访问它们的寄存器。cpu与外设需要通过事先约定的通信方式进行通信。(ps:这种事先约定的通信方式,就是传说中的协议。例如:uart,iic,iis,spi,can)
片上外设:集成在单片机上的外设,cpu可以直接像访问自己内部寄存器一样直接访问它们。(ps:这其实是单片机内部已经封装好了AXI,AHB,APB等高速通信协议,它已经帮我们实现了通信方式,cpu模块和片上外设模块物理上还是分离的)
cpu想要与片外外设通信,需要实现相关的通信协议。然而,大部分的片外外设的通信协议速率对于cpu来说都相当慢,例如iic,100khz~2M。而通信过程又是一个不可打断的过程,通信过程中,双方是不能中途离场的。因此,cpu往往会利用一种特殊的片上外设来代替自己进行通信协议的实现,这就是接口控制器。例如IIC控制器,IIS控制器,CAN控制器,SPI控制器。这就像你的朋友花了一小时给你敲摩斯密码,最终其实就是一句“晚上吃什么,要不要一起去吃烧烤?”如果你是亿万富豪,你肯定不应该花费时间在无意义的等待上,你应该雇一个牛马(正是在下)帮你等待,你只需要决定晚上去不去赴市长的约了。也许黄色的西装更好看,对吧。
所以单片机驱动的本质就是
片上外设的驱动:cpu直接配置片上外设的寄存器,就可以直接驱动硬件了。
片外外设的驱动: cpu配置片外外设对应通信协议的接口控制器的寄存器,首先驱动起来接口控制器,然后通过接口控制器配置片外外设的控制器,通过接口控制器间接控制片外外设。
(ps:假设我们需要控制一个IIC接口的adc,我们首先需要配置单片机上的IIC控制器,将其配置成对应模式,然后通过IIC控制器与ADC进行通信,将寄存器配置传给ADC,这样就可以成功配置ADC了。
片外外设:IIC接口的adc
对应通信协议: IIC通信协议
对应通信协议的接口控制器: IIC控制器(片上外设)
)
片上外设和片外外设的驱动区别很类似我们踢腿与挥棒的区别。
第三层
FPGA的角度来看待驱动程序,在fpga的世界里,外设和cpu已经解构为单纯的数字电路,它们之间并没有什么不同,所以驱动程序和其他程序也没什么不同,fpga的世界解释了为什么修改外设寄存器就可以改变外设的工作状态,所有的一切归结于电路的最基础功能,世界和谐统一。(随便了解一下fpga的语言就可以清晰的了解了)
第四层
Linux里的驱动程序。为了实现更复杂的功能,技术向前迈进,单片机开始进化,
从单片机里一个程序跑所有的功能,不分层,
到单片机里一个程序跑所有功能,分为驱动层,应用层,
到嵌入式linux里不同的程序跑不同的功能,分层。
嵌入式linux的驱动框架是一个很大的话题,因此另开一篇随笔。