CHANGED: - canSend message parameter is now a const pointer
authorChristian Taedcke
Wed, 10 Nov 2010 13:08:26 +0100
changeset 655 ea1ddcc77acf
parent 654 fc9af616633d
child 656 f923456f01e5
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
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<VCI_CAN_OBJ> 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)