cancel
Showing results for 
Search instead for 
Did you mean: 

STM32MP15: How to allocate FDCAN1 to the M4 and set bitrate 1Mbps & dbitrate 2Mbps?

smanger
Associate II

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.

4 REPLIES 4
mƎALLEm
ST Employee

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

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

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.

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

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.