摘要

设备之间为各类派生继承的关系,向上追本溯源,可谓同根而生。本文讲述嵌入式系统中“设备框架”或“设备树”的概念,分析其设计初衷、核心设计思想、实现原理等,并以RT-Thread系统的设备框架为例进行讲解。
在这里插入图片描述

设备框架概念

在嵌入式系统中,设备驱动框架或设备树是管理系统硬件资源、提高代码复用性和简化驱动开发过程的重要机制,例如Linux、RT-Thread、VxWorks、Zephyr等嵌入式系统中都支持此功能。
那么什么是设备框架呢?思考:为什么各式各样的鼠标插在电脑上,都能立刻正常工作?这是因为各个厂家都是参照同一套标准为鼠标进行软件接口设计,操作系统只需要按照这个接口去管理鼠标,就能达到预期效果。
在嵌入式系统中,设备框架就是为了管理硬件设备而设计的一套管理的结构、方法和工具,实现设备的管理、组织、交互。它在应用和实际设备之间构造了一个抽象层,这个抽象层将应用和硬件隔离,简化了硬件设备的管理,并为开发者提供了统一的接口来访问和控制硬件资源,使得应用不依赖于具体的硬件细节,两者可以独立存在与开发,降低耦合性,提高可靠性。

核心设计思想

为了实现设备框架应有的功能,应该向以下几个方向去努力

  • 统一设备模型,从应用层向下调用统一接口的需求出发,所有设备在设备框架中必须以统一的模型表示,只有这样才能被应用层统一管理。
  • 设备标识,虽然调用接口是相同的,但为了上层应用与实际设备能够正确匹配,设备必须有标识个体之间差异的字段,以便上层查找、使用。
  • 兼容各类设备,设备框架应该能将各类设备组织、管理起来,那统一的设备框架和支持各种设备的矛盾如何解决?按照面对对象的方式去构建,向上进行抽象化,总结各类设备相同的属性和方法,对外固定统一接口;向下具体化展现各类设备的差异性
  • 硬件平台接口,为了最终实现设备驱动程序,框架中需要包含与硬件平台相关的属性和方法,例如引脚号、中断号、DMA配置等信息。
  • 继承与派生,如何将设备框架中的向上抽象化、向下具体化相连接呢?使用面向对象中的继承与派生方法,将上层抽象与下层具体的框架进行层层剖析、层层连接。
  • 设备生命周期管理,支持设备的注册、查找、初始化、移除等操作。
  • 资源保护,设备框架应当支持对设备中的公共资源进行保护,保证多线程访问的安全性

框架分层

为了实现上述特性,设备框架按照3层实现:IO设备管理层、设备驱动框架层、设备驱动层
在这里插入图片描述

IO设备管理层

是应用层和底层设备的隔离带,将各种硬件设备(UART SPI IIC等)都抽象成统一形式进行描述,方便上层按照统一接口去管理这些设备。屏蔽底层设备升级、更替对上层的影响,上层应用和底层设备代码可以独立开发,降低耦合性,提高可靠性。
UART、SPI等设备属性和方法的差异性在下一层实现。

设备驱动框架层

实现某类设备驱动中与硬件平台无关的通用部分。
在上一层的基础上扩展出某类设备的独有属性,对同种类设备属性和方法的相同部分进行抽取、封装,剩余因硬件平台而不同的部分在下一层设备驱动层实现。

设备驱动层

负责创建最终设备实体,包含对具体硬件依赖的相关信息,实现直接驱动硬件的程序,并完成设备在系统中的注册。

设备统一模型

设备框架分为3层进行设计,相对应描述设备的统一模型也分为三层进行封装与实现,有关设备统一模型的类关系如下图所示:
在这里插入图片描述

各个类的具体成员及大致作用如下图所示:
在这里插入图片描述

这种统一的设备模型,按照面向对象的思想进行设计,从下往上不断抽象,将不同的细节屏蔽在下面,将相同的部分抽象到上一层;按照面向接口的思想进行设计,使用父类与子类的继承关系,将层层抽象进行连接,子类受到父类接口的限制,并各自实现父类的接口。不同的设备之间为各类派生继承的关系,向上追本溯源,可谓同根而生。

rt_object (object.c)

表示和管理系统中各内核对象的基础,几乎所有内核对象(线程、信号量、设备)都继承自rt_obiect,作用:

  • 统一内核对象管理接口,有助于实现对象的创建、删除、查找等通用操作
  • 使用name字段 进行对象查找,便于调试和使用
  • 对象类型标识标识特定对象独有的状态
  • 结合链表和对象容器(rt_object_container)来组织管理不同的对象,设备注册功能的核心功能就是将设备对象使用此处链表进行链接、管理。
    在这里插入图片描述

rt_device (device.c)

rt_device 是 RT-Thread 中所有设备的基类,将各种硬件设备(UART SPI IIC等)和虚拟设备(虚拟串口等)都抽象成rt_device,方便上层可以按照统一的接口,去管理这些设备。
UART、SPI等设备的具体属性和方法在下一层实现

rt_serial_device (serial.c)

在rt_device的基础上,扩展出对某类设备的独有特征,对同种类设备属性和方法的相同部分进行抽取、封装,其余不同部分在下一层设备驱动层实现。

stm32_uart (drv_uart.c)

在rt_serial_device的基础上,扩展出该种类设备在特定硬件上的属性和方法。

注册过程描述

注册过程其实就是对各个串口对象进行初始化的过程,类中这么多成员,应该由哪一层对这些成员进行初始化?原则(先1后2):

  • 优先级1原则:谁了解谁配置。例如,对于直接对硬件操作的接口在设备驱动层实现,设备驱动层就需要将此类接口注册到设备驱动框架层中。
  • 优先级2原则:谁使用谁配置。例如,设备管理层中表示有多少线程在使用此设备的标识,需要由设备管理层进行清零。
    设备注册过程序列图如图所示,复杂的设备多一层设备驱动框架层。
    !在这里插入图片描述

附赠:注册过程流图

在这里插入图片描述

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐