s32k-I.MX8 基于串口通讯xrce-dds搭建

发布时间 2023-12-14 14:10:40作者: 落叶满空山

s32k-iMX8平台XRCE-DDS的搭建

1. 引言

XRCE-DDS简述

      XRCE-DDS是可以在资源受限的MCU运行的DDS,在MCU侧运行客户端,通过代理服务参与DDS通信。

 

使用范围

       本文将描述整个XRCE-DDS在GEN2平台的搭建过程,包含SOC侧imx8上运行xrce-dds的anget和 s32k312单片机上运行的client的搭建。

2. 准备工作

Micro CDR库下载

eProsima Micro CDR是一个实现CDR标准序列化方法的C库。该库侧重于嵌入式和资源有限的系统。Micro CDR使用静态缓冲区,并允许在大端序和小端数中序列化和反序列化

Github下载:

git clone https://github.com/eProsima/Micro-CDR

 

Micro-XRCE-DDS-Agent下载

Anget端下载:

git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
 

Micro-XRCE-DDS-Client下载

Client端代码下载:
git clone https://github.com/eProsima/Micro-XRCE-DDS-Client.git
 

Installing the Micro XRCE-DDS Gen tool

git clone https://github.com/eProsima/Micro-XRCE-DDS-Gen.git
cd Micro-XRCE-DDS-Gen
git submodule init
git submodule update
./gradlew assemble
后续使用./scripts/microxrceddsgen xxx.idl生成数据结构的序列化和反序列化接口文件即可

Install S32DS tool

安装s32k编译环境,使得S32DS IDE中能进行编译和调试工作

3. 编译

Micro-cdr与Microxrcedds_client编译

Micro-cdr与mircoxrcedds_client需编译s32k环境对应版本,编译步骤如下:

 打开S32DS,选项栏中选择File->New->S32DS Library Project

 点击next->finish

  在项目目录端,右键点击src->import->File System

 

同上在项目include目录下import相应头文件

  修改config.h.in文件为config.h,内容如下

  右键项目Build Project,编译成功

   mircoxrcedds_client编译添加文件步骤同上,include/uxr/client/config.h对应的内容如下:

 

注意client选用的是UCLIENT_PROFILE_CUSTOM_TRANSPORT,我们将选用自定义的方式(通过lpuart)进行通讯

 

对microxrcedds_client进行裁剪

去掉非custom传输方式的代码

 

Client编译需包含cdr头文件,右键项目->Properties,cdr头文件路径加入Includes中

 

S32k主工程编译

        将上述编译的库链接到主工程中  

        添加头文件路径

        主工程中创建XRCE-DDS-Client发送接收的task

      将microdds Gen生成的.c和.h移至dds_task目录下

     结合LpUart自定义open/close/write/read接口

 

  建立会话后发送消息(参考client 例子example中CustomTransports消息发送)

Micro-XRCE-DDS-Agent编译

 修改CMakelists.txt,使得CMAKE_CXX_COMPILER与SYSROOT与Gen2平台匹配,以进行交叉编译

 自定义CustomAnget的init/fini/read/write函数,通过uart通讯实现

 设置串口通信的参数与单片机端保持一致

 完成编译

4. 通讯数据封装

由于串口通讯数据出现多包数据在缓冲区重叠的情况,导致在read的时候获取的数据包并非想得到的数据包,会导致xrce-dds在创建会话或者注册participant或者topic的时候失败,soc端和mcu端均存在此问题,需要对数据再次封装,识别数据帧的帧头和帧尾

7E 81 00 00 00 0A 01 05 00 02 00 00 00 80 7E  帧头和帧尾均添加7E,若数据中出现7E和7D, 转义为7D 02 和 7D 01

数据转义及处理

 

数据去头尾及解析

 

解析后的数据需要在recv_msg_function中多次返回,s32k端可将解析出的临时数据包放入ring_buf中,soc端可将解析出的数据放入二维容器中,再逐个返回

5. 备注

调试中遇到的问题及解决方案:

 

创建会话失败

    注册读写函数时,framing应设置为false

 

 Framing_io未使用可注释掉

my_custom_transport_open时,注意串口初始化不要多次进行,若其它地方已完成初始化,此处直接返回true即可

client端局部变量占空间较大,注意task创建线程时分配栈空间足够

 

创建participant/topic/publisher/datawriter失败

       此步骤发送字节约为388 Byte,并依次接收agent端注册成功返回消息,发送或接收字节丢失或者未解析出正确数据均会导致创建失败

此数据帧字节较多,需加上帧头帧尾后拆分发送,两端自定义write/read函数中加入sleep会导致数据接收不及时的问题,调试时需要注意

 

Soc端需采用O_NONBLOCK方式接收,通过select函数监视串口文件描述符实现数据端接收

 

注意read/write函数errorCode返回值的问题,若未接收到数据或者接收到异常buffer数据,返回errorCode > 0,否则交互会出现异常

 

uxr_run_session_time保持通讯失败,一个原因是timeout的时间过短,另外可修改client库中UXR_CONFIG_MIN_HEARTBEAT_TIME_INTERVAL的时间