# HG changeset patch # User Christian Taedcke # Date 1289390906 -3600 # Node ID ea1ddcc77acf51ef5b880d6ea6a9b0944d569d20 # Parent fc9af616633d9cc13396d92b3aac998615d70422 CHANGED: - canSend message parameter is now a const pointer ADDED : - IXXAT specific can bus watchdog to restart the VCI2 driver if a bus off, data ovverrun or remote queue overrun is detected. The can adapter cannot recover on its own. * * * CHANGED: - IXXAT::m_watchdogTimerId from DWORD to UINT_PTR to fix compiler warning diff -r fc9af616633d -r ea1ddcc77acf drivers/can_ixxat_win32/ixxat.cpp --- a/drivers/can_ixxat_win32/ixxat.cpp Thu Jan 27 17:45:48 2011 +0100 +++ b/drivers/can_ixxat_win32/ixxat.cpp Wed Nov 10 13:08:26 2010 +0100 @@ -57,8 +57,6 @@ #include "VCI2.h" #include "async_access_que.h" -#pragma warning(disable:4996) - #define CAN_NUM 0 class IXXAT @@ -80,16 +78,31 @@ static void VCI_CALLBACKATTR receive_queuedata_handler(UINT16 que_hdl, UINT16 count, VCI_CAN_OBJ* p_obj); static void VCI_CALLBACKATTR exception_handler(VCI_FUNC_NUM func_num, INT32 err_code, UINT16 ext_err, char* err_str); + static void CALLBACK canBusWatchdog(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime); + void watchdog(); private: UINT16 m_BoardHdl; UINT16 m_TxQueHdl; UINT16 m_RxQueHdl; async_access_que m_RX_Que; static IXXAT* m_callbackPtr; + static UINT_PTR m_watchdogTimerId; + static const unsigned int CAN_BUS_WATCHDOG_INTERVAL_MSEC = 10000; + + /** Bitmask inside sts from VCI_ReadCanStatus() that defines the can bus off state.*/ + static const unsigned char STS_CAN_BUS_OFF = 0x80; + + /** Bitmask inside sts from VCI_ReadCanStatus() that defines the can data overrun state.*/ + static const unsigned char STS_CAN_DATA_OVERRUN = 0x20; + + /** Bitmask inside sts from VCI_ReadCanStatus() that defines the remote queue overrun state.*/ + static const unsigned char STS_REMOTE_QUEUE_OVERRUN = 0x04; }; IXXAT *IXXAT::m_callbackPtr = NULL; +UINT_PTR IXXAT::m_watchdogTimerId = 0; + IXXAT::IXXAT(s_BOARD *board) : m_BoardHdl(0xFFFF), m_TxQueHdl(0xFFFF), m_RxQueHdl(0xFFFF) @@ -214,13 +227,16 @@ res = VCI_ConfigQueue(m_BoardHdl, CAN_NUM, VCI_TX_QUE, 100 , 0, 0, 0, &m_TxQueHdl); // definition of Receive Queue (interrupt mode) - res = VCI_ConfigQueue(m_BoardHdl, CAN_NUM, VCI_RX_QUE, 50, 1, 0, 100, &m_RxQueHdl); + res = VCI_ConfigQueue(m_BoardHdl, CAN_NUM, VCI_RX_QUE, 500, 1, 0, 100, &m_RxQueHdl); // assign the all IDs to the Receive Queue res = VCI_AssignRxQueObj(m_BoardHdl, m_RxQueHdl ,VCI_ACCEPT, 0, 0) ; // And now start the CAN res = VCI_StartCan(m_BoardHdl, CAN_NUM); + + //Start CAN Bus-Off watchdog + m_watchdogTimerId = SetTimer(NULL, NULL, IXXAT::CAN_BUS_WATCHDOG_INTERVAL_MSEC, IXXAT::canBusWatchdog); return true; } @@ -294,6 +310,60 @@ ::OutputDebugString(buf); } + void IXXAT::watchdog() + { + VCI_CAN_STS sts; + long res = VCI_ReadCanStatus(m_BoardHdl, CAN_NUM, &sts); + + if (res < 0) + { + char buf[200]; + ::sprintf(buf, "\nIXXAT canBusWatchdog: ERROR: Reading the can state failed!\n"); + ::OutputDebugString(buf); + } + else + { + if (sts.sts & (STS_CAN_BUS_OFF | STS_CAN_DATA_OVERRUN | STS_REMOTE_QUEUE_OVERRUN)) + { + if (sts.sts & STS_CAN_BUS_OFF) + { + ::OutputDebugString("\nIXXAT canBusWatchdog: CAN bus off detected!\n"); + } + if (sts.sts & STS_CAN_DATA_OVERRUN) + { + ::OutputDebugString("\nIXXAT canBusWatchdog: CAN data overrun detected!\n"); + } + if (sts.sts & STS_REMOTE_QUEUE_OVERRUN) + { + ::OutputDebugString("\nIXXAT canBusWatchdog: Remote queue overrun detected!\n"); + } + + if (VCI_ResetCan(m_BoardHdl, CAN_NUM) < 0) + { + ::OutputDebugString("\nIXXAT canBusWatchdog: ERROR: Resetting the can module failed!\n"); + } + + if (VCI_StartCan(m_BoardHdl, CAN_NUM) < 0) + { + ::OutputDebugString("\nIXXAT canBusWatchdog: ERROR: Restaring the can module failed!\n"); + } + } + } + + if (SetTimer(NULL, m_watchdogTimerId, IXXAT::CAN_BUS_WATCHDOG_INTERVAL_MSEC, IXXAT::canBusWatchdog) == 0) + { + char buf[200]; + ::sprintf(buf, "\nIXXAT canBusWatchdog: ERROR: Creation of the watchdog timer failed!\n"); + ::OutputDebugString(buf); + } + } + +void CALLBACK IXXAT::canBusWatchdog(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime) +{ + if (m_callbackPtr != NULL) + m_callbackPtr->watchdog(); +} + //------------------------------------------------------------------------ extern "C" UNS8 __stdcall canReceive_driver(CAN_HANDLE inst, Message *m)