ART-PI CAN驱动(fdcan2)的硬件过滤器配置不当触发了RT-Thread的断言异常。断言失败的位置在rt_hw_can_isr第835行,核心条件是:
(hdr < can->config.maxhdr && hdr >= 0) // 要求 hdr 在合法范围内当启用硬件过滤器后,驱动在中断中检索消息头索引(hdr)时,获得了无效索引值,原因如下:
硬件过滤器配置冲突
使能硬件过滤器时,驱动要求为每个接收的CAN消息分配一个有效的"消息头"(Header),而:
maxhdr 值过小(如配置为0或负数)驱动程序初始化缺陷
STM32的FDCAN驱动需显式配置Rx FIFO深度,而过滤器必须关联到特定FIFO。未正确初始化会导致中断中访问非法索引。
在打开设备前,配置CAN的接收缓冲深度:
/* 在 rt_device_open() 前添加 */
struct rt_can_config_item cfg = {
.maxhdr = 8, // 典型值:8-64(根据硬件能力调整)
.mode = RT_CAN_MODE_NORMAL,
.ticks = 50, // 接收超时ticks
};
rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void*)CAN2K1MBPS); // 设置波特率
rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void*)RT_CAN_MODE_NORMAL);
rt_device_control(can_dev, RT_CAN_CMD_SET_MAX_HDR, &cfg); // 关键配置过滤器必须关联到Rx FIFO:
struct rt_can_filter_config filter = {
.items = {
{ .id = 0x123, .mode = RT_CAN_FILTER_STD }, // 示例:标准ID过滤器
},
.count = 1, // 过滤器数量
.fifo = RT_CAN_FIFO0 // 绑定到FIFO0
};
rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &filter); // 启用硬件过滤修改驱动源码 drv_fdcan.c:
// 在 FDCAN 初始化函数中找到 hw_fdcan_init() 函数
static int hw_fdcan_init(struct rt_can_device *can, const char *name)
{
...
can->config.maxhdr = 8; // 确保 maxhdr > 0 且小于硬件FIFO容量
FDCAN_CONFIG->RxFIFO0Size = 8; // 设置Rx FIFO深度为8(匹配maxhdr)
...
}rt_hw_can_isr()函数:// 修改断言前的索引检查逻辑:
// 文件: drv_fdcan.c (约835行)
if (hdr >= can->config.maxhdr || hdr < 0) {
rt_kprintf("Invalid hdr=%d! maxhdr=%dn", hdr, can->config.maxhdr);
break; // 跳过无效消息
}#include
#define CAN_DEV_NAME "fdcan2"
static struct rt_semaphore rx_sem;
static rt_device_t can_dev;
static rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem);
return RT_EOK;
}
int can_sample(void)
{
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
can_dev = rt_device_find(CAN_DEV_NAME);
if (!can_dev) {
rt_kprintf("CAN device not found!n");
return -RT_ERROR;
}
/* 步骤1&2:配置波特率、模式、缓冲区、过滤器 */
struct rt_can_config_item cfg = {
.maxhdr = 8,
.mode = RT_CAN_MODE_NORMAL,
.ticks = 50
};
rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void*)CAN2K1MBPS);
rt_device_control(can_dev, RT_CAN_CMD_SET_MAX_HDR, &cfg); // 关键!
struct rt_can_filter_config filter = {
.items = {{ .id = 0x100, .mode = RT_CAN_FILTER_STD }},
.count = 1,
.fifo = RT_CAN_FIFO0
};
rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &filter);
/* 打开设备 */
rt_device_open(can_dev, RT_DEVICE_OFLAG_RDWR);
rt_device_set_rx_indicate(can_dev, rx_callback);
return RT_EOK;
}
注意:
- 确保
maxhdr值 ≤ 硬件FIFO深度(查看MCU手册确认FDCAN FIFO大小)
- 过滤器数量不可超过硬件上限(ART-PI的STM32H750支持最多28个过滤器)
- 若仍有异常,检查RT-Thread的FDCAN驱动版本是否有已知问题
举报
更多回帖