2025-06-30 7:50 AM - last edited on 2025-06-30 7:55 AM by Andrew Neil
I am able to use FDCAN1 to communicate on the A7 by adding the following to `STM32MPU-Ecosystem-v6.0.0/Developer-Package/stm32mp1-openstlinux-6.6-yocto-scarthgap-mpu-v24.11.06/sources/arm-ostl-linux-gnueabi/linux-stm32mp-6.6.48-stm32mp-r1-r0/linux-6.6.48/arch/arm/boot/dts/st/stm32mp157f-dk2.dts`:
&m_can1 {
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&m_can1_pins_b>;
        pinctrl-1 = <&m_can1_sleep_pins_b>;
        clocks = <&scmi_clk CK_SCMI_HSE>, <&rcc FDCAN_K>;
        status = "okay";
};I'd like to allocate this can device to the M4 and use the example `STM32Cube_FW_MP1_V1.7.0/Projects/STM32MP157C-DK2/Examples/FDCAN`
I need help is fixing this code to get a bitrate of 1Mbps and dbitrate of 2Mbps.
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.FrameFormat = FDCAN_FRAME_CLASSIC;
//  hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
  hfdcan1.Init.Mode = FDCAN_FRAME_FD_NO_BRS;
  hfdcan1.Init.AutoRetransmission = ENABLE;
  hfdcan1.Init.TransmitPause = ENABLE;
  hfdcan1.Init.ProtocolException = DISABLE;
	/* Bit time configuration:
	 ************************
	 Bit time parameter         |   Nominal    |   Data
	 ---------------------------|--------------|--------------
	 fdcan_ker_ck               | 80 MHz       | 80 MHz
	 Time_quantum (tq)          | 12.5 ns      | 12.5 ns
	 Prescaler                  |  2           |  1
	 Synchronization_segment    |  1 tq        |  1 tq
	 Propagation_segment        | 19 tq        |  5 tq
	 Phase_segment_1            | 10 tq        |  2 tq
	 Phase_segment_2            | 10 tq        |  2 tq
	 Synchronization_Jump_width | 10 tq        |  2 tq
	 Bit_length                 | 80 tq = 1 �s |  10 tq = 0.125 �s
	 Bit_rate                   |  1 MBit/s    |  8 MBit/s
	 */
  hfdcan1.Init.NominalPrescaler = 0x1;
  hfdcan1.Init.NominalSyncJumpWidth = 11;
  hfdcan1.Init.NominalTimeSeg1 = 68;
  hfdcan1.Init.NominalTimeSeg2 = 11;
//  hfdcan1.Init.NominalPrescaler = 0;
//  hfdcan1.Init.NominalSyncJumpWidth = 0xA;
//  hfdcan1.Init.NominalTimeSeg1 = 0x1D;
//  hfdcan1.Init.NominalTimeSeg2 = 0xA;
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 4;
  hfdcan1.Init.DataTimeSeg1 = 31;
  hfdcan1.Init.DataTimeSeg2 = 8;
//  hfdcan1.Init.DataPrescaler = 0x1;
//  hfdcan1.Init.DataSyncJumpWidth = 0x2;
//  hfdcan1.Init.DataTimeSeg1 = 0x7;
//  hfdcan1.Init.DataTimeSeg2 = 0x2;
  hfdcan1.Init.MessageRAMOffset = 0;
//  hfdcan1.Init.StdFiltersNbr = 0;
//  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.StdFiltersNbr = 1;
  hfdcan1.Init.ExtFiltersNbr = 1;
  hfdcan1.Init.RxFifo0ElmtsNbr = 8;
  hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
  hfdcan1.Init.RxFifo1ElmtsNbr = 2;
  hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
  hfdcan1.Init.RxBuffersNbr = 8;
  hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_64;
  hfdcan1.Init.TxEventsNbr = 0;
  hfdcan1.Init.TxBuffersNbr = 0;
  hfdcan1.Init.TxFifoQueueElmtsNbr = 6;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
  HAL_StatusTypeDef hst = HAL_FDCAN_Init(&hfdcan1);
  if (hst != HAL_OK)
  {
    Error_Handler_Int(hst);
  }
  /* USER CODE BEGIN FDCAN1_Init 2 */
//  SET_BIT(hfdcan1.Instance->TEST, FDCAN_TEST_LBCK);
//  SET_BIT(hfdcan1->Instance->CCCR, FDCAN_CCCR_MON);
  /* USER CODE END FDCAN1_Init 2 */
}Thanks! Steve.
2025-06-30 8:50 AM - edited 2025-06-30 8:55 AM
Hello,
I'm not a MPU expert, but these lines prevent you to use the peripheral in CAN-FD frame:
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_FRAME_FD_NO_BRS;Classic means CAN2.0. There is no data rate here and setting data timing are discarded by the peripheral.
You need to activate the CAN-FD format with bitrate switching. For example with STM32H7 product the configuration is as the following:
  hfdcan.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
  hfdcan.Init.Mode = FDCAN_MODE_NORMAL;and in the Tx header you need to tell that there will be a bitrate switching:
TxHeader.BitRateSwitch = FDCAN_BRS_ON;This article may also help you: STM32 FDCAN running at 8 Mb/s on NUCLEO boards
2025-06-30 8:56 AM
After I posted this, I realized that I had the frame format and mode wrong. I had since changed them. I'm more interested in the the variables for the `bitrate` and the `data bitrate`. I think that's what's causing me biggest headache.
2025-06-30 8:59 AM - edited 2025-06-30 9:02 AM
As I said I'm not expert of MPU products as I don't have idea about their environment but you need also to activate the delay compensation. See this thread. And use a Crystal as clock source for FDCAN.
Also use Kvaser CAN-FD bit time calculator from this link.
2025-06-30 12:15 PM
I have added the delay compensation as shown in the thread from above. This did not change anything as far as I can tell.
I have updated the `stm32mp157f-dk2.dts` file so that instead of `m_can1`, it's now `m4_can1`.
&m4_can1 {
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&m_can1_pins_b>;
        pinctrl-1 = <&m_can1_sleep_pins_b>;
        clocks = <&scmi_clk CK_SCMI_HSE>, <&rcc FDCAN_K>;
        status = "okay";
};I rebuilt and uploaded the kernel, still no luck.
I'm not quite sure what this line means in the `dts` file (can I or do I need to assign one or more of these clocks to the M4?):
clocks = <&scmi_clk CK_SCMI_HSE>, <&rcc FDCAN_K>;I'm not sure what the speeds of these clocks are on the `STM32MP157F-DK2`. That will have a big impact on the nominal bitrate and data bitrate calculations.
