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))));
}
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.
-------------------------------------------------------------------------------
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
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.
If you use my code of MCAN_TransferHandleIRQ, does it change anything for you?
We did not measure any difference. Maybe it is because we already have the following construction in the Rx handler.
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:
This construction takes on a fraction longer but also crashes after a while.
We also see after some testing that the handler is called and the interruptReq stays zero. The same scenario Tomas captured in the assert.
But if we place a breakpoint after the copy we see that the IR register contains some interrupts.
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.
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..
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