Skip to main content
TOlli
Senior
July 3, 2020
Solved

Correct sequence to reconfiguring CAN FD settings

  • July 3, 2020
  • 1 reply
  • 1064 views

Hi,

I've been trying to get my CAN FD configuration going, but I'm running into issue when I need to reconfigure the timing parameters for different bandwidth.

My original code, generated partly by CubeMX looks like this:

 hfdcan1.Instance = FDCAN1;
 hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
 hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
 hfdcan1.Init.AutoRetransmission = DISABLE;
 hfdcan1.Init.TransmitPause = DISABLE;
 hfdcan1.Init.ProtocolException = DISABLE;
 hfdcan1.Init.NominalPrescaler = 1;
 hfdcan1.Init.NominalSyncJumpWidth = 16;
 hfdcan1.Init.NominalTimeSeg1 = 63;
 hfdcan1.Init.NominalTimeSeg2 = 16;
 hfdcan1.Init.DataPrescaler = 1;
 hfdcan1.Init.DataSyncJumpWidth = 2;
 hfdcan1.Init.DataTimeSeg1 = 7;
 hfdcan1.Init.DataTimeSeg2 = 2;
 hfdcan1.Init.MessageRAMOffset = 0;
 hfdcan1.Init.StdFiltersNbr = 1;
 hfdcan1.Init.ExtFiltersNbr = 0;
 hfdcan1.Init.RxFifo0ElmtsNbr = 2;
 hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
 hfdcan1.Init.RxFifo1ElmtsNbr = 0;
 hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
 hfdcan1.Init.RxBuffersNbr = 0;
 hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
 hfdcan1.Init.TxEventsNbr = 0;
 hfdcan1.Init.TxBuffersNbr = 0;
 hfdcan1.Init.TxFifoQueueElmtsNbr = 2;
 hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
 hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
 if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
 {
 Error_Handler();
 }
 
HAL_GPIO_WritePin(DigitalCanSilentOut01_GPIO_Port, DigitalCanSilentOut01_Pin, GPIO_PIN_RESET);
HAL_FDCAN_EnableISOMode(&hfdcan1);
HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, 6, 0);
HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
HAL_FDCAN_Start(&hfdcan1);

And this is all I need to get the initial configuration going. Now when I want to change the settings a little, like a reconfiguration, I use this kind of flow:

uint32_t configureFdCan(FDCAN_HandleTypeDef *dev, CanConfigurationPreset preset) {
 
	if(dev->Instance == FDCAN1) {
 
		FDCAN_FilterTypeDef filterDefinition;
 
		/* Make the transceiver go silent */
		HAL_GPIO_WritePin(DigitalCanSilentOut01_GPIO_Port, DigitalCanSilentOut01_Pin, GPIO_PIN_SET);
		/* Stop the peripheral from responding */
		HAL_FDCAN_Stop(dev);
 
		while(HAL_FDCAN_GetState(dev) != HAL_FDCAN_STATE_READY) {
			/* Wait here until the device is good for configuration */
		}
 
		HAL_FDCAN_DeInit(dev);
 
		while(HAL_FDCAN_GetState(dev) != HAL_FDCAN_STATE_RESET) {
			/* Wait here until the device is good for configuration */
		}
 
		switch (preset) {
		case CAN_NOBRS_1000:
 
			break;
		case CAN_NOBRS_500:
 
			break;
		case CAN_NOBRS_250:
 
			break;
		case CAN_BRS_1000_8000:
 
			dev->Instance = FDCAN1;
			dev->Init.FrameFormat = FDCAN_FRAME_FD_BRS;
			dev->Init.Mode = FDCAN_MODE_NORMAL;
			dev->Init.AutoRetransmission = DISABLE;
			dev->Init.TransmitPause = DISABLE;
			dev->Init.ProtocolException = DISABLE;
			dev->Init.NominalPrescaler = 1;
			dev->Init.NominalSyncJumpWidth = 16;
			dev->Init.NominalTimeSeg1 = 63;
			dev->Init.NominalTimeSeg2 = 16;
			dev->Init.DataPrescaler = 1;
			dev->Init.DataSyncJumpWidth = 2;
			dev->Init.DataTimeSeg1 = 7;
			dev->Init.DataTimeSeg2 = 2;
			dev->Init.MessageRAMOffset = 0;
			dev->Init.StdFiltersNbr = 1;
			dev->Init.ExtFiltersNbr = 0;
			dev->Init.RxFifo0ElmtsNbr = 2;
			dev->Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
			dev->Init.RxFifo1ElmtsNbr = 0;
			dev->Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
			dev->Init.RxBuffersNbr = 0;
			dev->Init.RxBufferSize = FDCAN_DATA_BYTES_8;
			dev->Init.TxEventsNbr = 0;
			dev->Init.TxBuffersNbr = 0;
			dev->Init.TxFifoQueueElmtsNbr = 2;
			dev->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
			dev->Init.TxElmtSize = FDCAN_DATA_BYTES_8;
 
			/* Enable standard frame, instead of the Bosch model */
			HAL_FDCAN_EnableISOMode(dev);
 
			/* Set and enable the transceiver compensation */
			/* These values seem to work for now, but a further investigation to CAN FD
			* examples reveals that ST sets the offset to be equal to (dataSeg1)*Prescale,
			* which in our application would be 7.
			* They set the window to 0
			* The example can be found from H745I-DISCO image transmission example.
			*/
			HAL_FDCAN_ConfigTxDelayCompensation(dev, 6, 0);
			HAL_FDCAN_EnableTxDelayCompensation(dev);
 
			break;
		case CAN_BRS_1000_5000:
 
			break;
		case CAN_BRS_1000_2000:
 
			break;
		case CAN_BRS_500_2000:
 
			break;
		}
 
		/* Check for correct initialization */
		if(HAL_FDCAN_Init(dev) != HAL_OK) {
			Error_Handler();
		}
 
		/* Configure filter for the communication */
		filterDefinition.IdType = FDCAN_STANDARD_ID;
		filterDefinition.FilterIndex = 0;
		filterDefinition.FilterType = FDCAN_FILTER_RANGE;
		filterDefinition.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
		filterDefinition.FilterID1 = 100;
		filterDefinition.FilterID2 = 200;
 
		HAL_FDCAN_ConfigFilter(dev, &filterDefinition);
		HAL_FDCAN_ConfigGlobalFilter(dev,
				FDCAN_FILTER_REJECT,	/* Command for non-matching standard id */
				FDCAN_FILTER_REJECT,	/* Command for non-matching extended id */
				FDCAN_REJECT_REMOTE,	/* Command for remote standard frame */
				FDCAN_REJECT_REMOTE);	/* command for remote extended frame */
 
		/* Take transceiver out of silent mode */
		HAL_GPIO_WritePin(DigitalCanSilentOut01_GPIO_Port, DigitalCanSilentOut01_Pin, GPIO_PIN_RESET);
		/* Start the device again */
		if(HAL_FDCAN_Start(dev) == HAL_ERROR){
			Error_Handler();
		}
 }

But this causes the communication to become full of stuff errors. Even though the settings are the same.

Is this something I can't achieve by using the HAL driver commands? And I need to start using the registers directly.

Best regards,

This topic has been closed for replies.
Best answer by TOlli

Made some progress with good old fashion trial and error (man the manual could use a flowchart with the HAL commands on how this goes and what are the states etc.).

But I ended up scrapping the DeInit calls from the configuration. It seems to be enough to just stop the device, and then configure the .init, run Init-function and start the device back up again. Seems to work for now, but my setup is probably a little simple to bring out the more difficult cases.

I'm only running a custom board against a Ixxat USB CAN FD device on my laptop.

Hope this helps someone.

1 reply

TOlli
TOlliAuthorBest answer
Senior
July 6, 2020

Made some progress with good old fashion trial and error (man the manual could use a flowchart with the HAL commands on how this goes and what are the states etc.).

But I ended up scrapping the DeInit calls from the configuration. It seems to be enough to just stop the device, and then configure the .init, run Init-function and start the device back up again. Seems to work for now, but my setup is probably a little simple to bring out the more difficult cases.

I'm only running a custom board against a Ixxat USB CAN FD device on my laptop.

Hope this helps someone.