Introduced SdoCommand class to replace coe_datatypes.[ch]; added CoE abort codes in user space-
This commit is contained in:
parent
b46070f279
commit
8da5077e9c
6
TODO
6
TODO
|
|
@ -8,11 +8,11 @@ $Id$
|
|||
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ void CommandDownload::execute(MasterDevice &m, const StringVector &args)
|
|||
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 @@ void CommandDownload::execute(MasterDevice &m, const StringVector &args)
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef __COMMANDDOWNLOAD_H__
|
||||
#define __COMMANDDOWNLOAD_H__
|
||||
|
||||
#include "Command.h"
|
||||
#include "SdoCommand.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
class CommandDownload:
|
||||
public Command
|
||||
public SdoCommand
|
||||
{
|
||||
public:
|
||||
CommandDownload();
|
||||
|
|
|
|||
|
|
@ -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 @@ void CommandSdos::listSlaveSdos(
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef __COMMANDSDOS_H__
|
||||
#define __COMMANDSDOS_H__
|
||||
|
||||
#include "Command.h"
|
||||
#include "SdoCommand.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
class CommandSdos:
|
||||
public Command
|
||||
public SdoCommand
|
||||
{
|
||||
public:
|
||||
CommandSdos();
|
||||
|
|
|
|||
|
|
@ -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 @@ void CommandUpload::execute(MasterDevice &m, const StringVector &args)
|
|||
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 @@ void CommandUpload::execute(MasterDevice &m, const StringVector &args)
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef __COMMANDUPLOAD_H__
|
||||
#define __COMMANDUPLOAD_H__
|
||||
|
||||
#include "Command.h"
|
||||
#include "SdoCommand.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
class CommandUpload:
|
||||
public Command
|
||||
public SdoCommand
|
||||
{
|
||||
public:
|
||||
CommandUpload();
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ ethercat_SOURCES = \
|
|||
CommandVersion.cpp \
|
||||
CommandXml.cpp \
|
||||
MasterDevice.cpp \
|
||||
coe_datatypes.cpp \
|
||||
SdoCommand.cpp \
|
||||
main.cpp \
|
||||
sii_crc.cpp
|
||||
|
||||
|
|
@ -77,8 +77,8 @@ noinst_HEADERS = \
|
|||
CommandVersion.h \
|
||||
CommandXml.h \
|
||||
MasterDevice.h \
|
||||
SdoCommand.h \
|
||||
byteorder.h \
|
||||
coe_datatypes.h \
|
||||
sii_crc.h
|
||||
|
||||
REV = `if test -s $(srcdir)/../svnrevision; then \
|
||||
|
|
|
|||
|
|
@ -359,14 +359,12 @@ void MasterDevice::sdoDownload(ec_ioctl_slave_sdo_download_t *data)
|
|||
{
|
||||
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 @@ void MasterDevice::sdoUpload(ec_ioctl_slave_sdo_upload_t *data)
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ class MasterDeviceException:
|
|||
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 MasterDeviceException:
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
{}
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -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);
|
||||
|
||||
/*****************************************************************************/
|
||||
Loading…
Reference in New Issue