[文章]OpenHarmony平台驱动案例--UART

阅读量0
1
2


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

  • UART平台驱动开发

  • UART应用程序开发

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

  • TX:发送数据端,和对端的RX相连。

  • RX:接收数据端,和对端的TX相连。

  • RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连。

  • CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连。

图1 UART的2线相连
微信截图_20230817154837.png
图2 UART的4线相连
微信截图_20230817154921.png
UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。
2.2、UART驱动开发2.2.1、UART驱动开发接口
为了保证上层在调用UART接口时能够正确的操作UART控制器,核心层在//drivers/hdf_core/framework/support/platform/include/uart/uart_core.h中定义了以下钩子函数,驱动适配者需要在适配层实现这些函数的具体功能,并与钩子函数挂接,从而完成适配层与核心层的交互。
UartHostMethod定义:
  1. <span><span class="cm-keyword">struct</span> <span class="cm-def">UartHostMethod</span> {</span>
  2. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">Init</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>);</span>
  3. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">Deinit</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>);</span>
  4. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">Read</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-variable-3">uint8_t</span> <span class="cm-variable-3">*</span><span class="cm-variable">data</span>, <span class="cm-variable-3">uint32_t</span> <span class="cm-variable">size</span>);</span>
  5. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">Write</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-variable-3">uint8_t</span> <span class="cm-variable-3">*</span><span class="cm-variable">data</span>, <span class="cm-variable-3">uint32_t</span> <span class="cm-variable">size</span>);</span>
  6. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">GetBaud</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-variable-3">uint32_t</span> <span class="cm-variable-3">*</span><span class="cm-variable">baudRate</span>);</span>
  7. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">SetBaud</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-variable-3">uint32_t</span> <span class="cm-variable">baudRate</span>);</span>
  8. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">GetAttribute</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-keyword">struct</span> <span class="cm-def">UartAttribute</span> <span class="cm-operator">*</span><span class="cm-variable">attribute</span>);</span>
  9. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">SetAttribute</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-keyword">struct</span> <span class="cm-def">UartAttribute</span> <span class="cm-operator">*</span><span class="cm-variable">attribute</span>);</span>
  10. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">SetTransMode</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-keyword">enum</span> <span class="cm-variable">UartTransMode</span> <span class="cm-variable">mode</span>);</span>
  11. <span>    <span class="cm-variable-3">int32_t</span> (<span class="cm-operator">*</span><span class="cm-variable">pollEvent</span>)(<span class="cm-keyword">struct</span> <span class="cm-def">UartHost</span> <span class="cm-operator">*</span><span class="cm-variable">host</span>, <span class="cm-variable-3">void</span> <span class="cm-variable-3">*</span><span class="cm-variable">filep</span>, <span class="cm-variable-3">void</span> <span class="cm-variable-3">*</span><span class="cm-variable">table</span>);</span>
  12. <span>};</span>
复制代码
UartHostMethod结构体成员的回调函数功能说明:
微信截图_20230817155021.png
2.2.2、UART驱动开发步骤
UART模块适配HDF框架包含以下四个步骤:

  • 实例化驱动入口。

  • 配置属性文件。

  • 实例化UART控制器对象。

  • 驱动调试。

我们以///drivers/hdf_core/adapter/khdf/linux/platform/uart/uart_adapter.c为例(该UART驱动是建立于Linux UART子系统基础上创建)。
2.2.2.1、驱动实例化驱动入口
驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
UART驱动入口开发参考:
  1. <span><span class="cm-keyword">struct</span> <span class="cm-def">HdfDriverEntry</span> <span class="cm-def">g_hdfUartchdog</span> <span class="cm-operator">=</span> {</span>
  2. <span>    .<span class="cm-variable">moduleVersion</span> <span class="cm-operator">=</span> <span class="cm-number">1</span>,</span>
  3. <span>    .<span class="cm-variable">moduleName</span> <span class="cm-operator">=</span> <span class="cm-string">"HDF_PLATFORM_UART"</span>,</span>
  4. <span>    .<span class="cm-variable">Bind</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartBind</span>,</span>
  5. <span>    .<span class="cm-variable">Init</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartInit</span>,</span>
  6. <span>    .<span class="cm-variable">Release</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartRelease</span>,</span>
  7. <span>};</span>
  8. <span><span>​</span></span>
  9. <span><span class="cm-variable">HDF_INIT</span>(<span class="cm-variable">g_hdfUartchdog</span>);</span>
复制代码
2.2.2.2、配置属性文件
完成驱动入口注册之后,需要在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描述,具体修改如下:
  1. <span>device_uart :: device {</span>
  2. <span>    device0 :: deviceNode {</span>
  3. <span>        policy = 1;<span class="cm-tab"> </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 驱动服务发布的策略,policy大于等于1(用户态可见为2,仅内核态可见为1)</span>
  4. <span>        priority = 40;<span class="cm-tab">  </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 驱动启动优先级</span>
  5. <span>        permission = 0644;<span class="cm-tab">  </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 驱动创建设备节点权限</span>
  6. <span>        moduleName = "HDF_PLATFORM_UART";<span class="cm-tab">   </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致</span>
  7. <span>        serviceName = "HDF_PLATFORM_UART_0";<span class="cm-tab">    </span><span class="cm-tab">    </span>// 驱动对外发布服务的名称,必须唯一,必须要按照HDF_PLATFORM_UART_X的格式,X为UART控制器编号</span>
  8. <span>        deviceMatchAttr = "rockchip_rk3568_uart_0"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值一致</span>
  9. <span>    }</span>
  10. <span>    device1 :: deviceNode {</span>
  11. <span>        policy = 2;</span>
  12. <span>        permission = 0644;</span>
  13. <span>        priority = 40;</span>
  14. <span>        moduleName = "HDF_PLATFORM_UART";</span>
  15. <span>        serviceName = "HDF_PLATFORM_UART_1";</span>
  16. <span>        deviceMatchAttr = "rockchip_rk3568_uart_1";</span>
  17. <span>    }</span>
  18. <span>}</span>
复制代码
uart_config.hcs 配置参考//vendor/lockzhiner/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs,具体修改如下:
  1. <span>root {</span>
  2. <span>    platform {</span>
  3. <span>        uart_config {</span>
  4. <span>            template uart_device {</span>
  5. <span>                serviceName = "";</span>
  6. <span>                match_attr = "";</span>
  7. <span>                driver_name = "ttyS";</span>
  8. <span>                num = 0;</span>
  9. <span>            }</span>
  10. <span><span>​</span></span>
  11. <span>            device_uart_0x0000 :: uart_device {</span>
  12. <span>                match_attr = "rockchip_rk3568_uart_0";</span>
  13. <span>            }</span>
  14. <span>            device_uart_0x0001 :: uart_device {</span>
  15. <span>                num = 1;<span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 序号,是Linux的/dev/ttySXXX,XXX即是num</span>
  16. <span>                match_attr = "rockchip_rk3568_uart_1";<span class="cm-tab">  </span>// 必须和device_info.hcs中对应的设备的deviceMatchAttr值一致</span>
  17. <span>                <span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span><span class="cm-tab">    </span>// 注意rockchip_rk3568_uart_XX,XX表示的OH的UART序号,必须从0开始,顺序递增</span>
  18. <span>            }</span>
  19. <span>        }</span>
  20. <span>    }</span>
  21. <span>}</span>
复制代码
2.2.2.3、实例化UART控制器对象
完成驱动入口注册之后,下一步就是以核心层UartDev对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化UartDev成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind、Init、Release)。
  1. <span><span class="cm-comment">// 定义UartHostMethod成员g_uartHostMethod,实现uart相应接口</span></span>
  2. <span><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">UartHostMethod</span> <span class="cm-def">g_uartHostMethod</span> <span class="cm-operator">=</span> {</span>
  3. <span>    .<span class="cm-variable">Init</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterInit</span>,</span>
  4. <span>    .<span class="cm-variable">Deinit</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterDeInit</span>,</span>
  5. <span>    .<span class="cm-variable">Read</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterRead</span>,</span>
  6. <span>    .<span class="cm-variable">Write</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterWrite</span>,</span>
  7. <span>    .<span class="cm-variable">SetBaud</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterSetBaud</span>,</span>
  8. <span>    .<span class="cm-variable">GetBaud</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterGetBaud</span>,</span>
  9. <span>    .<span class="cm-variable">SetAttribute</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterSetAttribute</span>,</span>
  10. <span>    .<span class="cm-variable">GetAttribute</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterGetAttribute</span>,</span>
  11. <span>    .<span class="cm-variable">SetTransMode</span> <span class="cm-operator">=</span> <span class="cm-variable">UartAdapterSetTransMode</span>,</span>
  12. <span>};</span>
  13. <span><span>​</span></span>
  14. <span><span class="cm-keyword">static</span> <span class="cm-variable-3">int32_t</span> <span class="cm-def">HdfUartBind</span>(<span class="cm-keyword">struct</span> <span class="cm-def">HdfDeviceObject</span> <span class="cm-operator">*</span><span class="cm-variable">obj</span>);</span>
  15. <span><span class="cm-keyword">static</span> <span class="cm-variable-3">int32_t</span> <span class="cm-def">HdfUartInit</span>(<span class="cm-keyword">struct</span> <span class="cm-def">HdfDeviceObject</span> <span class="cm-operator">*</span><span class="cm-variable">obj</span>);</span>
  16. <span><span class="cm-keyword">static</span> <span class="cm-variable-3">void</span> <span class="cm-def">HdfUartRelease</span>(<span class="cm-keyword">struct</span> <span class="cm-def">HdfDeviceObject</span> <span class="cm-operator">*</span><span class="cm-variable">obj</span>);</span>
  17. <span><span class="cm-keyword">struct</span> <span class="cm-def">HdfDriverEntry</span> <span class="cm-def">g_hdfUartchdog</span> <span class="cm-operator">=</span> {</span>
  18. <span>    .<span class="cm-variable">moduleVersion</span> <span class="cm-operator">=</span> <span class="cm-number">1</span>,</span>
  19. <span>    .<span class="cm-variable">moduleName</span> <span class="cm-operator">=</span> <span class="cm-string">"HDF_PLATFORM_UART"</span>,</span>
  20. <span>    .<span class="cm-variable">Bind</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartBind</span>,</span>
  21. <span>    .<span class="cm-variable">Init</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartInit</span>,</span>
  22. <span>    .<span class="cm-variable">Release</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartRelease</span>,</span>
  23. <span>};</span>
  24. <span><span>​</span></span>
  25. <span><span class="cm-variable">HDF_INIT</span>(<span class="cm-variable">g_hdfUartchdog</span>);</span>
复制代码
2.2.2.4、驱动调试
建议先在Linux下修改确认,再移植到OpenHarmony。
2.3、UART应用开发
UART模块应用比较广泛,主要用于实现设备之间的低速串行通信,例如输出打印信息,当然也可以外接各种模块,如GPS、蓝牙等。
2.3.1、接口说明
UART模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/uart_if.h。
UART驱动API接口功能介绍如下所示:
微信截图_20230817155059.png
(1)UartOpen
在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。
  1. DevHandle UartOpen(uint32_t port);
复制代码
UartOpen参数定义如下:
微信截图_20230817155115.png

UartOpen返回值定义如下:

微信截图_20230817155127.png

假设系统中的UART端口号为1,获取该UART设备句柄的示例如下:
  1. <span><span class="cm-variable">DevHandle</span> <span class="cm-variable">handle</span> <span class="cm-operator">=</span> <span class="cm-variable">NULL</span>;    <span class="cm-comment">// UART设备句柄</span></span>
  2. <span><span class="cm-variable-3">uint32_t</span> <span class="cm-variable">port</span> <span class="cm-operator">=</span> <span class="cm-number">1</span>;          <span class="cm-comment">// UART设备端口号</span></span>
  3. <span><span>​</span></span>
  4. <span><span class="cm-variable">handle</span> <span class="cm-operator">=</span> <span class="cm-variable">UartOpen</span>(<span class="cm-variable">port</span>);</span>
  5. <span><span class="cm-keyword">if</span> (<span class="cm-variable">handle</span> <span class="cm-operator">==</span> <span class="cm-variable">NULL</span>) {</span>
  6. <span>    <span class="cm-variable">HDF_LOGE</span>(<span class="cm-string">"UartOpen: open uart_%u failed!\n"</span>, <span class="cm-variable">port</span>);</span>
  7. <span>    <span class="cm-keyword">return</span>;</span>
  8. <span>}</span>
复制代码
(2)UartSetBaud
在通信之前,需要设置UART的波特率。
  1. int32_t UartSetBaud(DevHandle handle, uint32_t baudRate);
复制代码
UartSetBaud参数定义如下:
微信截图_20230817155142.png

UartSetBaud返回值定义如下:
微信截图_20230817155151.png
(3)UartGetBaud
设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率。
  1. int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate);
复制代码
UartGetBaud参数定义如下:
微信截图_20230817155203.png
UartGetBaud返回值定义如下:
微信截图_20230817155215.png

(4)UartSetAttribute
在通信之前,需要设置UART的设备属性。
  1. int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute);
复制代码
UartSetAttribute参数定义如下:
微信截图_20230817155230.png
UartSetAttribute返回值定义如下:
微信截图_20230817155241.png
(5)UartGetAttribute
设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性。
  1. int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute);
复制代码
UartGetAttribute参数定义如下:
微信截图_20230817155255.png
UartGetAttribute返回值定义如下:
微信截图_20230817155305.png
(6)UartSetTransMode
在通信之前,需要设置UART的传输模式。
  1. int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode);
复制代码
UartSetTransMode参数定义如下:
微信截图_20230817155320.png
UartSetTransMode返回值定义如下:
微信截图_20230817160756.png
(7)UartWrite
向UART设备写入指定长度的数据。
  1. int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size);
复制代码
UartWrite参数定义如下:
微信截图_20230817160812.png
UartWrite返回值定义如下:
微信截图_20230817160822.png
(8)UartRead
从UART设备中读取指定长度的数据。
  1. int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size);
复制代码
UartRead参数定义如下:
微信截图_20230817160835.png
UartRead返回值定义如下:
微信截图_20230817160846.png
(9)UartClose
UART通信完成之后,需要销毁UART设备句柄。
  1. void UartClose(DevHandle handle);
复制代码
UartClose参数定义如下:
微信截图_20230817160857.png

2.2.2、开发流程
使用UART的一般流程如下图所示:
微信截图_20230817160907.png
3、程序解析3.1、准备工作
查看《凌蒙派-RK3568开发板排针说明表》(即Git仓库的//docs/board/凌蒙派-RK3568开发板排针说明表v1.0.xlsx),具体如下:
微信截图_20230817160917.png
3.2、Linux内核解析
3.2.1、创建Linux内核Git
请参考《OpenHarmony如何为内核打patch》(即Git仓库的//docs/OpenHarmony如何为内核打patch.docx)。
3.2.2、修改设备树PWM7配置
修改//arch/arm64/boot/dts/rockchip/rk3568-lockzhiner-x0.dtsi(即该目录是指已打Patch后的Linux内核,不是OpenHarmony主目录),具体如下所示:
  1. <span>&amp;uart5 {</span>
  2. <span><span class="cm-tab">    </span>status = "okay";</span>
  3. <span><span class="cm-tab">    </span>pinctrl-names = "default";</span>
  4. <span><span class="cm-tab">    </span>pinctrl-0 = &lt;&amp;uart5m1_xfer&gt;;</span>
  5. <span>};</span>
复制代码
3.2.3、创建内核patch
请参考《OpenHarmony如何为内核打patch》(即Git仓库的//docs/OpenHarmony如何为内核打patch.docx)。
3.2.4、替换OpenHarmony的内核patch
将制作出的kernel.patch替换到//kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch即可。
3.3、OpenHarmony配置树配置
3.3.1、device_info.hcs
//vendor/lockzhiner/rk3568/hdf_config/khdf/device_info/device_info.hcs已定义好,具体如下:
  1. <span>device_uart :: device {</span>
  2. <span>    device0 :: deviceNode {</span>
  3. <span>        policy = 1;</span>
  4. <span>        priority = 40;</span>
  5. <span>        permission = 0644;</span>
  6. <span>        moduleName = "HDF_PLATFORM_UART";</span>
  7. <span>        serviceName = "HDF_PLATFORM_UART_0";</span>
  8. <span>        deviceMatchAttr = "rockchip_rk3568_uart_0";</span>
  9. <span>    }</span>
  10. <span>    device1 :: deviceNode {</span>
  11. <span>        policy = 2;</span>
  12. <span>        permission = 0644;</span>
  13. <span>        priority = 40;</span>
  14. <span>        moduleName = "HDF_PLATFORM_UART";</span>
  15. <span>        serviceName = "HDF_PLATFORM_UART_1";</span>
  16. <span>        deviceMatchAttr = "rockchip_rk3568_uart_1";</span>
  17. <span>    }</span>
  18. <span>    device2 :: deviceNode {</span>
  19. <span>        policy = 2;</span>
  20. <span>        permission = 0644;</span>
  21. <span>        priority = 40;</span>
  22. <span>        moduleName = "HDF_PLATFORM_UART";</span>
  23. <span>        serviceName = "HDF_PLATFORM_UART_2";</span>
  24. <span>        deviceMatchAttr = "rockchip_rk3568_uart_2";</span>
  25. <span>    }</span>
  26. <span>}</span>
复制代码
注意:



  • device2是我们新增的设备节点,给uart5使用。

  • policy必须为2,表示对内核态和用户态提供服务。否则,应用程序无法调用。

  • HDF_PLATFORM_UART_2,后面跟着的数据“2”,是UartOpen()的端口号。

  • HDF_PLATFORM_UART_2,后面跟着的数据“2”,必须是递增的。

3.3.2、rk3568_uart_config.hcs
//vendor/lockzhiner/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs,具体内容如下:
  1. <span>root {</span>
  2. <span>    platform {</span>
  3. <span>        uart_config {</span>
  4. <span>            template uart_device {</span>
  5. <span>                serviceName = "";</span>
  6. <span>                match_attr = "";</span>
  7. <span>                driver_name = "ttyS";</span>
  8. <span>                num = 0;</span>
  9. <span>            }</span>
  10. <span><span>​</span></span>
  11. <span>            device_uart_0x0000 :: uart_device {</span>
  12. <span>                match_attr = "rockchip_rk3568_uart_0";</span>
  13. <span>            }</span>
  14. <span>            device_uart_0x0001 :: uart_device {</span>
  15. <span>                num = 1;</span>
  16. <span>                match_attr = "rockchip_rk3568_uart_1";</span>
  17. <span>            }</span>
  18. <span>            device_uart_0x0002 :: uart_device {</span>
  19. <span>                num = 5;</span>
  20. <span>                match_attr = "rockchip_rk3568_uart_2";</span>
  21. <span>            }</span>
  22. <span>        }</span>
  23. <span>    }</span>
  24. <span>}</span>
复制代码
注意:

  • device_uart_0x0002是新增的,为uart5准备的。

  • match_attr的名称必须是rockchip_rk3568_uart_2。

3.4、OpenHarmony UART平台驱动
在//drivers/hdf_core/adapter/khdf/linux/platform/uart/uart_adapter.c已编写对接Linux PWM驱动的相关代码,具体内容如下:
  1. <span><span class="cm-keyword">struct</span> <span class="cm-def">HdfDriverEntry</span> <span class="cm-def">g_hdfUartchdog</span> <span class="cm-operator">=</span> {</span>
  2. <span>    .<span class="cm-variable">moduleVersion</span> <span class="cm-operator">=</span> <span class="cm-number">1</span>,</span>
  3. <span>    .<span class="cm-variable">moduleName</span> <span class="cm-operator">=</span> <span class="cm-string">"HDF_PLATFORM_UART"</span>,</span>
  4. <span>    .<span class="cm-variable">Bind</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartBind</span>,</span>
  5. <span>    .<span class="cm-variable">Init</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartInit</span>,</span>
  6. <span>    .<span class="cm-variable">Release</span> <span class="cm-operator">=</span> <span class="cm-variable">HdfUartRelease</span>,</span>
  7. <span>};</span>
  8. <span><span>​</span></span>
  9. <span><span class="cm-variable">HDF_INIT</span>(<span class="cm-variable">g_hdfUartchdog</span>);</span>
复制代码
该部分代码不细述,感兴趣的读者可以去详读。
3.5、应用程序
3.5.1、uart_test.c
uart相关头文件如下所示:
  1. #include "uart_if.h"                 // UART标准接口头文件
复制代码
主函数定义UART接口调用,具体如下:
  1. <span><span class="cm-variable-3">int</span> <span class="cm-def">main</span>(<span class="cm-variable-3">int</span> <span class="cm-variable">argc</span>, <span class="cm-variable-3">char*</span> <span class="cm-variable">argv</span>[])</span>
  2. <span>{</span>
  3. <span>    <span class="cm-variable">DevHandle</span> <span class="cm-variable">handle</span> <span class="cm-operator">=</span> <span class="cm-variable">NULL</span>;</span>
  4. <span>    <span class="cm-keyword">struct</span> <span class="cm-def">UartAttribute</span> <span class="cm-def">attribute</span>;</span>
  5. <span>    <span class="cm-variable-3">int32_t</span> <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span>
  6. <span>    <span class="cm-variable-3">uint8_t</span> <span class="cm-variable">wbuff</span>[<span class="cm-variable">STRING_MAXSIZE</span>] <span class="cm-operator">=</span> <span class="cm-string">"HelloWorld"</span>;</span>
  7. <span>    <span class="cm-variable-3">uint8_t</span> <span class="cm-variable">rbuff</span>[<span class="cm-variable">STRING_MAXSIZE</span>] <span class="cm-operator">=</span> { <span class="cm-number">0</span> };</span>
  8. <span>    ......</span>
  9. <span><span>​</span></span>
  10. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">dataBits</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_DATABIT_8</span>;   <span class="cm-comment">// UART传输数据位宽,一次传输7个bit</span></span>
  11. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">parity</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_PARITY_NONE</span>;   <span class="cm-comment">// UART传输数据无校检</span></span>
  12. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">stopBits</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_STOPBIT_1</span>;   <span class="cm-comment">// UART传输数据停止位为1位</span></span>
  13. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">rts</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_RTS_DIS</span>;          <span class="cm-comment">// UART禁用RTS</span></span>
  14. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">cts</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_CTS_DIS</span>;          <span class="cm-comment">// UART禁用CTS</span></span>
  15. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">fifoRxEn</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_RX_FIFO_EN</span>;  <span class="cm-comment">// UART使能RX FIFO</span></span>
  16. <span>    <span class="cm-variable">attribute</span>.<span class="cm-variable">fifoTxEn</span> <span class="cm-operator">=</span> <span class="cm-variable">UART_ATTR_TX_FIFO_EN</span>;  <span class="cm-comment">// UART使能TX FIFO</span></span>
  17. <span><span>​</span></span>
  18. <span>    <span class="cm-variable">handle</span> <span class="cm-operator">=</span> <span class="cm-variable">UartOpen</span>(<span class="cm-variable">m_uart_port</span>);</span>
  19. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">handle</span> <span class="cm-operator">==</span> <span class="cm-variable">NULL</span>) {</span>
  20. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartOpen: open uart port %u failed!\n"</span>, <span class="cm-variable">m_uart_port</span>);</span>
  21. <span>        <span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span>
  22. <span>    }</span>
  23. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartOpen successful and uart port = %d\n"</span>, <span class="cm-variable">m_uart_port</span>);</span>
  24. <span><span>​</span></span>
  25. <span>    <span class="cm-comment">// 设置UART波特率</span></span>
  26. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartSetBaud</span>(<span class="cm-variable">handle</span>, <span class="cm-variable">m_uart_baudrate</span>);</span>
  27. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">!=</span> <span class="cm-variable">HDF_SUCCESS</span>) {</span>
  28. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartSetBaud: set baud failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  29. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  30. <span>    }</span>
  31. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartSetBaud successful and uart baudrate = %d\n"</span>, <span class="cm-variable">m_uart_baudrate</span>);</span>
  32. <span><span>​</span></span>
  33. <span>    <span class="cm-comment">// 设置UART设备属性</span></span>
  34. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartSetAttribute</span>(<span class="cm-variable">handle</span>, <span class="cm-operator">&amp;</span><span class="cm-variable">attribute</span>);</span>
  35. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">!=</span> <span class="cm-variable">HDF_SUCCESS</span>) {</span>
  36. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartSetAttribute: set attribute failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  37. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  38. <span>    }</span>
  39. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartSetAttribute successful\n"</span>);</span>
  40. <span><span>​</span></span>
  41. <span>    <span class="cm-comment">// 获取UART设备属性</span></span>
  42. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartGetAttribute</span>(<span class="cm-variable">handle</span>, <span class="cm-operator">&amp;</span><span class="cm-variable">attribute</span>);</span>
  43. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">!=</span> <span class="cm-variable">HDF_SUCCESS</span>) {</span>
  44. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartGetAttribute: get attribute failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  45. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  46. <span>    }</span>
  47. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartGetAttribute successful\n"</span>);</span>
  48. <span><span>​</span></span>
  49. <span>    <span class="cm-comment">// 设置UART传输模式为非阻塞模式</span></span>
  50. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartSetTransMode</span>(<span class="cm-variable">handle</span>, <span class="cm-variable">UART_MODE_RD_NONBLOCK</span>);</span>
  51. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">!=</span> <span class="cm-variable">HDF_SUCCESS</span>) {</span>
  52. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartSetTransMode: set trans mode failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  53. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  54. <span>    }</span>
  55. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartSetTransMode successful\n"</span>);</span>
  56. <span><span>​</span></span>
  57. <span>    <span class="cm-comment">// 向UART设备写入数据</span></span>
  58. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartWrite</span>(<span class="cm-variable">handle</span>, <span class="cm-variable">wbuff</span>, (<span class="cm-variable-3">uint32_t</span>)<span class="cm-variable">strlen</span>((<span class="cm-variable-3">char</span> <span class="cm-variable-3">*</span>)<span class="cm-variable">wbuff</span>));</span>
  59. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">!=</span> <span class="cm-variable">HDF_SUCCESS</span>) {</span>
  60. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartWrite: write data failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  61. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  62. <span>    }</span>
  63. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartWrite successful and wbuff = %s\n"</span>, <span class="cm-variable">wbuff</span>);</span>
  64. <span><span>​</span></span>
  65. <span>    <span class="cm-comment">// 从UART设备读取5字节的数据</span></span>
  66. <span>    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">UartRead</span>(<span class="cm-variable">handle</span>, <span class="cm-variable">rbuff</span>, <span class="cm-variable">STRING_MAXSIZE</span>);</span>
  67. <span>    <span class="cm-keyword">if</span> (<span class="cm-variable">ret</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>) {</span>
  68. <span>        <span class="cm-variable">PRINT_ERROR</span>(<span class="cm-string">"UartRead: read data failed, ret %d\n"</span>, <span class="cm-variable">ret</span>);</span>
  69. <span>        <span class="cm-keyword">goto</span> <span class="cm-variable">ERR</span>;</span>
  70. <span>    }</span>
  71. <span>    <span class="cm-variable">PRINT_INFO</span>(<span class="cm-string">"UartRead successful and rbuff = %s\n"</span>, <span class="cm-variable">rbuff</span>);</span>
  72. <span><span>​</span></span>
  73. <span><span class="cm-variable">ERR</span>:</span>
  74. <span>    <span class="cm-comment">// 销毁UART设备句柄</span></span>
  75. <span>    <span class="cm-variable">UartClose</span>(<span class="cm-variable">handle</span>);</span>
  76. <span>    <span class="cm-keyword">return</span> <span class="cm-variable">ret</span>;</span>
  77. <span>}</span>
复制代码
3.5.2、BUILD.gn
编写应用程序的BUILD.gn,具体内容如下:
  1. <span>import("//build/ohos.gni")</span>
  2. <span>import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")</span>
  3. <span><span>​</span></span>
  4. <span>print("samples: compile rk3568_uart_test")</span>
  5. <span>ohos_executable("rk3568_uart_test") {</span>
  6. <span>  sources = [ "uart_test.c" ]</span>
  7. <span>  include_dirs = [</span>
  8. <span>    "$hdf_framework_path/include",</span>
  9. <span>    "$hdf_framework_path/include/core",</span>
  10. <span>    "$hdf_framework_path/include/osal",</span>
  11. <span>    "$hdf_framework_path/include/platform",</span>
  12. <span>    "$hdf_framework_path/include/utils",</span>
  13. <span>    "$hdf_uhdf_path/osal/include",</span>
  14. <span>    "$hdf_uhdf_path/ipc/include",</span>
  15. <span>    "//base/hiviewdfx/hilog/interfaces/native/kits/include",</span>
  16. <span>    "//third_party/bounds_checking_function/include",</span>
  17. <span>  ]</span>
  18. <span><span>​</span></span>
  19. <span>  deps = [</span>
  20. <span>    "$hdf_uhdf_path/platform:libhdf_platform",</span>
  21. <span>    "$hdf_uhdf_path/utils:libhdf_utils",</span>
  22. <span>    "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",</span>
  23. <span>  ]</span>
  24. <span><span>​</span></span>
  25. <span>  cflags = [</span>
  26. <span>    "-Wall",</span>
  27. <span>    "-Wextra",</span>
  28. <span>    "-Werror",</span>
  29. <span>    "-Wno-format",</span>
  30. <span>    "-Wno-format-extra-args",</span>
  31. <span>  ]</span>
  32. <span><span>​</span></span>
  33. <span>  part_name = "product_rk3568"</span>
  34. <span>  install_enable = true</span>
  35. <span>}</span>
复制代码
3.5.3、参与应用程序编译
编辑//vendor/lockzhiner/rk3568/samples/BUILD.gn,开启编译选项。具体如下:
  1. "b08_platform_device_uart/app:rk3568_uart_test",
复制代码
4、程序编译
建议使用docker编译方法,运行如下:
  1. <span>hb <span class="cm-keyword">set</span> <span class="cm-attribute">-root</span> .</span>
  2. <span>hb <span class="cm-keyword">set</span></span>
  3. <span><span class="cm-comment"># 选择lockzhiner下的rk3568编译分支。</span></span>
  4. <span>hb build <span class="cm-attribute">-f</span></span>
复制代码
5、运行结果
运行如下:
  1. <span><span class="cm-comment"># rk3568_uart_test -b 115200 -p 2</span></span>
  2. <span>uart port:             <span class="cm-tab"> </span><span class="cm-number">2</span></span>
  3. <span>uart baud rate:         <span class="cm-number">115200</span></span>
  4. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">127</span>, info: UartOpen successful and uart port <span class="cm-operator">=</span> <span class="cm-number">2</span></span>
  5. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">135</span>, info: UartSetBaud successful and uart baudrate <span class="cm-operator">=</span> <span class="cm-number">115200</span></span>
  6. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">143</span>, info: UartSetAttribute successful</span>
  7. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">151</span>, info: UartGetAttribute successful</span>
  8. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">159</span>, info: UartSetTransMode successful</span>
  9. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">167</span>, info: UartWrite successful and wbuff <span class="cm-operator">=</span> HelloWorld</span>
  10. <span>../../vendor/lockzhiner/rk3568/samples/b08_platform_device_uart/app/uart_test.c, main, <span class="cm-number">175</span>, info: UartRead successful and rbuff <span class="cm-operator">=</span></span>
  11. <span><span class="cm-comment">#</span></span>
复制代码
注意:

  • rbuff获取的时候可能为空。因为本次案例是基于非阻塞,电脑端发送的串口可能没有获取到数据。

建议:

  • 读者可以尝试使用堵塞方式,再测试看看。






回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉