cancel
Showing results for 
Search instead for 
Did you mean: 

FDCAN Clock Divider can silently change your actual CAN bit rate

rclar.6
Senior

 

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)

1 REPLY 1
TDK
Super User

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".