From 1d48c1d7a5a4fd3153cc7cab2949d51cbabba3d8 Mon Sep 17 00:00:00 2001
From: armar-user <armar6@kit.edu>
Date: Mon, 16 Dec 2019 14:25:18 +0100
Subject: [PATCH] fixed several bugs in EtherCAT::readErrorCounters()

---
 .../libraries/ArmarXEtherCAT/EtherCAT.cpp     | 59 ++++++++++++-------
 .../libraries/ArmarXEtherCAT/EtherCAT.h       |  3 +-
 .../ArmarXEtherCAT/EtherCATRTUnit.cpp         |  1 +
 3 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.cpp b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.cpp
index 76552f55e..4e03cce5d 100644
--- a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.cpp
+++ b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.cpp
@@ -705,7 +705,7 @@ void EtherCAT::printALStatusError(uint16_t slave)
 {
     std::string name = "Unknown";
 
-    AbstractSlavePtr slavePtr =  getSlaveAtId(slave);
+    AbstractSlavePtr slavePtr =  getSlaveAtIndex(slave);
     if (slavePtr)
     {
         name = slavePtr->getSlaveIdentifier().humanName;
@@ -717,6 +717,19 @@ void EtherCAT::printALStatusError(uint16_t slave)
                  << ", name: " << ec_slave[slave].name;
 }
 
+int EtherCAT::ecx_APRD_with_error_handling(uint16_t ADP, uint16_t ADO, uint16_t length, void* data, int timeout, uint16_t slaveIndex, const std::string& name, int port)
+{
+    int retval = ecx_APRD(ecx_context.port, ADP, ADO, length, data, timeout);
+    if (retval <= 0)
+    {
+        std::stringstream ss;
+        ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << ADO;
+        ARMARX_ERROR << "ecx_APRD failed: WC = " << retval << " (-1: EC_NOFRAME) . Slavenumber " << slaveIndex << "\tname: " << name << "\tport:" << port
+                     << "\taddr: " << ss.str();
+    }
+    return retval;
+}
+
 void EtherCAT::readErrorCounters()
 {
     IceUtil::Time start = IceUtil::Time::now(IceUtil::Time::Monotonic);
@@ -724,39 +737,45 @@ void EtherCAT::readErrorCounters()
     {
         std::string name = "Unknown";
 
-        AbstractSlavePtr slavePtr =  getSlaveAtId(slaveIndex);
+        AbstractSlavePtr slavePtr =  getSlaveAtIndex(slaveIndex);
         if (slavePtr)
         {
             name = slavePtr->getSlaveIdentifier().humanName;
         }
 
-        auto ADPh = (uint16)(1 - slaveIndex);
-        uint16_t configAddr = ecx_APRDw(ecx_context.port, ADPh, ECT_REG_STADR, 100000);
+        uint16 ADPh = (uint16)(1 - slaveIndex);
+
+        //not used, only confusing info...
+        //uint16_t configAddr = ecx_APRDw(ecx_context.port, ADPh, ECT_REG_STADR, 100000);
         for (int i = 0; i < 4; i++)
         {
 
             // Error handling taken from
             // https://www.ethercat.org/download/documents/EtherCAT_Diagnosis_For_Users_DE.pdf
             // or Armar6RT/etc/doc/EtherCAT_Diagnosis_For_Users_DE.pdf
-            uint8_t rxError;
-            uint8_t invalidFrameCounter; // or Physical error count
-            uint8_t previousErrorCounter; // shows the error counter of a predecessor
-            uint8_t linkLostCounter;
-            ecx_APRD(ecx_context.port, ADPh, 0x300 + i * 2, 1, &rxError, 100000);
-            ecx_APRD(ecx_context.port, ADPh, 0x301 + i * 2, 1, &invalidFrameCounter, 100000);
-            ecx_APRD(ecx_context.port, ADPh, 0x308 + i, 1, &previousErrorCounter, 100000);
-            ecx_APRD(ecx_context.port, ADPh, 0x310 + i, 1, &linkLostCounter, 100000);
-            if (rxError > 0 || invalidFrameCounter > 0 || previousErrorCounter > 0 || linkLostCounter > 0)
+            uint8_t rxErrorCounter = 0;
+            uint8_t invalidFrameCounter = 0; // or Physical error count
+            uint8_t forwardedRxErrorCounter = 0; // shows the error counter of a predecessor
+            uint8_t linkLostCounter = 0;
+            int ret1 = ecx_APRD_with_error_handling(ADPh, 0x300 + i * 2, 1, &invalidFrameCounter, 100000, slaveIndex, name, i);
+            int ret2 = ecx_APRD_with_error_handling(ADPh, 0x301 + i * 2, 1, &rxErrorCounter, 100000, slaveIndex, name, i);
+            int ret3 = ecx_APRD_with_error_handling(ADPh, 0x308 + i, 1, &forwardedRxErrorCounter, 100000, slaveIndex, name, i);
+            int ret4 = ecx_APRD_with_error_handling(ADPh, 0x310 + i, 1, &linkLostCounter, 100000, slaveIndex, name, i);
+
+            if (rxErrorCounter > 0 || invalidFrameCounter > 0 || forwardedRxErrorCounter > 0 || linkLostCounter > 0)
+            {
+                ARMARX_ERROR << "Errors found for Slavenumber " << slaveIndex << "\tname: " << name << "\tport:" << i << ": "
+                             << VAROUT((int)rxErrorCounter) << "\t" << VAROUT((int)invalidFrameCounter) << "\t" << VAROUT((int)forwardedRxErrorCounter) << "\t" << VAROUT((int)linkLostCounter);
+            }
+            else if (ret1 > 0 && ret2 > 0 && ret3 > 0 && ret4 > 0)
             {
-                ARMARX_ERROR << "non zero frame error counter found: Slavenumber " << slaveIndex << "\tname: " << name
-                             << "\tconfig addr: " << (int)configAddr << ":  port " << i << ": "
-                             << VAROUT((int)rxError) << "\t" << VAROUT((int)invalidFrameCounter) << "\t" << VAROUT((int)previousErrorCounter) << "\t" << VAROUT((int)linkLostCounter);
+                ARMARX_INFO << "no errors for Slavenumber " << slaveIndex << "\tname: " << name << "\tport:" << i;
             }
         }
         if ((IceUtil::Time::now(IceUtil::Time::Monotonic) - start).toMilliSeconds() > 10)
         {
             updatePDO();
-            ARMARX_RT_LOGF_INFO("Updated BUS to prevent timeout").deactivateSpam(1);
+            ARMARX_RT_LOGF_INFO("Updated BUS to prevent timeout");
             start = IceUtil::Time::now(IceUtil::Time::Monotonic);
         }
     }
@@ -902,7 +921,7 @@ void EtherCAT::errorHandling()
         ec_errort error;
         while (ec_poperror(&error))
         {
-            auto slave = getSlaveAtId(error.Slave);
+            auto slave = getSlaveAtIndex(error.Slave);
             if (error.Etype == EC_ERR_TYPE_EMERGENCY)
             {
                 ARMARX_RT_LOGF_WARN("Found emergency error for slave %s (id: %d) from timestamp %d: error code: %d, error reg: %d, error index: %d, error sub index: %d",
@@ -1442,12 +1461,12 @@ int EtherCAT::getMappedSize()
     return actualMappedSize;
 }
 
-AbstractSlavePtr EtherCAT::getSlaveAtId(uint16_t slaveId) const
+AbstractSlavePtr EtherCAT::getSlaveAtIndex(uint16_t slaveIndex) const
 {
     for (AbstractSlavePtr slave : slaves)
     {
         //        ARMARX_INFO << "Checking slave: " << slave->getSlaveNumber() << " vs  " << slaveId;
-        if (slave->getSlaveNumber() == slaveId)
+        if (slave->getSlaveNumber() == slaveIndex)
         {
             return slave;
         }
diff --git a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.h b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.h
index 9e283b596..e5c4317bf 100644
--- a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.h
+++ b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCAT.h
@@ -82,7 +82,7 @@ namespace armarx
         std::array<char, IOmapSize>& getIOMapBuffer();
 
         int getMappedSize();
-        AbstractSlavePtr getSlaveAtId(uint16_t slaveId) const;
+        AbstractSlavePtr getSlaveAtIndex(uint16_t slaveIndex) const;
         std::vector<AbstractSlavePtr> getSlaves();
 
         bool getProductCode(uint16_t slave, uint32_t& productCode) const;
@@ -154,6 +154,7 @@ namespace armarx
     protected:
         void readErrorCounters();
 
+        int ecx_APRD_with_error_handling(uint16_t ADP, uint16_t ADO, uint16_t length, void* data, int timeout, uint16_t slaveIndex, const std::string& name, int port);
     private:
         //Hiding the constructor to avoid illegal creation of the Bus (singelton pattern)
         EtherCAT();
diff --git a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCATRTUnit.cpp b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCATRTUnit.cpp
index 7a2f418f4..fb6c0946d 100644
--- a/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCATRTUnit.cpp
+++ b/source/RobotAPI/libraries/ArmarXEtherCAT/EtherCATRTUnit.cpp
@@ -126,6 +126,7 @@ void EtherCATRTUnit::onInitRobotUnit()
     EtherCAT& bus = EtherCAT::getBus();
     bus.setMainUnitPtr(this);
     bus.setDeviceContainerPtr(deviceContainerPtr);
+    bus.setCheckErrorCountersOnWKCError(getProperty<bool>("checkErrorCountersOnEtherCATError").getValue());
 
 }
 
-- 
GitLab