Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* 2021-8-25 SVCHAO The baud rate is configured according to the different APB1 frequencies.
f4-series only.
* 2025-09-20 wdfk_prog Implemented sendmsg_nonblocking op to support framework's async TX.
* 2026-02-02 wdfk_prog Drain multiple RX frames per ISR with a bounded limit.
*/

#include "drv_can.h"
Expand All @@ -24,6 +25,14 @@
#define LOG_TAG "drv_can"
#include <drv_log.h>

#ifndef CAN_ISR_DRAIN_LIMIT
/*
* bxCAN FIFO depth is 3 (FMP[1:0]=0..3). Draining up to 3 frames can clear the FIFO in one ISR,
* reducing FULL/OVERRUN without letting ISR time grow unbounded.
*/
#define CAN_ISR_DRAIN_LIMIT 3
#endif

/* attention !!! baud calculation example: Tclk / ((ss + bs1 + bs2) * brp) = 36 / ((1 + 8 + 3) * 3) = 1MHz*/
#if defined (SOC_SERIES_STM32F1)/* APB1 36MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
Expand Down Expand Up @@ -745,10 +754,20 @@ static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo)
switch (fifo)
{
case CAN_RX_FIFO0:
/* save to user list */
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_MSG_PENDING))
/* save to user list: drain multiple frames per ISR to reduce FULL/OVERRUN */
if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_MSG_PENDING))
{
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
for (rt_uint32_t i = 0; i < CAN_ISR_DRAIN_LIMIT; i++)
{
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) == 0)
{
break;
}
else
{
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
}
}
}
/* Check FULL flag for FIFO0 */
if (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FF0) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_FULL))
Expand All @@ -766,10 +785,20 @@ static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo)
}
break;
case CAN_RX_FIFO1:
/* save to user list */
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_MSG_PENDING))
/* save to user list: drain multiple frames per ISR to reduce FULL/OVERRUN */
if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_MSG_PENDING))
{
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
for (rt_uint32_t i = 0; i < CAN_ISR_DRAIN_LIMIT; i++)
{
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) == 0)
{
break;
}
else
{
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
}
}
}
/* Check FULL flag for FIFO1 */
if (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FF1) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_FULL))
Expand Down
38 changes: 29 additions & 9 deletions components/drivers/include/drivers/dev_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,42 @@ enum CANBAUD
* res = rt_device_control(can_dev, RT_CAN_CMD_START, &cmd_arg);
* RT_ASSERT(res == RT_EOK);
*
* #define CAN_RX_BATCH_SIZE 8
*
* while (1)
* {
* // Block and wait for the semaphore, which is released by the receive callback.
* rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
*
* // Read one frame of data from the CAN device's general message queue.
* rx_msg.hdr_index = -1;
* rt_device_read(can_dev, 0, &rx_msg, sizeof(rx_msg));
*
* // Print the received message's ID and data.
* rt_kprintf("Received a message. ID: 0x%x, Data: ", rx_msg.id);
* for (int i = 0; i < rx_msg.len; i++)
* // Drain all pending frames in batches.
* struct rt_can_msg rx_buf[CAN_RX_BATCH_SIZE];
* rt_ssize_t read_size;
* rt_size_t count;
* do
* {
* rt_kprintf("%02x ", rx_msg.data[i]);
* for (rt_size_t i = 0; i < CAN_RX_BATCH_SIZE; i++)
* {
* rx_buf[i].hdr_index = -1;
* }
*
* read_size = rt_device_read(can_dev, 0, rx_buf, sizeof(rx_buf));
* if (read_size <= 0)
* {
* break;
* }
* count = (rt_size_t)(read_size / sizeof(rx_buf[0]));
* for (rt_size_t i = 0; i < count; i++)
* {
* // Print the received message's ID and data.
* rt_kprintf("Received a message. ID: 0x%x, Data: ", rx_buf[i].id);
* for (int j = 0; j < rx_buf[i].len; j++)
* {
* rt_kprintf("%02x ", rx_buf[i].data[j]);
* }
* rt_kprintf("\n");
* }
* }
* rt_kprintf("\n");
* while(count == CAN_RX_BATCH_SIZE);
* }
* }
*
Expand Down