通用外设接口
rtthread对常用的片内外设做了抽象,为同一类外设提供了通用接口,对于不同的MCU片内外设都可以使用同一套外设接口进行访问。
串口驱动框架
serial.c serial.h
1 | struct rt_serial_device |
举例说明下ops里面串口的配置方法:
1 | // control方法是可以说是多个方法的集合,它根据 cmd 的不同,可以执行不同的操作:比如:开中断、关中断、配置串口dma、配置dma中断等 |
串口设备使用步骤:
1.串口设备实例化一个串口驱动设备对象,并通过rt_hw_serial_register()接口注册到设备框架中。
2.串口设备驱动框架通过rt_device_register()接口将设备注册到IO设备管理中。
3.应用程序通过IO设备管理提供的接口访问串口设备硬件。
串口设备时序图:

1 | @startuml |
时序图软件:plantuml
1.驱动注册到驱动框架:注册设备的操作方法
1 | // 驱动注册到驱动框架 |
2.驱动框架注册到IO设备管理器:驱动框架设备挂载到内核对象链表
1 | // 驱动框架设备注册到IO设备管理器 |
注册设备时的flags参数:
1 |
驱动层到io设备管理层对象空间占用是一层一层减小

串口回调:
1 | // 在串口中断中回调 |
SPI设备管理
1 | // spi总线对象 |
- SPI总线创建、SPI从设备挂载到总线时序图

SPI总线是一个虚拟的设备(对应MCU硬件上的SPI控制器),总线可以挂载多个从设备,靠CS引脚来区分,总线现在被哪个从设备占用。 struct rt_spi_bus总线对象里的owner用来记录当前总线被哪个从设备占用。struct rt_spi_device从设备对象里的bus用来记录当前从设备挂载在哪个总线上。
1.SPI总线设备创建,drv_spi.c 驱动层里面实例化一个SPI总线对象。
2.SPI总线设备注册到 SPI设备驱动框架层:spi_core.c、spi_device.c ,通过 rt_spi_bus_register() 接口。
3.SPI设备驱动框架对象注册到IO管理层:rt_device.c ,通过 rt_device_register() 接口。
SPI设备驱动框架层由两个文件组成:spi_core.c、spi_device.c
4.在SPI从机设备驱动创建一个SPI从设备:对应具体的SPI外设芯片,在设备的驱动程序实现:比如 ssd1306.c ,使用 rt_spi_bus_attach_device() 里面会实例化一个spi从设备对象,并把从设备对象挂载到指定的一个总线上。
由于 rt_spi_bus_attach_device() 只是创建了一个从设备对象,并把它挂载到一个总线,但并没有配置该从设备通信时主设备该设置成什么参数配置(每个从设备占用总线通信的时候可能需要的总线配置是不一样的,默认的配置是 0),这里需要接着调用 rt_spi_configure() 接口配置总线以适合该从设备和总线(主设备)通信:数据宽度、时钟速度、模式等配置。配置完这么参数后总线上的主设备从能和这个从设备通信。
1 | int ssd1306_attach_to_spi_bus(void) |
总线:主设备+虚拟总线的统称。
5.挂载从设备对象到SPI总线:ssd1306.c 和步骤 4 创建对象时合成在一起了,通过 rt_spi_bus_attach_device() 接口。
6.注册spi从设备对象到IO设备管理层:rt_device.c ,通过 rt_device_register() 接口。
7.通过从设备的设备句柄调用 rt_spi_transfer_message() 就可以对从设备收发数据。
8.spi_drv.c 驱动中在检测到该从机是首次收发数据的时候,会调用congfig() 先配置从机,接着在 通过 xfer() 收发本次的数据。
spi_drv.c 驱动中动过检测发送数据的总线对象里面的 owner 是否是本从设备,是代表总线之前就已经被该设备占用,之前肯定是配置过从设备了,不是就代表之前总线不是被该从设备占用需要配置该从设备。

小结:
1.rtthread中把MUC内部的SPI控制器虚拟成了一个虚拟总线。
2.总线在系统启动是就已经创建并注册到IO设备管理器。
3.当我们在应用程序中需要创建挂载一个从设备的时候,首先创建从设备并挂载到总线,还要设置好该从设备与总线通信时,总线的配置参数。