cancel
Showing results for 
Search instead for 
Did you mean: 

Correct sequence to reconfiguring CAN FD settings

TOlli
Senior

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,

1 ACCEPTED SOLUTION

Accepted Solutions
TOlli
Senior

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.

View solution in original post

1 REPLY 1
TOlli
Senior

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.