OpenHarmony系统平台驱动概述
OpenHarmony系统平台驱动(PlatformDriver),即平台设备驱动,它用于驱动平台设备(PlatformDevice),为系统及外设驱动提供访接口。这里的平台设备,泛指I2C/UART等总线、以及GPIO/RTC等SOC片内硬件资源。
OpenHarmony系统平台驱动框架是OpenHarmony系统驱动框架的重要组成部分,它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制,为各类平台设备驱动的实现提供标准模型。
OpenHarmony系统平台驱动框架为外设提供了标准的平台设备访问接口,使其不必关注具体硬件及OS平台;同时为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制。
为实现这个目标,OpenHarmony系统平台驱动框架满足如下特性:
- 统一的平台设备访问接口:对平台设备操作接口进行统一封装,屏蔽不同SOC平台硬件差异以及不同OS形态差异。
- 统一的平台驱动适配接口:为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制,而不必关注设备管理及公共业务流程。
- 提供设备注册、管理、访问控制等与SOC无关的公共能力。
OpenHarmony系统平台驱动框架目前支持的设备类型包括但不限于:I2C/SPI/UART/MIPI_DSI/SDIO/GPIO/PWM/WATCHDOG/RTC/DMA
OpenHarmony平台驱动框架介绍
OpenHarmony系统平台驱动框架组成
OpenHarmony系统平台驱动框架主要由平台接口层、平台核心层以及平台适配层三个部分组成。
1)平台接口层 以API的形式提供标准的平台设备访问接口。
平台接口层以设备句柄加配套API的形式对外提供统一的、标准的访问接口。
设备句柄是DevHandle类型的实例,通过不同设备模块提供的Open/Close方法进行获取、释放。成功获取设备句柄后,即可使用相应的API执行设备操作。例如通过I2cTransfer完成一次I2C数据传输。
这是一种代理模式,即接口层API不直接引用实际设备对象,而是通过DevHandle作为代理,间接访问设备;而所有来自外设驱动的访问,都建议走接口层,以获得最佳的稳定性。
不同类型设备的API使用,请参考如下官方文档的平台驱动章节:
https://device.OpenHarmony系统.com/cn/docs/develop/drive/oem_drive_hdfdev-0000001051715456
2)平台核心层 提供平台设备模型及公共业务框架。
提供统一适配接口:定义了标准的设备对象模型,驱动程序仅需关注标准对象模型的适配。
抽取公共业务框架:将不同设备模块的公共流程、算法加以抽取,使得具体设备驱动更加轻薄。
设备管理:设备注册、注销、设备查找、访问控制。
3)平台适配层 提供特定平台设备的适配驱动,并遵守核心层约束。
驱动具体平台设备硬件,并创建对应的设备模型对象,注册到核心层纳入统一管理。
平台接口层分析
前面说过,在接口层,我们用DevHandle类型的设备句柄表示一个平台设备对象,然后针对不同类型设备提供一套标准的API方法用于设备访问。那么设备句柄和真实的设备对象如何关联呢?
查看DevHandle的定义,发现它就是一个void类型指针:
/**
-
@brief Defines the common device handle of the platform driver.
-
The handle is associated with a specific platform device and is used as the
-
first input parameter for all APIs of the platform driver.
-
@since 1.0
*/
typedef void* DevHandle;
实际上,在内核态,这个指针可以直接指向实际设备对象,但是对于某些类型的平台设备,我们需要在用户态提供同样的DevHandle类型及配套API,而实际设备对象在内核空间,我们无法直接获取和使用内核空间的地址。我们的解决办法是将平台设备对象实现为一个HDF设备服务,这样借助HDF DeviceManager的设备服务机制,可以在用户态、内核态同时获取到设备服务,而用户态同内核态通信的问题交由HDF DeviceManager处理。此时,DevHandle只需要关联到这个设备服务即可,而void*类型保证了足够的灵活性。
根据DevHandle和设备对象关联方式的不同,接口层的设计有三种模式,下面将一一讲解。
1.独立服务模式
这种模式用于需要在用户态和内核态同时提供API的设备类型,DevHandle同设备对象的关联方式为:
用户态:关联到平台设备对应的设备服务
内核态度:关联到实际平台设备对象或其设备服务(在内核态两者可互相转换)
这样,每一个设备对象,会独立发布一个设备服务,来处理外部访问,服务收到API的访问请求之后,通过提取请求参数,并调用实际设备对象的相应内部方法。
这种方式的优点是管理比较简单,因为它借助了HDF DeviceManager的服务管理能力;但是缺点是需要为每一个设备对象配置设备节点,以便发布设备服务。
这种模式的典型实践是UART模块,这在后面介绍驱动适配时会详细介绍。
2.统一服务模式
有时候,同一类型的设备对象可能会很多,例如I2C模块,可能同时有十几个控制器。如果采用独立服务的模式,每一个控制器,作为一个平台设备,为其创建一个设备服务,那么将会有十几个服务被创建,不光要配置很多设备节点,而且这些服务还会占用内存资源。
这时,我们可以为一类设备对象,创建一个平台设备管理器(PlatformManager)对象,并同时对外发布一个管理器服务,由这个管理器服务来统一处理外部访问。当用户需要打开某个设备时,先通过HDF DeviceManager获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备,并返回一个设备描述符,而这个描述符仍然可以由DevHandle类型表示。
这种模式的实践代表是I2C模块,PlatformManager实现为I2cManager,而PlatformDevice则是I2cCntlr,感兴趣的读者可以阅读一下drivers/framework下的i2c_if.c/i2c_core.c一探究竟。
3.无服务模式
这种模式用于不需要在用户态提供API的设备类型或者没有用户态、内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址。而PlatformManager的实现比较自由,它不需要实现设备服务,只需做好某种类型的设备管理即可,甚至在C语言中,由于无法进行OOP编程,很多模块直接将这个功能面向过程化了,使得没有一个具体的结构体与之对应。但是,我们仍然强调PlatformManager这个概念,也期望随着后续平台驱动框架的演进,逐步完善、规范化,形成更加统一的编程风格。
平台核心层分析
平台核心层的作用是承上启下,其主要内容包括:
提供适配接口:为具体的平台设备驱动提