Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024_RSOC】设备和驱动——1.框架基础
发布于 2024-07-25 21:10:50 浏览:240
订阅该版
#设备和驱动——1.框架基础 ###设备模型 RT-Thread 提供了一套简单的 I/O 设备模型框架,如下图所示,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。 ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-dev.png) **I/O 设备管理层**: 它实现了对设备驱动程序的封装。应用程序通过图中的"I/O设备管理层"**提供的标准接口**访问底层设备。 **设备驱动框架层** 它将不同厂家的同类硬件设备驱动中**相同的部分抽取出**来,**将不同部分留出接口**,由驱动程序实现。比如说,stm32芯片上的串口和adiuno芯片上的串口可以通过设备驱动框架合成在一起。这样,即使是不同的芯片,用户依然可以用相同接口函数使用。 **设备驱动层** 它是最接近底层硬件的一层,是真正意义上的对硬件驱动的程序。而且对于操作逻辑简单的设备,可以不经过设备驱动框架层,直接将设备注册到 I/O 设备管理器中。 下面是对简单设备和复杂设备的对比。 **简单设备** ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-call.png) 驱动层直接通过rt_device_register()函数注册到管理层,这样用户就可以通过rt_device_find()查找到设备,然后使用 I/O 设备管理接口来访问硬件。 **复杂设备**(这里以看门狗为例) ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/wtd-uml.png) 驱动层根据看门狗设备模型定义,创建出具备硬件访问能力的看门狗设备驱动,并将该看门狗设备通过 rt_hw_watchdog_register() 接口注册到相应看门狗设备**驱动框架**中。 **疑问**:为什么复杂的设备需要通过不同的注册函数将设备注册到设备管理层呢? 我认为,其根本原因就是用户的需求不同。就拿上述两个例子来说,对于简单的IO设备用户只需要查找,打开,读取,写入,关闭的功能,因为设备简单,所以用户的需求也不大。说简单点就是设备太简单,大家都是一样的,做不出复杂的功能。而对于复杂的设备,比如说看门狗,用户需要设置看门狗溢出时间,这是看门狗所独有的需求。所以对于看门狗,驱动层需要通过相应的看门狗注册函数进入其对应的驱动框架中,将不同的用户使用接口(设置看门狗溢出时间)独立出来。 ** 疑问:**为什么要通过这种方式来对设备进行创建和管理呢?(以spi为例子) ![QQ图片20240726110142.png](https://oss-club.rt-thread.org/uploads/20240726/2d2efa0dfebcdf5caec609efd7587452.png.webp) 可以看见不同厂家对SPI的接口API设计都不同,这就导致如果一个产品在更换不同产商的芯片后,其驱动代码基本上要重新写。(因为基本是都是直接用产商的SPI接口去编写程序的)。而通过上述的这种管理方式,可以把SPI的驱动和设备驱动分离,从而实现再更换芯片后只需要对SPI接口进行编写,而不需要对程序编写。 ![QQ图片20240726111602.png](https://oss-club.rt-thread.org/uploads/20240726/0bb0bffb1056182a78e23bac7f3d537a.png.webp) 举个例子: 在stm32的板子上如果要点一个灯,函数为:HAL_GPIO_WRITE_PIN(GPIOX,GPIO_PIN_X), 而在Arduino的板子如果要点一个灯则是:digitalWrite(pin, 1); 通过上述的方式,在RT中无论32的芯片还是Arduino芯片,都是用rt_pin_write()来点灯。 (前提是底层的驱动已经写好了,一般来说常用的外设RT官方都是写好的,直接用就行) ###设备的创建(驱动层)和注册(驱动层->驱动框架层->管理层) 驱动层负责创建设备实例,并注册到 I/O 设备管理器中,可以通过动态和静态两种方式创建设备。 RT-Thread 支持多种 I/O 设备类型,主要设备类型如下所示: RT_Device_Class_Char /* 字符设备 */ RT_Device_Class_Block /* 块设备 */ RT_Device_Class_NetIf /* 网络接口设备 */ RT_Device_Class_MTD /* 内存设备 */ RT_Device_Class_RTC /* RTC 设备 */ RT_Device_Class_Sound /* 声音设备 */ RT_Device_Class_Graphic /* 图形设备 */ RT_Device_Class_I2CBUS /* I2C 总线设备 */ RT_Device_Class_USBDevice /* USB device 设备 */ RT_Device_Class_USBHost /* USB host 设备 */ RT_Device_Class_SPIBUS /* SPI 总线设备 */ RT_Device_Class_SPIDevice /* SPI 设备 */ RT_Device_Class_SDIO /* SDIO 设备 */ RT_Device_Class_Miscellaneous /* 杂类设备 */ 设备被创建后,需要实现它访问硬件的操作方法。 比如下面 ![QQ图片20240725195511.png](https://oss-club.rt-thread.org/uploads/20240725/0d1bf95b509969879eb98574be76677e.png.webp) **xxx**需要注意的是设备的创建对应删除,而设备的注册对应注销,注销设备后是不会释放空间的,只是把设备从设备列表中删除了。 **重点**:**下面STM32F4板子的GPIO为例,看一下RT_Thread官方的驱动是如何写的。** 先从驱动层来看, ![QQ图片20240726151651.png](https://oss-club.rt-thread.org/uploads/20240726/4da6e6e5a7657c3093383618e7bad5b7.png.webp) ![QQ图片20240726151748.png](https://oss-club.rt-thread.org/uploads/20240726/c8eeb0c237a6e39d7ead5135ce7dab59.png.webp) 观察上诉两幅图可知,RT官方的驱动文件中都是一些用STM32厂商的GPIO接口函数编写的程序(HAL库),这也是不同芯片在编写时的不同之处。那么如何实现驱动层->(框架层)->管理层呢?我们接着往下看(记住上面红框部分) ![QQ图片1png.png](https://oss-club.rt-thread.org/uploads/20240726/5d52a4f49826f18055ed505bc7c2bd0b.png.webp) 在pin.h这个文件中创建了一个上图这样的基于父类的框架。其中,父类是所有框架都共有的结构体,我们看看里面有些什么。 ![QQ图片2png.png](https://oss-club.rt-thread.org/uploads/20240726/636ab10cd40fcd8cded92de7adf45c42.png.webp) 而另一个结构体**指针**指向的就是**gpio的服务函数了,用于管理层编写留给用户的接口** ![QQ图片5png.png](https://oss-club.rt-thread.org/uploads/20240726/55ef17838e86129542d9626640fcaafc.png.webp) ![26.png](https://oss-club.rt-thread.org/uploads/20240727/ad6ca764a14618521bb796430acd672b.png) 其内容就是用stm厂商(HAL库)的gpio接口编写的函数。 看到这里我们应该有个疑问,作者讲了这莫多也没看到驱动框架层和驱动层的联系啊,或者说他们之间到底是怎么连接上的呢?答案往往在不经意间给告诉你了!!!! 还记得让你记住的红框部分吗? ![1123123958.png](https://oss-club.rt-thread.org/uploads/20240727/f01e26e0ac15b073fa4f5ad1e37b4119.png) 这个GPIO独有的注册函数会将GPIO设备注册到设备管理层,然后应用层就可以继续通过管理层留给用户的接口来进行对设备的访问了!!! 我们来看看这个注册函数到底是肿莫个事! ![QQ1片1png.png](https://oss-club.rt-thread.org/uploads/20240726/f65f071702aa8f5c25b5c7ee3883571f.png.webp) 可以看出,在GPIO的注册函数中,会先经过框架层的处理,最终会调用rt_device_register()这个rt官方的注册函数,从而把这个设备注册到设备管理层中。 其中,_hw_pin就是用驱动框架结构体类型创建的结构体。 ![QQ图片6png.png](https://oss-club.rt-thread.org/uploads/20240727/fc5f9af1f7babdc5b4247d33dc7a9965.png.webp) ###设备的使用(应用层->管理层->(框架层)->驱动层) **访问设备** **对于简单的设备**应用程序可直接通过RT官方设备管理接口来访问硬件设备,**当设备驱动实现后**(只有写好驱动才能与硬件进行交互),应用程序就可以访问该硬件。设备管理接口与设备的操作方法的映射关系下图所示: ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-fun-call.png) **而对于复杂的设备**,管理层一般会用服务函数(就是用驱动层的ops 结构体里包含的函数)**再编写一些留给用户的接口函数**,实现应用层->管理层,最终对底层硬件的使用。 下面GPIO为例,看一下RT_Thread官方的驱动是如何使用设备的。 ![11111.png](https://oss-club.rt-thread.org/uploads/20240727/585bdc199d663d3a4f05349dab6f3340.png.webp) 可以看出,这两个函数都是通过框架结构体里的服务函数指针(ops)来实现对底层驱动的访问。而服务函数就是用厂商gpio接口编写的。 通过这种方式,让每一层都做着自己的事情,使得每一层的联系都不大便于用户程序的移植和维护。 ###既然我们已经了解了驱动的基本结构,那我们如何去配置一个用ENV开启的驱动呢? 在驱动目录下创建一个自己的驱动文件,记住自己if判断的宏 ![1.png](https://oss-club.rt-thread.org/uploads/20240728/9794b02f3520611893a1f6d9bc2e8f96.png.webp) 在同目录下打开SConscript文件,添加内容 ![2.png](https://oss-club.rt-thread.org/uploads/20240728/c301800e3d4ea0d420d56f2ff4f463a4.png.webp) 意思就是判断BSP_DEMO这个宏是否定义,定义了就把drv.demo.c这个文件加入构建。 然后打开ENV菜单配置文件(Kconfig)添加内容 ![3.png](https://oss-club.rt-thread.org/uploads/20240728/fa9587cc9897214366d9349dc5cec6d3.png.webp) 意思是添加一个bool类型的宏,默认值为n,字符串为提示内容。 之后就可以在菜单中使能我们的驱动了,虽然没有内容qwq ![4.png](https://oss-club.rt-thread.org/uploads/20240728/30fd55219ba4f4c1f30b883fa5cdf454.png)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
马桶盖盖子
这家伙很懒,什么也没写!
文章
7
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
文件系统
DMA
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
ota在线升级
I2C_IIC
WIZnet_W5500
UART
flash
packages_软件包
cubemx
PWM
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
中断
flashDB
socket
Debug
GD32
编译报错
msh
keil_MDK
at_device
MicroPython
rt_mq_消息队列_msg_queue
ulog
C++_cpp
本月问答贡献
出出啊
1513
个答案
341
次被采纳
小小李sunny
1438
个答案
289
次被采纳
张世争
775
个答案
167
次被采纳
crystal266
546
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部