SemiDrive X9H PTG3.9:Can 与 Vircan 的调试

一、概述

目前 SemiDrive X9H 的 SDK 中,在 Safety 域运行 Freertos,在 AP 域运行 Linux。而对于 CAN 资源来说, SemiDrvie X9H 只有两路 CAN 资源,并且都分配到 Safety 域。对于物理 CAN 的收发都在 Safety,芯驰自行研发了 CAN Service,使得 AP 想要访问 CAN 通过 CAN Service,CAN Service 在 Linux 操作系统创建设备节点,X9H 的核间通信架构提供 Linux 设备节点和 Safety 域的物理节点之间的通信,在 linux 端 映射 CAN 成 /dev/vircan 设备文件,用户层可以按照标准 unix 文件方式访问。

二、使用环境

硬件:SemiDrive SD003_X9H REF_A03 DEMO Board

软件:X9 PTG3.9

工具:USBCANFD-200U

三、连接图

PC 端的 CAN 收发器 USBCANFD-200U 与板端的 CAN 总线连接图。

连接图

四、CAN Service 主要功能

CAN service 是由芯驰自行开发、运行在 Safety Island 上的服务,主要功能如下:

1、接收来自 CAN 总线的数据;

2、兼并接收来自外部 MCU 的数据;

3、转发来自  CAN 总线或外部 MCU 的数据并发送到远端 AP;

4、接收来自远端 AP 的数据并转发到 CAN 或外部 MCU。

代码路径:/buildsystem/rtos/freertos_safetyos/framework/service/can_proxy

五、代码修改

在 SemiDrive SDK 中,CAN 的初始化是以 4 路CAN 为模型的,但是 SemiDrive X9H 只有 2 路 CAN 资源,所以修改代码成 2 路资源的,以下是代码的修改:

路径:/buildsystem/rtos/lk_boot/chipdev/can/flexcan/Can.c

static const struct can_sleep_scr gCanSleepSCR[MAX_FLEXCAN_CH] = {

    [CAN1] = {APB_SCR_SAF_BASE + (0x600U << 10), 4U, 5U},

    [CAN2] = {APB_SCR_SAF_BASE + (0x604U << 10), 4U, 5U},

    //2022.12.9 Ryan xiugai

    //[CAN3] = {APB_SCR_SAF_BASE + (0x608U << 10), 4U, 5U},

    //[CAN4] = {APB_SCR_SAF_BASE + (0x60CU << 10), 4U, 5U},

路径:/buildsystem/rtos/lk_boot/chipdev/can/flexcan/can_cfg.c

struct Can_ControllerConfig gCan_CtrllerConfig[CAN_CTRL_CONFIG_CNT] = {

    {

        .controllerId = CAN1,

        .baseAddr = (uint32)APB_CAN1_BASE,

        .irq_num = CANFD1_IPI_INT_MBOR_NUM,

        .flexcanCfg = {

            .clkSrc = FLEXCAN_ClkSrcPeri,   /* 80MHz */

            .maxMbNum = 14U,

            .enableSelfWakeup = true,

            .enableIndividMask = true,

            .enableCANFD = true,

            BAUDRATE_1M_5M,

            .can_fd_cfg = {

                .enableISOCANFD = true,

                .enableBRS = true,

                .enableTDC = true,

                .TDCOffset = 8U,

                .r0_mb_data_size = CAN_FD_64BYTES_PER_MB,

                .r1_mb_data_size = CAN_FD_64BYTES_PER_MB

            }

        }

    },

   

    {

        .controllerId = CAN2,

        .baseAddr = (uint32)APB_CAN2_BASE,

        .irq_num = CANFD2_IPI_INT_MBOR_NUM,

        .flexcanCfg = {

            .clkSrc = FLEXCAN_ClkSrcPeri,   /* 80MHz */

            .maxMbNum = 14U,

            .enableSelfWakeup = true,

            .enableIndividMask = true,

            .enableCANFD = true,

            BAUDRATE_1M_5M,

            .can_fd_cfg = {

                .enableISOCANFD = true,

                .enableBRS = true,

                .enableTDC = true,

                .TDCOffset = 8U,

                .r0_mb_data_size = CAN_FD_64BYTES_PER_MB,

                .r1_mb_data_size = CAN_FD_64BYTES_PER_MB

            }

        }

    },

    #if 0

    {

        .controllerId = CAN3,

        .baseAddr = (uint32)APB_CAN3_BASE,

        .irq_num = CANFD3_IPI_INT_MBOR_NUM,

        .flexcanCfg = {

            .clkSrc = FLEXCAN_ClkSrcPeri,   /* 80MHz */

            .maxMbNum = 14U,

            .enableSelfWakeup = true,

            .enableIndividMask = true,

            .enableCANFD = true,

            BAUDRATE_1M_5M,

            .can_fd_cfg = {

                .enableISOCANFD = true,

                .enableBRS = true,

                .enableTDC = true,

                .TDCOffset = 8U,

                .r0_mb_data_size = CAN_FD_64BYTES_PER_MB,

                .r1_mb_data_size = CAN_FD_64BYTES_PER_MB

            }

        }

    },

 

    {

        .controllerId = CAN4,

        .baseAddr = (uint32)APB_CAN4_BASE,

        .irq_num = CANFD4_IPI_INT_MBOR_NUM,

        .flexcanCfg = {

            .clkSrc = FLEXCAN_ClkSrcPeri,   /* 80MHz */

            .maxMbNum = 14U,

            .enableSelfWakeup = true,

            .enableIndividMask = true,

            .enableCANFD = true,

            BAUDRATE_1M_5M,

            .can_fd_cfg = {

                .enableISOCANFD = true,

                .enableBRS = true,

                .enableTDC = true,

                .TDCOffset = 8U,

                .r0_mb_data_size = CAN_FD_64BYTES_PER_MB,

                .r1_mb_data_size = CAN_FD_64BYTES_PER_MB

            }

        }

    },

路径:/buildsystem/rtos/lk_boot/chipdev/can/rules.mk

ifneq ($(filter g9%, $(CHIPVERSION)), )

GLOBAL_DEFINES += MAX_FLEXCAN_CH=20

else ifeq ($(CHIPVERSION), v9t)

GLOBAL_DEFINES += MAX_FLEXCAN_CH=8

else

GLOBAL_DEFINES += MAX_FLEXCAN_CH=2//Ryan add 原本 4

endif

路径:/buildsystem/rtos/lk_boot/framework/communication/include/ipcc_config.h

/* global flag to enable ipcc-rpmsg */

#ifndef CONFIG_IPCC_RPMSG

#define CONFIG_IPCC_RPMSG           (1) //Ryan add 原本 0

#endif

路径: /buildsystem/rtos/lk_boot/framework/service/can_proxy/interface/can/can_port.c

int can_if_init(struct cp_if_t *cpif)

{

    extern const Can_ConfigType gCan_Config;

    Can_Init(&gCan_Config);

    if(cpif->if_id <= 1)

      Can_SetControllerMode(cpif->if_id, CAN_CS_STARTED);

    cpif->if_state = cpifStateRunning;

    return 0;

上面的修改都会自动同步 rtos/freertos_safetyos 的相关文件修改。


六、测试

1、物理 CAN 通信验证

SDK 提供了can_test 和 can_sample 两个应用,测试需要把这两个编进去,同时,由于FreeRTOS 验证 CAN 需要把 can_proxy 这个关掉,不然会冲突,无法编译通过。

路径:/buildsystem/rtos/freertos_safetyos/project/safety-x9-ref-serdes.mk

SUPPORT_CAN_SAMPLE_CODE := true

SUPPORT_CAN_TEST := true

##########################

#library define

##########################

SUPPORT_DCF := true

SUPPORT_3RD_RPMSG_LITE := true

SUPPORT_RPC := false

编译烧录后在 Safety 串口直接运行 can_sample,会发送一帧 CAN 数据到 PC 端。

can 发送数据到 PC

显示

以上表示 PC 端正常接收一帧数据。

之后从 PC 端发一帧数据

pc 发送数据到 can

pc 发送数据给 can
can 接收 pc 发送

可以看出,板端也接收成功了,并且 ID 和数据都是准确的,说明物理 CAN 可以正常通信。 

2、Linux 端 vircan 通信

Linux 端的 /dev/vircan 就是 Vircan 设备,SDK 代码提供了 candump 和 cansend 两个工具用来测试 Vircan 设备,在测试前需要先把 cluster 应用关掉,不然该应用会占用 Vircan,同时需要把 can_proxy 这个服务打开,不然会一直报错:

查看进程

关闭 cluster 可以直接先用 ps 查看进程,之后用 kill 掉,也可以在以下文件,删除这个应用:

路径:/buildsystem/yocto/meta-semidrive/conf/distro/cluster-qt.conf

关闭 cluster

之后在 Linux 终端下,输入

candump /dev/vircan

之后进入等待 PC CAN 的数据发送,PC CAN 发送数据

pc 发送

pc 发送数据

如下,表示接收成功

linux 接收

之后在 LINUX 终端下输入

cansend /dev/vircan -i 0x55 0x11 0x12 0x13 0x14 0x15

linux 发送数据

之后在 PC CAN 可以看到

pc 接收 Linux 数据

以上表示PC CAN 成功接收,至此,Linux 端的 vircan 正常通信。

七、参考文献

《SemiDrive高性能车载处理器核间通信应用指南_Rev00.04.pdf》

《Semidrive_X9_V9_CAN应用指南_Rev0.3.pdf》

八、预告

实现 X9H 的 CAN 通信,预计接下会将写一篇关于在 AP 端通过 CAN 将固件包发送给 MCU 的文章,感兴趣可以在评论区留下评论或关注。

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论

Topone

Topone

2023年9月7日
楼主,AP端通过CAN将固件包发送给MCU的文章什么时候更新