2025-11-21 4:18 AM - last edited on 2025-11-21 5:18 AM by mƎALLEm
Hi,
I Have developed a code to send and receive CAN messages using STM32U5A5 nucleo board. I am able to send and receive CAN messages however when receiving FDCAN interrupt is not always triggered leading to message loss. The behavior is random. I am using FreeRTOS to send the received messages to task using queue and re-transmit the same message.
The HAL software pack I am using for U5 is 1.6.0.
Following is the relevant code snippet. And attached is the .ioc snippet.
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32u5xx_nucleo.h"
#define MAX_CAN_DATA_LENGTH 8U
typedef struct {
FDCAN_RxHeaderTypeDef CanHeader;
uint8_t CanData[MAX_CAN_DATA_LENGTH];
} CanFrame_t;
/**
* @brief FDCAN1 Initialization Function
* None
* @retval None
*/
static void MX_FDCAN1_Init(void)
{
/* USER CODE BEGIN FDCAN1_Init 0 */
/* USER CODE END FDCAN1_Init 0 */
/* USER CODE BEGIN FDCAN1_Init 1 */
/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV2;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 128;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 14;
hfdcan1.Init.NominalTimeSeg2 = 5;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */
/* USER CODE END FDCAN1_Init 2 */
}
void FDCAN_Module_Init(uint32_t CanID)
{
FDCAN_FilterTypeDef sFilterConfig;
/// Configure the CAN filter
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 0; /// Use Filter 0
sFilterConfig.FilterType = FDCAN_FILTER_MASK; /// Use mask filtering
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; /// Route to Rx FIFO 0
/// Listen for any ID where the first 16 bits match 0x18F0, regardless of the lower 13 bits (ID bits 28-16 checked)
sFilterConfig.FilterID1 = CanID;
sFilterConfig.FilterID2 = 0x1FFFFFE0; /// Mask for extended ID
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
printf("CAN Receive filter configuration failed \r\n");
Error_Handler();
}
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
printf("Failed to start CAN communication \r\n");
Error_Handler();
}
/// Enable the Rx FIFO 0 interrupt
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
printf("Failed to activate CAN notification \r\n");
Error_Handler();
}
}
void FDCAN_Transmit_Extended_Frame(uint32_t extended_id, uint8_t* data, uint8_t length)
{
FDCAN_TxHeaderTypeDef TxHeader;
/// Configure the Tx Header for Extended Format
TxHeader.Identifier = extended_id; /// The 29-bit ID
TxHeader.IdType = FDCAN_EXTENDED_ID; /// Set ID type to Extended
TxHeader.TxFrameType = FDCAN_DATA_FRAME; /// Data frame
TxHeader.DataLength = FDCAN_DLC_BYTES_8; /// Data Length Code (DLC)
TxHeader.FDFormat = FDCAN_CLASSIC_CAN; /// Use classic CAN mode
TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; /// Don't use Tx Event FIFO
TxHeader.BitRateSwitch = FDCAN_BRS_OFF; /// Bit rate switch off
TxHeader.MessageMarker = 0; /// Message marker (optional)
// Use timeout 0 to just attempt transmission without blocking
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data) != HAL_OK)
{
printf("Failed to transmit CAN message \r\n");
Error_Handler();
}
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
CanFrame_t CanRxData;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
memset(&CanRxData.CanData[0], 0, sizeof(CanRxData.CanData));
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
// Retrieve the message from Rx FIFO 0
while (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CanRxData.CanHeader, CanRxData.CanData) == HAL_OK)
{
if (CanRxData.CanHeader.IdType == FDCAN_EXTENDED_ID)
{
if (xQueueSendFromISR(xCanQueue, &CanRxData, &xHigherPriorityTaskWoken) != pdPASS)
{
/// TODO: Handle ISR error
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
}
static void CanTaskHandler(void *pArgument)
{
CanFrame_t ReceivedCanFrame;
/// TODO: Fetch CAN ID from EEPROM before initializing
FDCAN_Module_Init(0x18F00100);
while (1)
{
if (xQueueReceive(xCanQueue, &ReceivedCanFrame, pdMS_TO_TICKS(QUEUE_TIMEOUT_MS)) == pdPASS)
{
FDCAN_Transmit_Extended_Frame(0x12300100, ReceivedCanFrame.CanData, 3);
}
vTaskDelay(1000);
}
}
#define CAN_QUEUE_SIZE 10
#define QUEUE_TIMEOUT_MS 1000
#define CAN_STACK_SIZE 256
#define CAN_TASK_PRIORITY 6
QueueHandle_t xCanQueue;
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
BaseType_t Error = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the System Power */
SystemPower_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_FDCAN1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
/* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
{
Error_Handler();
}
TaskHandle_t CanTaskHandle;
xCanQueue = xQueueCreate(CAN_QUEUE_SIZE, sizeof(CanFrame_t));
xTaskCreate(CanTaskHandler, "CanTaskHandle", CAN_STACK_SIZE, NULL, CAN_TASK_PRIORITY, &CanTaskHandle);
/* Start scheduler */
vTaskStartScheduler();
return 0;
}
2025-11-21 5:07 AM - edited 2025-11-21 5:08 AM
Hello @Vibhor_Meshram and welcome to the ST community,
I'm already curious how are you receiving CAN frames even in intermittent way with those parameters set to 0:
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
Please test the communication without RTOS first. Test also with the Loopback mode. This is how to debug such kind of issues.