[MCAN]基于 HPM MCAN 自定义消息 RAM 配置指南
先楫系列MCU芯片(HPM6200之后)集成了博世 MCAN IP,MCAN的消息RAM共享一块32KB的AHB SRAM(HPM5300之后)。
在定义接收和发送的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 资源,在保证不丢帧的前提下兼顾内存利用率。
从上述的消息存储器排列可以知道,如果按照以上的顺序排列,那么配置步骤如下:
定义一个mcan_ram_config_t的变量,比如ram_cfg
过滤器决定哪些帧能进入 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个 */
过滤器的单元长度在标准ID是4字节,在扩展ID是8字节,标准ID过滤最大可以128个单位长度数量,扩展ID是64个单位长度数量。
本文单路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字节,可以翻阅手册查看。
首先确定消息元素的数据大小,这是所有区域的基础,影响每个元素占用的字节数。由于本项目需要同时支持 CAN 2.0 和 CAN FD,所有区域统一配置为 64 字节。
需要看下手册的接收缓存数据格式,可以看到消息RAM除了要存储数据段的数据,还需要额外8字节存储CAN的ID和时间错等相关信息
那么如果接收CANFD最大数据长度64字节就是需要64+8字节=72字节,按32bit对齐就是18个字。
一个接收的单位长度是72字节,本文只使用RXFIFO0,深度配置为最大的64,那么单路4608字节,四路需要18432字节。
这里直接使用最大的32深度FIFO,那么单路需要2304字节,四路就需要9216字节。
TX Event FIFO 记录每帧发送完成的硬件时间戳,深度必须和 TX FIFO 保持一致,否则高速发送时溢出导致时间戳丢失。
#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))
#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
(三)配置 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;
由于本文需要同时支持 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_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 一致,否则时间戳静默丢失





