Introduced SdoCommand class to replace coe_datatypes.[ch]; added CoE abort codes in user space-
--- 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);
-
-/*****************************************************************************/