This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28069: eCAN transmit ack bit still set after being cleared

Part Number: TMS320F28069


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!