linux驱动 — 学习总结

前言

linux驱动学习也有一段时间了,但是其中断断续续的,以前是不得要领,一直在门外徘徊,后面也是自己特别感兴趣,感觉linux这东西挺有趣、挺有技术含量,我非得去弄一下不可,有些人说弄linux就得从应用开始,我看了下应用层的代码,这不跟windows下的差不多吗,本人原本是做mcu开发的,像stm32这种,linux应用层的东西感觉用不上也没意思,我应该从驱动开始,趁着工作没那么忙,又仔细学了下,于是有了如下收获,特记录一下:

学习记录

1、学习了led驱动、beep驱动、按键驱动、其实这些驱动本质都差不多,都是对IO进行控制或者读取,有直接写驱动(将设备也写在驱动里),也有引入设备树的,引入设备树后驱动代码减少了,多的就是设备树节点描述与驱动文件中引用设备树相关API进行操作,其它都大同小异;

2、其次做了定时器实验,linux是一个工具非常丰富的操作系统,里面很多东西都给我们弄好了,不需要我们重复造轮子,比如内核定时器,我们只需要初始化定时器,增加/删除/修改定时器等操作,都跟其它嵌入式操作系统一致

3、做了中断实验,像定时器、中断这些通用功能很多地方都可以用到,是一定要掌握的,像IO口中断,需要在设备树中将IO相关信息进行描述,在代码中通过request_irq注册中断,中断需要注意的就是上半部与下半部,对那些不能被打断、时间敏感、硬件相关的操作应该放在上半部,其它可以放在下半部,下半部主要用软中断、tasklet或者工作队列,工作队列的好处是可以指定延迟多久再执行!

4、misc驱动框架,加上platform框架,就是我们实际开发中最常用的存在,misc 驱动其实就是最简单的字符设备驱动,像led、beep、adc等都可以归到misc类驱动,其专门提供了misc_register接口,这个接口就是封装了字符设备申请设备号、创建类、创建设备等那一套,所以misc驱动的父设备号也是确定的(10),我们用时只要注册一个misc_device就可以了,所以需要操作IO相关的驱动都可以用它来完成

5、input驱动框架,这个跟misc类似,Linux的驱动设计是趋向于分层的,大多数设备都有自己归属的类型,input它负责的是输入设备驱动,像键盘、鼠标、触摸屏等,也是属于字符设备,只是在此基础上套上了 input 框架,用户只需要负责上报输入事件,input 核心层将负责处理这些事件

6、i2c、spi、rs232等驱动框架、这些其实是实际存在的总线驱动,像上面那些是不存在的总线驱动,但是linux为了统一操作,增加了platform这种虚拟总线,所有设备都可以通过它进行注册,通过名称或者属性与驱动进行匹配,于是所有的驱动,不管实际有无总线,都可以通过总线与设备进行匹配,从而做到了设备与驱动的分离,驱动、总线、设备是linux驱动开发必须要理解掌握的概念

7、通过使用设备树与不使用设备树的区别,设备树只是为了减少驱动代码而存在的,可以将设备从驱动中分离出来,所以说设备树是一个好东西,能使用设备树的话坚决使用设备树,我就很喜欢用,加个设备节点,然后编译一下,从设备树启动在device-tree下就有了你的这个节点,真的太省事了,然后在你驱动里读取你这个节点中的信息进行操作就可以了

8、回过头来看应用程序:应用程序是最上层的程序,理解起来也比较简单,因为linux下一切兼文件,所以在应用程序中就是打开open、读read、写write、控制ioctrl、关闭close等这些操作,跟操作文件一样一样的,应用层操作这些接口,这些接口到系统调用然后到内核最后到驱动层也是对应这些接口,我们只需要遵循这个框架编写驱动程序就行,linux下90%以上的驱动都已经弄好了,但是需要你理解熟悉各种不同的驱动框架,因为只有你熟悉了,才能进行修改,出现问题才能排查,只有当你理解熟悉了,编写驱动才会轻松简单又高效,所以说学习linux驱动就是熟悉linux驱动框架!

注意事项

学习linux驱动开发,首先字符设备驱动是必须要会的,然后就是理解platform总线设备驱动框架,其实platform框架就是在字符设备驱动上加了层外衣,使得驱动跟设备分离,中间通过platform总线进行匹配,而匹配这部分又是linux内核完成的事

我们只需要按规定进行设备描述与驱动编写,设备描述就是用设备树来完成,驱动编写就是向platform总线注册一个驱动,platform总线会自动跟设备树中名称相同设备进行匹配,匹配上了就执行probe函数,probe函数中就是我们熟悉的字符设备驱动的实现过程!

其次设备树,设备树是用来描述设备节点的,设备节点的描述以前是放在驱动中,后面提取出来了,使得驱动跟设备分离,更好的便于管理,设备树文件通过make dtbs编译成.dtb文件,然后开发板从设备树文件启动,当然也可以直接编译进内核

然后在/proc/device-tree目录下就可以看到你所用的设备树生成的节点,不过设备树只是相当于你的仓库,设备树中的节点相当于仓库中的一些物料,所以你要把它们用起来还需要将他们组装,放置到特定的场景中,这就相当于驱动程序,等你组装好电路环境搭建好后,最后就是通电使用了,这就是应用程序

学习感悟

至此,linux下一般的驱动,比如led、beep、key等驱动编写流程已经非常熟悉,对中断、定时器的使用也有了比较多的理解,对platform设备驱动总线的框架也基本掌握,接下来需要对更复杂一点的驱动进行熟悉,linux自身包含了很多驱动,需要去了解熟悉然后才能运用,只有熟悉了它自身的驱动,才能更好地进行工作,不要自己重复造轮子

随着学习的深入,给我最深的感受是发现linux下驱动开发的道路有很多,可以步行,也可以骑自行车,还可以坐汽车坐火车等,条条道路通罗马,只是选择不同效率不同,比如module_platform_driver这个函数,它一个接口实现了platform总线的注册、删除等一系列操作;再比如misc_register接口,实现了字符设备申请设备号、初始化cdev、创建类、创建设备等一系列操作,功能实现是一样一样的,但是大大简化了代码量,而实际中就是这么用的!

到目前为止,我现在linux驱动开发应该到了铂金段位,希望接下来攻克钻石,道阻且长,行则将至!

后记:碰巧公司需要MTK平台下这方面驱动开发,于是我勉为其难的接手了,现在已经在板子上调通了按键IO口驱动,使用了中断、工作队列等去消抖,也调了几个I2C的模块,暴露一些接口给安卓层调用,在adb下测试能正常工作,其它像LCD、MIC、音频等的驱动还在调试中,多亏身边有位linux非常厉害的大佬,时不时向他取点经,感觉收获不小,真的非常感谢他,祝愿他健康长寿!

你可能感兴趣的:(linux驱动,linux,stm32)