Skip to main content
seppeltronics_v
Associate III
April 4, 2023
Question

CAN-Bus no callback/received frame; FDCAN STM32G474

  • April 4, 2023
  • 9 replies
  • 8955 views

Hello,

when I try to receive a CAN-Frame it is not received by the Microcontroller, it is within the range, I have no idea what the issue is.

Thanks to everybody in advance, Best Regards, Seppel

0693W00000bhUdqQAE.png0693W00000bhUe5QAE.png 

0693W00000bhUeFQAU.png 

void FDCAN_Config(FDCAN_HandleTypeDef *pHfdcan)
{
 
 pHandleToFdCan = pHfdcan;
 
 /* Configure Rx filter */
 sFilterConfig.IdType = FDCAN_STANDARD_ID;
 sFilterConfig.FilterIndex = 0;
 sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
 sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
 sFilterConfig.FilterID1 = 0x700;
 sFilterConfig.FilterID2 = 0x7FF;
 if (HAL_FDCAN_ConfigFilter(pHandleToFdCan, &sFilterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Configure global filter:
 Filter all remote frames with STD and EXT ID
 Reject non matching frames with STD ID and EXT ID */
 if (HAL_FDCAN_ConfigGlobalFilter(pHandleToFdCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT) != HAL_OK)
 {
 Error_Handler();
 }
 
 
 
 /* Start the FDCAN module */
 if (HAL_FDCAN_Start(pHandleToFdCan) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_FDCAN_ActivateNotification(pHandleToFdCan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
 {
 Error_Handler();
 }
 
}

0693W00000bhUf3QAE.png 

P.S. TX works perfectly fine, as you can see it Ack's the 0x701 Frame that was received.

This topic has been closed for replies.

9 replies

AndrewST
Associate II
April 4, 2023

Can you show the "when I try to receive a CAN-Frame" part of your code? What does your callback function look like?

seppeltronics_v
Associate III
April 4, 2023

Hello,

as far as I'm aware the Function "HAL_FDCAN_RxFifo0Callback" needs to be implemented, which I did, I set a breakpoint, but it is never involked. "HAL_FDCAN_IRQHandler" is also never invoked.

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *phfdcan, uint32_t RxFifo0ITs)
{
 if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
 {
 /* Retrieve Rx messages from RX FIFO0 */
 if (HAL_FDCAN_GetRxMessage(phfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
 {
 Error_Handler();
 }
 else
 {
 // HAL_Ok
 if ((RxHeader.DataLength == CanMsgLen_Pressure)&&(RxHeader.Identifier == CanMsgId_Control))
 {
 canSendData = RxData[0U];
 }
 
 }
 
 }
}

Best Regards, Seppel

AndrewST
Associate II
April 4, 2023

That looks about right.

How about your receive buffers configuration?

0693W00000bhVJhQAM.png

seppeltronics_v
Associate III
April 4, 2023

Hello,

there is no "Receive Buffer Configuration" in the IDE. How did you find it for the STM32G474?

I think there are 3 RX Buffers for the controller if I remember right, but I have no idea how to configure these and I have not found examples wher it is done.

Best Regards, Seppel

P.S. Nothing about RX-Buffers in the generated fdcan.c file.

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file fdcan.c
 * @brief This file provides code for the configuration
 * of the FDCAN instances.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2023 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "fdcan.h"
 
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
FDCAN_HandleTypeDef hfdcan2;
 
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
 
 /* USER CODE BEGIN FDCAN2_Init 0 */
 
 /* USER CODE END FDCAN2_Init 0 */
 
 /* USER CODE BEGIN FDCAN2_Init 1 */
 
 /* USER CODE END FDCAN2_Init 1 */
 hfdcan2.Instance = FDCAN2;
 hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;
 hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
 hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
 hfdcan2.Init.AutoRetransmission = DISABLE;
 hfdcan2.Init.TransmitPause = DISABLE;
 hfdcan2.Init.ProtocolException = DISABLE;
 hfdcan2.Init.NominalPrescaler = 4;
 hfdcan2.Init.NominalSyncJumpWidth = 1;
 hfdcan2.Init.NominalTimeSeg1 = 59;
 hfdcan2.Init.NominalTimeSeg2 = 20;
 hfdcan2.Init.DataPrescaler = 8;
 hfdcan2.Init.DataSyncJumpWidth = 1;
 hfdcan2.Init.DataTimeSeg1 = 29;
 hfdcan2.Init.DataTimeSeg2 = 10;
 hfdcan2.Init.StdFiltersNbr = 0;
 hfdcan2.Init.ExtFiltersNbr = 0;
 hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
 if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN FDCAN2_Init 2 */
 
 /* USER CODE END FDCAN2_Init 2 */
 
}
 
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 if(fdcanHandle->Instance==FDCAN2)
 {
 /* USER CODE BEGIN FDCAN2_MspInit 0 */
 
 /* USER CODE END FDCAN2_MspInit 0 */
 
 /** Initializes the peripherals clocks
 */
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
 PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* FDCAN2 clock enable */
 __HAL_RCC_FDCAN_CLK_ENABLE();
 
 __HAL_RCC_GPIOB_CLK_ENABLE();
 /**FDCAN2 GPIO Configuration
 PB5 ------> FDCAN2_RX
 PB6 ------> FDCAN2_TX
 */
 GPIO_InitStruct.Pin = RXD_CanTransceiver_Pin|TXD_CanTransceiver_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN2;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
 __HAL_SYSCFG_FASTMODEPLUS_ENABLE(SYSCFG_FASTMODEPLUS_PB6);
 
 /* FDCAN2 interrupt Init */
 HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn, 1, 0);
 HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
 HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 1, 0);
 HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
 /* USER CODE BEGIN FDCAN2_MspInit 1 */
 
 /* USER CODE END FDCAN2_MspInit 1 */
 }
}
 
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* fdcanHandle)
{
 
 if(fdcanHandle->Instance==FDCAN2)
 {
 /* USER CODE BEGIN FDCAN2_MspDeInit 0 */
 
 /* USER CODE END FDCAN2_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_FDCAN_CLK_DISABLE();
 
 /**FDCAN2 GPIO Configuration
 PB5 ------> FDCAN2_RX
 PB6 ------> FDCAN2_TX
 */
 HAL_GPIO_DeInit(GPIOB, RXD_CanTransceiver_Pin|TXD_CanTransceiver_Pin);
 
 /* FDCAN2 interrupt Deinit */
 HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn);
 HAL_NVIC_DisableIRQ(FDCAN2_IT1_IRQn);
 /* USER CODE BEGIN FDCAN2_MspDeInit 1 */
 
 /* USER CODE END FDCAN2_MspDeInit 1 */
 }
}
 
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */

AndrewST
Associate II
April 4, 2023

The screenshot I took is for an F series MPU, but as far as FDCAN is concerned, this should be very similar to the Gs.

AndrewST
Associate II
April 4, 2023

Can you copy-paste the FDCAN_InitTypeDef structure declaration that was generated?

seppeltronics_v
Associate III
April 4, 2023

This one?

Call:

/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
 
 /* USER CODE BEGIN FDCAN2_Init 0 */
 
 /* USER CODE END FDCAN2_Init 0 */
 
 /* USER CODE BEGIN FDCAN2_Init 1 */
 
 /* USER CODE END FDCAN2_Init 1 */
 hfdcan2.Instance = FDCAN2;
 hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;
 hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
 hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
 hfdcan2.Init.AutoRetransmission = DISABLE;
 hfdcan2.Init.TransmitPause = DISABLE;
 hfdcan2.Init.ProtocolException = DISABLE;
 hfdcan2.Init.NominalPrescaler = 4;
 hfdcan2.Init.NominalSyncJumpWidth = 1;
 hfdcan2.Init.NominalTimeSeg1 = 59;
 hfdcan2.Init.NominalTimeSeg2 = 20;
 hfdcan2.Init.DataPrescaler = 8;
 hfdcan2.Init.DataSyncJumpWidth = 1;
 hfdcan2.Init.DataTimeSeg1 = 29;
 hfdcan2.Init.DataTimeSeg2 = 10;
 hfdcan2.Init.StdFiltersNbr = 0;
 hfdcan2.Init.ExtFiltersNbr = 0;
 hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
 if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN FDCAN2_Init 2 */
 
 /* USER CODE END FDCAN2_Init 2 */
 
}

AndrewST
Associate II
April 4, 2023

Not quite.  FDCAN_InitTypeDef structure declaration.

This is the type for your Init above.

AndrewST
Associate II
April 4, 2023

I mean this guy:

typedef struct
{
 uint32_t FrameFormat; /*!< Specifies the FDCAN frame format.
 This parameter can be a value of @ref FDCAN_frame_format */
 
 uint32_t Mode; /*!< Specifies the FDCAN mode.
 This parameter can be a value of @ref FDCAN_operating_mode */
 
 FunctionalState AutoRetransmission; /*!< Enable or disable the automatic retransmission mode.
 This parameter can be set to ENABLE or DISABLE */
 
 FunctionalState TransmitPause; /*!< Enable or disable the Transmit Pause feature.
 This parameter can be set to ENABLE or DISABLE */
 
 FunctionalState ProtocolException; /*!< Enable or disable the Protocol Exception Handling.
 This parameter can be set to ENABLE or DISABLE */
 
 uint32_t NominalPrescaler; /*!< Specifies the value by which the oscillator frequency is
 divided for generating the nominal bit time quanta.
 This parameter must be a number between 1 and 512 */
 
 uint32_t NominalSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
 hardware is allowed to lengthen or shorten a bit to perform
 resynchronization.
 This parameter must be a number between 1 and 128 */
 
 uint32_t NominalTimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
 This parameter must be a number between 2 and 256 */
 
 uint32_t NominalTimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
 This parameter must be a number between 2 and 128 */
 
 uint32_t DataPrescaler; /*!< Specifies the value by which the oscillator frequency is
 divided for generating the data bit time quanta.
 This parameter must be a number between 1 and 32 */
 
 uint32_t DataSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
 hardware is allowed to lengthen or shorten a data bit to
 perform resynchronization.
 This parameter must be a number between 1 and 16 */
 
 uint32_t DataTimeSeg1; /*!< Specifies the number of time quanta in Data Bit Segment 1.
 This parameter must be a number between 1 and 32 */
 
 uint32_t DataTimeSeg2; /*!< Specifies the number of time quanta in Data Bit Segment 2.
 This parameter must be a number between 1 and 16 */
 
 uint32_t MessageRAMOffset; /*!< Specifies the message RAM start address.
 This parameter must be a number between 0 and 2560 */
 
 uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters.
 This parameter must be a number between 0 and 128 */
 
 uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
 This parameter must be a number between 0 and 64 */
 
 uint32_t RxFifo0ElmtsNbr; /*!< Specifies the number of Rx FIFO0 Elements.
 This parameter must be a number between 0 and 64 */
 
 uint32_t RxFifo0ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
 This parameter can be a value of @ref FDCAN_data_field_size */
 
 uint32_t RxFifo1ElmtsNbr; /*!< Specifies the number of Rx FIFO 1 Elements.
 This parameter must be a number between 0 and 64 */
 
 uint32_t RxFifo1ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
 This parameter can be a value of @ref FDCAN_data_field_size */
 
 uint32_t RxBuffersNbr; /*!< Specifies the number of Dedicated Rx Buffer elements.
 This parameter must be a number between 0 and 64 */
 
 uint32_t RxBufferSize; /*!< Specifies the Data Field Size in an Rx Buffer element.
 This parameter can be a value of @ref FDCAN_data_field_size */
 
 uint32_t TxEventsNbr; /*!< Specifies the number of Tx Event FIFO elements.
 This parameter must be a number between 0 and 32 */
 
 uint32_t TxBuffersNbr; /*!< Specifies the number of Dedicated Tx Buffers.
 This parameter must be a number between 0 and 32 */
 
 uint32_t TxFifoQueueElmtsNbr; /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
 This parameter must be a number between 0 and 32 */
 
 uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
 This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
 
 uint32_t TxElmtSize; /*!< Specifies the Data Field Size in a Tx Element.
 This parameter can be a value of @ref FDCAN_data_field_size */
 
} FDCAN_InitTypeDef;

seppeltronics_v
Associate III
April 4, 2023

Are you working for ST. Is there someone who knows that CAN-Controller and knows how to set up the behaviour of the RX-Queue etc. ? That fancy presentation, nice for marketing, but useless for engineers with no references to HAL function: STM32G4-Peripheral-Flexible_Datarate_Controller_Area_Network_FDCAN.pdf

/**
 * @brief FDCAN Init structure definition
 */
typedef struct
{
 uint32_t ClockDivider; /*!< Specifies the FDCAN kernel clock divider.
 The clock is common to all FDCAN instances.
 This parameter is applied only at initialisation of
 first FDCAN instance.
 This parameter can be a value of @ref FDCAN_clock_divider. */
 
 uint32_t FrameFormat; /*!< Specifies the FDCAN frame format.
 This parameter can be a value of @ref FDCAN_frame_format */
 
 uint32_t Mode; /*!< Specifies the FDCAN mode.
 This parameter can be a value of @ref FDCAN_operating_mode */
 
 FunctionalState AutoRetransmission; /*!< Enable or disable the automatic retransmission mode.
 This parameter can be set to ENABLE or DISABLE */
 
 FunctionalState TransmitPause; /*!< Enable or disable the Transmit Pause feature.
 This parameter can be set to ENABLE or DISABLE */
 
 FunctionalState ProtocolException; /*!< Enable or disable the Protocol Exception Handling.
 This parameter can be set to ENABLE or DISABLE */
 
 uint32_t NominalPrescaler; /*!< Specifies the value by which the oscillator frequency is
 divided for generating the nominal bit time quanta.
 This parameter must be a number between 1 and 512 */
 
 uint32_t NominalSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
 hardware is allowed to lengthen or shorten a bit to perform
 resynchronization.
 This parameter must be a number between 1 and 128 */
 
 uint32_t NominalTimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
 This parameter must be a number between 2 and 256 */
 
 uint32_t NominalTimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
 This parameter must be a number between 2 and 128 */
 
 uint32_t DataPrescaler; /*!< Specifies the value by which the oscillator frequency is
 divided for generating the data bit time quanta.
 This parameter must be a number between 1 and 32 */
 
 uint32_t DataSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
 hardware is allowed to lengthen or shorten a data bit to
 perform resynchronization.
 This parameter must be a number between 1 and 16 */
 
 uint32_t DataTimeSeg1; /*!< Specifies the number of time quanta in Data Bit Segment 1.
 This parameter must be a number between 1 and 32 */
 
 uint32_t DataTimeSeg2; /*!< Specifies the number of time quanta in Data Bit Segment 2.
 This parameter must be a number between 1 and 16 */
 
 uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters.
 This parameter must be a number between 0 and 28 */
 
 uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
 This parameter must be a number between 0 and 8 */
 
 uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
 This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
 
} FDCAN_InitTypeDef;

AndrewST
Associate II
April 4, 2023

I am just another user who has FDCAN working on a somewhat similar MPU, that's all.

LCE
Principal II
April 4, 2023

I don't know how similar G4 / H7 FDCANs are, so all of the following might only apply to the H7.

The H7 has some 10 kB SRAM reserved for FDCAN.

This "CAN-RAM" is used for:

  • filter settings
  • RX & TX buffers and FIFOs

The RAM layout depends on your INIT settings, how many filters, buffers, etcpp you assign.

Then it calculates the RAM (starting) addresses / pointers from that.

First thing I see in your init:

StdFiltersNbr = 0; ExtFiltersNbr = 0;

Which means you have no filters assigned to memory.

Comparing to my H7 source, I also miss the settings for RX & TX buffers & FIFO, so my H7 init looks like this:

void MX_FDCAN1_Init(uint32_t u32DataRate)
{
	FDCAN_HandleTypeDef *phCan = &hCan1;
	FDCAN_FilterTypeDef sFilterConfig = { 0 };
 
	phCan->Instance = FDCAN1;
 
	phCan->Init.FrameFormat 			= FDCAN_FRAME_FD_BRS;
	phCan->Init.Mode 					= FDCAN_MODE_NORMAL;//FDCAN_MODE_EXTERNAL_LOOPBACK;//
	phCan->Init.AutoRetransmission 		= ENABLE;
	phCan->Init.TransmitPause 			= ENABLE;
	phCan->Init.ProtocolException 		= ENABLE;
 
/* clock / timing */
 
/* nominal = arbitration phase
 *	NBTP
 * 	80 MHz: tq = NominalPrescaler x (1/fdcan_ker_ck)
 *		-> tq = 12.5 ns
 *	data rate = 1 / ((SyncSeg + Seg1 + Seg2) * tq)
 *		with SyncSeg = 1
 *	0.5 Mbps = 160 * tq
 *		-> TimeSeg1 + TimeSeg2 = 157
 */
	phCan->Init.NominalPrescaler 		= 1;		/* tq = NominalPrescaler x (1/fdcan_ker_ck) */
#if( 1 )
/* 5000 ppm */
	phCan->Init.NominalTimeSeg1 		= 138;		/* NTSEG1 1..256, NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
	phCan->Init.NominalTimeSeg2 		= 21;		/* NTSEG2 1..128 */
	phCan->Init.NominalSyncJumpWidth 	= 20;		/* NSJW 1..128 should be < NTSEG2 */
#else
/* 500 ppm */
	phCan->Init.NominalTimeSeg1 		= 155;		/* NTSEG1 1..256, NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
	phCan->Init.NominalTimeSeg2 		= 4; 		/* NTSEG2 1..128 */
	phCan->Init.NominalSyncJumpWidth 	= 3; 		/* NSJW 1..128 should be < NTSEG2 */
#endif
 
/* data = data phase with bit rate switching
 *	DBTP
 * 	80 MHz: tq = DataPrescaler x (1/fdcan_ker_ck)
 *		-> tq = 12.5 ns
 *	data rate = 1 / ((SyncSeg + Seg1 + Seg2) * tq)
 *		with SyncSeg = 1
 */
	phCan->Init.DataPrescaler 			= 1;		/* DBRP 1..32 */
 
	CanInitBsrDataRate(phCan, u32DataRate);
 
/* RAM: filters, buffers */
	/* start pos in RAM of 2560 32-bit words */
	phCan->Init.MessageRAMOffset 		= 0;
 
	phCan->Init.StdFiltersNbr 			= 16;
	phCan->Init.ExtFiltersNbr 			= 16;
 
	phCan->Init.RxFifo0ElmtsNbr 		= 16;
	phCan->Init.RxFifo0ElmtSize 		= FDCAN_DATA_BYTES_64;
 
	phCan->Init.RxFifo1ElmtsNbr 		= 16;
	phCan->Init.RxFifo1ElmtSize 		= FDCAN_DATA_BYTES_64;
 
	phCan->Init.RxBuffersNbr 			= 16;
	phCan->Init.RxBufferSize 			= FDCAN_DATA_BYTES_64;
 
	phCan->Init.TxEventsNbr 			= 0;
	phCan->Init.TxBuffersNbr 			= 4;
	phCan->Init.TxFifoQueueElmtsNbr 	= 4;
	phCan->Init.TxFifoQueueMode 		= FDCAN_TX_FIFO_OPERATION;
	phCan->Init.TxElmtSize 				= FDCAN_DATA_BYTES_64;
 
	if( HAL_FDCAN_Init(phCan) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
 
/* Filters - STANDARD */
	sFilterConfig.FilterType 		= 0;	/* ignored for FDCAN_FILTER_TO_RXBUFFER */
	sFilterConfig.FilterID2 		= 0;	/* ignored for FDCAN_FILTER_TO_RXBUFFER */
 
	/* Configure standard ID reception filter to Rx buffer 0 */
	sFilterConfig.IdType 			= FDCAN_STANDARD_ID;
	sFilterConfig.FilterIndex 		= 0;
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXBUFFER;
	sFilterConfig.RxBufferIndex 	= 0;								/* store ID1 to this RX buffer */
	sFilterConfig.FilterID1 		= CAN_FILTER_STD_TEST_RXB_ID1;		/* MessageID and FilterID1 must match exactly */
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
	/* Configure standard ID reception filter to Rx buffer 1 */
	sFilterConfig.IdType 			= FDCAN_STANDARD_ID;
	sFilterConfig.FilterIndex 		= 1;
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXBUFFER;
	sFilterConfig.RxBufferIndex 	= 1;							/* store ID1 to this RX buffer */
	sFilterConfig.FilterID1 		= CAN_FILTER_STD_TEST_RXB_ID2;		/* MessageID and FilterID1 must match exactly */
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
	/* Configure standard ID reception filter to Rx buffer 2 */
	sFilterConfig.IdType 			= FDCAN_STANDARD_ID;
	sFilterConfig.FilterIndex 		= 2;
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXBUFFER;
	sFilterConfig.RxBufferIndex 	= 2;							/* store ID1 to this RX buffer */
	sFilterConfig.FilterID1 		= CAN_FILTER_STD_TEST_RXB_ID3;		/* MessageID and FilterID1 must match exactly */
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
	/* Configure standard ID reception filter to Rx buffer 3 */
	sFilterConfig.IdType 			= FDCAN_STANDARD_ID;
	sFilterConfig.FilterIndex 		= 3;
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXBUFFER;
	sFilterConfig.RxBufferIndex 	= 3;							/* store ID1 to this RX buffer */
	sFilterConfig.FilterID1 		= CAN_FILTER_STD_TEST_RXB_ID4;		/* MessageID and FilterID1 must match exactly */
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
/* Filters - EXTENDED */
	sFilterConfig.RxBufferIndex 	= 0;	/* ignored if not FDCAN_FILTER_TO_RXBUFFER */
 
	/* Configure extended ID reception filter to Rx FIFO 0 */
	sFilterConfig.IdType 			= FDCAN_EXTENDED_ID;
	sFilterConfig.FilterIndex 		= 0;
	sFilterConfig.FilterType 		= FDCAN_FILTER_RANGE_NO_EIDM;	/* Range from FilterID1 to FilterID2, no EIDM mask */
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXFIFO0;
	sFilterConfig.FilterID1 		= CAN_FILTER_EXT_TEST_RXF_ID1;
	sFilterConfig.FilterID2 		= CAN_FILTER_EXT_TEST_RXF_ID2;
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
	/* Configure extended ID reception filter to Rx FIFO 1 */
	sFilterConfig.IdType 			= FDCAN_EXTENDED_ID;
	sFilterConfig.FilterIndex 		= 1;
	sFilterConfig.FilterType 		= FDCAN_FILTER_RANGE_NO_EIDM;	/* Range from FilterID1 to FilterID2, no EIDM mask */
	sFilterConfig.FilterConfig 		= FDCAN_FILTER_TO_RXFIFO1;
	sFilterConfig.FilterID1 		= CAN_FILTER_EXT_TEST_RXF_ID3;
	sFilterConfig.FilterID2 		= CAN_FILTER_EXT_TEST_RXF_ID4;
	HAL_FDCAN_ConfigFilter(phCan, &sFilterConfig);
 
	/* Configure global filter to reject all non-matching frames */
	HAL_FDCAN_ConfigGlobalFilter(phCan, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
 
#if( 0 )
	/* Configure Rx FIFO 0 watermark to 2 */
	HAL_FDCAN_ConfigFifoWatermark(phCan, FDCAN_CFG_RX_FIFO0, 2);
 
	/* Activate Rx FIFO 0 watermark notification */
	HAL_FDCAN_ActivateNotification(phCan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
#endif
 
	/* timestamp enable, bit time, no prescaler */
	phCan->Instance->TSCC = 1;
 
/* enable TDC = transmitter delay compensation
 *	this is a MUST for high data rates
 */
	/* configure Tx Delay Compensation : TdcOffset = DataTimeSeg1 * DataPrescaler */
	uint32_t u32TdcOffs = ((uint32_t)phCan->Instance->DBTP >> FDCAN_DBTP_DTSEG1_Pos) + 1;
	uint32_t u32TdcFltWdw = 0;
 
	/* set TDC filter window */
	phCan->Instance->TDCR = (u32TdcFltWdw << FDCAN_TDCR_TDCF_Pos);
	/* set TDC offset */
	phCan->Instance->TDCR |= (u32TdcOffs << FDCAN_TDCR_TDCO_Pos);
	/* enable TDC */
	phCan->Instance->DBTP |= FDCAN_DBTP_TDC;
 
/* start FDCAN */
	HAL_FDCAN_Start(phCan);
}
 

LCE
Principal II
April 4, 2023

Don't forget that CubeMX is just a basic setup-thingy.

So use the debugger or the UART to check register settings, like interrupt enable, memory addresses, ...

I just see that I had to put some interrupt enables in the MSP init with direct register settings.

I usually don't use HAL for the important stuff, but until now FDCAN was only a feasability check.

And yes, it works, although I had some problems getting the 8 Mbps running...

static uint32_t HAL_RCC_FDCAN_CLK_ENABLED = 0;
 
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* phCan)
{
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };
 
	if( phCan->Instance == FDCAN1 )
	{
		/* FDCAN1 clock enable */
		HAL_RCC_FDCAN_CLK_ENABLED++;
		if( HAL_RCC_FDCAN_CLK_ENABLED == 1 )
		{
			__HAL_RCC_FDCAN_CLK_ENABLE();
		}
 
		__HAL_RCC_GPIOH_CLK_ENABLE();
		/** FDCAN1 GPIO Configuration
			PH14	------> FDCAN1_RX
			PH13	------> FDCAN1_TX
		*/
		GPIO_InitStruct.Pin 	= FDCAN1_RX_Pin | FDCAN1_TX_Pin;
		GPIO_InitStruct.Mode 	= GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull 	= GPIO_NOPULL;
		GPIO_InitStruct.Speed 	= GPIO_SPEED_FREQ_LOW;
		GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
		HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
 
	/* FDCAN1 interrupt Init */
		HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 10, 0);
		HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
		HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 10, 0);
		HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
 
		/* interrupt enable, all lines to 0 */
		phCan->Instance->ILS = 0;
		phCan->Instance->IE = (FDCAN_IE_DRXE | FDCAN_IE_RF1NE | FDCAN_IE_RF0NE );
		phCan->Instance->ILE = FDCAN_ILE_EINT0;
		phCan->Instance->IR = 0xFFFFFFFF;
	}
 
}

LCE
Principal II
April 4, 2023

And in the IRQ handler I check its source, set some flags which I check later in main, then call the HAL IRQ handler to reset register flags.

/**
 * @brief This function handles FDCAN1 interrupt 0.
 */
void FDCAN1_IT0_IRQHandler(void)
{
	/* get PTP time */
	ETH_PTPTime_GetTime(&sTimeCanRx);
 
	if( FDCAN1->IR & FDCAN_IR_RF0N )
	{
		sCan1RxFifo0.RxdIrq = 1;
		sCan1RxFifo0.sTimeRx.seconds = sTimeCanRx.seconds;
		sCan1RxFifo0.sTimeRx.nanosec = sTimeCanRx.nanosec;
	}
	if( FDCAN1->IR & FDCAN_IR_RF1N )
	{
		sCan1RxFifo1.RxdIrq = 1;
		sCan1RxFifo1.sTimeRx.seconds = sTimeCanRx.seconds;
		sCan1RxFifo1.sTimeRx.nanosec = sTimeCanRx.nanosec;
	}
	if( FDCAN1->IR & FDCAN_IR_DRX )
	{
		sCan1RxBuffer.RxdIrq = 1;
		sCan1RxBuffer.sTimeRx.seconds = sTimeCanRx.seconds;
		sCan1RxBuffer.sTimeRx.nanosec = sTimeCanRx.nanosec;
	}
 
	HAL_FDCAN_IRQHandler(&hCan1);
}

seppeltronics_v
Associate III
April 12, 2023

Hello,

the issue is resolved:

Issue visible in the Code:

hfdcan2.Init.StdFiltersNbr = 0;

Solution, change the Config in the Stm32CubeIde, set the number of filters to 1, the generated code will be:

hfdcan2.Init.StdFiltersNbr = 1;

Thanks a lot to everybody supporting the case.

Best Regards, Seppel

P.S. It is so obvious that if you use a filter the number of filters should not be zero. But as always: "You know afterwards, what you could have known in advance". 8)