专栏算法工具链J6X can transfer sample

J6X can transfer sample

新手村2025-07-31
97
0

1. 功能概述

1.1. 软件架构说明

  • J6X芯片位于MCU域的CAN控制器负责完成雷达、底盘和车身等CAN数据收发。由于感知等应用位于Acore,因此部分CAN数据需要通过IPC核间通信机制转发到Acore。

  • 为保证传输可靠性,转发机制需要实现数据正确性检测、丢包检测和传输超时检测等机制。此外,还需要规避MCU侧高频转发小数据块导致CPU占用率过高,造成MCU实时性降低等性能问题。

J6X CAN转发方案的核心流程如下:

  • 首先通过MCU侧CAN2IPC模块将CAN通道映射到对应IPC通道,然后通过Acore侧CanHal模块将IPC通道反映射为虚拟CAN设备通道。最后用户通过CanHal提供的API接口获取虚拟CAN设备中的数据。其中,CAN2IPC模块为MCU侧服务,CanHal模块为Acore侧提供给应用程序的动态库。

  • CAN2IPC模块周期性采集MCU侧CAN数据,按照指定传输协议进行打包,然后通过IPC核间通信转发到Acore。Ipc instance 0中的channel0~channel7默认分配给CAN转发使用。

  • CanHal模块获取来自MCU侧的IPC数据,按照指定的传输协议解析数据,并支持业务软件通过API获取原始CAN帧。

Acore与MCU之间透传CAN数据架构图

数据流如上图所示:

  • 雷达、底盘等外设数据通过CAN的PHY和控制器器件被MCU域CAN驱动接收后,CAN驱动将数据上报并缓存在hobot CANIF模块。

  • CAN2IPC Service周期性从CANIF模块取出CAN帧,按照可靠传输协议进行打包,然后通过IPC核间通信机制转发给Acore。

  • CanHal模块获取来自MCU侧的IPC数据,按照指定的传输协议解析数据,Acore 应用程序通过CanHal Lib库提供的API获取CAN帧。

方案特性说明:

  • 支持数据透传正确性校验。

  • 支持数据透传丢包检测。

  • 支持传输超时检测。MCU侧CAN2IPC转发数据时将数据包打上MCU侧的时间戳,Acore CanHal接收到数据后会读取Acore的时间戳,如果传输超时会报警。注意,需要提前启动时间同步完成MCU RTC时间和Acore 网卡phc0的时间同步。

  • 支持多个CAN通道并行传输。MCU侧多个CAN控制器的数据可同时被转发给Acore,Acore应用程序通过CanHal从不同通道号读出CAN数据。

  • 由于CanHal底层通过ipc核间通信进行传输,而ipc目前不支持多个进程或者线程读写同一个通道,因此CanHal也不支持该特性。

透传协议如下所示:

Filed

Len(Byte)

Introduction

startFlag0

1

0xa5

startFlag1

1

0x3c

startFlag2

1

0x96

startFlag3

1

0x5a

startFlag4

1

0xa5

frameType

1

can=0, canfd=1, can/canfd=3

reserved

1

Reserved

reserved

1

Reserved

length

2

Msg data length in byte. Use Big Endian

Eg: length = 0x1234, byte[0]=0x12,byte[1]=0x34

data

N

can/canfd data.

crc

2

range: from startFlag0 to data filed. Use Big Endian

Eg: crc= 0x1234, byte[0]=0x12,byte[1]=0x34

endFlag0

1

‘\n’

endFlag1

1

‘\n’

endFlag2

1

‘\n’

endFlag3

1

‘\n’

每次透传以包为单位,每个包中包含多个CAN帧。为保证可靠传输,包的传输协议如上表所示。

  • startFlag0~startFlag4字段为固定的包头分隔符,endFlag0~endFlag4字段为固定的包尾分隔符。

  • frameType字段为MCU侧透传过来的CAN帧类型,包括CAN、CANFD以及两者混合型,具体由MCU侧CAN2IPC指定。

  • count字段为rolling counter,每传输1包就递增1,达到最大值255后从0开始循环计数。

  • length字段为CAN数据长度,crc字段对前面所有数据进行正确性校验。data区域存放多帧CAN数据,CAN帧格式如下文所示。

Filed

Len(Byte)

Introduction

time_stamp

8

unit: ms

use Big Endian

id

4

frame ID

Use Big Endian

count

1

count from 0-255

frameType

1

CanIdFormat type:

CAN_STANDARD=0

CAN_FD_STANDARD=1

CAN_EXTENDED=2

CAN_FD_EXTENDED=3

channel

1

can controller channel

length

1

can frame length

data

N

can data. No more than 64 byte.

  • 上表中,time_stamp字段为CAN帧在MCU侧打上的时间戳,id字段为CAN帧id。

  • count字段为该包中所有CAN帧的rolling counter,用于丢帧检测。frameType表示CAN帧类型。channel字段用于表示CAN帧来自哪一个CAN控制器。

  • length字段表示CAN帧数据长度,data区域为CAN帧数据。

由于CAN转发核心模块分别为Acore侧的CanHal模块和MCU侧的CAN2IPC模块,下文具体介绍两个模块。

1.2. 代码位置与目录结构

MCU侧CAN2IPC源码目录:mcu/Service/HouseKeeping/can_ipc/hb_CAN2IPC.c

  • 源码中hb_CAN2IPC_MainFunction函数被OS周期性调用,其内部通过调用hb_CAN2IPC_Proc 函数将指定的CAN控制器数据通过IPC转发到Acore。

  • hb_CAN2IPC_Proc 函数中三个传入参数分别为:CAN控制器、ipc instance、ipc 指定instance下的虚拟chennel。

如下示例代码将CAN4和CAN6分别通过ipc intance0的channel4和 intance0的channel6分别转发给Acore。

Acore CanHal使用可参考sample源码目录:test/samples/platform_samples/source/S83_Sample/S83E02_Communication/canhal_sample

sample 目录结构如下:

注意,etc目录下为json配置文件,默认已经有底盘和雷达CAN接入的json配置文件。json文件配置主要包括3个json配置文件:node.json、ipcf_channel.json、channels.json。目前为了支持多进程,各个进程都会去当前路径下的config目录下寻找这3个配置文件。

node.json负责创建虚拟CAN设备节点给CanHal API访问。关键配置选项包括:

  • channel_id字段指定该虚拟CAN设备从ipc配置文件ipcf_channel.json中哪一个节点获取数据。

  • target字段表示该虚拟CAN设备节点的名称,CanHal API通过该名称访问指定的节点。

  • enable字段表示该节点是否使能。

ipcf_channel.json将node.json中用到的ipc节点映射到具体的instance和channel。

channels.json指定ipc配置文件,用户一般不需要更改。

1.3. API说明

CanHal API接口基本特性:

  • 支持多通道并行传输,CanHal通过target参数决定获取哪一个CAN通道的数据

  • 支持多进程,各个进程可以分别读取不同通道CAN数据。但是不支持多个进程或者线程读取同一个CAN通道数据。

  • 支持用户通过传入target参数获取CAN frame数据(核心功能)

  • 支持用户通过传入target参数获取raw数据(调试功能,暂不启用)

  • 支持用户通过传入target参数发送raw数据(调试功能,暂不启用)

  • 支持用户通过传入target参数发送CAN frame数据(调试功能,暂不启用)

  • 支持CAN/CANFD类型的数据

  • 由于转发数据来自于MCU侧,因此Acore CanHal与MCU侧固件配合使用。MCU固件指定转发哪些CAN通道、转发周期等配置。

Acore应用程序通过CanHal获取MCU侧CAN帧的流程伪代码如下:

  • 首先执行canInit()完成初始化,然后调用 canRecvMsgFrame()从指定通道获取当前传输过来的一包CAN数据,其中target参数为json文件中配置好的通道。

  • 其中,pack信息包含这一包数据的信息,包括CAN帧数量、mcu侧的时间戳以及Acore侧的monotic时间戳等信息。

  • CanHal会从这一包ipc数据中解析出CAN帧,用户通过frame指针读取出所有CAN帧。

  • 最后执行canDeInit()释放资源。

CanHal 各个API具体介绍如下:

1.3.1. canInit

【函数声明】

int canInit();

【参数描述】

  • N/A

【返回值】

  • 0:成功

  • 非0:失败,返回错误码

【功能描述】

任务的初始化,申请相关的资源

【示例代码】

1.3.2. canDeInit

【函数声明】

void canDeInit();

【参数描述】

  • [IN] N/A

【返回值】

  • N/A

【功能描述】

功能注销,释放相关资源

【示例代码】

1.3.3. canRecvMsgRaw

【函数声明】

int canRecvMsgRaw(const char *target, uint8_t *rx_buf, hobot::canhal::Pack_Info *pack);

【参数描述】

  • [IN] target:目标节点

  • [OUT] rx_buf:接收数据指针

  • [OUT] pack:包信息指针

【返回值】

  • 0:成功

  • 非0:失败,返回错误码

【功能描述】

接收原始数据(调试功能,暂不启用)

【示例代码】

1.3.4. canSendMsgRaw

【函数声明】

int canSendMsgRaw(const char *target, uint8_t *tx_buf, hobot::canhal::Pack_Info *pack);

【参数描述】

  • [IN] target:目标节点

  • [IN] tx_buf:发送数据指针

  • [IN] pack:包信息指针

【返回值】

  • 0或者正数:成功发送的数据量

  • 负数:失败

【功能描述】

发送原始数据(调试功能,暂不启用)

【示例代码】

1.3.5. canRecvMsgFrame

【函数声明】

int canRecvMsgFrame(const char *target, hobot::canhal::CanFrame *frame, hobot::canhal::Pack_Info *pack);

【参数描述】

  • [IN] target:目标节点

  • [OUT] frame:can帧地址

  • [OUT] pack:包信息指针

【返回值】

  • 0:成功

  • 非0:失败,返回错误码

【功能描述】

接收CAN帧数据

【示例代码】

1.3.6. canSendMsgFrame

【函数声明】

int canSendMsgFrame(const char *target, struct canframe *frame, hobot::canhal::Pack_Info *pack);

【参数描述】

  • [IN] target:目标节点

  • [IN] tx_buf:发送数据指针

  • [IN] pack:包信息指针

【返回值】

  • 0或者正数:成功发送的数据量

  • 负数:失败

【功能描述】

发送CAN帧数据(调试功能,暂不启用)

【示例代码】

1.3.7. CanHal API Error code

2. 编译

2.1. 编译环境

本sample的编译环境使用SDK中的build工具,请参考: Build 环境建立

2.2. 编译说明

执行如下编译命令即可单独编译出Acore CanHal sample程序。

3. 运行

3.1. 支持平台

J6X Matrix

3.2. 板端部署及配置

需要做好如下准备工作:

  • 完成MCU和Acore之间的时间同步:CAN转发具有传输超时检测机制,即MCU给CAN帧打上MCU域的时间戳后,Acore Canhal接收到CAN帧时会读取本地网卡phc0的时间,并比较两者时间差,若高于阈值则API返回传输超时错误码。超时报警阈值默认为28毫秒,如需修改,可在node.json中为各个节点添加max_delay配置项,单位为毫秒。

  • 将MCU的CAN4和CAN6分别与底盘和雷达连接(也可以使用tsmaster或者canoe提供回灌数据)。

3.3. 运行指南

3.3.1. 运行方法

在Acore进入控制台,执行如下操作。

完成时间同步:

如果MCU侧的CAN帧时间戳使用RTC软件时间戳方案,则执行如下步骤将RTC时间同步到Acore phc0:

如果MCU侧的CAN帧时间戳使用xgmac硬件时间戳方案,则使用如下命令将xgmac时间同步到phc0(以下假设上述xgmac对应的eth索引为eth3)

获取底盘数据:

获取雷达数据:

3.3.2. 运行结果说明

如上打印获取到一次IPC传输包中的多个CAN帧数据。pack中ength字段表示CAN帧数量,soc_ts字段为Linux monotic时间,mcu_ts为CAN帧在MCU侧打上的时间戳。

3.3.3. 注意事项

  • Acore获取到CAN帧中的MCU时间戳在什么时刻被打上?MCU CAN模块使用RTC软件时间戳时,CAN2IPC软件在每个转发周期到来时,从Canif模块获取到CAN帧后再打上时间戳并转发数据到Acore;若使用xgmac硬件时间戳,则CAN帧到达CAN控制器时,会由硬件自动打上xgmac硬件时间戳。

  • 如何配置转发周期?过小的转发周期导致MCU CPU开销过大,过大的转发周期导致实时性降低。用户需要根据业务需求决定转发周期,OS调度 CAN2IPC模块的hb_CAN2IPC_MainFunction API周期即是转发周期。

  • 传输超时检测机制如何工作?完成时间同步后,CAN帧在MCU侧会被打上MCU域时间戳ts1,当报文转发到Acore后CanHal获取网卡phc0的时间戳ts2,当ts1和ts2差值超过阈值(默认是28ms)时会产生”Exceed max delay!”报警。

  • 是否支持多进程?支持多个进程或者线程读取不同的通道数据,但是不支持多个进程或者线程读取同一个通道数据。

  • Acore json配置文件需要放在哪里?目前集成CanHal动态库的进程会在当前目录下寻找Config目录中的channels.json、ipcf_channel.json、nodes.json这3个配置文件。因此用户需要在进程当前目录下创建Config目录,并存放上述3个配置文件。为便于用户使用,后续更新版本后会将各个进程的配置文件统一放在特定配置目录下。

算法工具链
社区征文征程6技术深度解析官方教程
评论0
0/1000