cancel
Showing results for 
Search instead for 
Did you mean: 

CAN communication not working F407 with G431

bushy_foxx
Associate II

I have two Nucleo boards that are connected with a CAN bus (Transceiver SN65HVD230).

I would like to communicate with standard CAN, eight data bytes, data rate 50000 bit/s.

For the F407 all TX & RX events are triggering (reused old working code) the CubeMX settings (HCLK 168 MHz, periphiral clk 42 MHz) are:

CubeMX_F407.PNG

The G431 is not working as expected, the CubeMX settings (HCLK 170 MHz, peripheral clocks 170 MHz) are:

CubeMX_G431.PNG

The G431 TX/RX interrupts are working only in external Loopback mode in normal mode nothing triggers. Some code for the configuration of the G431 CAN:

 

HAL_StatusTypeDef CAN1_Start(int8_t CAN_HW_init)
{
	HAL_StatusTypeDef status;
	FDCAN_FilterTypeDef filterConfig;

	if(CAN_HW_init == 1)
	{
		MX_FDCAN1_Init();
	}

	// Configure Rx filter
	filterConfig.IdType = FDCAN_STANDARD_ID;
	filterConfig.FilterIndex = 0;
	filterConfig.FilterType = FDCAN_FILTER_MASK; // FDCAN_FILTER_RANGE;
	filterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
	filterConfig.FilterID1 = 0x000;
	filterConfig.FilterID2 = 0x000; // 0x7FF; // 0x1FFFFFFF; //

	if (HAL_FDCAN_ConfigFilter(&hfdcan1, &filterConfig) != HAL_OK)
	{
		Error_Handler();
	}

	// Start the FDCAN module
	status = HAL_FDCAN_Start(&hfdcan1);
	if (status != HAL_OK)
	{
		Error_Handler();
	}

	if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_TX_BUFFER0 | FDCAN_RX_FIFO0) != HAL_OK)
	//if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_TX_BUFFER0 | FDCAN_TX_BUFFER1 | FDCAN_TX_BUFFER2) != HAL_OK)
	//if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
	{
		Error_Handler();
	}

	return status;
}

// send CAN message
void CAN1_TX(uint32_t CAN_ID, uint8_t CAN_RTR, uint8_t* CAN_Tx_Data)
{
	//FDCAN_TxHeaderTypeDef CanTxHeader;

	CanTxHeader.Identifier = CAN_ID;
	CanTxHeader.IdType = FDCAN_STANDARD_ID;
	CanTxHeader.DataLength = FDCAN_DLC_BYTES_8; // CAN_DLC; //
	CanTxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // FDCAN_ESI_PASSIVE; //
	CanTxHeader.BitRateSwitch = FDCAN_BRS_OFF;
	CanTxHeader.FDFormat = FDCAN_CLASSIC_CAN; // FDCAN_FD_CAN;
	CanTxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; //FDCAN_STORE_TX_EVENTS; //
	CanTxHeader.MessageMarker = 0;

	if(CAN_RTR == 0)
	{
		CanTxHeader.TxFrameType = FDCAN_DATA_FRAME;
	}
	else
	{
		CanTxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
	}


	/* Start the Transmission process */
	if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &CanTxHeader, CAN_Tx_Data) != HAL_OK)
	{
		/* Transmission request Error */
		Error_Handler();
	}
	HAL_Delay(10);
}

// Transmission Complete callback FDCAN_Tx_location
void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
	can_tx_ready = 1; // finished transmission
}

// FDCAN RX callback
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
	if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
	{
	    /* Retrieve Rx messages from RX FIFO0 */
	    if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CanRxHeader, can_rx_data) != HAL_OK)
	    {
	    	Error_Handler();
	    }

		can_state_change = 1;
	}
}

I need some advice, please help.

Best Regards,

Erik

1 ACCEPTED SOLUTION

Accepted Solutions

Indeed, there is no crystal on the NUCLEO-G431KB board but you can use STLINK-MCO output as clock source from the STLINK. The STLINK is already clocked by a Crystal. And from G4 you need to configure HSE in Bypass mode. 

As that NUCLEO board feature  STLINK V3, STLINK -MCO output frequency value is configurable.

Please read this article: How to use STLINK-V3 MCO output on Nucleo boards as a precise clock source for STM32

If still having issues. Please attach the a complete but very simple projects for both F4 and G4 including the ioc files.

 

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.

View solution in original post

4 REPLIES 4
mƎALLEm
ST Employee

Hello @bushy_foxx and welcome to the ST community,

You configured the FDCAN interface in Loopback mode for STM32G4. You need to change it to Normal mode and Classic format.

mALLEm_1-1746429622149.png

Also you need to use a crystal for CAN peripheral for both F4 and G4. Avoid using HSI and other internal RC sources.

 

 

 

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.

The hardware that I am using is:

- STM32F407G-DISC1; there is a crystal HSE is selected

- STM32G431KBT6; there is no crystal on the board; the clock setting is as follows:

CubeMX_G431_2.PNG

In switched between Loopback External and Normal Mode for the STM32G431KBT6

If I run the G4 in Loopback external, the TX & RX interrupts are triggered correctly (functions HAL_FDCAN_TxBufferCompleteCallback(...) and HAL_FDCAN_RxFifo0Callback(...), see code example initial post). Also the receive interrupt at the F407 is triggered; I can see the data while debugging the F407 with CubeIDE. Furthermore, I can see the bits on the oscilloscope.

If I run the G4 in Normal Mode no TX & RX Interrupt is triggered, the F407 is still connected to the bus for that hardware setup. Seems that nothing goes out on the TX line.

The SN65HVD230 Transceiver is on a CAN Waveshare Devboard, both sides 120 Ohm terminated, the cable in between is currently only about 1 m.

What are further useful checks?

Best Regards,
Erik

 

Indeed, there is no crystal on the NUCLEO-G431KB board but you can use STLINK-MCO output as clock source from the STLINK. The STLINK is already clocked by a Crystal. And from G4 you need to configure HSE in Bypass mode. 

As that NUCLEO board feature  STLINK V3, STLINK -MCO output frequency value is configurable.

Please read this article: How to use STLINK-V3 MCO output on Nucleo boards as a precise clock source for STM32

If still having issues. Please attach the a complete but very simple projects for both F4 and G4 including the ioc files.

 

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.

Many thanks for the further advice!

I switched the clock configuration of the G4 to HSE, STLINK-MCO. Some changes in my code and filter configuration was necessary, now both devices communicate. Some code snippets for the community...

STM32G431:

// main.c
FDCAN_RxHeaderTypeDef CanRxHeader;
FDCAN_TxHeaderTypeDef CanTxHeader;
uint8_t can_tx_data[8], can_rx_data[8];
uint8_t can_state_change = 0;
uint8_t can_tx_ready = 1;

// Transmission Complete callback FDCAN_Tx_location
void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
	can_tx_ready = 1; // finished transmission
}

// FDCAN RX callback
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
	if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
	{
	    // Retrieve Rx messages from RX FIFO0
	    if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CanRxHeader, can_rx_data) != HAL_OK)
	    {
	    	Error_Handler();
	    }

		can_state_change = 1;
	}
}

void CAN1_TX(uint32_t CAN_ID, uint8_t CAN_RTR, uint8_t* CAN_Tx_Data)
{
	CanTxHeader.Identifier = CAN_ID;
	CanTxHeader.IdType = FDCAN_STANDARD_ID;
	CanTxHeader.DataLength = FDCAN_DLC_BYTES_8;
	CanTxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; 
	CanTxHeader.BitRateSwitch = FDCAN_BRS_OFF;
	CanTxHeader.FDFormat = FDCAN_CLASSIC_CAN; 
	CanTxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; 
	CanTxHeader.MessageMarker = 0;

	if(CAN_RTR == 0)
	{
		CanTxHeader.TxFrameType = FDCAN_DATA_FRAME;
	}
	else
	{
		CanTxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
	}

	// Start the Transmission process
	can_tx_ready = 0;
	if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &CanTxHeader, CAN_Tx_Data) != HAL_OK)
	{
	    Error_Handler();

	    HAL_FDCAN_Stop(&hfdcan1);
	    if (HAL_FDCAN_DeInit(&hfdcan1) != HAL_OK)
	    {
	      Error_Handler();
	    }

	    CAN1_Start(1);
	}
	else
	{
		int timeout_cnt = 0;
		while(can_tx_ready == 0)
		{
			HAL_Delay(5);
			timeout_cnt++;
			if (timeout_cnt == 10)
			{
				break; // no device on the bus...
			}
		}
	}
}

HAL_StatusTypeDef CAN1_Start(int8_t CAN_HW_init)
{
	HAL_StatusTypeDef status;
	FDCAN_FilterTypeDef filterConfig;

	if(CAN_HW_init == 1)
	{
		MX_FDCAN1_Init();
	}

	// Configure Rx filter
	filterConfig.IdType = FDCAN_STANDARD_ID;
	filterConfig.FilterIndex = 0;
	filterConfig.FilterType = FDCAN_FILTER_MASK; // FDCAN_FILTER_RANGE;
	filterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
	filterConfig.FilterID1 = 0x000;
	filterConfig.FilterID2 = 0x000; 

	if (HAL_FDCAN_ConfigFilter(&hfdcan1, &filterConfig) != HAL_OK)
	{
		Error_Handler();
	}

	// Start the FDCAN module
	status = HAL_FDCAN_Start(&hfdcan1);
	if (status != HAL_OK)
	{
		Error_Handler();
	}

	if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE | FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_TX_BUFFER0 | FDCAN_TX_BUFFER1 | FDCAN_TX_BUFFER2) != HAL_OK)
	{
		Error_Handler();
	}

	return status;
}

HAL_StatusTypeDef CAN1_Stop(int8_t CAN_HW_deinit)
{
	HAL_StatusTypeDef status;
	status = HAL_FDCAN_Stop(&hfdcan1);

	if(CAN_HW_deinit == 1)
	{
		status = HAL_FDCAN_DeInit(&hfdcan1);
	}

	return status;
}

 

STM32F407:

// main.c
CAN_RxHeaderTypeDef CanRxHeader;
uint8_t can_tx_data[8], can_rx_data[8];
uint8_t can_state_change = 0;
uint8_t can_tx_ready = 1;

void CAN1_TX(uint32_t CAN_DLC, uint32_t CAN_ID, uint8_t CAN_RTR, uint8_t* CAN_Tx_Data)
{
	uint32_t TxMailbox;
	CAN_TxHeaderTypeDef CanTxHeader;

	CanTxHeader.DLC = CAN_DLC;
	CanTxHeader.StdId = CAN_ID;
	CanTxHeader.IDE = CAN_ID_STD;

	if(CAN_RTR == 0)
	{
		CanTxHeader.RTR = CAN_RTR_DATA;
	}
	else
	{
		CanTxHeader.RTR = CAN_RTR_REMOTE;
	}

	can_tx_ready = 0;
	if (HAL_CAN_AddTxMessage(&hcan1, &CanTxHeader, CAN_Tx_Data, &TxMailbox) != HAL_OK)
	{
		HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);
		ErrorPresent = 't';
	    Error_Handler();

	    HAL_CAN_Stop(&hcan1);
	    if (HAL_CAN_DeInit(&hcan1) != HAL_OK)
	    {
	      Error_Handler();
	    }

	    CAN1_Start(1);
	}
	else
	{
		while(can_tx_ready == 0) {}
	}
}

HAL_StatusTypeDef CAN1_Start(int8_t CAN_HW_init)
{
	HAL_StatusTypeDef status;
	CAN_FilterTypeDef filterConfig;

	if(CAN_HW_init == 1)
	{
		MX_CAN1_Init();
	}

	filterConfig.FilterBank = 0; // CAN1: 0-13, CAN2: 14-27;
	filterConfig.FilterActivation = ENABLE;
	filterConfig.FilterFIFOAssignment = 0;
	filterConfig.FilterIdHigh = 0x0000;
	filterConfig.FilterIdLow = 0x0000;
	filterConfig.FilterMaskIdHigh = 0x0000;
	filterConfig.FilterMaskIdLow = 0x0000;
	filterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
	filterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
	filterConfig.FilterActivation = ENABLE;

	HAL_CAN_ConfigFilter(&hcan1, &filterConfig);
	HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING);
	status = HAL_CAN_Start(&hcan1);
	return status;
}

HAL_StatusTypeDef CAN1_Stop(int8_t CAN_HW_deinit)
{
	HAL_StatusTypeDef status;
	status = HAL_CAN_Stop(&hcan1);

	if(CAN_HW_deinit == 1)
	{
		status = HAL_CAN_DeInit(&hcan1);
	}

	return status;
}

// stm32f4xx_it.c
extern CAN_RxHeaderTypeDef CanRxHeader;
extern uint8_t can_rx_data;
extern uint8_t can_state_change, can_tx_ready;

void CAN1_TX_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_TX_IRQn 0 */

  /* USER CODE END CAN1_TX_IRQn 0 */
  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_TX_IRQn 1 */

  can_tx_ready = 1; // finished transmission

  /* USER CODE END CAN1_TX_IRQn 1 */
}

/**
  * @brief This function handles CAN1 RX0 interrupts.
  */
void CAN1_RX0_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */

  /* USER CODE END CAN1_RX0_IRQn 0 */
  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */

  HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &CanRxHeader, &can_rx_data);
  can_state_change = 1;

  /* USER CODE END CAN1_RX0_IRQn 1 */
}

 

Both devices are configured with 50kbit/s.

Best Regards,
Erik