2025-07-29 4:18 AM
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)
2025-07-29 6:11 AM
Related/duplicate:
CAN alternate functions *NOT* configured in stm32I... - STMicroelectronics Community
Again, please include your IOC file so the issue can be duplicated.