Skip to main content
Visitor 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

    This topic has been closed for replies.
    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

    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).

    MFrie.7Author
    Visitor 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.

    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

     

    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
     }