Hi,
I set up a CAN receiver demo, based on the simple_rx.c example in TivaWare. Since I was losing messages, I am trying to add FIFO functionality, following the can_device_fifo.c example of StellarisWare. However, it seems no matter how hard I try, my FIFO fills up and I lose messages.
A minimal example to show what I'm having. It is based on TI's simple_rc.c example
void
CANIntHandler(void)
{
uint32_t ui32Status;
uint32_t ui32ErrStatus;
// Read the CAN interrupt status to find the cause of the interrupt
ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
UARTprintf("--> %u\n", ui32Status);
// If the cause is a controller status interrupt, then get the status
if(ui32Status == CAN_INT_INTID_STATUS)
{
ui32ErrStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
}
// Check if the cause is message object 1 to 8, which is the size of the FIFO that we are using for
// receiving messages.
else if(ui32Status <=8)
{
// Read message and clear the message object interrupt.
CANMessageGet(CAN0_BASE, ui32Status, &sCANMessage, 1);
if(sCANMessage.ui32Flags & MSG_OBJ_DATA_LOST)
{
UARTprintf("! ID=0x%08X %u\n", sCANMessage.ui32MsgID, ui32Status);
} else {
UARTprintf("ID=0x%08X %u\n", sCANMessage.ui32MsgID, ui32Status);
}
sCANMessage.ui32Flags = 0;
// Increment a counter to keep track of how many messages have been
// received. In a real application this could be used to set flags to
// indicate when a message is received.
g_ui32MsgCount++;
}
in the main loop I set up the FIFO using:
sCANMessage.ui32MsgID = 0;
sCANMessage.ui32MsgIDMask = 0;
sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_EXTENDED_ID | MSG_OBJ_FIFO;
sCANMessage.ui32MsgLen = 8;
for (ui32idx = 1; ui32idx<8; ui32idx++){
CANMessageSet(CAN0_BASE, ui32idx, &sCANMessage, MSG_OBJ_TYPE_RX);
}
// Last message object does not have the FIFO flag
sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_EXTENDED_ID;
CANMessageSet(CAN0_BASE, 8, &sCANMessage, MSG_OBJ_TYPE_RX);
The main loop does nothing anymore, just stays in endless for loop.
Running this code with a device connected on CAN0 gives some output:
--> 32768
--> 1
ID=0x00010007 1
--> 32768
--> 32768
--> 2
ID=0x00010009 2
--> 32768
--> 2
ID=0x00010007 2
--> 32768
--> 32768
--> 3
ID=0x00010009 3
--> 32768
--> 3
ID=0x00010007 3
--> 32768
--> 32768
--> 4
ID=0x00010009 4
--> 32768
--> 4
ID=0x00010007 4
--> 32768
--> 32768
--> 5
ID=0x00010009 5
--> 32768
--> 5
ID=0x10000000 5
--> 32768
--> 6
ID=0x10000001 6
--> 32768
--> 7
ID=0x10000002 7
--> 8
! ID=0x10000500 8
--> 32768
--> 6
ID=0x10000600 6
--> 32768
--> 6
ID=0x00010007 6
--> 32768
--> 32768
--> 7
ID=0x00010009 7
--> 32768
--> 7
ID=0x00010007 7
--> 32768
--> 32768
--> 8
! ID=0x00010009 8
--> 32768
--> 8
! ID=0x00010007 8
--> 32768
--> 32768
--> 8
! ID=0x00010009 8
I have two questions:
- You can see that the FIFO entries (1 to 8) fill up gradually, but never empties fast enough by the interrupt calls to CANGetMessage. Eventually I get message loss, indicated by the exclamation marks at the end.
I don't know how messages can be removed faster than calling CANGetMessage in the interrupt already, so why does the FIFO still fill up so fast?
- Also, lots of status interrupts are generated just for the sake of notifying an received message (RXOK). I wanted to avoid this by disabling CAN_INT_STATUS interrupts:
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
However, when I do that, I get "spurious" interrupts with ui32Status = 0. Why is that?