fsl_mcan driver dropping interrupts bug

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

fsl_mcan driver dropping interrupts bug

1,342 Views
tomasxvavra
Contributor I

Hello, I think that there is a severe bug in fsl_mcan.c driver (SDK2.6.0). I am using LPC54618 dev kit.

Function MCAN_TransferHandleIRQ clears all interrupt flags insted of only the "solved ones". If there are simultanous interrupts pending, then only one gets processed and others are ignored.

Problematic part is MCAN_ClearStatusFlag(base, result);

void MCAN_TransferHandleIRQ(CAN_Type *base, mcan_handle_t *handle)
{
    /* Assertion. */
    assert(NULL != handle);

    status_t status = kStatus_MCAN_UnHandled;
    uint32_t result;

    /* Store Current MCAN Module Error and Status. */
    result = base->IR;

    do
    {
        /* Solve Rx FIFO, Tx interrupt. */
        if (result & kMCAN_TxTransmitCompleteFlag)
        {
            status = kStatus_MCAN_TxIdle;
            MCAN_TransferAbortSend(base, handle, handle->txbufferIdx);
        }
        else if (result & kMCAN_RxFifo0NewFlag)
        {
            MCAN_ReadRxFifo(base, 0U, handle->rxFifoFrameBuf);
            status = kStatus_MCAN_RxFifo0Idle;
            MCAN_TransferAbortReceiveFifo(base, 0U, handle);
        }
        else if (result & kMCAN_RxFifo0LostFlag)
        {
            status = kStatus_MCAN_RxFifo0Lost;
        }
        else if (result & kMCAN_RxFifo1NewFlag)
        {
            MCAN_ReadRxFifo(base, 1U, handle->rxFifoFrameBuf);
            status = kStatus_MCAN_RxFifo1Idle;
            MCAN_TransferAbortReceiveFifo(base, 1U, handle);
        }
        else if (result & kMCAN_RxFifo1LostFlag)
        {
            status = kStatus_MCAN_RxFifo0Lost;
        }
        else
        {
            ;
        }

        /* Clear resolved Rx FIFO, Tx Buffer IRQ. */
        MCAN_ClearStatusFlag(base, result);

        /* Calling Callback Function if has one. */
        if (handle->callback != NULL)
        {
            handle->callback(base, handle, status, result, handle->userData);
        }

        /* Reset return status */
        status = kStatus_MCAN_UnHandled;

        /* Store Current MCAN Module Error and Status. */
        result = base->IR;
    } while ((0U != MCAN_GetStatusFlag(base, 0xFFFFFFFFU)) ||
             (0U != (result & (kMCAN_ErrorWarningIntFlag | kMCAN_BusOffIntFlag | kMCAN_ErrorPassiveIntFlag))));
}

Following modified code works correctly.

void MCAN_TransferHandleIRQ(CAN_Type *base, mcan_handle_t *handle)
{
    /* Assertion. */
    assert(NULL != handle);

    enum _mcan_status status = kStatus_MCAN_UnHandled;
    uint32_t interruptReq;
    uint32_t interruptReqHandled;

    /* Store Current MCAN Module Error and Status. */
    interruptReq = base->IR;

    //assert(interruptReq != 0);

    do
    {
        interruptReqHandled = 0;

        /* Solve Rx FIFO, Tx interrupt. */
        if (interruptReq & kMCAN_TxTransmitCompleteFlag)
        {
            interruptReqHandled = kMCAN_TxTransmitCompleteFlag;
            status = kStatus_MCAN_TxIdle;
            MCAN_TransferAbortSend(base, handle, handle->txbufferIdx);
        }
        else if (interruptReq & kMCAN_RxFifo0NewFlag)
        {
            interruptReqHandled = kMCAN_RxFifo0NewFlag;
            MCAN_ReadRxFifo(base, 0U, handle->rxFifoFrameBuf);
            status = kStatus_MCAN_RxFifo0Idle;
            MCAN_TransferAbortReceiveFifo(base, 0U, handle);
        }
        else if (interruptReq & kMCAN_RxFifo0LostFlag)
        {
            interruptReqHandled = kMCAN_RxFifo0LostFlag;
            status = kStatus_MCAN_RxFifo0Lost;
        }
        else if (interruptReq & kMCAN_RxFifo1NewFlag)
        {
            interruptReqHandled = kMCAN_RxFifo1NewFlag;
            MCAN_ReadRxFifo(base, 1U, handle->rxFifoFrameBuf);
            status = kStatus_MCAN_RxFifo1Idle;
            MCAN_TransferAbortReceiveFifo(base, 1U, handle);
        }
        else if (interruptReq & kMCAN_RxFifo1LostFlag)
        {
            interruptReqHandled = kMCAN_RxFifo1LostFlag;
            status = kStatus_MCAN_RxFifo0Lost;
        }
        else
        {
            interruptReqHandled = interruptReq;
        }

        /* Clear resolved Rx FIFO, Tx Buffer IRQ. */
        MCAN_ClearStatusFlag(base, interruptReqHandled);

        /* Calling Callback Function if has one. */
        if (handle->callback != NULL)
        {
            handle->callback(base, handle, status, interruptReq, handle->userData);
        }

        /* Reset return status */
        status = kStatus_MCAN_UnHandled;

        /* Store Current MCAN Module Error and Status. */
        interruptReq = base->IR;
    } while ((0U != MCAN_GetStatusFlag(base, 0xFFFFFFFFU)) ||
             (0U != (interruptReq & (kMCAN_ErrorWarningIntFlag | kMCAN_BusOffIntFlag | kMCAN_ErrorPassiveIntFlag))));
}
Labels (1)
0 Kudos
9 Replies

1,119 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Tomas Vavra 

This issue will be fixed in next SDK release v2.7.0.

Thanks for bringing the problem to our attention.


Have a great day,
Jun Zhang

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,119 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

HI Teus Verbeek

Tomas Vavra's issue has been reported internally.

Could you please create a new thread for your issue. We need separate the different issue for better track.

Thanks.

Jun Zhang 

0 Kudos

1,118 Views
teus
Contributor I

We have an issue that is very simular to this one. What is looks like is that we are missing Tx interrupts in the same handler. 

This results in a crash in the fsl_mcan which can only be recoverd by setting TXBAR register to 1. Then it runs for a while and it stops sending CAN messages again.

We are working with a LPC54608. 

0 Kudos

1,119 Views
tomasxvavra
Contributor I

If you use my code of MCAN_TransferHandleIRQ, does it change anything for you?

0 Kudos

1,119 Views
teus
Contributor I

We did not measure any difference. Maybe it is because we already have the following construction in the Rx handler.

pastedImage_1.png

The above code solves a lot of trouble with the receiving part of the driver. But now (a few months later) the transmitting part is giving trouble.

We added a simular construction to the Tx handling:

pastedImage_2.png

This construction takes on a fraction longer but also crashes after a while.

0 Kudos

1,119 Views
teus
Contributor I

We also see after some testing that the handler is called and the interruptReq stays zero. The same scenario Tomas captured in the  assert.  

pastedImage_2.png

But if we place a breakpoint after the copy we see that the IR register contains some interrupts.

0 Kudos

1,119 Views
tomasxvavra
Contributor I

Yes, this is another issue I have been also investigating but didn't found anything.. Iterrupt handler is called and IR register is zero, I have no idea how could this be happening.

0 Kudos

1,119 Views
tomasxvavra
Contributor I

Is original standalone mcan driver for LPC546xx (can.c) from NXP better? I am finding that SDK contains just too many bugs and its killing my productivity I used to have with NXP products..

0 Kudos

1,119 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Tomas.

Thanks for letting us know. I will feed back your findings to SDK development team. I will let you know if any update.

Have a nice day,

Jun Zhang

0 Kudos