Using Vybrid FlexCAN with Interrupts

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;
	}
}

This interrupts are already used by the driver. If you would like to use interrupt based CAN than you would need to write driver on your own. Do you see any limitations with polling messages?

I will try to make it work with polling method.
Thank you