4

OpenHarmony平台驱动案例--UART

 1 year ago
source link: https://www.51cto.com/article/763895.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
b2a265652808b3126bd540d6234447c0774af1.png

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

一、程序介绍

本程序是基于OpenHarmony标准系统编写的平台驱动案例:UART
详细资料请参考官网:

二、基础知识

1、UART简介

UART指异步收发传输器(Universal Asynchronous Receiver/Transmitter),是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。
两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是:

  • TX:发送数据端,和对端的RX相连。
  • RX:接收数据端,和对端的TX相连。
  • RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连。
  • CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连。

UART的2线相连:

resize,w_535,h_237

UART的4线相连:

resize,w_515,h_222

UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。

2、UART驱动开发

(1)、UART驱动开发接口

为了保证上层在调用UART接口时能够正确的操作UART控制器,核心层在//drivers/hdf_core/framework/support/platform/include/uart/uart_core.h中定义了以下钩子函数,驱动适配者需要在适配层实现这些函数的具体功能,并与钩子函数挂接,从而完成适配层与核心层的交互。

UartHostMethod定义:

resize,w_820,h_305

UartHostMethod结构体成员的回调函数功能说明:

resize,w_820,h_750

(2)、UART驱动开发步骤

UART模块适配HDF框架包含以下四个步骤:

  • 实例化驱动入口。
  • 配置属性文件。
  • 实例化UART控制器对象。
  • 驱动调试。
    我们以///drivers/hdf_core/adapter/khdf/linux/platform/uart/uart_adapter.c为例(该UART驱动是建立于Linux UART子系统基础上创建)。

驱动实例化驱动入口

驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

UART驱动入口开发参考:

resize,w_820,h_237
配置属性文件

完成驱动入口注册之后,需要在device_info.hcs文件中添加deviceNode信息,deviceNode信息与驱动入口注册相关。本例以两个UART控制器为例,如有多个器件信息,则需要在device_info.hcs文件增加对应的deviceNode信息。器件属性值与核心层UartDev成员的默认值或限制范围有密切关系,比如Uart设备号,需要在uart_config.hcs文件中增加对应的器件属性。

本次案例以rk3568为案例(即文件//vendor/lockzhiner/rk3568/hdf_config/khdf/device_info/device_info.hcs),添加deviceNode描述,具体修改如下:

resize,w_820,h_460

uart_config.hcs 配置参考//vendor/lockzhiner/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs,具体修改如下:

resize,w_820,h_508

(3)实例化UART控制器对象

完成驱动入口注册之后,下一步就是以核心层UartDev对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化UartDev成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind、Init、Release)。

resize,w_820,h_595
(4)驱动调试

建议先在Linux下修改确认,再移植到OpenHarmony。

3、UART应用开发

UART模块应用比较广泛,主要用于实现设备之间的低速串行通信,例如输出打印信息,当然也可以外接各种模块,如GPS、蓝牙等。

(1)接口说明

UART模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/uart_if.h。
UART驱动API接口功能介绍如下所示:

resize,w_820,h_396

UartOpen

在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。

resize,w_820,h_47

UartOpen参数定义如下:

resize,w_820,h_91

UartOpen返回值定义如下:

resize,w_820,h_125

假设系统中的UART端口号为1,获取该UART设备句柄的示例如下:

resize,w_820,h_208

UartSetBaud

在通信之前,需要设置UART的波特率。

resize,w_820,h_47

UartSetBaud参数定义如下:

resize,w_820,h_123

UartSetBaud返回值定义如下:

resize,w_820,h_125

UartGetBaud

设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率。

resize,w_820,h_45

UartGetBaud参数定义如下:

resize,w_820,h_127

UartGetBaud返回值定义如下:

resize,w_820,h_128

UartSetAttribute

在通信之前,需要设置UART的设备属性。

resize,w_820,h_45

UartSetAttribute参数定义如下:

resize,w_820,h_130

UartGetAttribute返回值定义如下:

resize,w_820,h_128

UartGetAttribute

设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性。

resize,w_820,h_43

UartGetAttribute参数定义如下:

resize,w_820,h_129

UartGetAttribute返回值定义如下:

resize,w_820,h_128

UartSetTransMode

在通信之前,需要设置UART的传输模式。

resize,w_820,h_45

UartSetTransMode参数定义如下:

resize,w_820,h_124

UartSetTransMode返回值定义如下:

resize,w_820,h_127

UartWrite

向UART设备写入指定长度的数据。

resize,w_820,h_44

UartWrite参数定义如下:

resize,w_820,h_163

UartWrite返回值定义如下:

resize,w_820,h_120

UartRead

从UART设备中读取指定长度的数据。

resize,w_820,h_45

UartRead参数定义如下:

resize,w_820,h_165

UartRead返回值定义如下:

resize,w_820,h_122

UartClose

UART通信完成之后,需要销毁UART设备句柄。

resize,w_820,h_46

UartClose参数定义如下:

resize,w_820,h_89

(2)开发流程

使用UART的一般流程如下图所示:

resize,w_304,h_322

三、程序解析

1、准备工作

查看《凌蒙派-RK3568开发板_排针说明表_》(即Git仓库的//docs/board/凌蒙派-RK3568开发板_排针说明表_v1.0.xlsx),具体如下:

resize,w_820,h_128

2、Linux内核解析

(1)创建Linux内核Git

请参考《OpenHarmony如何为内核打patch》(即Git仓库的//docs/OpenHarmony如何为内核打patch.docx)。

(2)修改设备树PWM7配置

修改//arch/arm64/boot/dts/rockchip/rk3568-lockzhiner-x0.dtsi(即该目录是指已打Patch后的Linux内核,不是OpenHarmony主目录),具体如下所示:

resize,w_820,h_138

(3)创建内核patch

请参考《OpenHarmony如何为内核打patch》(即Git仓库的//docs/OpenHarmony如何为内核打patch.docx)。

(4)替换OpenHarmony的内核patch

将制作出的kernel.patch替换到//kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch即可。

3、OpenHarmony配置树配置

(1)device_info.hcs

//vendor/lockzhiner/rk3568/hdf_config/khdf/device_info/device_info.hcs已定义好,具体如下:

resize,w_820,h_613
  • device2是我们新增的设备节点,给uart5使用。
  • policy必须为2,表示对内核态和用户态提供服务。否则,应用程序无法调用。
  • HDF_PLATFORM_UART_2,后面跟着的数据“2”,是UartOpen()的端口号。
  • HDF_PLATFORM_UART_2,后面跟着的数据“2”,必须是递增的。

(2)rk3568_uart_config.hcs

//vendor/lockzhiner/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs,具体内容如下:

resize,w_820,h_577
  • device_uart_0x0002是新增的,为uart5准备的。
  • match_attr的名称必须是rockchip_rk3568_uart_2。

4、OpenHarmony UART平台驱动

在//drivers/hdf_core/adapter/khdf/linux/platform/uart/uart_adapter.c已编写对接Linux PWM驱动的相关代码,具体内容如下:

resize,w_820,h_228

该部分代码不细述,感兴趣的读者可以去详读。

5、应用程序

(1)uart_test.c

uart相关头文件如下所示:

resize,w_820,h_50

主函数定义UART接口调用,具体如下:

resize,w_820,h_1816

(2)BUILD.gn

编写应用程序的BUILD.gn,具体内容如下:

resize,w_820,h_829

(3)参与应用程序编译

编辑//vendor/lockzhiner/rk3568/samples/BUILD.gn,开启编译选项。具体如下:

resize,w_820,h_43

四、程序编译

建议使用docker编译方法,运行如下:

resize,w_820,h_117

五、运行结果

运行如下:

resize,w_820,h_369
  • rbuff获取的时候可能为空。因为本次案例是基于非阻塞,电脑端发送的串口可能没有获取到数据。
    建议:
  • 读者可以尝试使用堵塞方式,再测试看看。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK