I’m trying to use the VF61 CAN port with interrupt handlers.
The Toradex CAN demo (polling method) works fine, so I started from this demo and add interupt initialization and a thread to attend the CAN reception event.
The problem is that in Rx thread WaitForSingleObject never captures that event.
Thank you for your support.
Sample code:
#include "stdafx.h"
#include "int_vyb.h"
#include "int.h"
#include "can_vyb.h"
HANDLE hCan;
HANDLE hIntr = NULL;
HANDLE hEvent;
HANDLE hIrqThread;
BOOL threadStatus = 1;
void CanRxProcess(DWORD *sysirq);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hCan = NULL;
BOOL returnValue = FALSE;
DWORD sysIrq;
// Initialize CAN without affecting hardware registers
hCan = VybCan_Init(L"CAN2");
if (hCan == NULL)
{
printf("Error in CAN initialization\r\n");
return 0;
}
returnValue = VybCan_SetConfigString(hCan, L"Implementation", L"FlexCAN", StoreToRegistry);
returnValue = VybCan_SetConfigString(hCan, L"Interface", L"CAN2", StoreToRegistry);
returnValue = VybCan_SetConfigString(hCan, L"FrameFormat", L"extended", StoreToRegistry);
returnValue = VybCan_SetConfigString(hCan, L"FilterRemote", L"none", StoreToRegistry);
returnValue = VybCan_SetConfigString(hCan, L"RtrFormat", L"data", StoreToRegistry);
returnValue = VybCan_SetConfigInt(hCan, L"FilterID", 0x00, StoreToRegistry);
returnValue = VybCan_SetConfigInt(hCan, L"FilterMask", 0x00, StoreToRegistry);
returnValue = VybCan_SetConfigInt(hCan, L"BitRateHz", 250000, StoreVolatile);
returnValue = VybCan_SetConfigInt(hCan, L"Timeout", 5000, StoreVolatile);
if (!VybCan_Open(hCan))
{
printf("CAN Rx Open failed\r\n");
return 0;
}
// Create an Event
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent == NULL)
{
printf("ERROR:: Create Event failed number %d\r\n", GetLastError());
return -1;
}
// Initialize interrupt Library
hIntr = Int_Init();
if (hIntr == NULL)
{
printf("ERROR:: interrupt init function");
return 0;
}
// Get the system interrupt for the corresponding Irq number
sysIrq = Int_RequestSysInterrupt(hIntr, IRQ_FlexCAN1);
// Initialize interrupt
BOOL result = Int_InterruptInitialize(hIntr, sysIrq, hEvent, NULL, 0);
// Create thread to handle Interrupt event
hIrqThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)CanRxProcess, &sysIrq, 0, NULL);
printf("\nPress enter to exit\r\n");
fflush(stdin);
getchar();
threadStatus = 0;
Sleep(1000);
VybCan_Close(hCan);
Int_InterruptDisable(hIntr, sysIrq);
Int_ReleaseSysIntr(hIntr, sysIrq);
Int_Deinit(hIntr);
return 0;
}
//*****************************************************************************
/// CAN receive process
void CanRxProcess(DWORD *sysirq)
{
tCanMsg canBuf;
DWORD returnValue, lpdwExitCode;
BYTE data[8] = {0}; // Rx buffer
canBuf.dataLen = 8;
while (threadStatus)
{
DWORD waitHandleResult = WaitForSingleObject(hEvent, 5000);
switch(waitHandleResult)
{
case WAIT_OBJECT_0:
returnValue = VybCan_Read(hCan, &canBuf);
if ((returnValue > 0) && (returnValue != -1))
{
printf("CAN Receive: Frame ID = %x, %x Remote/Data Frame = %s\n", canBuf.id, canBuf.canMsgFlags, (canBuf.canMsgFlags & CanMsgFlags_RTR ? "REMOTE" : "DATA"));
// display received data
if ((canBuf.canMsgFlags & CanMsgFlags_RTR) == 0)
{
printf("Data:");
for (int i = 0; i < 8; i++)
{
printf(" %d", canBuf.data[i]);
}
}
}
else
{
printf("CAN Receive error\r\n");
}
Int_InterruptDone(hIntr, *sysirq);
break;
default:
printf("No data\r\n");
break;
}
}
printf("Close Thread \r\n");
if (hIrqThread != NULL)
{
GetExitCodeThread(hIrqThread, &lpdwExitCode);
// Exit Thread
ExitThread(lpdwExitCode);
hIrqThread = NULL;
}
}