Skip to main content
MFrie.7
Associate II
March 28, 2025
Solved

Enable FDCAN_IT_ARB_PROTOCOL_ERROR

  • March 28, 2025
  • 2 replies
  • 957 views

Hello
I use CAN FD and have a functioning communication with 3 participants. Now I want to activate the interrupt that notifies me when the device has lost the arbitration contest.

I forward each of the four NVIC interrupts in stm32h7xx_hal_fdcan:

void FDCAN2_IT0_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&hfdcan2);
}
When initializing CAN, I activate the interrupt:
retVal = HAL_FDCAN_ActivateNotification(m_Fdcan2Handle, FDCAN_IT_ARB_PROTOCOL_ERROR, 0);

and set the CallbackHandle beforehand:
retVal = HAL_FDCAN_RegisterTxEventFifoCallback(m_Fdcan2Handle, MyCallback);
SYSM_ASSERT_STOP(retVal == HAL_OK, retVal);
retVal = HAL_FDCAN_RegisterErrorStatusCallback(m_Fdcan2Handle, MyCallback);
SYSM_ASSERT_STOP(retVal == HAL_OK, retVal);
retVal = HAL_FDCAN_RegisterTxBufferAbortCallback(m_Fdcan2Handle, MyCallback);
SYSM_ASSERT_STOP(retVal == HAL_OK, retVal);
retVal = HAL_FDCAN_RegisterTxEventFifoCallback(m_Fdcan2Handle, MyCallback);
SYSM_ASSERT_STOP(retVal == HAL_OK, retVal);

Despite arbitration collisions, I do not end up in my callback “MyCallback”.

What have I overlooked?

Best regards

Best answer by MFrie.7

Hallo, as a workaround I made it work with the FiFo size of 1 and the FiFoEmpty-Interrupt:

 void CCan::txFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan)
 {

 uint32_t TXBRP = hfdcan->Instance->TXBRP;
 uint32_t TXBFC = hfdcan->Instance->TXBCF;
 uint32_t TXBTO = hfdcan->Instance->TXBTO;

 /* Arbitration loss or frame transmission disturbed? */
 if ((TXBFC & ~TXBTO) != 0 && !TXBRP)
 {
 /* Check if there was an error in the data or arbitration phase.
 * Lost arbitration is not rated as error (See FDCAN_PSR.LEC). */
 bool dataPhaseError = hfdcan->Instance->IR & FDCAN_FLAG_DATA_PROTOCOL_ERROR;
 bool dataArbError = hfdcan->Instance->IR & FDCAN_FLAG_ARB_PROTOCOL_ERROR;

 if(dataPhaseError == false && dataArbError == false )
 {
 /* Retransmit the Message */
 HAL_StatusTypeDef retVal;
 if(hfdcan->Instance == FDCAN1)
 {
 retVal = HAL_FDCAN_AddMessageToTxFifoQ(hfdcan, &latestCanMessage[0].txHeader, latestCanMessage[0].dataWithSerial);
 SYSM_ASSERT_NO_STOP(retVal == HAL_OK, hfdcan->ErrorCode);
 }
 else if(hfdcan->Instance == FDCAN2)
 {
 retVal = HAL_FDCAN_AddMessageToTxFifoQ(hfdcan, &latestCanMessage[1].txHeader, latestCanMessage[1].dataWithSerial);
 SYSM_ASSERT_NO_STOP(retVal == HAL_OK, hfdcan->ErrorCode);
 }
 else
 {
 SYSM_ASSERT_STOP(0, hfdcan->Instance);
 }
 }
 }
 }

There are still some cases, in which an error in the arbitration-phase is evaluated as arbitration loss (See FDCAN_PSR.LEC), but since it will only occure rarely, its fine for my SW.

Best regards

Manuel

 

2 replies

mƎALLEm
Technical Moderator
March 28, 2025

Hello,

First, please use </> button to share your code. See this link. (I've edited your post).

Second, according to the description of the PEA bit it might be not intended to signal a lost of arbitration but to signal a protocol error that occurred during the arbitration phase:

mALLEm_0-1743160958725.png

I may ask internally and get back to you as soon as I have an answer. Internal ticket 206406 has been submitted (not accessible by the community users).

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
MFrie.7
MFrie.7Author
Associate II
March 31, 2025

Hello,

Thank you for your reply and opening an internal ticket.

In the reference manual I see an other possible solution for this problem, but I can't get it to work:

 

MFrie7_1-1743420478858.png

I check TXBTO and TXBFC for a lost of the arbitration contest like this:

 if (TXBFC & ~TXBTO) 
 {
 ...

The problem with this is, that I now count to much lost of arbitration contest. Perhaps I need to trigger TXBRP from 1 to 0? I have not found a way (Interrupt) for that.

mƎALLEm
Technical Moderator
April 2, 2025

I don't think this is an efficient way as it's not exclusively to signal the loss of the arbitration but also an issue in transmission. 

mALLEm_0-1743583470032.png

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
Technical Moderator
March 28, 2025

Hello @MFrie.7 

For better debugging, please ensure that the return value retVal is equal to HAL_OK when calling the HAL functions.

 retVal = HAL_FDCAN_ActivateNotification(m_Fdcan2Handle, FDCAN_IT_ARB_PROTOCOL_ERROR, 0);
 if (retVal != HAL_OK)
 {
 // Error handler
 }

 

"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.Saket_Om"