Skip to main content
rclar.6
Associate III
July 29, 2025
Question

FDCAN Clock Divider can silently change your actual CAN bit rate

 

FDCAN Clock Divider can silently change your actual CAN bit rate

I ran into an issue on an STM32G474 where FDCAN3 would not receive any messages on a 250 kbps CAN bus. Error counters (REC) climbed rapidly, indicating a timing mismatch.

After a lot of debugging, I discovered that the FDCAN Clock Divider was set to the clock from my FDCAN1, which was DIV8  even though CubeMX was showing a baud rate of 250 kbps in the GUI.

 

By tricking the GUI by setting the FDCAN3 to 2Mbps instead of the 250kbps I needed it all started working properly, i.e. 250k times 8 is 2M.

Here is a useful function to look at what is going on in CAN on stm32s......

 

 
void Print_FDCAN_Config(FDCAN_HandleTypeDef * hfdcan)
{
	uint32_t prescaler = hfdcan->Init.NominalPrescaler;
	uint32_t sjw = hfdcan->Init.NominalSyncJumpWidth;
	uint32_t ts1 = hfdcan->Init.NominalTimeSeg1;
	uint32_t ts2 = hfdcan->Init.NominalTimeSeg2;
	uint32_t mode = hfdcan->Init.Mode;
	uint32_t framefmt = hfdcan->Init.FrameFormat;
	uint32_t clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN);


	double clk_div = 1.0;
	switch (hfdcan->Init.ClockDivider) {
	case FDCAN_CLOCK_DIV1: clk_div = 1.0; break;
	case FDCAN_CLOCK_DIV2: clk_div = 2.0; break;
	case FDCAN_CLOCK_DIV4: clk_div = 4.0; break;
	case FDCAN_CLOCK_DIV8: clk_div = 8.0; break;
	}


	if (hfdcan->Instance == FDCAN1) {
		printf("\n\r====================\n\rFDCAN1 ");
	} else if (hfdcan->Instance == FDCAN2) {
		printf("\n\r====================\n\rFDCAN2 ");
	} else if (hfdcan->Instance == FDCAN3) {
		printf("\n\r====================\n\rFDCAN3 ");
		printf("Forcing clk_div to value set by FDCAN1 \r\n");
		switch (hfdcan1.Init.ClockDivider) {
		case FDCAN_CLOCK_DIV1: clk_div = 1.0; break;
		case FDCAN_CLOCK_DIV2: clk_div = 2.0; break;
		case FDCAN_CLOCK_DIV4: clk_div = 4.0; break;
		case FDCAN_CLOCK_DIV8: clk_div = 8.0; break;
		}
		printf("i.e. from 1 to %f\r\n", clk_div);

	} else {
		printf("\n\r====================\n\rUnknown FDCAN : %p \r\n Error exiting......\r\n", (void *)hfdcan->Instance);
	}

	printf(" Configuration:\r\n");
	printf(" Clock (Hz): %lu clk_div %f\r\n", clk, clk_div);

	printf(" Mode: %s\r\n", (mode == FDCAN_MODE_INTERNAL_LOOPBACK) ? "Loopback" :
			(mode == FDCAN_MODE_BUS_MONITORING) ? "Bus Monitoring" :
					(mode == FDCAN_MODE_NORMAL) ? "Normal" : "Other");

	printf(" FrameFormat: %s\r\n", (framefmt == FDCAN_FRAME_CLASSIC) ? "Classic CAN" :
			(framefmt == FDCAN_FRAME_FD_BRS) ? "CAN‑FD w/ BRS" :
					(framefmt == FDCAN_FRAME_FD_NO_BRS) ? "CAN‑FD no BRS" :
							"Unknown");

	printf(" Nominal Timing: Prescaler=%lu, SJW=%lu, TS1=%lu, TS2=%lu\n\r",
			prescaler, sjw, ts1, ts2);

	double bit_time = ((1.0/(double)clk)*(double)prescaler*clk_div) * (double)( ts1 + ts2 + 1);

	double bit_time_n = bit_time * 1e9; // in nano seconds


	printf(" Bit time: %lf ns : bit_rate %lf \r\n", bit_time_n, 1.0/bit_time);
	double sample_point = (1.0 + (double)ts1) / (1.0 + (double)ts1 + (double)ts2) * 100.0;
	printf(" Sample point: %.2f%%\r\n", sample_point);
	FDCAN_ErrorCountersTypeDef ec;
	HAL_FDCAN_GetErrorCounters(hfdcan, &ec);
	printf(" Error Counters: REC=%u, TEC=%u\n\r\n", ec.RxErrorCnt, ec.TxErrorCnt);

	printf("FDCAN kernel clock = %lu Hz\r\n", HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN));
	printf("SystemCoreClock = %lu Hz\r\n", SystemCoreClock);

}

 

This was very deceptive as it was telling me FDCAN3 was configured for 250kbps but really it was for 31.25kbps

 

This should be a bug report for:

STM32CubeIDE

Version: 1.16.0
Build: 21983_20240628_1741 (UTC)

(C) 2024 STMicroelectronics ALL RIGHTS RESERVED.

 

 

Also the code generated DID NOT configure the alternate pins for CANFD3 and the MX_INIT functions overwrote the settings for the CAN pins (kept setting alternate function to 11 instead of 9)

This topic has been closed for replies.

1 reply

TDK
July 29, 2025

Related/duplicate:

CAN alternate functions *NOT* configured in stm32I... - STMicroelectronics Community

 

Again, please include your IOC file so the issue can be duplicated.

"If you feel a post has answered your question, please click ""Accept as Solution""."