rtt设备io框架面向对象学习-框架
rtt面向对象oopc——3.对官方IO设备模型框架图的补充绘图已学习了,这里再对照补充下。
两个图,官方图和补充图。
为何说面向对象学习?因为人家就是用的面向对象的思想进行设计的,你用面向过程能看到啥?只能看到指针,以为哎呀这不是指针吗?简单!是简单,但是你还可以站在更高层次看待代码,站在设计者的角度,更高层次,吹吹不一样的牛。
所谓框架,现在想来其实就是一堆规则,人为规则,人为规律,全是人为的么?应该是结合自然(或事实/客观)规律探索出来的人为规则吧。
但是是人主导的,人来解释规则,所以说是人为规则也没问题。
rtt设备io框架分多少层,也是人对规律分析后人主导的规则吧。就比如设备基类,就很明显的人为痕迹,人为得统一到init/open/read/write,就像linux的统一一切到文件一样的道理,有很深的人为因素。但是又融合了自然客观规律,说人为也对,说不是人为也对,结合体,混合体。
1.设备基类层
rt_device类是属于抽象类,所有子类得实现其特定的方法,这是对子类的约束——也是最高约束!比如rt_serial,rt_spi_bus等等,缺图截个图把各个子类调用rt_decice_register的图截下,可以看到不同子类实现各自的父类方法。
看它们都调用设备基类的rt_decice_register函数来注册。
其实凡是注册,就是初始化结构体或者类似c++中类的构造函数——但是这里和c++的构造函数执行顺序相反——c++构造函数是先执行父类构造函数再执行子类构造函数,而这里是先执行子类构造函数再执行父类构造函数。
该层的管理接口device.c,它的实质也是p->init等方式调用子类重写的方法。那为啥不用p->init等方式直接调用?答案当然是可以这样调用的,但是直接调用很麻烦,因为它有些状态呀,限制呀要判断下,每次调用前都要写一堆if判断语句,而且这些判断是共通的,那为何不封装成函数,减少调用复杂度呢?所以封装成了函数。
2.设备驱动框架层
设备驱动框架层的类(rt_device的子类,比如rt_serial,rt_spi_bus等等)也另外添加了各有自己独有的方法,需要继承者(子类)来实现,也属于抽象类。
这层的管理接口(如rt_serial.c等),对上重写rt_device基类的方法,对下这些重写的方法内部实现又调用该类定义需要子类重写的方法。封装下是为了调用简单。也是通过rt_xxx_register实现注册或者构造的。
3.设备驱动层
再下面是驱动层,bsp在此,编写各个硬件的驱动对接到rtt设备驱动框架层,一般是最终的子类对象,属于最终实例化的子类。
这层的管理接口(如rt_stm32_usart.c等),重写(或说实现)rt_serial等设备驱动框架层类定义的方法。也是通过rt_hw_xxx_register实现注册或者构造的。
一般这层实现(重写)的方法,已经是到最后了,它的实现是调用sdk来实现的,已经和硬件驱动强关联了。
4.SDK层
在下面是硬件厂家sdk。例如stm32提供的LL/hal/std/寄存器库等库。
完全是和硬件芯片强相关了。
3.硬件层
再下面就是纯纯的硬件电路板了。
和硬件电路设计相关。
物质决定意识,哎呀,在这呀!
4.再思考
越上层越接近人性化,越贴近人的直接目的;
越下层越远离人的需求,根本看不懂,因为内部实现和需求两码事。
这种特性,对于编程语言来说也是如此,越是高级的语言越人性化,越和用户要的功能越接近。