Hi,
i have a problem with my eCAN interrupt service routine (mailbox 0 to 30 are receive mailbox, while mailbox 31 is a transmit mailbox):
interrupt void canISR(void)
{
struct ECAN_REGS ECanShadow;
ECanShadow.CANRMP.all = ECanaRegs.CANRMP.all;
ECanShadow.CANTA.all = ECanaRegs.CANTA.all;
ECanShadow.CANGIF0.all = ECanaRegs.CANGIF0.all;
if (!ECanShadow.CANGIF0.bit.GMIF0)
{
// ... do something
// clear all system interrupts flag
ECanaRegs.CANGIF0.all = ECanShadow.CANGIF0.all;
// Acknowledge interrupt to recieve more interrupts from PIE group 9
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;
return;
}
const Uint16 mailBoxNum = ECanShadow.CANGIF0.bit.MIV0;
if (mailBoxNum != 31)
{
// ... do something
}
else
{
ECanaRegs.CANTA.all = ECanShadow.CANTA.all; // this should clear ECanaRegs.CANTA.bit.TA31
}
// Acknowledge interrupt to recieve more interrupts from PIE group 9
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;
}
It works fine almost always but in some rare cases CANTA.TA31 is not properly cleared, thus no other eCAN interrupt is ever triggered.
I've found out that when this happens:
- the last triggered interrupt is actually a transmitting mailbox interrupt, in fact CANGIF0.MIV0 = 31 and CANTA.TA31 is set
- CANGIF0.GMIF0 is set and no other bit in CANGIF0 is set (actually, sometimes CANGIF0.TCOF is set too, but this should not trigger any interrupt since CANGIM.TCOM = 0)
- all can error registers are 0
- CANTA.TA31 is still set after the assignment ECanaRegs.CANTA.all = ECanShadow.CANTA.all, which is supposed to clear it.
Furthermore, I'm pretty sure that no one starts trasmitting a message while the previous trasmission is still pending, so i guess that for no reason the eCAN module should set TA31 at the same time the cpu is trying to clear it
I haven't been able to reproduce this issue at will.
The following workaround seems to work fine:
ECanaRegs.CANTA.all = ECanShadow.CANTA.all; do { ECanShadow.CANTA.all = ECanaRegs.CANTA.all; if (ECanShadow.CANTA.all) { ECanaRegs.CANTA.all = ECanShadow.CANTA.all; } } while (ECanShadow.CANTA.all);
Has someone ever encountered an issue like this? Am i missing something?
Thanks!