I am testing flexcan on colibri imx6 WinCE1.3b4 with Toradex CE Libraries v2.1 as customer also reports the same issue to us. The test code is based on Can_Demo application. Before entering ‘2’ to receive CAN frame, USB2CAN adapter on PC has sent 400 frames to imx6. Then input ‘2’, and the first read can frame’s ID is wrong as well as the data payload.
It can also happen if the gap of each frame is 1ms from USB2CAN adapter on PC meanwhile printing every frame received on iMX6(it is not easy to reproduce if only printing 500th frame instead of each one). Is it possible that the buffer in flexcan driver is overflow if Can_Read
is not called
timely when the frame gap is very small e.g. 1ms. CAN bus is critical task in this customer’s project, wrong frame ID is not accepted as this wrong id could be in valid range 29bit/11bit.
Here is the main code.
DWORD CanRxProcess(HANDLE hCan)
{
INT i;
tCanMsg canBuf = {0};
BYTE data[8] = {0}; // Rx buffer
DWORD busStatus;
INT j =0;
// Configure timeout to 5 sec, by default it is set to 1 sec
Can_SetConfigInt(hCan, L"Timeout", 5000, StoreVolatile); // optional
// 4. Use CAN
while(1)
{
canBuf.dataLen = 8;
if (Can_Read(hCan, &canBuf))
{
j++;
printf("\nCAN Receive: Frame ID = 0x%x, len %d, COUNT: %d\n", canBuf.id, canBuf.dataLen, j);
if(canBuf.id == 0x11)
{
}
else
{
//return 0;
printf("\nCAN Receive error, other ID found.\r\n");
printf("\nCAN Receive: Frame ID = 0x%x, len %d\n", canBuf.id, canBuf.dataLen);
for (i = 0; i<canBuf.dataLen; i++)
{
printf(" %d", canBuf.data[i]);
}
return 0;
}
}
else
{
printf("\nCAN Receive error\r\n");
Can_GetConfigInt(hCan, L"BusStatus", &busStatus);
printf("BusStatus %x\n",busStatus);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow)
{
HANDLE hCan = NULL;
BOOL isSelectionDone = FALSE;
INT selectedOption;
BOOL returnValue = FALSE;
DWORD busStatus;
UNREFERENCED_PARAMETER(instance);
UNREFERENCED_PARAMETER(prevInstance);
UNREFERENCED_PARAMETER(cmdLine);
UNREFERENCED_PARAMETER(cmdShow);
printf("Toradex CAN demo\r\n");
hCan = Can_Init(L"CAN1"); // Internal CAN
if (hCan == NULL)
{
printf("Error in CAN initialization\r\n");
return FALSE;
}
{
uIo ioRx = COLIBRI_PIN(63);
uIo ioTx = COLIBRI_PIN(55);
Can_SetConfigInt(hCan, L"ioRx", ioRx.GenericDefinition, StoreToRegistry);
Can_SetConfigInt(hCan, L"ioTx", ioTx.GenericDefinition, StoreToRegistry);
}
returnValue = Can_SetConfigString(hCan, L"FilterFrameFormat", L"None", StoreVolatile);
returnValue = Can_SetConfigString(hCan, L"FilterRemote", L"None", StoreVolatile);
returnValue = Can_SetConfigInt(hCan, L"FilterID", 0x00, StoreVolatile); //
returnValue = Can_SetConfigInt(hCan, L"FilterMask", 0x00, StoreVolatile); //
{
DWORD bitRate;
bitRate = 250000;
returnValue = Can_SetConfigInt(hCan, L"BitRateHz", bitRate, StoreVolatile);
}
if (!Can_Open(hCan))
{
printf("CAN Open failed\r\n");
Can_Deinit(hCan);
return 0;
}
returnValue = Can_GetConfigInt(hCan, L"BusStatus", &busStatus);
printf("BusStatus %x\n",busStatus);
do
{
printf("\nOptions:\n");
printf("1. CAN Transmit 2. CAN Receive 3. Quit\n\n");
printf("Choose the option and press Enter key: ");
scanf_s("%d", &selectedOption);
printf("\n");
switch (selectedOption)
{
case 1:
/// CAN Transmit
CanTxProcess(hCan);
break;
case 2:
/// CAN Receive
CanRxProcess(hCan);
break;
case 3:
/// Quits the demo
isSelectionDone = TRUE;
break;
default:
printf("Invalid entry, try again!\n\n");
isSelectionDone = FALSE;
}
} while (!isSelectionDone);
Can_Close(hCan);
Can_Deinit(hCan);
return(TRUE);
}