cancel
Showing results for 
Search instead for 
Did you mean: 

Receiving intermittent interrupts on CAN Rx for STM32U5A5 nucleo board

Vibhor_Meshram
Visitor

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
  * @PAram 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;
}

Vibhor_Meshram_0-1763727411126.pngVibhor_Meshram_1-1763727448670.pngVibhor_Meshram_2-1763727470708.pngVibhor_Meshram_3-1763727490861.png

 

0 REPLIES 0