Hello,
We have lately had some strange CAN-frame problems. About once every 50 hour we lose one or several CAN-frames. Sometimes also erroneous data is received in the CAN-messageboxes.
We have a MPC5554 Controller with a FlexCAN2-module
We have three tasks which may access the messageboxes:
1. OS scheduled periodic polling and transmitting-function
2. Interrupt-handled polling function
3. Transmitting function of sporadic messages
We have set up 16 messageboxes for our three CAN-modules:
0-3 : Transmit messageboxes
4-13 : Periodically polled messageboxes
14-15 : Interrupt-handled RX-messageboxed
We suspect that when two or three of these taskes at the same time are accessing the registers of the CAN-module, this could result in unpredicable behaviour.
The tasks are implemented as follows:
1. OS scheduled periodic polling and transmitting-function:
For all CAN-modules:
For all messageboxes 4-13 (mbuff) where flags raised :
busy = 1;
while (busy)
{
dummy = mbuff->CS.B.CODE; // locks MB
busy = (uint8)(0x1 & dummy);
}
canID = mbuff->ID;
length = mbuff->CS.B.LENGTH;
memcpy(data, (uint8*)mbuff->DATA.B, length);
dummy = touCan->TIMER.R; // releases lock of MB
For all messages in TX-queue (use mbuff 0-3):
mbuff->CS.B.CODE = CANHW_CODE_TX_NOT_READY; // code 1000
mbuff->CS.B.LENGTH = size;
mbuff->ID = canId;
memcpy((U8 *) mbuff->DATA.B, data, size);
mbuff->CS.B.CODE = CANHW_CODE_TX_ONCE; // code 1100
2. Interrupt-handled periodic polling function:
For all flags raised in MB 14-15 (mbuff) of the current CAN-module:
busy = 1;
while (busy)
{
dummy = mbuff->CS.B.CODE; // locks MB
busy = (uint8)(0x1 & dummy);
}
canID = mbuff->ID;
length = mbuff->CS.B.LENGTH;
memcpy(data, (uint8*)mbuff->DATA.B, length);
dummy = touCan->TIMER.R; // releases lock of MB
3. Transmitting function of sporadic messages:
Stop_Interrupts();
mbuff->CS.B.CODE = CANHW_CODE_TX_NOT_READY; // code 1000
mbuff->CS.B.LENGTH = size;
mbuff->ID = canId;
memcpy((U8 *) mbuff->DATA.B, data, size);
mbuff->CS.B.CODE = CANHW_CODE_TX_ONCE; // code 1100
Enable_Interrupts();
What can happen if we have locked an MB and then an interrupt is raised resulting in handling of interrupt-handled messageboxes. After the interrupt-routine we return to the periodic polled function and start reading from a Messagebox which is not locked. What can happen? Can this result in lost CAN-frames or erroneous received CAN-frames?
Our errors occur for both periodically received CAN-frames and interrupt-handled CAN-frames.
Best regards
Peter Pap
I do not have exactly your setup, but the behaviour you describe looks like a race condition.
Especially the definition of 'busy': It looks like a global/function-static variable shared with the ISR;
if it is, you have a race-condition built-in, otherwise you could just as well have written
while (mbuff->CS.B.CODE & 0x01); // Locks MB
Also, the "sporadic messages" block the interrupts, but if the "OS scheduled periodic polling and
transmitting" can be interrupted by the "sporadic messages" (round-robin or priority-driven scheduling),
chances are that the same message buffer is then overwritten, and after enabling the interrupts again,
the "OS scheduled" will resume its writing of the buffer, probably resulting in garbage.
For a more detailed analysis, more coding details would be required, though.
HTH,
Johan