2020-07-03 04:56 AM
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,
Solved! Go to Solution.
2020-07-06 06:05 AM
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.
2020-07-06 06:05 AM
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.