Introduced SdoCommand class to replace coe_datatypes.[ch]; added CoE abort codes in user space-
authorFlorian Pose <fp@igh-essen.com>
Fri, 01 Aug 2008 10:10:55 +0000
changeset 1184 75cd6681eb08
parent 1183 d77f634ab0b5
child 1185 337ce4fc2383
Introduced SdoCommand class to replace coe_datatypes.[ch]; added CoE abort codes in user space-
TODO
tool/CommandDownload.cpp
tool/CommandDownload.h
tool/CommandSdos.cpp
tool/CommandSdos.h
tool/CommandUpload.cpp
tool/CommandUpload.h
tool/Makefile.am
tool/MasterDevice.cpp
tool/MasterDevice.h
tool/SdoCommand.cpp
tool/SdoCommand.h
tool/coe_datatypes.cpp
tool/coe_datatypes.h
--- a/TODO	Fri Aug 01 09:32:35 2008 +0000
+++ b/TODO	Fri Aug 01 10:10:55 2008 +0000
@@ -8,11 +8,11 @@
 
 Version 1.4.0:
 
+* Abort code messages in userspace.
+* Repair rcethercat status.
 * Attach Pdo names from SII or Coe dictionary to Pdos read via CoE.
 * Update documentation.
-* Race in jiffies frame timeout?
-* Repair rcethercat status.
-* Abort code messages in userspace.
+* Check for possible race condition in jiffy-based frame timeout calculation.
 
 Future issues:
 
--- a/tool/CommandDownload.cpp	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandDownload.cpp	Fri Aug 01 10:10:55 2008 +0000
@@ -9,13 +9,12 @@
 using namespace std;
 
 #include "CommandDownload.h"
-#include "coe_datatypes.h"
 #include "byteorder.h"
 
 /*****************************************************************************/
 
 CommandDownload::CommandDownload():
-    Command("download", "Write an Sdo entry to a slave.")
+    SdoCommand("download", "Write an Sdo entry to a slave.")
 {
 }
 
@@ -66,7 +65,7 @@
     stringstream strIndex, strSubIndex, strValue, err;
     ec_ioctl_slave_sdo_download_t data;
     unsigned int number;
-    const CoEDataType *dataType = NULL;
+    const DataType *dataType = NULL;
     SlaveList slaves;
 
     if (args.size() != 3) {
@@ -207,6 +206,12 @@
 
 	try {
         m.sdoDownload(&data);
+	} catch (MasterDeviceSdoAbortException &e) {
+        delete [] data.data;
+        err << "Sdo transfer aborted with code 0x"
+            << setfill('0') << hex << setw(8) << e.abortCode
+            << ": " << abortText(e.abortCode);
+        throwCommandException(err);
 	} catch(MasterDeviceException &e) {
         delete [] data.data;
         throw e;
--- a/tool/CommandDownload.h	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandDownload.h	Fri Aug 01 10:10:55 2008 +0000
@@ -7,12 +7,12 @@
 #ifndef __COMMANDDOWNLOAD_H__
 #define __COMMANDDOWNLOAD_H__
 
-#include "Command.h"
+#include "SdoCommand.h"
 
 /****************************************************************************/
 
 class CommandDownload:
-    public Command
+    public SdoCommand
 {
     public:
         CommandDownload();
--- a/tool/CommandSdos.cpp	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandSdos.cpp	Fri Aug 01 10:10:55 2008 +0000
@@ -9,12 +9,11 @@
 using namespace std;
 
 #include "CommandSdos.h"
-#include "coe_datatypes.h"
 
 /*****************************************************************************/
 
 CommandSdos::CommandSdos():
-    Command("sdos", "List Sdo dictionaries.")
+    SdoCommand("sdos", "List Sdo dictionaries.")
 {
 }
 
@@ -83,7 +82,7 @@
     ec_ioctl_slave_sdo_t sdo;
     ec_ioctl_slave_sdo_entry_t entry;
     unsigned int i, j;
-    const CoEDataType *d;
+    const DataType *d;
     
     if (showHeader)
         cout << "=== Slave " << slave.position << " ===" << endl;
--- a/tool/CommandSdos.h	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandSdos.h	Fri Aug 01 10:10:55 2008 +0000
@@ -7,12 +7,12 @@
 #ifndef __COMMANDSDOS_H__
 #define __COMMANDSDOS_H__
 
-#include "Command.h"
+#include "SdoCommand.h"
 
 /****************************************************************************/
 
 class CommandSdos:
-    public Command
+    public SdoCommand
 {
     public:
         CommandSdos();
--- a/tool/CommandUpload.cpp	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandUpload.cpp	Fri Aug 01 10:10:55 2008 +0000
@@ -9,13 +9,12 @@
 using namespace std;
 
 #include "CommandUpload.h"
-#include "coe_datatypes.h"
 #include "byteorder.h"
 
 /*****************************************************************************/
 
 CommandUpload::CommandUpload():
-    Command("upload", "Read an Sdo entry from a slave.")
+    SdoCommand("upload", "Read an Sdo entry from a slave.")
 {
 }
 
@@ -66,7 +65,7 @@
     int sval;
     ec_ioctl_slave_sdo_upload_t data;
     unsigned int uval;
-    const CoEDataType *dataType = NULL;
+    const DataType *dataType = NULL;
 
     if (args.size() != 2) {
         err << "'" << getName() << "' takes two arguments!";
@@ -133,6 +132,12 @@
 
 	try {
 		m.sdoUpload(&data);
+	} catch (MasterDeviceSdoAbortException &e) {
+        delete [] data.target;
+        err << "Sdo transfer aborted with code 0x"
+            << setfill('0') << hex << setw(8) << e.abortCode
+            << ": " << abortText(e.abortCode);
+        throwCommandException(err);
 	} catch (MasterDeviceException &e) {
         delete [] data.target;
         throw e;
--- a/tool/CommandUpload.h	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/CommandUpload.h	Fri Aug 01 10:10:55 2008 +0000
@@ -7,12 +7,12 @@
 #ifndef __COMMANDUPLOAD_H__
 #define __COMMANDUPLOAD_H__
 
-#include "Command.h"
+#include "SdoCommand.h"
 
 /****************************************************************************/
 
 class CommandUpload:
-    public Command
+    public SdoCommand
 {
     public:
         CommandUpload();
--- a/tool/Makefile.am	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/Makefile.am	Fri Aug 01 10:10:55 2008 +0000
@@ -54,7 +54,7 @@
 	CommandVersion.cpp \
 	CommandXml.cpp \
 	MasterDevice.cpp \
-	coe_datatypes.cpp \
+	SdoCommand.cpp \
 	main.cpp \
 	sii_crc.cpp
 
@@ -77,8 +77,8 @@
 	CommandVersion.h \
 	CommandXml.h \
 	MasterDevice.h  \
+	SdoCommand.h \
 	byteorder.h \
-	coe_datatypes.h \
 	sii_crc.h
 
 REV = `if test -s $(srcdir)/../svnrevision; then \
--- a/tool/MasterDevice.cpp	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/MasterDevice.cpp	Fri Aug 01 10:10:55 2008 +0000
@@ -359,14 +359,12 @@
 {
     if (ioctl(fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, data) < 0) {
         stringstream err;
-        err << "Failed to download Sdo: ";
         if (errno == EIO && data->abort_code) {
-            err << "Abort code 0x" << hex << setfill('0')
-                << setw(8) << data->abort_code;
+            throw MasterDeviceSdoAbortException(data->abort_code);
         } else {
-            err << strerror(errno);
+            err << "Failed to download Sdo: " << strerror(errno);
+            throw MasterDeviceException(err);
         }
-        throw MasterDeviceException(err);
 	}
 }
 
@@ -376,14 +374,12 @@
 {
     if (ioctl(fd, EC_IOCTL_SLAVE_SDO_UPLOAD, data) < 0) {
         stringstream err;
-        err << "Failed to upload Sdo: ";
         if (errno == EIO && data->abort_code) {
-            err << "Abort code 0x" << hex << setfill('0')
-                << setw(8) << data->abort_code;
+            throw MasterDeviceSdoAbortException(data->abort_code);
         } else {
-            err << strerror(errno);
+            err << "Failed to upload Sdo: " << strerror(errno);
+            throw MasterDeviceException(err);
         }
-        throw MasterDeviceException(err);
     }
 }
 
--- a/tool/MasterDevice.h	Fri Aug 01 09:32:35 2008 +0000
+++ b/tool/MasterDevice.h	Fri Aug 01 10:10:55 2008 +0000
@@ -22,6 +22,11 @@
     friend class MasterDevice;
     
     protected:
+        /** Constructor with string parameter. */
+        MasterDeviceException(
+                const string &s /**< Message. */
+                ): runtime_error(s) {}
+
         /** Constructor with stringstream parameter. */
         MasterDeviceException(
                 const stringstream &s /**< Message. */
@@ -30,6 +35,24 @@
 
 /****************************************************************************/
 
+class MasterDeviceSdoAbortException:
+    public MasterDeviceException 
+{
+    friend class MasterDevice;
+
+    public:
+        uint32_t abortCode;
+    
+    protected:
+        /** Constructor with stringstream parameter. */
+        MasterDeviceSdoAbortException(uint32_t code):
+            MasterDeviceException("Sdo transfer aborted.") {
+                abortCode = code;
+            };
+};
+
+/****************************************************************************/
+
 class MasterDevice
 {
     public:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/SdoCommand.cpp	Fri Aug 01 10:10:55 2008 +0000
@@ -0,0 +1,116 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include "SdoCommand.h"
+
+/*****************************************************************************/
+
+SdoCommand::SdoCommand(const string &name, const string &briefDesc):
+    Command(name, briefDesc)
+{
+}
+
+/****************************************************************************/
+
+const SdoCommand::DataType *SdoCommand::findDataType(const string &str)
+{
+    const DataType *d;
+    
+    for (d = dataTypes; d->name; d++)
+        if (str == d->name)
+            return d;
+
+    return NULL;
+}
+
+/****************************************************************************/
+
+const SdoCommand::DataType *SdoCommand::findDataType(uint16_t code)
+{
+    const DataType *d;
+    
+    for (d = dataTypes; d->name; d++)
+        if (code == d->coeCode)
+            return d;
+
+    return NULL;
+}
+
+/****************************************************************************/
+
+const char *SdoCommand::abortText(uint32_t abortCode)
+{
+    const AbortMessage *abortMsg;
+
+    for (abortMsg = abortMessages; abortMsg->code; abortMsg++) {
+        if (abortMsg->code == abortCode) {
+            return abortMsg->message;
+        }
+    }
+
+    return "???";
+}
+
+/****************************************************************************/
+
+const SdoCommand::DataType SdoCommand::dataTypes[] = {
+    {"int8",   0x0002, 1},
+    {"int16",  0x0003, 2},
+    {"int32",  0x0004, 4},
+    {"uint8",  0x0005, 1},
+    {"uint16", 0x0006, 2},
+    {"uint32", 0x0007, 4},
+    {"string", 0x0009, 0},
+    {"raw",    0xffff, 0},
+    {}
+};
+
+/*****************************************************************************/
+
+/** Sdo abort messages.
+ *
+ * The "Abort Sdo transfer request" supplies an abort code, which can be
+ * translated to clear text. This table does the mapping of the codes and
+ * messages.
+ */
+const SdoCommand::AbortMessage SdoCommand::abortMessages[] = {
+    {0x05030000, "Toggle bit not changed"},
+    {0x05040000, "Sdo protocol timeout"},
+    {0x05040001, "Client/Server command specifier not valid or unknown"},
+    {0x05040005, "Out of memory"},
+    {0x06010000, "Unsupported access to an object"},
+    {0x06010001, "Attempt to read a write-only object"},
+    {0x06010002, "Attempt to write a read-only object"},
+    {0x06020000, "This object does not exist in the object directory"},
+    {0x06040041, "The object cannot be mapped into the Pdo"},
+    {0x06040042, "The number and length of the objects to be mapped would"
+     " exceed the Pdo length"},
+    {0x06040043, "General parameter incompatibility reason"},
+    {0x06040047, "Gerneral internal incompatibility in device"},
+    {0x06060000, "Access failure due to a hardware error"},
+    {0x06070010, "Data type does not match, length of service parameter does"
+     " not match"},
+    {0x06070012, "Data type does not match, length of service parameter too"
+     " high"},
+    {0x06070013, "Data type does not match, length of service parameter too"
+     " low"},
+    {0x06090011, "Subindex does not exist"},
+    {0x06090030, "Value range of parameter exceeded"},
+    {0x06090031, "Value of parameter written too high"},
+    {0x06090032, "Value of parameter written too low"},
+    {0x06090036, "Maximum value is less than minimum value"},
+    {0x08000000, "General error"},
+    {0x08000020, "Data cannot be transferred or stored to the application"},
+    {0x08000021, "Data cannot be transferred or stored to the application"
+     " because of local control"},
+    {0x08000022, "Data cannot be transferred or stored to the application"
+     " because of the present device state"},
+    {0x08000023, "Object dictionary dynamic generation fails or no object"
+     " dictionary is present"},
+    {}
+};
+
+/****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/SdoCommand.h	Fri Aug 01 10:10:55 2008 +0000
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#ifndef __SDOCOMMAND_H__
+#define __SDOCOMMAND_H__
+
+#include "Command.h"
+
+/****************************************************************************/
+
+class SdoCommand:
+    public Command
+{
+    public:
+        SdoCommand(const string &, const string &);
+
+        struct DataType {
+            const char *name;
+            uint16_t coeCode;
+            unsigned int byteSize;
+        };
+        static const DataType *findDataType(const string &);
+        static const DataType *findDataType(uint16_t);
+        static const char *abortText(uint32_t);
+
+    private:
+        struct AbortMessage {
+            uint32_t code;
+            const char *message;
+        };
+
+        static const DataType dataTypes[];
+        static const AbortMessage abortMessages[];
+};
+
+/****************************************************************************/
+
+#endif
--- a/tool/coe_datatypes.cpp	Fri Aug 01 09:32:35 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*****************************************************************************
- *
- * $Id$
- *
- ****************************************************************************/
-
-#include "coe_datatypes.h"
-
-/****************************************************************************/
-
-static const CoEDataType dataTypes[] = {
-    {"int8",   0x0002, 1},
-    {"int16",  0x0003, 2},
-    {"int32",  0x0004, 4},
-    {"uint8",  0x0005, 1},
-    {"uint16", 0x0006, 2},
-    {"uint32", 0x0007, 4},
-    {"string", 0x0009, 0},
-    {"raw",    0xffff, 0},
-    {}
-};
-
-/****************************************************************************/
-
-const CoEDataType *findDataType(const string &str)
-{
-    const CoEDataType *d;
-    
-    for (d = dataTypes; d->name; d++)
-        if (str == d->name)
-            return d;
-
-    return NULL;
-}
-
-/****************************************************************************/
-
-const CoEDataType *findDataType(uint16_t code)
-{
-    const CoEDataType *d;
-    
-    for (d = dataTypes; d->name; d++)
-        if (code == d->coeCode)
-            return d;
-
-    return NULL;
-}
-
-/*****************************************************************************/
--- a/tool/coe_datatypes.h	Fri Aug 01 09:32:35 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*****************************************************************************
- *
- * $Id$
- *
- ****************************************************************************/
-
-#include <inttypes.h>
-
-#include <string>
-using namespace std;
-
-/****************************************************************************/
-
-struct CoEDataType {
-    const char *name;
-    uint16_t coeCode;
-    unsigned int byteSize;
-};
-
-/****************************************************************************/
-
-const CoEDataType *findDataType(const string &);
-const CoEDataType *findDataType(uint16_t);
-
-/*****************************************************************************/