2020-06-22 06:10 AM
Hi,
I've tried finding a document that would describe what do the different error codes mean for the CAN FD module.
Does anyone have a link or an idea where to search from?
My CAN FD peripheral ends up in error status 516 at some point and I can't find what it means.
Solved! Go to Solution.
2020-06-30 01:12 AM
I did some further digging on the issue and found function HAL_FDCAN_ConfigTxDelayCompensation. This function is needed when operating at 8Mbps (I had to start using it after 5Mbps).
Since the bit time is so small, the transmitter delays play a bigger role and will cause errors. The delay can be compensated by using the above function and then activating the functionality with HAL_FDCAN_EnableTxDelayCompensation function.
This allowed me to transmit with 1Mbps in arbitration phase and 8Mbps in data phase with the occasional stuffing error. Final piece to the puzzle was adjusting the settings on the CAN module so that both arbitration and data phase use the same prescaler and arbitration just uses a very large bit time quanta (I adjusted for 80tq).
This was the last piece of the puzzle to get communication working properly with my laptop.
Hopefully someone will find this helpful.
Best regards.
2020-06-23 01:38 AM
I did some digging and I think I solved one of the issues.
So I managed to get the error status back down to 512, which means I lost the flag for "HAL_FDCAN_ERROR_NOT_READY", but I'm left with the HAL_FDCAN_ERROR_FIFO_FULL.
This happens after exactly two revolutions of my software, which makes sense given the configuration (The clock to FDCAN is set to 80MHz and I'm aiming for 1Mbit/s normal transfer and 8Mbit/s for the fast transfer):
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = ENABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = DISABLE;
hfdcan2.Init.NominalPrescaler = 8;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 7;
hfdcan2.Init.NominalTimeSeg2 = 2;
hfdcan2.Init.DataPrescaler = 1;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 7;
hfdcan2.Init.DataTimeSeg2 = 2;
hfdcan2.Init.MessageRAMOffset = 32;
hfdcan2.Init.StdFiltersNbr = 1;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.RxFifo0ElmtsNbr = 2;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxFifo1ElmtsNbr = 0;
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxBuffersNbr = 0;
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.TxEventsNbr = 0;
hfdcan2.Init.TxBuffersNbr = 0;
hfdcan2.Init.TxFifoQueueElmtsNbr = 2;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
The RAM offset is an arbitrary number at this point since CAN 1 is enabled but the settings are empty (I haven't even configured this):
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
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 = 1;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 0;
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 = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
The two instances are on different cores if that matters. FDCAN 2 is with CM7.
Now my code that is used to send looks like this (a running task in FreeRTOS):
void sendFdCanMessages(void *pvParameters) {
static FDCAN_TxHeaderTypeDef txHeader;
txHeader.Identifier = 0x111;
txHeader.IdType = FDCAN_STANDARD_ID;
txHeader.TxFrameType = FDCAN_DATA_FRAME;
txHeader.DataLength = FDCAN_DLC_BYTES_8;
txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
txHeader.BitRateSwitch = FDCAN_BRS_ON;
txHeader.FDFormat = FDCAN_FD_CAN;
txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
txHeader.MessageMarker = 0;
uint32_t value {0};
uint32_t command {0};
for(;;) {
value = rand();
command = rand();
packCanFdPayload(txPayload, &value, sizeof(value), &command, sizeof(command));
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &txHeader, &txPayload[0]);
vTaskDelay(1000);
}
}
I start the CAN instance using this command, straight after it has been initialized by CubeMX code:
HAL_FDCAN_Start(&hfdcan2);
Shouldn't the HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &txHeader, &txPayload[0]); initiate the transmission without further commands?
Now after two cycles of the task, the buffer is full and I end up with the Error Status of 512
Best regards,
2020-06-25 09:32 PM
I managed to solve the issue, it seems that my timing parameters for the CAN (seg1, seg2, prescale) were off, causing the communication between units to go bad.
If anyone comes to this topic with the same problem, calculate the CAN 2.0 timing variables with this:
http://www.bittiming.can-wiki.info/
It gives better answers and an actual explanation rather than the "values out of nowhere" seen in ST example projects for the dev boards. At the moment it does not calculate values for CAN FD, but you should be able to get up to 5Mbps by just making the traditional part 1Mbps and then adjusting the prescaler if the clock for CAN is 80MHz before scaling.
Best regards,
2020-06-30 01:12 AM
I did some further digging on the issue and found function HAL_FDCAN_ConfigTxDelayCompensation. This function is needed when operating at 8Mbps (I had to start using it after 5Mbps).
Since the bit time is so small, the transmitter delays play a bigger role and will cause errors. The delay can be compensated by using the above function and then activating the functionality with HAL_FDCAN_EnableTxDelayCompensation function.
This allowed me to transmit with 1Mbps in arbitration phase and 8Mbps in data phase with the occasional stuffing error. Final piece to the puzzle was adjusting the settings on the CAN module so that both arbitration and data phase use the same prescaler and arbitration just uses a very large bit time quanta (I adjusted for 80tq).
This was the last piece of the puzzle to get communication working properly with my laptop.
Hopefully someone will find this helpful.
Best regards.
2024-08-22 08:05 AM
In case someone runs in some weird errors on FDCAN, this confirmed works. You must initialize the complete txHeader structure otherwise you might get weird stuff on the bus. For example inconsistent IDs, remote frames instead of standard frames etc.