Skip to main content
Visitor II
May 4, 2020
Question

STM32MP1 FDCAN not leaving init mode (Zephyr os project)

  • May 4, 2020
  • 3 replies
  • 2207 views

Hello !

I have some trouble implementing a FDCAN internal loopback on the STM32MP157c-dk2.

I have linked the FDCAN1 Instance to the cortex M4 and I don't have any can bus to connect it to yet so I'm trying to implement an internal loopback. I took the exemple code that came with the stm32cube (STM32CubeMP1/Projects/STM32MP157C-DK2/Examples) tool and I replaced the external loopback mode with the internal one.

The code blocks after having put the messages in the tx fifo (function HAL_FDCAN_IsTxBufferMessagePending() ).

The messages are written in memory but they are never sent.

I found that the FDCAN never ended it's init phase (FDCAN_CCCR_INIT stays set even after HAL_FDCAN_Start() function is called)

I tried to force using the same protocol used to set it but it causes a timeout.

Is anyone knowing why it won't switch to the normal operation mode ?

Thanks in advance.

Paul

ps : here is the code, I'm not in engineering mode so the device tree is managed by zephyr, I added the correct FDCAN address to it, don't know if something is missing

can1: can@4400e000 {
			compatible = "st,stm32-can-fd";
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <0x4400e000 0x400>;
			interrupts = <19 0>, <21 0>;
			interrupt-names = "LINE_1", "LINE_0";
			clocks = <&rcc STM32_CLOCK_BUS_APB2 0x01000000>;
			status = "disabled";
			label = "CAN_1";
		};

MX_GPIO_Init();
 MX_FDCAN1_Init();
/*##-1 Configure the FDCAN filters ########################################*/
 /* Configure standard ID reception filter to Rx FIFO 0 */
 sFilterConfig.IdType = FDCAN_STANDARD_ID;
 sFilterConfig.FilterIndex = 0;
 sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
 sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
 sFilterConfig.FilterID1 = 0x444;
 sFilterConfig.FilterID2 = 0x555;
 if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Configure extended ID reception filter to Rx FIFO 1 */
 sFilterConfig.IdType = FDCAN_EXTENDED_ID;
 sFilterConfig.FilterIndex = 0;
 sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM;
 sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
 sFilterConfig.FilterID1 = 0x1111111;
 sFilterConfig.FilterID2 = 0x2222222;
 if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 /*##-2 Start FDCAN controller (continuous listening CAN bus) ##############*/
 if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
 {
 Error_Handler();
 }
 
 /*##-3 Transmit messages ##################################################*/
 /* Add message to Tx FIFO */
 TxHeader.Identifier = 0x444;
 TxHeader.IdType = FDCAN_STANDARD_ID;
 TxHeader.TxFrameType = FDCAN_DATA_FRAME;
 TxHeader.DataLength = FDCAN_DLC_BYTES_12;
 TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
 TxHeader.BitRateSwitch = FDCAN_BRS_ON;
 TxHeader.FDFormat = FDCAN_FD_CAN;
 TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
 TxHeader.MessageMarker = 0x52;
 if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Add second message to Tx FIFO */
 TxHeader.Identifier = 0x1111112;
 TxHeader.IdType = FDCAN_EXTENDED_ID;
 TxHeader.TxFrameType = FDCAN_DATA_FRAME;
 TxHeader.DataLength = FDCAN_DLC_BYTES_12;
 TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
 TxHeader.BitRateSwitch = FDCAN_BRS_ON;
 TxHeader.FDFormat = FDCAN_FD_CAN;
 TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
 TxHeader.MessageMarker = 0xCC;
 if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData1) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Add third message to Tx FIFO */
 TxHeader.Identifier = 0x1111113;
 TxHeader.IdType = FDCAN_EXTENDED_ID;
 TxHeader.TxFrameType = FDCAN_DATA_FRAME;
 TxHeader.DataLength = FDCAN_DLC_BYTES_12;
 TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
 TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
 TxHeader.FDFormat = FDCAN_FD_CAN;
 TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
 TxHeader.MessageMarker = 0xDD;
 if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData2) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Get tick */
 Tickstart = HAL_GetTick();
 
 /* Check transmission occurred before timeout */
 while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0 | FDCAN_TX_BUFFER1 | FDCAN_TX_BUFFER2) != 0)
 {
 if((HAL_GetTick() - Tickstart) > TX_FAST_TIMEOUT)
 {
 Error_Handler();
 break;
 }
 } 
 
 /*##-4 Receive messages ###################################################*/
 /* Get tick */
 Tickstart = HAL_GetTick();
 /* Check one message is received in Rx FIFO 0 */
 while(HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1)
 {
 if((HAL_GetTick() - Tickstart) > RX_FAST_TIMEOUT)
 {
 Error_Handler();
 break;
 }
 }
 
 /* Retrieve message from Rx FIFO 0 */
 if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Compare payload to expected data */
 if (BufferCmp8b(TxData0, RxData, 12) != 0)
 {
 Error_Handler();
 }
 
 /* Get tick */
 Tickstart = HAL_GetTick();
 /* Check two messages are received in Rx FIFO 1 */
 while(HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2)
 {
 if((HAL_GetTick() - Tickstart) > RX_FAST_TIMEOUT)
 {
 Error_Handler();
 break;
 }
 }
 
 /* Retrieve message from Rx FIFO 1 */
 if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &RxHeader, RxData) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Compare payload to expected data */
 if (BufferCmp8b(TxData1, RxData, 12) != 0)
 {
 Error_Handler();
 }
 
 /* Retrieve next message from Rx FIFO 1 */
 if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &RxHeader, RxData) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Compare payload to expected data */
 if (BufferCmp8b(TxData2, RxData, 12) != 0)
 {
 Error_Handler();
 }
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_FD_BRS;
 hfdcan1.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK;
 hfdcan1.Init.AutoRetransmission = ENABLE;
 hfdcan1.Init.TransmitPause = DISABLE;
 hfdcan1.Init.ProtocolException = ENABLE;
	/* 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 = 0x2;
 hfdcan1.Init.NominalSyncJumpWidth = 0xA;
 hfdcan1.Init.NominalTimeSeg1 = 0x1D;
 hfdcan1.Init.NominalTimeSeg2 = 0xA;
 hfdcan1.Init.DataPrescaler = 0x1;
 hfdcan1.Init.DataSyncJumpWidth = 0x2;
 hfdcan1.Init.DataTimeSeg1 = 0x7;
 hfdcan1.Init.DataTimeSeg2 = 0x2;
 hfdcan1.Init.MessageRAMOffset = 0;
 hfdcan1.Init.StdFiltersNbr = 1;
 hfdcan1.Init.ExtFiltersNbr = 1;
 hfdcan1.Init.RxFifo0ElmtsNbr = 8;
 hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_12;
 hfdcan1.Init.RxFifo1ElmtsNbr = 2;
 hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_12;
 hfdcan1.Init.RxBuffersNbr = 8;
 hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_12;
 hfdcan1.Init.TxEventsNbr = 2;
 hfdcan1.Init.TxBuffersNbr = 8;
 hfdcan1.Init.TxFifoQueueElmtsNbr = 8;
 hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
 hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_12; 
 if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN FDCAN1_Init 2 */
 
 /* USER CODE END FDCAN1_Init 2 */
 
}
/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 
 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOI_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
 
/**
 * @brief Compares two buffers.
 * @par Input
 * - pBuffer1, pBuffer2: buffers to be compared.
 * - BufferLength: buffer's length
 * @par Output
 * None.
 * @retval
 * 0: pBuffer1 identical to pBuffer2
 * 1: pBuffer1 differs from pBuffer2
 */
static uint32_t BufferCmp8b(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
 while(BufferLength--)
 {
 if(*pBuffer1 != *pBuffer2)
 {
 return 1;
 }
 
 pBuffer1++;
 pBuffer2++;
 }
 return 0;
}

    This topic has been closed for replies.

    3 replies

    Technical Moderator
    May 4, 2020

    Hi @PNgou.1​ 

    This sentence "I'm not in engineering mode so the device tree is managed by zephyr" is puzzling me.

    Can you clarify your software architecture Linux A7 + M4 Zephyr ? Or else ?

    Thanks

    Olivier

    PNgou.1Author
    Visitor II
    May 4, 2020

    Hi @Community member​, Thanks for responding,

    Indeed I'm actually running linux on the A7 and Zephyr on the M4.

    I asked on Zephyr forums for the FDCAN support but no driver has been developed yet. I took example on a pull request for the device tree modification (https://github.com/zephyrproject-rtos/zephyr/pull/22832).

    Paul

    Visitor II
    April 13, 2022

    I have the same problem (but with a bare metal project). Have you found any solution?