[MCAN]基于 HPM MCAN 自定义消息 RAM 配置指南

一、前言

先楫系列MCU芯片(HPM6200之后)集成了博世 MCAN IP,MCAN的消息RAM共享一块32KB的AHB SRAM(HPM5300之后)。

image.png

在文档中也提到MCAN的消息存储器示意图:

image.png

 在定义接收和发送的FIFO深度上,开发者可以根据自身应用来决定深度,比如接收分为两个RXFIFO,最大也可以达到64*2=128个深度,发送上最大也可以达到32个深度。消息 RAM 完全可编程,各区域深度按需裁剪,灵活适配不同场景。

HPM SDK默认通过 mcan_get_default_ram_config() 自动分配消息 RAM,使用简单,适合绝大多数场景。当需要更大的收发缓冲(如 CAN 盒高速转发),可以手动填写 mcan_ram_config_t。

本文将以 CAN 盒(4路 CAN,支持 CAN FD) 为典型场景,详细介绍如何根据实际需求自定义消息 RAM 各区域深度,充分利用 32KB AHB RAM 资源,在保证不丢帧的前提下兼顾内存利用率。

二、自定义消息 RAM 配置步骤

从上述的消息存储器排列可以知道,如果按照以上的顺序排列,那么配置步骤如下:

定义一个mcan_ram_config_t的变量,比如ram_cfg

(一)配置 ID 过滤器数量

过滤器决定哪些帧能进入 RXFIFO,CAN 盒透传场景配置全通过滤器。这部分过滤器设置本文不做阐述,待下篇文章。

这里预留了8个过滤器,实际只需要 1 个全通过滤器即可接收所有帧,预留 8 个是为了后续支持白名单过滤功能扩展。

#define CUSTOM_MCAN_STD_FLT_CNT     8   /* 11位ID过滤器,预留8个 */
#define CUSTOM_MCAN_EXT_FLT_CNT     8   /* 29位ID过滤器,预留8个 */

可以在HPM SDK的MCAN驱动宏定义有所定义看到:

过滤器的单元长度在标准ID是4字节,在扩展ID是8字节,标准ID过滤最大可以128个单位长度数量,扩展ID是64个单位长度数量。

image.png

本文单路CAN的过滤器占用RAM消息是84+88=96字节,四路占用384字节。

在代码中配置如下:

ram_cfg.enable_ext_filter = true; //使能扩展ID过滤
ram_cfg.ext_filter_elem_count = CUSTOM_MCAN_EXT_FLT_CNT; //单位长度数量为8,可设置8个过滤器
ram_cfg.enable_std_filter = true; //使能标准ID过滤
ram_cfg.std_filter_elem_count = CUSTOM_MCAN_STD_FLT_CNT; //单位长度数量为8,可设置8个过滤器

至于为什么过滤器的单元长度在标准ID是4字节,在扩展ID是8字节,可以翻阅手册查看。

(二)配置CANFD数据大小,确定消息RAM大小。

首先确定消息元素的数据大小,这是所有区域的基础,影响每个元素占用的字节数。由于本项目需要同时支持 CAN 2.0 和 CAN FD,所有区域统一配置为 64 字节。

1、接收数据FIFO大小分配

需要看下手册的接收缓存数据格式,可以看到消息RAM除了要存储数据段的数据,还需要额外8字节存储CAN的ID和时间错等相关信息

image.png

那么如果接收CANFD最大数据长度64字节就是需要64+8字节=72字节,按32bit对齐就是18个字。

一个接收的单位长度是72字节,本文只使用RXFIFO0,深度配置为最大的64,那么单路4608字节,四路需要18432字节。

2、发送数据FIFO大小分配

这里直接使用最大的32深度FIFO,那么单路需要2304字节,四路就需要9216字节。

3、发送事件FIFO大小分配

TX Event FIFO 记录每帧发送完成的硬件时间戳,深度必须和 TX FIFO 保持一致,否则高速发送时溢出导致时间戳丢失。

4、验证四路 RAM 总占用

在这里可以使用宏定义来包含,可以参考以下

#define CUSTOM_MCAN_FLT_CNT           8
#define CUSTOM_MCAN_STD_FLT_CNT       CUSTOM_MCAN_FLT_CNT
#define CUSTOM_MCAN_EXT_FLT_CNT       CUSTOM_MCAN_FLT_CNT
#define CUSTOM_MCAN_MSG_SIZE_IN_WORDS 18 /* 64-bytes + 2 words of message header  */
#define CUSTOM_MCAN_TXBUF_ELEM_CNT    0
#define CUSTOM_MCAN_TXFIFO_ELEM_CNT   32
#define CUSTOM_MCAN_RXFIFO0_ELEM_CNT   64
#define CUSTOM_MCAN_TX_EVT_ELEM_CNT   32
#define CUSTOM_MCAN_ENABLE_RXFIFO0    1
#define CUSTOM_MCAN_ENABLE_RXFIFO1    0
#define CUSTOM_MCAN_ENABLE_RXBUF      0
#define CUSTOM_MCAN_WATRERMARK_RXFIFO0  20

#define CUSTOM_MCAN_MSG_BUF_SIZE_IN_WORDS ((CUSTOM_MCAN_STD_FLT_CNT * MCAN_FILTER_ELEM_STD_ID_SIZE + \
                                            CUSTOM_MCAN_EXT_FLT_CNT * MCAN_FILTER_ELEM_EXT_ID_SIZE + \
                                            CUSTOM_MCAN_TXBUF_ELEM_CNT * CUSTOM_MCAN_MSG_SIZE_IN_WORDS * sizeof(uint32_t) + \
                                            CUSTOM_MCAN_TXFIFO_ELEM_CNT * CUSTOM_MCAN_MSG_SIZE_IN_WORDS * sizeof(uint32_t) + \
                                            CUSTOM_MCAN_RXFIFO0_ELEM_CNT * CUSTOM_MCAN_MSG_SIZE_IN_WORDS * sizeof(uint32_t) + \
                                            CUSTOM_MCAN_TX_EVT_ELEM_CNT * MCAN_TXEVT_ELEM_SIZE) / sizeof(uint32_t))

最终代入到指向ahb sram的缓存中

#if defined(HPM_MCAN0)
ATTR_PLACE_AT(".ahb_sram") uint32_t mcan0_msg_buf[CUSTOM_MCAN_MSG_BUF_SIZE_IN_WORDS];
#endif
#if defined(HPM_MCAN1)
ATTR_PLACE_AT(".ahb_sram") uint32_t mcan1_msg_buf[CUSTOM_MCAN_MSG_BUF_SIZE_IN_WORDS];
#endif
#if defined(HPM_MCAN2)
ATTR_PLACE_AT(".ahb_sram") uint32_t mcan2_msg_buf[CUSTOM_MCAN_MSG_BUF_SIZE_IN_WORDS];
#endif
#if defined(HPM_MCAN3)
ATTR_PLACE_AT(".ahb_sram") uint32_t mcan3_msg_buf[CUSTOM_MCAN_MSG_BUF_SIZE_IN_WORDS];
#endif

总结如下:

image.png

编译后的AHB RAM占用,符合预期

image.png

(三)配置 TX FIFO 深度和RX Event FIFO 深度

由于本文需要同时支持 CAN 2.0 和 CAN FD,所有区域统一配置为 64 字节。data_field_size 需要设为 MCAN_DATA_FIELD_SIZE_64BYTES,每个消息元素固定占用 72B。

ram_cfg.tx_evt_fifo_elem_count = CUSTOM_MCAN_TX_EVT_ELEM_CNT;
ram_cfg.txbuf_fifo_or_queue_elem_count = CUSTOM_MCAN_TXFIFO_ELEM_CNT;
ram_cfg.txbuf_dedicated_txbuf_elem_count = CUSTOM_MCAN_TXBUF_ELEM_CNT;
ram_cfg.txbuf_data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;

(四)配置 RX FIFO0 深度和工作模式

由于本文需要同时支持 CAN 2.0 和 CAN FD,所有区域统一配置为 64 字节。工作模式选择 BLOCKING(当前代码实际配置),使能 FIFO FULL 中断以及收到未读取20帧触发中断,保证抗突发能力。

ram_cfg.rxbuf_data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
ram_cfg.rxbuf_elem_count = 0; /* Not enable the rxbuf */
ram_cfg.enable_rxbuf = (CUSTOM_MCAN_ENABLE_RXBUF == 1) ? true : false;
ram_cfg.rxfifos[0].enable = (CUSTOM_MCAN_ENABLE_RXFIFO0 == 1) ? true : false;
ram_cfg.rxfifos[0].data_field_size = MCAN_DATA_FIELD_SIZE_64BYTES;
ram_cfg.rxfifos[0].elem_count = CUSTOM_MCAN_RXFIFO0_ELEM_CNT;
ram_cfg.rxfifos[0].operation_mode = MCAN_FIFO_OPERATION_MODE_BLOCKING;
ram_cfg.rxfifos[0].watermark = CUSTOM_MCAN_WATRERMARK_RXFIFO0; /* 收到20帧触发中断 */

(五)调用 mcan_init 

所有参数填入 mcan_ram_config_t 后调用初始化mcan_init,需要检查返回值。

三、总结

本文以 USB CAN 盒(4路 CAN FD)为典型场景,介绍了 先楫系列MCU的 MCAN 自定义消息 RAM 的完整配置流程:

1、ID 过滤器:STD/EXT 各预留 8 个,实际只需 1 个全通过滤器即可透传所有帧

2、数据大小:统一配置为 64 字节(72B/元素),兼容 CAN 2.0 和 CAN FD,避免混合场景下数据溢出

3、TX FIFO + TX Event FIFO:各 32 深度,TX Event 深度必须与 TX FIFO 一致,否则时间戳静默丢失

4、RX FIFO0:64 深度 BLOCKING 模式,Watermark=20,保证抗突发能力的同时可感知丢帧

0
0

订阅

发表回复 0

Your email address will not be published. Required fields are marked *

captcha
Enter the characters shown in the image:
Reload

This CAPTCHA helps ensure that you are human. Please enter the requested characters.