Skip to content

Commit 1eaa85c

Browse files
wdfk-progRbb666
authored andcommitted
feat[STM32][CAN]: drain RX FIFO frames in ISR with a bounded limit to reduce overruns
- Add CAN_ISR_DRAIN_LIMIT (default 3) to cap ISR work - Drain multiple frames per RX0/RX1 interrupt to reduce FIFO FULL/OVERRUN
1 parent 2b95c34 commit 1eaa85c

File tree

1 file changed

+35
-6
lines changed
  • bsp/stm32/libraries/HAL_Drivers/drivers

1 file changed

+35
-6
lines changed

bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* 2021-8-25 SVCHAO The baud rate is configured according to the different APB1 frequencies.
1616
f4-series only.
1717
* 2025-09-20 wdfk_prog Implemented sendmsg_nonblocking op to support framework's async TX.
18+
* 2026-02-02 wdfk_prog Drain multiple RX frames per ISR with a bounded limit.
1819
*/
1920

2021
#include "drv_can.h"
@@ -24,6 +25,14 @@
2425
#define LOG_TAG "drv_can"
2526
#include <drv_log.h>
2627

28+
#ifndef CAN_ISR_DRAIN_LIMIT
29+
/*
30+
* bxCAN FIFO depth is 3 (FMP[1:0]=0..3). Draining up to 3 frames can clear the FIFO in one ISR,
31+
* reducing FULL/OVERRUN without letting ISR time grow unbounded.
32+
*/
33+
#define CAN_ISR_DRAIN_LIMIT 3
34+
#endif
35+
2736
/* attention !!! baud calculation example: Tclk / ((ss + bs1 + bs2) * brp) = 36 / ((1 + 8 + 3) * 3) = 1MHz*/
2837
#if defined (SOC_SERIES_STM32F1)/* APB1 36MHz(max) */
2938
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
@@ -745,10 +754,20 @@ static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo)
745754
switch (fifo)
746755
{
747756
case CAN_RX_FIFO0:
748-
/* save to user list */
749-
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_MSG_PENDING))
757+
/* save to user list: drain multiple frames per ISR to reduce FULL/OVERRUN */
758+
if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_MSG_PENDING))
750759
{
751-
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
760+
for (rt_uint32_t i = 0; i < CAN_ISR_DRAIN_LIMIT; i++)
761+
{
762+
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) == 0)
763+
{
764+
break;
765+
}
766+
else
767+
{
768+
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
769+
}
770+
}
752771
}
753772
/* Check FULL flag for FIFO0 */
754773
if (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FF0) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO0_FULL))
@@ -766,10 +785,20 @@ static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo)
766785
}
767786
break;
768787
case CAN_RX_FIFO1:
769-
/* save to user list */
770-
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_MSG_PENDING))
788+
/* save to user list: drain multiple frames per ISR to reduce FULL/OVERRUN */
789+
if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_MSG_PENDING))
771790
{
772-
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
791+
for (rt_uint32_t i = 0; i < CAN_ISR_DRAIN_LIMIT; i++)
792+
{
793+
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) == 0)
794+
{
795+
break;
796+
}
797+
else
798+
{
799+
rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8);
800+
}
801+
}
773802
}
774803
/* Check FULL flag for FIFO1 */
775804
if (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FF1) && __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_RX_FIFO1_FULL))

0 commit comments

Comments
 (0)