rtt的io设备框架面向对象学习-框架总括

rtt面向对象oopc——3.对官方IO设备模型框架图的补充绘图已学习了,这里再对照补充下。

为何说面向对象学习?因为人家就是用的面向对象的思想进行设计的,你用面向过程能看到啥?只能看到指针,以为哎呀这不是指针吗?简单!是简单,但是你还可以站在更高层次看待代码,站在设计者的角度,更高层次,吹吹不一样的牛。

所谓框架,现在想来其实就是一堆规则,人为规则,人为规律,全是人为的么?应该是结合自然(或事实/客观)规律探索出来的人为规则吧。

但是是人主导的,人来解释规则,所以说是人为规则也没问题。

rtt的io设备框架分多少层,也是人对规律分析后人主导的规则吧。就比如设备基类,就很明显的人为痕迹,人为得统一到init/open/read/write,就像linux的统一一切到文件一样的道理,有很深的人为因素。但是又融合了自然客观规律,说人为也对,说不是人为也对,结合体,混合体。

这套框架的目的是
(1)对上为上层提供统一的外设操作接口,提高上层代码的可重用性;
(2)对下抽象外设io硬件,实现跨平台(跨bsp)对接。

oopc参考文章

1.设备基类层

rt_device类是属于抽象类,所有子类得实现其特定的方法,这是对子类的约束——也是最高约束!比如rt_serial,rt_spi_bus等等,缺图截个图把各个子类调用rt_decice_register的图截下,可以看到不同子类实现各自的父类方法。
看它们都调用设备基类的rt_decice_register函数来注册。

其实凡是注册,就是初始化结构体或者类似c++中类的构造函数——但是这里和c++的构造函数执行顺序相同——先执行父类构造函数再执行子类构造函数。

该层的管理接口device.c,它的实质也是p->init等方式调用子类重写的方法。那为啥不用p->init等方式直接调用?答案当然是可以这样调用的,但是直接调用很麻烦,因为它有些状态呀,限制呀要判断下,每次调用前都要写一堆if判断语句,而且这些判断是共通的,那为何不封装成函数,减少调用复杂度呢?所以封装成了函数。

在这里插入图片描述
设备基类定义了其子类要重写的方法——也是对子类的约束,如上设备基类的类图里用c++的纯虚方法——vitual init=0等——来表示这些约束方法。

2.设备驱动框架层

设备驱动框架层的类(rt_device的子类,比如rt_serial,rt_spi_bus等等)也另外添加了各有自己独有的方法,需要继承者(子类)来实现,也属于抽象类

这层的管理接口(如rt_serial.c等),对上重写rt_device基类的方法,对下这些重写的方法内部实现又调用该类定义需要子类重写的方法。封装下是为了调用简单。也是通过rt_xxx_register实现注册或者构造的。

比如spi总线基类所在层次。
在这里插入图片描述
如上类图,spi总线基类继承自设备基类必须重写设备基类的纯虚方法(init等),然后呢,它本身又是抽象类,因为它又定义了其子类要重新实现的方法,如上类图用c++的纯虚方法来表示:
vitual configure=0,
vitual xfer=0。

3.设备驱动层

再下面是驱动层,bsp在此,编写各个硬件的驱动对接到rtt设备驱动框架层,一般是最终的子类对象,属于最终实例化的子类
这层的管理接口(如rt_stm32_usart.c等),重写(或说实现)rt_serial等设备驱动框架层类定义的方法。也是通过rt_hw_xxx_register实现注册或者构造的。
一般这层实现(重写)的方法,已经是到最后了,它的实现是调用sdk来实现的,已经和硬件驱动强关联了。

比如stm32硬件spi类:
请添加图片描述
如上类图,stm32_spi类是这个层次——驱动层,这个类是可以实例化的实现类。
stm32_spi类继承spi总线基类必须重写spi总线基类的纯虚方法——configure,xfer方法——这两个方法已是通过对应bsp的sdk厂家驱动来实现,完全和硬件强相关了。
其他厂家一样——这样就对接到统一的框架里面去,实现跨硬件平台了。

4.SDK层

在下面是硬件厂家sdk。例如stm32提供的LL/hal/std/寄存器库等库。
完全是和硬件芯片强相关了。

3.硬件层

再下面就是纯纯的硬件电路板了。
和硬件电路设计相关。
物质决定意识,哎呀,在这呀!

4.总结

每个rtt类都有对应的register函数,从功能来看,它实现了该类结构体的初始化,结构体在面向对象中也是类对象,所以它实现了该类对象的初始化,这就是面向对象的该类的构造函数的功能,所以register函数就是该类的构造函数。反注册函数就是改类的析构函数。
有继承关系的话——c的实现是结构体里包含结构体的方式,同时该类的构造函数(register)最后会调用父类的构造函数——按照先调用子类构造/初始化函数,再调用父类的构造/初始化函数方式——其实也是子类构造/初始化函数调用父类构造/初始化函数的流程,来完成设备对象的初始化/构造。——从函数调用返回顺序看是和xc++的构造流程一样了,先返回父类构造函数再返回子类构造函数。最终放到对象容器里来管理。

5.再思考

越上层越接近人性化,越贴近人的直接目的;
越下层越远离人的需求,根本看不懂,因为内部实现和需求两码事。

这种特性,对于编程语言来说也是如此,越是高级的语言越人性化,越和用户要的功能越接近。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值