Moved every command into a separate file.
--- a/tool/Makefile.am Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/Makefile.am Tue Jul 22 14:17:20 2008 +0000
@@ -35,8 +35,23 @@
ethercat_SOURCES = \
MasterDevice.cpp MasterDevice.h \
+ coe_datatypes.cpp \
+ sii_crc.cpp \
cmd_alias.cpp \
cmd_config.cpp \
+ cmd_data.cpp \
+ cmd_debug.cpp \
+ cmd_domain.cpp \
+ cmd_master.cpp \
+ cmd_pdos.cpp \
+ cmd_sdos.cpp \
+ cmd_sdo_download.cpp \
+ cmd_sdo_upload.cpp \
+ cmd_slaves.cpp \
+ cmd_sii_read.cpp \
+ cmd_sii_write.cpp \
+ cmd_states.cpp \
+ cmd_xml.cpp \
main.cpp
ethercat_CXXFLAGS = -I../master -Wall
--- a/tool/MasterDevice.cpp Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/MasterDevice.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -10,65 +10,13 @@
#include <sys/ioctl.h>
#include <sstream>
+#include <iomanip>
using namespace std;
-#if 0
-#include <iostream>
-#include <fstream>
-#include <cctype> // toupper()
-#include <list>
-#endif
-
#include "MasterDevice.h"
/****************************************************************************/
-struct CoEDataType {
- const char *name;
- uint16_t coeCode;
- unsigned int byteSize;
-};
-
-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;
-}
-
-/****************************************************************************/
-
MasterDevice::MasterDevice()
{
index = 0;
@@ -89,848 +37,22 @@
index = i;
}
-#if 0
-/*****************************************************************************/
-
-bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b)
-{
- return a.alias < b.alias
- || (a.alias == b.alias && a.position < b.position);
-}
-
-/** Lists the bus configuration.
- */
-void Master::showConfigs()
-{
- ec_ioctl_master_t master;
- unsigned int i;
- ec_ioctl_config_t config;
- ConfigList configList;
-
- open(Read);
- getMaster(&master);
-
- for (i = 0; i < master.config_count; i++) {
- getConfig(&config, i);
- configList.push_back(config);
- }
-
- configList.sort();
-
- if (verbosity == Verbose) {
- showDetailedConfigs(configList);
- } else {
- listConfigs(configList);
- }
-}
-
-/****************************************************************************/
-
-void Master::outputData(int domainIndex)
-{
- open(Read);
-
- if (domainIndex == -1) {
- unsigned int i;
- ec_ioctl_master_t master;
-
- getMaster(&master);
-
- for (i = 0; i < master.domain_count; i++) {
- outputDomainData(i);
- }
- } else {
- outputDomainData(domainIndex);
- }
-}
-
-/****************************************************************************/
-
-void Master::setDebug(const vector<string> &commandArgs)
-{
- stringstream str;
- int debugLevel;
-
- if (commandArgs.size() != 1) {
- stringstream err;
- err << "'debug' takes exactly one argument!";
- throw MasterDeviceException(err.str());
- }
-
- str << commandArgs[0];
- str >> resetiosflags(ios::basefield) // guess base from prefix
- >> debugLevel;
-
- if (str.fail()) {
- stringstream err;
- err << "Invalid debug level '" << commandArgs[0] << "'!";
- throw MasterDeviceException(err.str());
- }
-
- open(ReadWrite);
-
- if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) {
- stringstream err;
- err << "Failed to set debug level: " << strerror(errno);
- throw MasterDeviceException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::showDomains(int domainIndex)
-{
- open(Read);
-
- if (domainIndex == -1) {
- unsigned int i;
- ec_ioctl_master_t master;
-
- getMaster(&master);
-
- for (i = 0; i < master.domain_count; i++) {
- showDomain(i);
- }
- } else {
- showDomain(domainIndex);
- }
-}
-
-/****************************************************************************/
-
-void Master::showMaster()
-{
- ec_ioctl_master_t data;
- stringstream err;
- unsigned int i;
-
- open(Read);
- getMaster(&data);
-
- cout
- << "Master" << index << endl
- << " Phase: ";
-
- switch (data.phase) {
- case 0: cout << "Waiting for device..."; break;
- case 1: cout << "Idle"; break;
- case 2: cout << "Operation"; break;
- default:
- err << "Invalid master phase " << data.phase;
- throw MasterDeviceException(err.str());
- }
-
- cout << endl
- << " Slaves: " << data.slave_count << endl;
-
- for (i = 0; i < 2; i++) {
- cout << " Device" << i << ": ";
- if (data.devices[i].address[0] == 0x00
- && data.devices[i].address[1] == 0x00
- && data.devices[i].address[2] == 0x00
- && data.devices[i].address[3] == 0x00
- && data.devices[i].address[4] == 0x00
- && data.devices[i].address[5] == 0x00) {
- cout << "None.";
- } else {
- cout << hex << setfill('0')
- << setw(2) << (unsigned int) data.devices[i].address[0] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[1] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[2] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[3] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[4] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[5] << " ("
- << (data.devices[i].attached ? "attached" : "waiting...")
- << ")" << endl << dec
- << " Tx count: " << data.devices[i].tx_count << endl
- << " Rx count: " << data.devices[i].rx_count;
- }
- cout << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::listPdos(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- listSlavePdos(i, true);
- }
- } else {
- listSlavePdos(slavePosition, false);
- }
-}
-
-/****************************************************************************/
-
-void Master::listSdos(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- listSlaveSdos(i, true);
- }
- } else {
- listSlaveSdos(slavePosition, false);
- }
-}
-
-/****************************************************************************/
-
-void Master::sdoDownload(
- int slavePosition,
- const string &dataTypeStr,
- const vector<string> &commandArgs
- )
-{
- stringstream strIndex, strSubIndex, strValue, err;
- ec_ioctl_slave_sdo_download_t data;
- unsigned int number;
- const CoEDataType *dataType = NULL;
-
- if (slavePosition < 0) {
- err << "'sdo_download' requires a slave! Please specify --slave.";
- throw MasterDeviceException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 3) {
- err << "'sdo_download' takes 3 arguments!";
- throw MasterDeviceException(err.str());
- }
-
- strIndex << commandArgs[0];
- strIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> data.sdo_index;
- if (strIndex.fail()) {
- err << "Invalid Sdo index '" << commandArgs[0] << "'!";
- throw MasterDeviceException(err.str());
- }
-
- strSubIndex << commandArgs[1];
- strSubIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> number;
- if (strSubIndex.fail() || number > 0xff) {
- err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
- throw MasterDeviceException(err.str());
- }
- data.sdo_entry_subindex = number;
-
- if (dataTypeStr != "") { // data type specified
- if (!(dataType = findDataType(dataTypeStr))) {
- err << "Invalid data type '" << dataTypeStr << "'!";
- throw MasterDeviceException(err.str());
- }
- } else { // no data type specified: fetch from dictionary
- ec_ioctl_slave_sdo_entry_t entry;
-
- open(ReadWrite);
-
- try {
- getSdoEntry(&entry, slavePosition,
- data.sdo_index, data.sdo_entry_subindex);
- } catch (MasterDeviceException &e) {
- err << "Failed to determine Sdo entry data type. "
- << "Please specify --type.";
- throw MasterDeviceException(err.str());
- }
- if (!(dataType = findDataType(entry.data_type))) {
- err << "Pdo entry has unknown data type 0x"
- << hex << setfill('0') << setw(4) << entry.data_type << "!"
- << " Please specify --type.";
- throw MasterDeviceException(err.str());
- }
- }
-
- if (dataType->byteSize) {
- data.data_size = dataType->byteSize;
- } else {
- data.data_size = DefaultBufferSize;
- }
-
- data.data = new uint8_t[data.data_size + 1];
-
- strValue << commandArgs[2];
- strValue >> resetiosflags(ios::basefield); // guess base from prefix
- strValue.exceptions(ios::failbit);
-
- try {
- switch (dataType->coeCode) {
- case 0x0002: // int8
- {
- int16_t val; // uint8_t is interpreted as char
- strValue >> val;
- if (val > 127 || val < -128)
- throw ios::failure("Value out of range");
- *data.data = val;
- break;
- }
- case 0x0003: // int16
- {
- int16_t val;
- strValue >> val;
- *(int16_t *) data.data = cputole16(val);
- break;
- }
- case 0x0004: // int32
- {
- int32_t val;
- strValue >> val;
- *(int32_t *) data.data = cputole32(val);
- break;
- }
- case 0x0005: // uint8
- {
- uint16_t val; // uint8_t is interpreted as char
- strValue >> val;
- if (val > 0xff)
- throw ios::failure("Value out of range");
- *data.data = val;
- break;
- }
- case 0x0006: // uint16
- {
- uint16_t val;
- strValue >> val;
- *(uint16_t *) data.data = cputole16(val);
- break;
- }
- case 0x0007: // uint32
- {
- uint32_t val;
- strValue >> val;
- *(uint32_t *) data.data = cputole32(val);
- break;
- }
- case 0x0009: // string
- if (strValue.str().size() >= data.data_size) {
- err << "String too large";
- throw MasterDeviceException(err.str());
- }
- data.data_size = strValue.str().size();
- strValue >> (char *) data.data;
- break;
-
- default:
- delete [] data.data;
- err << "Unknown data type 0x" << hex << dataType->coeCode;
- throw MasterDeviceException(err.str());
- }
- } catch (ios::failure &e) {
- delete [] data.data;
- err << "Invalid value argument '" << commandArgs[2]
- << "' for type '" << dataType->name << "'!";
- throw MasterDeviceException(err.str());
- }
-
- open(ReadWrite);
-
- 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;
- } else {
- err << strerror(errno);
- }
- delete [] data.data;
- throw MasterDeviceException(err.str());
- }
-
- delete [] data.data;
-}
-
-/****************************************************************************/
-
-void Master::sdoUpload(
- int slavePosition,
- const string &dataTypeStr,
- const vector<string> &commandArgs
- )
-{
- stringstream strIndex, strSubIndex;
- int sval;
- ec_ioctl_slave_sdo_upload_t data;
- unsigned int uval;
- const CoEDataType *dataType = NULL;
-
- if (slavePosition < 0) {
- stringstream err;
- err << "'sdo_upload' requires a slave! Please specify --slave.";
- throw MasterDeviceException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 2) {
- stringstream err;
- err << "'sdo_upload' takes two arguments!";
- throw MasterDeviceException(err.str());
- }
-
- strIndex << commandArgs[0];
- strIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> data.sdo_index;
- if (strIndex.fail()) {
- stringstream err;
- err << "Invalid Sdo index '" << commandArgs[0] << "'!";
- throw MasterDeviceException(err.str());
- }
-
- strSubIndex << commandArgs[1];
- strSubIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> uval;
- if (strSubIndex.fail() || uval > 0xff) {
- stringstream err;
- err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
- throw MasterDeviceException(err.str());
- }
- data.sdo_entry_subindex = uval;
-
- if (dataTypeStr != "") { // data type specified
- if (!(dataType = findDataType(dataTypeStr))) {
- stringstream err;
- err << "Invalid data type '" << dataTypeStr << "'!";
- throw MasterDeviceException(err.str());
- }
- } else { // no data type specified: fetch from dictionary
- ec_ioctl_slave_sdo_entry_t entry;
-
- open(Read);
-
- try {
- getSdoEntry(&entry, slavePosition,
- data.sdo_index, data.sdo_entry_subindex);
- } catch (MasterDeviceException &e) {
- stringstream err;
- err << "Failed to determine Sdo entry data type. "
- << "Please specify --type.";
- throw MasterDeviceException(err.str());
- }
- if (!(dataType = findDataType(entry.data_type))) {
- stringstream err;
- err << "Pdo entry has unknown data type 0x"
- << hex << setfill('0') << setw(4) << entry.data_type << "!"
- << " Please specify --type.";
- throw MasterDeviceException(err.str());
- }
- }
-
- if (dataType->byteSize) {
- data.target_size = dataType->byteSize;
- } else {
- data.target_size = DefaultBufferSize;
- }
-
- data.target = new uint8_t[data.target_size + 1];
-
- open(Read);
-
- 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;
- } else {
- err << strerror(errno);
- }
- delete [] data.target;
- close();
- throw MasterDeviceException(err.str());
- }
-
- close();
-
- if (dataType->byteSize && data.data_size != dataType->byteSize) {
- stringstream err;
- err << "Data type mismatch. Expected " << dataType->name
- << " with " << dataType->byteSize << " byte, but got "
- << data.data_size << " byte.";
- throw MasterDeviceException(err.str());
- }
-
- cout << setfill('0');
- switch (dataType->coeCode) {
- case 0x0002: // int8
- sval = *(int8_t *) data.target;
- cout << sval << " 0x" << hex << setw(2) << sval << endl;
- break;
- case 0x0003: // int16
- sval = le16tocpu(*(int16_t *) data.target);
- cout << sval << " 0x" << hex << setw(4) << sval << endl;
- break;
- case 0x0004: // int32
- sval = le32tocpu(*(int32_t *) data.target);
- cout << sval << " 0x" << hex << setw(8) << sval << endl;
- break;
- case 0x0005: // uint8
- uval = (unsigned int) *(uint8_t *) data.target;
- cout << uval << " 0x" << hex << setw(2) << uval << endl;
- break;
- case 0x0006: // uint16
- uval = le16tocpu(*(uint16_t *) data.target);
- cout << uval << " 0x" << hex << setw(4) << uval << endl;
- break;
- case 0x0007: // uint32
- uval = le32tocpu(*(uint32_t *) data.target);
- cout << uval << " 0x" << hex << setw(8) << uval << endl;
- break;
- case 0x0009: // string
- cout << string((const char *) data.target, data.data_size)
- << endl;
- break;
- default:
- printRawData(data.target, data.data_size);
- break;
- }
-
- delete [] data.target;
-}
-
-/****************************************************************************/
-
-void Master::showSlaves(int slavePosition)
-{
- open(Read);
-
- if (verbosity == Verbose) {
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- showSlave(i);
- }
- } else {
- showSlave(slavePosition);
- }
- } else {
- listSlaves(slavePosition);
- }
-}
-
-/****************************************************************************/
-
-struct CategoryName {
- uint16_t type;
- const char *name;
-};
-
-static const CategoryName categoryNames[] = {
- {0x000a, "STRINGS"},
- {0x0014, "DataTypes"},
- {0x001e, "General"},
- {0x0028, "FMMU"},
- {0x0029, "SyncM"},
- {0x0032, "TXPDO"},
- {0x0033, "RXPDO"},
- {0x003c, "DC"},
- {}
-};
-
-const char *getCategoryName(uint16_t type)
-{
- const CategoryName *cn = categoryNames;
-
- while (cn->type) {
- if (cn->type == type) {
- return cn->name;
- }
- cn++;
- }
-
- return "unknown";
-}
-
-void Master::siiRead(int slavePosition)
-{
- ec_ioctl_slave_sii_t data;
- ec_ioctl_slave_t slave;
- unsigned int i;
- const uint16_t *categoryHeader;
- uint16_t categoryType, categorySize;
- stringstream err;
-
- if (slavePosition < 0) {
- stringstream err;
- err << "'sii_read' requires a slave! Please specify --slave.";
- throw MasterDeviceException(err.str());
- }
- data.slave_position = slavePosition;
-
- open(Read);
-
- getSlave(&slave, slavePosition);
-
- if (!slave.sii_nwords)
- return;
-
- data.offset = 0;
- data.nwords = slave.sii_nwords;
- data.words = new uint16_t[data.nwords];
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, &data) < 0) {
- stringstream err;
- delete [] data.words;
- err << "Failed to read SII: " << strerror(errno);
- throw MasterDeviceException(err.str());
- }
-
- if (verbosity == Verbose) {
- cout << "SII Area:" << hex << setfill('0');
- for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) {
- if (i % BreakAfterBytes) {
- cout << " ";
- } else {
- cout << endl << " ";
- }
- cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i);
- }
- cout << endl;
-
- if (data.nwords > 0x0040U) {
- // cycle through categories
- categoryHeader = data.words + 0x0040U;
- categoryType = le16tocpu(*categoryHeader);
- while (categoryType != 0xffff) {
- cout << "SII Category 0x" << hex
- << setw(4) << categoryType
- << " (" << getCategoryName(categoryType) << ")" << flush;
-
- if (categoryHeader + 1 > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterDeviceException(err.str());
- }
- categorySize = le16tocpu(*(categoryHeader + 1));
- cout << ", " << dec << categorySize << " words" << flush;
-
- if (categoryHeader + 2 + categorySize
- > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterDeviceException(err.str());
- }
-
- cout << hex;
- for (i = 0; i < categorySize * 2U; i++) {
- if (i % BreakAfterBytes) {
- cout << " ";
- } else {
- cout << endl << " ";
- }
- cout << setw(2) << (unsigned int)
- *((uint8_t *) (categoryHeader + 2) + i);
- }
- cout << endl;
-
- if (categoryHeader + 2 + categorySize + 1
- > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterDeviceException(err.str());
- }
- categoryHeader += 2 + categorySize;
- categoryType = le16tocpu(*categoryHeader);
- }
- }
- } else {
- for (i = 0; i < data.nwords; i++) {
- uint16_t *w = data.words + i;
- cout << *(uint8_t *) w << *((uint8_t *) w + 1);
- }
- }
-
- delete [] data.words;
-}
-
-/****************************************************************************/
-
-void Master::siiWrite(
- int slavePosition,
- bool force,
- const vector<string> &commandArgs
- )
-{
- stringstream err;
- ec_ioctl_slave_sii_t data;
- ifstream file;
- unsigned int byte_size;
- const uint16_t *categoryHeader;
- uint16_t categoryType, categorySize;
- uint8_t crc;
-
- if (slavePosition < 0) {
- err << "'sii_write' requires a slave! Please specify --slave.";
- throw MasterDeviceException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 1) {
- err << "'ssi_write' takes exactly one argument!";
- throw MasterDeviceException(err.str());
- }
-
- file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary);
- if (file.fail()) {
- err << "Failed to open '" << commandArgs[0] << "'!";
- throw MasterDeviceException(err.str());
- }
-
- // get length of file
- file.seekg(0, ios::end);
- byte_size = file.tellg();
- file.seekg(0, ios::beg);
-
- if (!byte_size || byte_size % 2) {
- stringstream err;
- err << "Invalid file size! Must be non-zero and even.";
- throw MasterDeviceException(err.str());
- }
-
- data.nwords = byte_size / 2;
- if (data.nwords < 0x0041 && !force) {
- err << "SII data too short (" << data.nwords << " words)! Mimimum is"
- " 40 fixed words + 1 delimiter. Use --force to write anyway.";
- throw MasterDeviceException(err.str());
- }
-
- // allocate buffer and read file into buffer
- data.words = new uint16_t[data.nwords];
- file.read((char *) data.words, byte_size);
- file.close();
-
- if (!force) {
- // calculate checksum over words 0 to 6
- crc = calcSiiCrc((const uint8_t *) data.words, 14);
- if (crc != ((const uint8_t *) data.words)[14]) {
- err << "CRC incorrect. Must be 0x"
- << hex << setfill('0') << setw(2) << (unsigned int) crc
- << ". Use --force to write anyway.";
- throw MasterDeviceException(err.str());
- }
-
- // cycle through categories to detect corruption
- categoryHeader = data.words + 0x0040U;
- categoryType = le16tocpu(*categoryHeader);
- while (categoryType != 0xffff) {
- if (categoryHeader + 1 > data.words + data.nwords) {
- err << "SII data seem to be corrupted! "
- << "Use --force to write anyway.";
- throw MasterDeviceException(err.str());
- }
- categorySize = le16tocpu(*(categoryHeader + 1));
- if (categoryHeader + 2 + categorySize + 1
- > data.words + data.nwords) {
- err << "SII data seem to be corrupted! "
- "Use --force to write anyway.";
- throw MasterDeviceException(err.str());
- }
- categoryHeader += 2 + categorySize;
- categoryType = le16tocpu(*categoryHeader);
- }
- }
-
- // send data to master
- open(ReadWrite);
- data.offset = 0;
- if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) {
- stringstream err;
- err << "Failed to write SII: " << strerror(errno);
- throw MasterDeviceException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::requestStates(
- int slavePosition,
- const vector<string> &commandArgs
- )
-{
- string stateStr;
- uint8_t state;
-
- if (commandArgs.size() != 1) {
- stringstream err;
- err << "'state' takes exactly one argument!";
- throw MasterDeviceException(err.str());
- }
-
- stateStr = commandArgs[0];
- transform(stateStr.begin(), stateStr.end(),
- stateStr.begin(), (int (*) (int)) std::toupper);
-
- if (stateStr == "INIT") {
- state = 0x01;
- } else if (stateStr == "PREOP") {
- state = 0x02;
- } else if (stateStr == "SAFEOP") {
- state = 0x04;
- } else if (stateStr == "OP") {
- state = 0x08;
- } else {
- stringstream err;
- err << "Invalid state '" << commandArgs[0] << "'!";
- throw MasterDeviceException(err.str());
- }
-
- open(ReadWrite);
-
- if (slavePosition == -1) {
- unsigned int i, numSlaves = slaveCount();
- for (i = 0; i < numSlaves; i++)
- requestState(i, state);
- } else {
- requestState(slavePosition, state);
- }
-}
-
-/****************************************************************************/
-
-void Master::generateXml(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- generateSlaveXml(i);
- }
- } else {
- generateSlaveXml(slavePosition);
- }
-}
-
-#endif
/****************************************************************************/
void MasterDevice::open(Permissions perm)
{
stringstream deviceName;
- if (fd != -1) { // already open
- return;
- }
-
- deviceName << "/dev/EtherCAT" << index;
-
- if ((fd = ::open(deviceName.str().c_str(),
- perm == ReadWrite ? O_RDWR : O_RDONLY)) == -1) {
- stringstream err;
- err << "Failed to open master device " << deviceName.str() << ": "
- << strerror(errno);
- throw MasterDeviceException(err.str());
+ if (fd == -1) { // not already open
+ deviceName << "/dev/EtherCAT" << index;
+
+ if ((fd = ::open(deviceName.str().c_str(),
+ perm == ReadWrite ? O_RDWR : O_RDONLY)) == -1) {
+ stringstream err;
+ err << "Failed to open master device " << deviceName.str() << ": "
+ << strerror(errno);
+ throw MasterDeviceException(err.str());
+ }
}
}
@@ -938,710 +60,12 @@
void MasterDevice::close()
{
- if (fd == -1)
- return;
-
- ::close(fd);
- fd = -1;
-}
-
-#if 0
-
-/*****************************************************************************/
-
-/** Lists the complete bus configuration.
- */
-void Master::showDetailedConfigs(const ConfigList &configList)
-{
- ConfigList::const_iterator configIter;
- unsigned int j, k, l;
- ec_ioctl_config_pdo_t pdo;
- ec_ioctl_config_pdo_entry_t entry;
- ec_ioctl_config_sdo_t sdo;
-
- for (configIter = configList.begin();
- configIter != configList.end();
- configIter++) {
-
- cout << "Alias: "
- << dec << configIter->alias << endl
- << "Position: " << configIter->position << endl
- << "Vendor Id: 0x"
- << hex << setfill('0')
- << setw(8) << configIter->vendor_id << endl
- << "Product code: 0x"
- << setw(8) << configIter->product_code << endl
- << "Attached: " << (configIter->attached ? "yes" : "no") << endl
- << "Operational: " << (configIter->operational ? "yes" : "no") << endl;
-
- for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) {
- if (configIter->syncs[j].pdo_count) {
- cout << "SM" << dec << j << " ("
- << (configIter->syncs[j].dir == EC_DIR_INPUT
- ? "Input" : "Output") << ")" << endl;
- for (k = 0; k < configIter->syncs[j].pdo_count; k++) {
- getConfigPdo(&pdo, configIter->config_index, j, k);
-
- cout << " Pdo 0x" << hex
- << setw(4) << pdo.index
- << " \"" << pdo.name << "\"" << endl;
-
- for (l = 0; l < pdo.entry_count; l++) {
- getConfigPdoEntry(&entry, configIter->config_index, j, k, l);
-
- cout << " Pdo entry 0x" << hex
- << setw(4) << entry.index << ":"
- << setw(2) << (unsigned int) entry.subindex
- << ", " << dec << (unsigned int) entry.bit_length
- << " bit, \"" << entry.name << "\"" << endl;
- }
- }
- }
- }
-
- cout << "Sdo configuration:" << endl;
- if (configIter->sdo_count) {
- for (j = 0; j < configIter->sdo_count; j++) {
- getConfigSdo(&sdo, configIter->config_index, j);
-
- cout << " 0x"
- << hex << setfill('0')
- << setw(4) << sdo.index << ":"
- << setw(2) << (unsigned int) sdo.subindex
- << ", " << dec << sdo.size << " byte: " << hex;
-
- switch (sdo.size) {
- case 1:
- cout << "0x" << setw(2)
- << (unsigned int) *(uint8_t *) &sdo.data;
- break;
- case 2:
- cout << "0x" << setw(4)
- << le16tocpu(*(uint16_t *) &sdo.data);
- break;
- case 4:
- cout << "0x" << setw(8)
- << le32tocpu(*(uint32_t *) &sdo.data);
- break;
- default:
- cout << "???";
- }
-
- cout << endl;
- }
- } else {
- cout << " None." << endl;
- }
-
- cout << endl;
- }
-}
-
-/*****************************************************************************/
-
-struct ConfigInfo {
- string alias;
- string pos;
- string ident;
- string att;
- string op;
-};
-
-/** Lists the bus configuration.
- */
-void Master::listConfigs(const ConfigList &configList)
-{
- ConfigList::const_iterator configIter;
- stringstream str;
- ConfigInfo info;
- typedef list<ConfigInfo> ConfigInfoList;
- ConfigInfoList list;
- ConfigInfoList::const_iterator iter;
- unsigned int maxAliasWidth = 0, maxPosWidth = 0,
- maxAttWidth = 0, maxOpWidth = 0;
-
- for (configIter = configList.begin();
- configIter != configList.end();
- configIter++) {
-
- str << dec << configIter->alias;
- info.alias = str.str();
- str.clear();
- str.str("");
-
- str << configIter->position;
- info.pos = str.str();
- str.clear();
- str.str("");
-
- str << hex << setfill('0')
- << "0x" << setw(8) << configIter->vendor_id
- << "/0x" << setw(8) << configIter->product_code;
- info.ident = str.str();
- str.clear();
- str.str("");
-
- str << (configIter->attached ? "attached" : "-");
- info.att = str.str();
- str.clear();
- str.str("");
-
- str << (configIter->operational ? "operational" : "-");
- info.op = str.str();
- str.clear();
- str.str("");
-
- list.push_back(info);
-
- if (info.alias.length() > maxAliasWidth)
- maxAliasWidth = info.alias.length();
- if (info.pos.length() > maxPosWidth)
- maxPosWidth = info.pos.length();
- if (info.att.length() > maxAttWidth)
- maxAttWidth = info.att.length();
- if (info.op.length() > maxOpWidth)
- maxOpWidth = info.op.length();
- }
-
- for (iter = list.begin(); iter != list.end(); iter++) {
- cout << setfill(' ') << right
- << setw(maxAliasWidth) << iter->alias
- << ":" << left
- << setw(maxPosWidth) << iter->pos
- << " "
- << iter->ident
- << " "
- << setw(maxAttWidth) << iter->att << " "
- << setw(maxOpWidth) << iter->op << " "
- << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::outputDomainData(unsigned int domainIndex)
-{
- ec_ioctl_domain_t domain;
- ec_ioctl_domain_data_t data;
- unsigned char *processData;
- unsigned int i;
-
- getDomain(&domain, domainIndex);
-
- if (!domain.data_size)
- return;
-
- processData = new unsigned char[domain.data_size];
-
- try {
- getData(&data, domainIndex, domain.data_size, processData);
- } catch (MasterDeviceException &e) {
- delete [] processData;
- throw e;
- }
-
- for (i = 0; i < data.data_size; i++)
- cout << processData[i];
- cout.flush();
-
- delete [] processData;
-}
-
-/****************************************************************************/
-
-void Master::showDomain(unsigned int domainIndex)
-{
- ec_ioctl_domain_t domain;
- unsigned char *processData;
- ec_ioctl_domain_data_t data;
- unsigned int i, j;
- ec_ioctl_domain_fmmu_t fmmu;
- unsigned int dataOffset;
-
- getDomain(&domain, domainIndex);
-
- cout << "Domain" << dec << domainIndex << ":"
- << " LogBaseAddr 0x"
- << hex << setfill('0')
- << setw(8) << domain.logical_base_address
- << ", Size " << dec << setfill(' ')
- << setw(3) << domain.data_size
- << ", WorkingCounter "
- << domain.working_counter << "/"
- << domain.expected_working_counter << endl;
-
- if (!domain.data_size || verbosity != Verbose)
- return;
-
- processData = new unsigned char[domain.data_size];
-
- try {
- getData(&data, domainIndex, domain.data_size, processData);
- } catch (MasterDeviceException &e) {
- delete [] processData;
- throw e;
- }
-
- for (i = 0; i < domain.fmmu_count; i++) {
- getFmmu(&fmmu, domainIndex, i);
-
- cout << " SlaveConfig "
- << dec << fmmu.slave_config_alias
- << ":" << fmmu.slave_config_position
- << ", SM" << (unsigned int) fmmu.sync_index << " ("
- << setfill(' ') << setw(6)
- << (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output")
- << "), LogAddr 0x"
- << hex << setfill('0')
- << setw(8) << fmmu.logical_address
- << ", Size " << dec << fmmu.data_size << endl;
-
- dataOffset = fmmu.logical_address - domain.logical_base_address;
- if (dataOffset + fmmu.data_size > domain.data_size) {
- stringstream err;
- err << "Fmmu information corrupted!";
- delete [] processData;
- throw MasterDeviceException(err.str());
- }
-
- cout << " " << hex << setfill('0');
- for (j = 0; j < fmmu.data_size; j++) {
- if (j && !(j % BreakAfterBytes))
- cout << endl << " ";
- cout << setw(2)
- << (unsigned int) *(processData + dataOffset + j) << " ";
- }
- cout << endl;
- }
-
- delete [] processData;
-}
-
-/****************************************************************************/
-
-void Master::listSlavePdos(
- uint16_t slavePosition,
- bool withHeader
- )
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sync_t sync;
- ec_ioctl_slave_sync_pdo_t pdo;
- ec_ioctl_slave_sync_pdo_entry_t entry;
- unsigned int i, j, k;
-
- getSlave(&slave, slavePosition);
-
- if (withHeader)
- cout << "=== Slave " << slavePosition << " ===" << endl;
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- cout << "SM" << i << ":"
- << " PhysAddr 0x"
- << hex << setfill('0')
- << setw(4) << sync.physical_start_address
- << ", DefaultSize "
- << dec << setfill(' ') << setw(4) << sync.default_size
- << ", ControlRegister 0x"
- << hex << setfill('0') << setw(2)
- << (unsigned int) sync.control_register
- << ", Enable " << dec << (unsigned int) sync.enable
- << endl;
-
- for (j = 0; j < sync.pdo_count; j++) {
- getPdo(&pdo, slavePosition, i, j);
-
- cout << " " << (sync.control_register & 0x04 ? "R" : "T")
- << "xPdo 0x"
- << hex << setfill('0')
- << setw(4) << pdo.index
- << " \"" << pdo.name << "\"" << endl;
-
- if (verbosity == Quiet)
- continue;
-
- for (k = 0; k < pdo.entry_count; k++) {
- getPdoEntry(&entry, slavePosition, i, j, k);
-
- cout << " Pdo entry 0x"
- << hex << setfill('0')
- << setw(4) << entry.index
- << ":" << setw(2) << (unsigned int) entry.subindex
- << ", " << dec << (unsigned int) entry.bit_length
- << " bit, \"" << entry.name << "\"" << endl;
- }
- }
- }
-}
-
-/****************************************************************************/
-
-void Master::listSlaveSdos(
- uint16_t slavePosition,
- bool withHeader
- )
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sdo_t sdo;
- ec_ioctl_slave_sdo_entry_t entry;
- unsigned int i, j;
- const CoEDataType *d;
-
- getSlave(&slave, slavePosition);
-
- if (withHeader)
- cout << "=== Slave " << slavePosition << " ===" << endl;
-
- for (i = 0; i < slave.sdo_count; i++) {
- getSdo(&sdo, slavePosition, i);
-
- cout << "Sdo 0x"
- << hex << setfill('0')
- << setw(4) << sdo.sdo_index
- << ", \"" << sdo.name << "\"" << endl;
-
- if (verbosity == Quiet)
- continue;
-
- for (j = 0; j <= sdo.max_subindex; j++) {
- getSdoEntry(&entry, slavePosition, -i, j);
-
- cout << " 0x" << hex << setfill('0')
- << setw(4) << sdo.sdo_index << ":"
- << setw(2) << (unsigned int) entry.sdo_entry_subindex
- << ", ";
-
- if ((d = findDataType(entry.data_type))) {
- cout << d->name;
- } else {
- cout << "type " << setw(4) << entry.data_type;
- }
-
- cout << ", " << dec << entry.bit_length << " bit, \""
- << entry.description << "\"" << endl;
- }
- }
-}
-
-/****************************************************************************/
-
-struct SlaveInfo {
- string pos;
- string alias;
- string relPos;
- string state;
- string flag;
- string name;
-};
-
-void Master::listSlaves(int slavePosition)
-{
- unsigned int numSlaves, i;
- ec_ioctl_slave_t slave;
- uint16_t lastAlias, aliasIndex;
- SlaveInfo slaveInfo;
- typedef list<SlaveInfo> SlaveInfoList;
- SlaveInfoList slaveInfoList;
- SlaveInfoList::const_iterator iter;
- stringstream str;
- unsigned int maxPosWidth = 0, maxAliasWidth = 0,
- maxRelPosWidth = 0, maxStateWidth = 0;
-
- open(Read);
-
- numSlaves = slaveCount();
-
- lastAlias = 0;
- aliasIndex = 0;
- for (i = 0; i < numSlaves; i++) {
- getSlave(&slave, i);
-
- if (slave.alias) {
- lastAlias = slave.alias;
- aliasIndex = 0;
- }
-
- if (slavePosition == -1 || i == (unsigned int) slavePosition) {
- str << dec << i;
- slaveInfo.pos = str.str();
- str.clear();
- str.str("");
-
- str << lastAlias;
- slaveInfo.alias = str.str();
- str.str("");
-
- str << aliasIndex;
- slaveInfo.relPos = str.str();
- str.str("");
-
- slaveInfo.state = slaveState(slave.state);
- slaveInfo.flag = (slave.error_flag ? 'E' : '+');
-
- if (strlen(slave.name)) {
- slaveInfo.name = slave.name;
- } else {
- str << "0x" << hex << setfill('0')
- << setw(8) << slave.vendor_id << ":0x"
- << setw(8) << slave.product_code;
- slaveInfo.name = str.str();
- str.str("");
- }
-
-
- slaveInfoList.push_back(slaveInfo);
-
- if (slaveInfo.pos.length() > maxPosWidth)
- maxPosWidth = slaveInfo.pos.length();
- if (slaveInfo.alias.length() > maxAliasWidth)
- maxAliasWidth = slaveInfo.alias.length();
- if (slaveInfo.relPos.length() > maxRelPosWidth)
- maxRelPosWidth = slaveInfo.relPos.length();
- if (slaveInfo.state.length() > maxStateWidth)
- maxStateWidth = slaveInfo.state.length();
- }
-
- aliasIndex++;
- }
-
- for (iter = slaveInfoList.begin(); iter != slaveInfoList.end(); iter++) {
- cout << setfill(' ') << right
- << setw(maxPosWidth) << iter->pos << " "
- << setw(maxAliasWidth) << iter->alias
- << ":" << left
- << setw(maxRelPosWidth) << iter->relPos << " "
- << setw(maxStateWidth) << iter->state << " "
- << iter->flag << " "
- << iter->name << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::showSlave(uint16_t slavePosition)
-{
- ec_ioctl_slave_t slave;
- list<string> protoList;
- list<string>::const_iterator protoIter;
-
- getSlave(&slave, slavePosition);
-
- cout << "=== Slave " << dec << slavePosition << " ===" << endl;
-
- if (slave.alias)
- cout << "Alias: " << slave.alias << endl;
-
- cout
- << "State: " << slaveState(slave.state) << endl
- << "Flag: " << (slave.error_flag ? 'E' : '+') << endl
- << "Identity:" << endl
- << " Vendor Id: 0x"
- << hex << setfill('0')
- << setw(8) << slave.vendor_id << endl
- << " Product code: 0x"
- << setw(8) << slave.product_code << endl
- << " Revision number: 0x"
- << setw(8) << slave.revision_number << endl
- << " Serial number: 0x"
- << setw(8) << slave.serial_number << endl;
-
- if (slave.mailbox_protocols) {
- cout << "Mailboxes:" << endl
- << " RX: 0x"
- << hex << setw(4) << slave.rx_mailbox_offset << "/"
- << dec << slave.rx_mailbox_size
- << ", TX: 0x"
- << hex << setw(4) << slave.tx_mailbox_offset << "/"
- << dec << slave.tx_mailbox_size << endl
- << " Supported protocols: ";
-
- if (slave.mailbox_protocols & EC_MBOX_AOE) {
- protoList.push_back("AoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_EOE) {
- protoList.push_back("EoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_COE) {
- protoList.push_back("CoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_FOE) {
- protoList.push_back("FoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_SOE) {
- protoList.push_back("SoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_VOE) {
- protoList.push_back("VoE");
- }
-
- for (protoIter = protoList.begin(); protoIter != protoList.end();
- protoIter++) {
- if (protoIter != protoList.begin())
- cout << ", ";
- cout << *protoIter;
- }
- cout << endl;
- }
-
- if (slave.has_general_category) {
- cout << "General:" << endl
- << " Group: " << slave.group << endl
- << " Image name: " << slave.image << endl
- << " Order number: " << slave.order << endl
- << " Device name: " << slave.name << endl;
-
- if (slave.mailbox_protocols & EC_MBOX_COE) {
- cout << " CoE details:" << endl
- << " Enable Sdo: "
- << (slave.coe_details.enable_sdo ? "yes" : "no") << endl
- << " Enable Sdo Info: "
- << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl
- << " Enable Pdo Assign: "
- << (slave.coe_details.enable_pdo_assign
- ? "yes" : "no") << endl
- << " Enable Pdo Configuration: "
- << (slave.coe_details.enable_pdo_configuration
- ? "yes" : "no") << endl
- << " Enable Upload at startup: "
- << (slave.coe_details.enable_upload_at_startup
- ? "yes" : "no") << endl
- << " Enable Sdo complete access: "
- << (slave.coe_details.enable_sdo_complete_access
- ? "yes" : "no") << endl;
- }
-
- cout << " Flags:" << endl
- << " Enable SafeOp: "
- << (slave.general_flags.enable_safeop ? "yes" : "no") << endl
- << " Enable notLRW: "
- << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl
- << " Current consumption: "
- << dec << slave.current_on_ebus << " mA" << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::generateSlaveXml(uint16_t slavePosition)
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sync_t sync;
- ec_ioctl_slave_sync_pdo_t pdo;
- string pdoType;
- ec_ioctl_slave_sync_pdo_entry_t entry;
- unsigned int i, j, k;
-
- getSlave(&slave, slavePosition);
-
- cout
- << "<?xml version=\"1.0\" ?>" << endl
- << " <EtherCATInfo>" << endl
- << " <!-- Slave " << slave.position << " -->" << endl
- << " <Vendor>" << endl
- << " <Id>" << slave.vendor_id << "</Id>" << endl
- << " </Vendor>" << endl
- << " <Descriptions>" << endl
- << " <Devices>" << endl
- << " <Device>" << endl
- << " <Type ProductCode=\"#x"
- << hex << setfill('0') << setw(8) << slave.product_code
- << "\" RevisionNo=\"#x"
- << hex << setfill('0') << setw(8) << slave.revision_number
- << "\">" << slave.order << "</Type>" << endl;
-
- if (strlen(slave.name)) {
- cout
- << " <Name><![CDATA["
- << slave.name
- << "]]></Name>" << endl;
- }
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- cout
- << " <Sm Enable=\"" << dec << (unsigned int) sync.enable
- << "\" StartAddress=\"" << sync.physical_start_address
- << "\" ControlByte=\"" << (unsigned int) sync.control_register
- << "\" DefaultSize=\"" << sync.default_size
- << "\" />" << endl;
- }
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- for (j = 0; j < sync.pdo_count; j++) {
- getPdo(&pdo, slavePosition, i, j);
- pdoType = (sync.control_register & 0x04 ? "R" : "T");
- pdoType += "xPdo";
-
- cout
- << " <" << pdoType
- << " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << pdo.index
- << "</Index>" << endl
- << " <Name>" << pdo.name << "</Name>" << endl;
-
- for (k = 0; k < pdo.entry_count; k++) {
- getPdoEntry(&entry, slavePosition, i, j, k);
-
- cout
- << " <Entry>" << endl
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << entry.index
- << "</Index>" << endl;
- if (entry.index)
- cout
- << " <SubIndex>"
- << dec << (unsigned int) entry.subindex
- << "</SubIndex>" << endl;
-
- cout
- << " <BitLen>"
- << dec << (unsigned int) entry.bit_length
- << "</BitLen>" << endl;
-
- if (entry.index) {
- cout
- << " <Name>" << entry.name
- << "</Name>" << endl
- << " <DataType>";
-
- if (entry.bit_length == 1) {
- cout << "BOOL";
- } else if (!(entry.bit_length % 8)) {
- if (entry.bit_length <= 64)
- cout << "UINT" << (unsigned int) entry.bit_length;
- else
- cout << "STRING("
- << (unsigned int) (entry.bit_length / 8)
- << ")";
- } else {
- cerr << "Invalid bit length "
- << (unsigned int) entry.bit_length << endl;
- }
-
- cout << "</DataType>" << endl;
- }
-
- cout << " </Entry>" << endl;
- }
-
- cout
- << " </" << pdoType << ">" << endl;
- }
- }
-
- cout
- << " </Device>" << endl
- << " </Devices>" << endl
- << " </Descriptions>" << endl
- << "</EtherCATInfo>" << endl;
-}
-#endif
+ if (fd != -1) {
+ ::close(fd);
+ fd = -1;
+ }
+}
+
/****************************************************************************/
unsigned int MasterDevice::slaveCount()
@@ -1755,8 +179,8 @@
/****************************************************************************/
-void MasterDevice::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex,
- unsigned int dataSize, unsigned char *mem)
+void MasterDevice::getData(ec_ioctl_domain_data_t *data,
+ unsigned int domainIndex, unsigned int dataSize, unsigned char *mem)
{
data->domain_index = domainIndex;
data->data_size = dataSize;
@@ -1799,13 +223,7 @@
if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) {
stringstream err;
- err << "Failed to get domain FMMU: ";
- if (errno == EINVAL)
- err << "Either domain " << domainIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) fmmuIndex + 1
- << " FMMus!";
- else
- err << strerror(errno);
+ err << "Failed to get domain FMMU: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1823,13 +241,7 @@
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC, sync)) {
stringstream err;
- err << "Failed to get sync manager: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers!";
- else
- err << strerror(errno);
+ err << "Failed to get sync manager: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1849,15 +261,7 @@
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO, pdo)) {
stringstream err;
- err << "Failed to get Pdo: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers, or sync manager "
- << (unsigned int) syncIndex << " contains less than "
- << pdoPos + 1 << " Pdos!" << endl;
- else
- err << strerror(errno);
+ err << "Failed to get Pdo: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1879,17 +283,7 @@
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO_ENTRY, entry)) {
stringstream err;
- err << "Failed to get Pdo entry: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers, or sync manager "
- << (unsigned int) syncIndex << " contains less than "
- << pdoPos + 1 << " Pdos, or the Pdo at position " << pdoPos
- << " contains less than " << (unsigned int) entryPos + 1
- << " entries!" << endl;
- else
- err << strerror(errno);
+ err << "Failed to get Pdo entry: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1907,13 +301,7 @@
if (ioctl(fd, EC_IOCTL_SLAVE_SDO, sdo)) {
stringstream err;
- err << "Failed to get Sdo: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << sdoPosition + 1 << " Sdos!"
- << endl;
- else
- err << strerror(errno);
+ err << "Failed to get Sdo: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1933,8 +321,7 @@
if (ioctl(fd, EC_IOCTL_SLAVE_SDO_ENTRY, entry)) {
stringstream err;
- err << "Failed to get Sdo entry: ";
- err << strerror(errno);
+ err << "Failed to get Sdo entry: " << strerror(errno);
throw MasterDeviceException(err.str());
}
}
@@ -1967,7 +354,51 @@
/****************************************************************************/
-#if 0
+void MasterDevice::setDebug(unsigned int debugLevel)
+{
+ if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) {
+ stringstream err;
+ err << "Failed to set debug level: " << strerror(errno);
+ throw MasterDeviceException(err.str());
+ }
+}
+
+/****************************************************************************/
+
+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;
+ } else {
+ err << strerror(errno);
+ }
+ throw MasterDeviceException(err.str());
+ }
+}
+
+/****************************************************************************/
+
+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;
+ } else {
+ err << strerror(errno);
+ }
+ throw MasterDeviceException(err.str());
+ }
+}
+
+/****************************************************************************/
+
void MasterDevice::requestState(
uint16_t slavePosition,
uint8_t state
@@ -1989,33 +420,4 @@
}
}
-/****************************************************************************/
-
-string Master::slaveState(uint8_t state)
-{
- switch (state) {
- case 1: return "INIT";
- case 2: return "PREOP";
- case 4: return "SAFEOP";
- case 8: return "OP";
- default: return "???";
- }
-}
-
-/****************************************************************************/
-
-void Master::printRawData(
- const uint8_t *data,
- unsigned int size)
-{
- cout << hex << setfill('0');
- while (size--) {
- cout << "0x" << setw(2) << (unsigned int) *data++;
- if (size)
- cout << " ";
- }
- cout << endl;
-}
-
-#endif
/*****************************************************************************/
--- a/tool/MasterDevice.h Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/MasterDevice.h Tue Jul 22 14:17:20 2008 +0000
@@ -8,9 +8,6 @@
#define __EC_MASTER_H__
#include <stdexcept>
-#include <string>
-#include <vector>
-#include <list>
using namespace std;
#include "../include/ecrt.h"
@@ -64,27 +61,12 @@
void getSdoEntry(ec_ioctl_slave_sdo_entry_t *, uint16_t, int, uint8_t);
void readSii(ec_ioctl_slave_sii_t *);
void writeSii(ec_ioctl_slave_sii_t *);
+ void setDebug(unsigned int);
+ void sdoDownload(ec_ioctl_slave_sdo_download_t *);
+ void sdoUpload(ec_ioctl_slave_sdo_upload_t *);
+ void requestState(uint16_t, uint8_t);
- protected:
-#if 0
- void outputDomainData(unsigned int);
- enum {BreakAfterBytes = 16};
- void showDomain(unsigned int);
- void listSlavePdos(uint16_t, bool = false);
- void listSlaveSdos(uint16_t, bool = false);
- void listSlaves(int);
- void showSlave(uint16_t);
- void generateSlaveXml(uint16_t);
- void requestState(uint16_t, uint8_t);
-
- static string slaveState(uint8_t);
- static void printRawData(const uint8_t *, unsigned int);
- static uint8_t calcSiiCrc(const uint8_t *, unsigned int);
-#endif
-
private:
- //enum {DefaultBufferSize = 1024};
-
unsigned int index;
int fd;
};
--- a/tool/cmd_alias.cpp Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/cmd_alias.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -10,6 +10,7 @@
using namespace std;
#include "globals.h"
+#include "sii_crc.h"
/*****************************************************************************/
@@ -82,47 +83,6 @@
/*****************************************************************************/
-/** Calculates the SII checksum field.
- *
- * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
- * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
- *
- * The below code was originally generated with PYCRC
- * http://www.tty1.net/pycrc
- *
- * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
- * --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
- *
- * \return CRC8
- */
-uint8_t calcSiiCrc(
- const uint8_t *data, /**< pointer to data */
- size_t length /**< number of bytes in \a data */
- )
-{
- unsigned int i;
- uint8_t bit, byte, crc = 0x48;
-
- while (length--) {
- byte = *data++;
- for (i = 0; i < 8; i++) {
- bit = crc & 0x80;
- crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
- if (bit) crc ^= 0x07;
- }
- }
-
- for (i = 0; i < 8; i++) {
- bit = crc & 0x80;
- crc <<= 1;
- if (bit) crc ^= 0x07;
- }
-
- return crc;
-}
-
-/*****************************************************************************/
-
/** Writes the Secondary slave address (alias) to the slave's SII.
*/
void writeSlaveAlias(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_data.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+using namespace std;
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+const char *help_data =
+ "[OPTIONS]\n"
+ "\n"
+ "Output binary domain data.\n"
+ "\n"
+ "Command-specific options:\n"
+ " --domain -d <index> Positive numerical domain index. If this option\n"
+ " is not specified, data of all domains are\n"
+ " output.\n";
+
+/****************************************************************************/
+
+void outputDomainData(unsigned int);
+
+/****************************************************************************/
+
+void command_data()
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (domainIndex == -1) {
+ unsigned int i;
+ ec_ioctl_master_t master;
+
+ masterDev.getMaster(&master);
+
+ for (i = 0; i < master.domain_count; i++) {
+ outputDomainData(i);
+ }
+ } else {
+ outputDomainData(domainIndex);
+ }
+}
+
+/****************************************************************************/
+
+void outputDomainData(unsigned int domainIndex)
+{
+ ec_ioctl_domain_t domain;
+ ec_ioctl_domain_data_t data;
+ unsigned char *processData;
+ unsigned int i;
+
+ masterDev.getDomain(&domain, domainIndex);
+
+ if (!domain.data_size)
+ return;
+
+ processData = new unsigned char[domain.data_size];
+
+ try {
+ masterDev.getData(&data, domainIndex, domain.data_size, processData);
+ } catch (MasterDeviceException &e) {
+ delete [] processData;
+ throw e;
+ }
+
+ for (i = 0; i < data.data_size; i++)
+ cout << processData[i];
+ cout.flush();
+
+ delete [] processData;
+}
+
+/****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_debug.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+const char *help_debug =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_debug(void)
+{
+ stringstream str;
+ int debugLevel;
+
+ if (commandArgs.size() != 1) {
+ stringstream err;
+ err << "'debug' takes exactly one argument!";
+ throw MasterDeviceException(err.str());
+ }
+
+ str << commandArgs[0];
+ str >> resetiosflags(ios::basefield) // guess base from prefix
+ >> debugLevel;
+
+ if (str.fail()) {
+ stringstream err;
+ err << "Invalid debug level '" << commandArgs[0] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ masterDev.open(MasterDevice::ReadWrite);
+ masterDev.setDebug(debugLevel);
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_domain.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,115 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+const char *help_domains =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void showDomain(unsigned int);
+
+/****************************************************************************/
+
+void command_domains(void)
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (domainIndex == -1) {
+ unsigned int i;
+ ec_ioctl_master_t master;
+
+ masterDev.getMaster(&master);
+
+ for (i = 0; i < master.domain_count; i++) {
+ showDomain(i);
+ }
+ } else {
+ showDomain(domainIndex);
+ }
+}
+
+/****************************************************************************/
+
+void showDomain(unsigned int domainIndex)
+{
+ ec_ioctl_domain_t domain;
+ unsigned char *processData;
+ ec_ioctl_domain_data_t data;
+ unsigned int i, j;
+ ec_ioctl_domain_fmmu_t fmmu;
+ unsigned int dataOffset;
+
+ masterDev.getDomain(&domain, domainIndex);
+
+ cout << "Domain" << dec << domainIndex << ":"
+ << " LogBaseAddr 0x"
+ << hex << setfill('0')
+ << setw(8) << domain.logical_base_address
+ << ", Size " << dec << setfill(' ')
+ << setw(3) << domain.data_size
+ << ", WorkingCounter "
+ << domain.working_counter << "/"
+ << domain.expected_working_counter << endl;
+
+ if (!domain.data_size || verbosity != Verbose)
+ return;
+
+ processData = new unsigned char[domain.data_size];
+
+ try {
+ masterDev.getData(&data, domainIndex, domain.data_size, processData);
+ } catch (MasterDeviceException &e) {
+ delete [] processData;
+ throw e;
+ }
+
+ for (i = 0; i < domain.fmmu_count; i++) {
+ masterDev.getFmmu(&fmmu, domainIndex, i);
+
+ cout << " SlaveConfig "
+ << dec << fmmu.slave_config_alias
+ << ":" << fmmu.slave_config_position
+ << ", SM" << (unsigned int) fmmu.sync_index << " ("
+ << setfill(' ') << setw(6)
+ << (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output")
+ << "), LogAddr 0x"
+ << hex << setfill('0')
+ << setw(8) << fmmu.logical_address
+ << ", Size " << dec << fmmu.data_size << endl;
+
+ dataOffset = fmmu.logical_address - domain.logical_base_address;
+ if (dataOffset + fmmu.data_size > domain.data_size) {
+ stringstream err;
+ err << "Fmmu information corrupted!";
+ delete [] processData;
+ throw MasterDeviceException(err.str());
+ }
+
+ cout << " " << hex << setfill('0');
+ for (j = 0; j < fmmu.data_size; j++) {
+ if (j && !(j % BreakAfterBytes))
+ cout << endl << " ";
+ cout << setw(2)
+ << (unsigned int) *(processData + dataOffset + j) << " ";
+ }
+ cout << endl;
+ }
+
+ delete [] processData;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_master.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_master =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_master(void)
+{
+ ec_ioctl_master_t data;
+ stringstream err;
+ unsigned int i;
+
+ masterDev.open(MasterDevice::Read);
+ masterDev.getMaster(&data);
+
+ cout
+ << "Master" << masterIndex << endl
+ << " Phase: ";
+
+ switch (data.phase) {
+ case 0: cout << "Waiting for device..."; break;
+ case 1: cout << "Idle"; break;
+ case 2: cout << "Operation"; break;
+ default:
+ err << "Invalid master phase " << data.phase;
+ throw MasterDeviceException(err.str());
+ }
+
+ cout << endl
+ << " Slaves: " << data.slave_count << endl;
+
+ for (i = 0; i < 2; i++) {
+ cout << " Device" << i << ": ";
+ if (data.devices[i].address[0] == 0x00
+ && data.devices[i].address[1] == 0x00
+ && data.devices[i].address[2] == 0x00
+ && data.devices[i].address[3] == 0x00
+ && data.devices[i].address[4] == 0x00
+ && data.devices[i].address[5] == 0x00) {
+ cout << "None.";
+ } else {
+ cout << hex << setfill('0')
+ << setw(2) << (unsigned int) data.devices[i].address[0] << ":"
+ << setw(2) << (unsigned int) data.devices[i].address[1] << ":"
+ << setw(2) << (unsigned int) data.devices[i].address[2] << ":"
+ << setw(2) << (unsigned int) data.devices[i].address[3] << ":"
+ << setw(2) << (unsigned int) data.devices[i].address[4] << ":"
+ << setw(2) << (unsigned int) data.devices[i].address[5] << " ("
+ << (data.devices[i].attached ? "attached" : "waiting...")
+ << ")" << endl << dec
+ << " Tx count: " << data.devices[i].tx_count << endl
+ << " Rx count: " << data.devices[i].rx_count;
+ }
+ cout << endl;
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_pdos.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_pdos =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void listSlavePdos(uint16_t, bool);
+
+/****************************************************************************/
+
+void command_pdos(void)
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (slavePosition == -1) {
+ unsigned int numSlaves = masterDev.slaveCount(), i;
+
+ for (i = 0; i < numSlaves; i++) {
+ listSlavePdos(i, true);
+ }
+ } else {
+ listSlavePdos(slavePosition, false);
+ }
+}
+
+/****************************************************************************/
+
+void listSlavePdos(uint16_t slavePosition, bool withHeader)
+{
+ ec_ioctl_slave_t slave;
+ ec_ioctl_slave_sync_t sync;
+ ec_ioctl_slave_sync_pdo_t pdo;
+ ec_ioctl_slave_sync_pdo_entry_t entry;
+ unsigned int i, j, k;
+
+ masterDev.getSlave(&slave, slavePosition);
+
+ if (withHeader)
+ cout << "=== Slave " << slavePosition << " ===" << endl;
+
+ for (i = 0; i < slave.sync_count; i++) {
+ masterDev.getSync(&sync, slavePosition, i);
+
+ cout << "SM" << i << ":"
+ << " PhysAddr 0x"
+ << hex << setfill('0')
+ << setw(4) << sync.physical_start_address
+ << ", DefaultSize "
+ << dec << setfill(' ') << setw(4) << sync.default_size
+ << ", ControlRegister 0x"
+ << hex << setfill('0') << setw(2)
+ << (unsigned int) sync.control_register
+ << ", Enable " << dec << (unsigned int) sync.enable
+ << endl;
+
+ for (j = 0; j < sync.pdo_count; j++) {
+ masterDev.getPdo(&pdo, slavePosition, i, j);
+
+ cout << " " << (sync.control_register & 0x04 ? "R" : "T")
+ << "xPdo 0x"
+ << hex << setfill('0')
+ << setw(4) << pdo.index
+ << " \"" << pdo.name << "\"" << endl;
+
+ if (verbosity == Quiet)
+ continue;
+
+ for (k = 0; k < pdo.entry_count; k++) {
+ masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
+
+ cout << " Pdo entry 0x"
+ << hex << setfill('0')
+ << setw(4) << entry.index
+ << ":" << setw(2) << (unsigned int) entry.subindex
+ << ", " << dec << (unsigned int) entry.bit_length
+ << " bit, \"" << entry.name << "\"" << endl;
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_sdo_download.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,180 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+#include "coe_datatypes.h"
+
+/****************************************************************************/
+
+const char *help_sdo_download =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_sdo_download(void)
+{
+ stringstream strIndex, strSubIndex, strValue, err;
+ ec_ioctl_slave_sdo_download_t data;
+ unsigned int number;
+ const CoEDataType *dataType = NULL;
+
+ if (slavePosition < 0) {
+ err << "'sdo_download' requires a slave! Please specify --slave.";
+ throw MasterDeviceException(err.str());
+ }
+ data.slave_position = slavePosition;
+
+ if (commandArgs.size() != 3) {
+ err << "'sdo_download' takes 3 arguments!";
+ throw MasterDeviceException(err.str());
+ }
+
+ strIndex << commandArgs[0];
+ strIndex
+ >> resetiosflags(ios::basefield) // guess base from prefix
+ >> data.sdo_index;
+ if (strIndex.fail()) {
+ err << "Invalid Sdo index '" << commandArgs[0] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ strSubIndex << commandArgs[1];
+ strSubIndex
+ >> resetiosflags(ios::basefield) // guess base from prefix
+ >> number;
+ if (strSubIndex.fail() || number > 0xff) {
+ err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+ data.sdo_entry_subindex = number;
+
+ if (dataTypeStr != "") { // data type specified
+ if (!(dataType = findDataType(dataTypeStr))) {
+ err << "Invalid data type '" << dataTypeStr << "'!";
+ throw MasterDeviceException(err.str());
+ }
+ } else { // no data type specified: fetch from dictionary
+ ec_ioctl_slave_sdo_entry_t entry;
+
+ masterDev.open(MasterDevice::ReadWrite);
+
+ try {
+ masterDev.getSdoEntry(&entry, slavePosition,
+ data.sdo_index, data.sdo_entry_subindex);
+ } catch (MasterDeviceException &e) {
+ err << "Failed to determine Sdo entry data type. "
+ << "Please specify --type.";
+ throw ExecutionFailureException(err);
+ }
+ if (!(dataType = findDataType(entry.data_type))) {
+ err << "Pdo entry has unknown data type 0x"
+ << hex << setfill('0') << setw(4) << entry.data_type << "!"
+ << " Please specify --type.";
+ throw ExecutionFailureException(err);
+ }
+ }
+
+ if (dataType->byteSize) {
+ data.data_size = dataType->byteSize;
+ } else {
+ data.data_size = DefaultBufferSize;
+ }
+
+ data.data = new uint8_t[data.data_size + 1];
+
+ strValue << commandArgs[2];
+ strValue >> resetiosflags(ios::basefield); // guess base from prefix
+ strValue.exceptions(ios::failbit);
+
+ try {
+ switch (dataType->coeCode) {
+ case 0x0002: // int8
+ {
+ int16_t val; // uint8_t is interpreted as char
+ strValue >> val;
+ if (val > 127 || val < -128)
+ throw ios::failure("Value out of range");
+ *data.data = val;
+ break;
+ }
+ case 0x0003: // int16
+ {
+ int16_t val;
+ strValue >> val;
+ *(int16_t *) data.data = cputole16(val);
+ break;
+ }
+ case 0x0004: // int32
+ {
+ int32_t val;
+ strValue >> val;
+ *(int32_t *) data.data = cputole32(val);
+ break;
+ }
+ case 0x0005: // uint8
+ {
+ uint16_t val; // uint8_t is interpreted as char
+ strValue >> val;
+ if (val > 0xff)
+ throw ios::failure("Value out of range");
+ *data.data = val;
+ break;
+ }
+ case 0x0006: // uint16
+ {
+ uint16_t val;
+ strValue >> val;
+ *(uint16_t *) data.data = cputole16(val);
+ break;
+ }
+ case 0x0007: // uint32
+ {
+ uint32_t val;
+ strValue >> val;
+ *(uint32_t *) data.data = cputole32(val);
+ break;
+ }
+ case 0x0009: // string
+ if (strValue.str().size() >= data.data_size) {
+ err << "String too large";
+ throw MasterDeviceException(err.str());
+ }
+ data.data_size = strValue.str().size();
+ strValue >> (char *) data.data;
+ break;
+
+ default:
+ delete [] data.data;
+ err << "Unknown data type 0x" << hex << dataType->coeCode;
+ throw MasterDeviceException(err.str());
+ }
+ } catch (ios::failure &e) {
+ delete [] data.data;
+ err << "Invalid value argument '" << commandArgs[2]
+ << "' for type '" << dataType->name << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ masterDev.open(MasterDevice::ReadWrite);
+
+ try {
+ masterDev.sdoDownload(&data);
+ } catch(MasterDeviceException &e) {
+ delete [] data.data;
+ throw e;
+ }
+
+ delete [] data.data;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_sdo_upload.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+#include "coe_datatypes.h"
+
+/****************************************************************************/
+
+const char *help_sdo_upload =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_sdo_upload(void)
+{
+ stringstream strIndex, strSubIndex;
+ int sval;
+ ec_ioctl_slave_sdo_upload_t data;
+ unsigned int uval;
+ const CoEDataType *dataType = NULL;
+
+ if (slavePosition < 0) {
+ stringstream err;
+ err << "'sdo_upload' requires a slave! Please specify --slave.";
+ throw MasterDeviceException(err.str());
+ }
+ data.slave_position = slavePosition;
+
+ if (commandArgs.size() != 2) {
+ stringstream err;
+ err << "'sdo_upload' takes two arguments!";
+ throw MasterDeviceException(err.str());
+ }
+
+ strIndex << commandArgs[0];
+ strIndex
+ >> resetiosflags(ios::basefield) // guess base from prefix
+ >> data.sdo_index;
+ if (strIndex.fail()) {
+ stringstream err;
+ err << "Invalid Sdo index '" << commandArgs[0] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ strSubIndex << commandArgs[1];
+ strSubIndex
+ >> resetiosflags(ios::basefield) // guess base from prefix
+ >> uval;
+ if (strSubIndex.fail() || uval > 0xff) {
+ stringstream err;
+ err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+ data.sdo_entry_subindex = uval;
+
+ if (dataTypeStr != "") { // data type specified
+ if (!(dataType = findDataType(dataTypeStr))) {
+ stringstream err;
+ err << "Invalid data type '" << dataTypeStr << "'!";
+ throw MasterDeviceException(err.str());
+ }
+ } else { // no data type specified: fetch from dictionary
+ ec_ioctl_slave_sdo_entry_t entry;
+
+ masterDev.open(MasterDevice::Read);
+
+ try {
+ masterDev.getSdoEntry(&entry, slavePosition,
+ data.sdo_index, data.sdo_entry_subindex);
+ } catch (MasterDeviceException &e) {
+ stringstream err;
+ err << "Failed to determine Sdo entry data type. "
+ << "Please specify --type.";
+ throw ExecutionFailureException(err);
+ }
+ if (!(dataType = findDataType(entry.data_type))) {
+ stringstream err;
+ err << "Pdo entry has unknown data type 0x"
+ << hex << setfill('0') << setw(4) << entry.data_type << "!"
+ << " Please specify --type.";
+ throw ExecutionFailureException(err);
+ }
+ }
+
+ if (dataType->byteSize) {
+ data.target_size = dataType->byteSize;
+ } else {
+ data.target_size = DefaultBufferSize;
+ }
+
+ data.target = new uint8_t[data.target_size + 1];
+
+ masterDev.open(MasterDevice::Read);
+
+ try {
+ masterDev.sdoUpload(&data);
+ } catch (MasterDeviceException &e) {
+ delete [] data.target;
+ throw e;
+ }
+
+ masterDev.close();
+
+ if (dataType->byteSize && data.data_size != dataType->byteSize) {
+ stringstream err;
+ err << "Data type mismatch. Expected " << dataType->name
+ << " with " << dataType->byteSize << " byte, but got "
+ << data.data_size << " byte.";
+ throw MasterDeviceException(err.str());
+ }
+
+ cout << setfill('0');
+ switch (dataType->coeCode) {
+ case 0x0002: // int8
+ sval = *(int8_t *) data.target;
+ cout << sval << " 0x" << hex << setw(2) << sval << endl;
+ break;
+ case 0x0003: // int16
+ sval = le16tocpu(*(int16_t *) data.target);
+ cout << sval << " 0x" << hex << setw(4) << sval << endl;
+ break;
+ case 0x0004: // int32
+ sval = le32tocpu(*(int32_t *) data.target);
+ cout << sval << " 0x" << hex << setw(8) << sval << endl;
+ break;
+ case 0x0005: // uint8
+ uval = (unsigned int) *(uint8_t *) data.target;
+ cout << uval << " 0x" << hex << setw(2) << uval << endl;
+ break;
+ case 0x0006: // uint16
+ uval = le16tocpu(*(uint16_t *) data.target);
+ cout << uval << " 0x" << hex << setw(4) << uval << endl;
+ break;
+ case 0x0007: // uint32
+ uval = le32tocpu(*(uint32_t *) data.target);
+ cout << uval << " 0x" << hex << setw(8) << uval << endl;
+ break;
+ case 0x0009: // string
+ cout << string((const char *) data.target, data.data_size)
+ << endl;
+ break;
+ default:
+ printRawData(data.target, data.data_size);
+ break;
+ }
+
+ delete [] data.target;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_sdos.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+#include "coe_datatypes.h"
+
+/****************************************************************************/
+
+const char *help_sdos =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void listSlaveSdos(uint16_t, bool);
+
+/****************************************************************************/
+
+void command_sdos(void)
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (slavePosition == -1) {
+ unsigned int numSlaves = masterDev.slaveCount(), i;
+
+ for (i = 0; i < numSlaves; i++) {
+ listSlaveSdos(i, true);
+ }
+ } else {
+ listSlaveSdos(slavePosition, false);
+ }
+}
+
+/****************************************************************************/
+
+void listSlaveSdos(
+ uint16_t slavePosition,
+ bool withHeader
+ )
+{
+ ec_ioctl_slave_t slave;
+ ec_ioctl_slave_sdo_t sdo;
+ ec_ioctl_slave_sdo_entry_t entry;
+ unsigned int i, j;
+ const CoEDataType *d;
+
+ masterDev.getSlave(&slave, slavePosition);
+
+ if (withHeader)
+ cout << "=== Slave " << slavePosition << " ===" << endl;
+
+ for (i = 0; i < slave.sdo_count; i++) {
+ masterDev.getSdo(&sdo, slavePosition, i);
+
+ cout << "Sdo 0x"
+ << hex << setfill('0')
+ << setw(4) << sdo.sdo_index
+ << ", \"" << sdo.name << "\"" << endl;
+
+ if (verbosity == Quiet)
+ continue;
+
+ for (j = 0; j <= sdo.max_subindex; j++) {
+ masterDev.getSdoEntry(&entry, slavePosition, -i, j);
+
+ cout << " 0x" << hex << setfill('0')
+ << setw(4) << sdo.sdo_index << ":"
+ << setw(2) << (unsigned int) entry.sdo_entry_subindex
+ << ", ";
+
+ if ((d = findDataType(entry.data_type))) {
+ cout << d->name;
+ } else {
+ cout << "type " << setw(4) << entry.data_type;
+ }
+
+ cout << ", " << dec << entry.bit_length << " bit, \""
+ << entry.description << "\"" << endl;
+ }
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_sii_read.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_sii_read =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+struct CategoryName {
+ uint16_t type;
+ const char *name;
+};
+
+static const CategoryName categoryNames[] = {
+ {0x000a, "STRINGS"},
+ {0x0014, "DataTypes"},
+ {0x001e, "General"},
+ {0x0028, "FMMU"},
+ {0x0029, "SyncM"},
+ {0x0032, "TXPDO"},
+ {0x0033, "RXPDO"},
+ {0x003c, "DC"},
+ {}
+};
+
+/****************************************************************************/
+
+const char *getCategoryName(uint16_t type)
+{
+ const CategoryName *cn = categoryNames;
+
+ while (cn->type) {
+ if (cn->type == type) {
+ return cn->name;
+ }
+ cn++;
+ }
+
+ return "unknown";
+}
+
+/****************************************************************************/
+
+void command_sii_read(void)
+{
+ ec_ioctl_slave_sii_t data;
+ ec_ioctl_slave_t slave;
+ unsigned int i;
+ const uint16_t *categoryHeader;
+ uint16_t categoryType, categorySize;
+ stringstream err;
+
+ if (slavePosition < 0) {
+ stringstream err;
+ err << "'sii_read' requires a slave! Please specify --slave.";
+ throw MasterDeviceException(err.str());
+ }
+ data.slave_position = slavePosition;
+
+ masterDev.open(MasterDevice::Read);
+
+ masterDev.getSlave(&slave, slavePosition);
+
+ if (!slave.sii_nwords)
+ return;
+
+ data.offset = 0;
+ data.nwords = slave.sii_nwords;
+ data.words = new uint16_t[data.nwords];
+
+ try {
+ masterDev.readSii(&data);
+ } catch (MasterDeviceException &e) {
+ delete [] data.words;
+ throw e;
+ }
+
+ if (verbosity == Verbose) {
+ cout << "SII Area:" << hex << setfill('0');
+ for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) {
+ if (i % BreakAfterBytes) {
+ cout << " ";
+ } else {
+ cout << endl << " ";
+ }
+ cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i);
+ }
+ cout << endl;
+
+ if (data.nwords > 0x0040U) {
+ // cycle through categories
+ categoryHeader = data.words + 0x0040U;
+ categoryType = le16tocpu(*categoryHeader);
+ while (categoryType != 0xffff) {
+ cout << "SII Category 0x" << hex
+ << setw(4) << categoryType
+ << " (" << getCategoryName(categoryType) << ")" << flush;
+
+ if (categoryHeader + 1 > data.words + data.nwords) {
+ err << "SII data seem to be corrupted!";
+ throw MasterDeviceException(err.str());
+ }
+ categorySize = le16tocpu(*(categoryHeader + 1));
+ cout << ", " << dec << categorySize << " words" << flush;
+
+ if (categoryHeader + 2 + categorySize
+ > data.words + data.nwords) {
+ err << "SII data seem to be corrupted!";
+ throw MasterDeviceException(err.str());
+ }
+
+ cout << hex;
+ for (i = 0; i < categorySize * 2U; i++) {
+ if (i % BreakAfterBytes) {
+ cout << " ";
+ } else {
+ cout << endl << " ";
+ }
+ cout << setw(2) << (unsigned int)
+ *((uint8_t *) (categoryHeader + 2) + i);
+ }
+ cout << endl;
+
+ if (categoryHeader + 2 + categorySize + 1
+ > data.words + data.nwords) {
+ err << "SII data seem to be corrupted!";
+ throw MasterDeviceException(err.str());
+ }
+ categoryHeader += 2 + categorySize;
+ categoryType = le16tocpu(*categoryHeader);
+ }
+ }
+ } else {
+ for (i = 0; i < data.nwords; i++) {
+ uint16_t *w = data.words + i;
+ cout << *(uint8_t *) w << *((uint8_t *) w + 1);
+ }
+ }
+
+ delete [] data.words;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_sii_write.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,112 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+using namespace std;
+
+#include "globals.h"
+#include "sii_crc.h"
+
+/****************************************************************************/
+
+const char *help_sii_write =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_sii_write(void)
+{
+ stringstream err;
+ ec_ioctl_slave_sii_t data;
+ ifstream file;
+ unsigned int byte_size;
+ const uint16_t *categoryHeader;
+ uint16_t categoryType, categorySize;
+ uint8_t crc;
+
+ if (slavePosition < 0) {
+ err << "'sii_write' requires a slave! Please specify --slave.";
+ throw MasterDeviceException(err.str());
+ }
+ data.slave_position = slavePosition;
+
+ if (commandArgs.size() != 1) {
+ err << "'ssi_write' takes exactly one argument!";
+ throw MasterDeviceException(err.str());
+ }
+
+ file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary);
+ if (file.fail()) {
+ err << "Failed to open '" << commandArgs[0] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ // get length of file
+ file.seekg(0, ios::end);
+ byte_size = file.tellg();
+ file.seekg(0, ios::beg);
+
+ if (!byte_size || byte_size % 2) {
+ stringstream err;
+ err << "Invalid file size! Must be non-zero and even.";
+ throw MasterDeviceException(err.str());
+ }
+
+ data.nwords = byte_size / 2;
+ if (data.nwords < 0x0041 && !force) {
+ err << "SII data too short (" << data.nwords << " words)! Mimimum is"
+ " 40 fixed words + 1 delimiter. Use --force to write anyway.";
+ throw MasterDeviceException(err.str());
+ }
+
+ // allocate buffer and read file into buffer
+ data.words = new uint16_t[data.nwords];
+ file.read((char *) data.words, byte_size);
+ file.close();
+
+ if (!force) {
+ // calculate checksum over words 0 to 6
+ crc = calcSiiCrc((const uint8_t *) data.words, 14);
+ if (crc != ((const uint8_t *) data.words)[14]) {
+ err << "CRC incorrect. Must be 0x"
+ << hex << setfill('0') << setw(2) << (unsigned int) crc
+ << ". Use --force to write anyway.";
+ throw MasterDeviceException(err.str());
+ }
+
+ // cycle through categories to detect corruption
+ categoryHeader = data.words + 0x0040U;
+ categoryType = le16tocpu(*categoryHeader);
+ while (categoryType != 0xffff) {
+ if (categoryHeader + 1 > data.words + data.nwords) {
+ err << "SII data seem to be corrupted! "
+ << "Use --force to write anyway.";
+ throw MasterDeviceException(err.str());
+ }
+ categorySize = le16tocpu(*(categoryHeader + 1));
+ if (categoryHeader + 2 + categorySize + 1
+ > data.words + data.nwords) {
+ err << "SII data seem to be corrupted! "
+ "Use --force to write anyway.";
+ throw MasterDeviceException(err.str());
+ }
+ categoryHeader += 2 + categorySize;
+ categoryType = le16tocpu(*categoryHeader);
+ }
+ }
+
+ // send data to master
+ masterDev.open(MasterDevice::ReadWrite);
+ data.offset = 0;
+ masterDev.writeSii(&data);
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_slaves.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,254 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+#include <list>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_slaves =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+void listSlaves(int);
+void showSlave(uint16_t);
+
+/****************************************************************************/
+
+void command_slaves()
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (verbosity == Verbose) {
+ if (slavePosition == -1) {
+ unsigned int numSlaves = masterDev.slaveCount(), i;
+
+ for (i = 0; i < numSlaves; i++) {
+ showSlave(i);
+ }
+ } else {
+ showSlave(slavePosition);
+ }
+ } else {
+ listSlaves(slavePosition);
+ }
+}
+
+/****************************************************************************/
+
+string slaveState(uint8_t state)
+{
+ switch (state) {
+ case 1: return "INIT";
+ case 2: return "PREOP";
+ case 4: return "SAFEOP";
+ case 8: return "OP";
+ default: return "???";
+ }
+}
+
+/****************************************************************************/
+
+struct SlaveInfo {
+ string pos;
+ string alias;
+ string relPos;
+ string state;
+ string flag;
+ string name;
+};
+
+void listSlaves(int slavePosition)
+{
+ unsigned int numSlaves, i;
+ ec_ioctl_slave_t slave;
+ uint16_t lastAlias, aliasIndex;
+ SlaveInfo slaveInfo;
+ typedef list<SlaveInfo> SlaveInfoList;
+ SlaveInfoList slaveInfoList;
+ SlaveInfoList::const_iterator iter;
+ stringstream str;
+ unsigned int maxPosWidth = 0, maxAliasWidth = 0,
+ maxRelPosWidth = 0, maxStateWidth = 0;
+
+ numSlaves = masterDev.slaveCount();
+
+ lastAlias = 0;
+ aliasIndex = 0;
+ for (i = 0; i < numSlaves; i++) {
+ masterDev.getSlave(&slave, i);
+
+ if (slave.alias) {
+ lastAlias = slave.alias;
+ aliasIndex = 0;
+ }
+
+ if (slavePosition == -1 || i == (unsigned int) slavePosition) {
+ str << dec << i;
+ slaveInfo.pos = str.str();
+ str.clear();
+ str.str("");
+
+ str << lastAlias;
+ slaveInfo.alias = str.str();
+ str.str("");
+
+ str << aliasIndex;
+ slaveInfo.relPos = str.str();
+ str.str("");
+
+ slaveInfo.state = slaveState(slave.state);
+ slaveInfo.flag = (slave.error_flag ? 'E' : '+');
+
+ if (strlen(slave.name)) {
+ slaveInfo.name = slave.name;
+ } else {
+ str << "0x" << hex << setfill('0')
+ << setw(8) << slave.vendor_id << ":0x"
+ << setw(8) << slave.product_code;
+ slaveInfo.name = str.str();
+ str.str("");
+ }
+
+
+ slaveInfoList.push_back(slaveInfo);
+
+ if (slaveInfo.pos.length() > maxPosWidth)
+ maxPosWidth = slaveInfo.pos.length();
+ if (slaveInfo.alias.length() > maxAliasWidth)
+ maxAliasWidth = slaveInfo.alias.length();
+ if (slaveInfo.relPos.length() > maxRelPosWidth)
+ maxRelPosWidth = slaveInfo.relPos.length();
+ if (slaveInfo.state.length() > maxStateWidth)
+ maxStateWidth = slaveInfo.state.length();
+ }
+
+ aliasIndex++;
+ }
+
+ for (iter = slaveInfoList.begin(); iter != slaveInfoList.end(); iter++) {
+ cout << setfill(' ') << right
+ << setw(maxPosWidth) << iter->pos << " "
+ << setw(maxAliasWidth) << iter->alias
+ << ":" << left
+ << setw(maxRelPosWidth) << iter->relPos << " "
+ << setw(maxStateWidth) << iter->state << " "
+ << iter->flag << " "
+ << iter->name << endl;
+ }
+}
+
+/****************************************************************************/
+
+void showSlave(uint16_t slavePosition)
+{
+ ec_ioctl_slave_t slave;
+ list<string> protoList;
+ list<string>::const_iterator protoIter;
+
+ masterDev.getSlave(&slave, slavePosition);
+
+ cout << "=== Slave " << dec << slavePosition << " ===" << endl;
+
+ if (slave.alias)
+ cout << "Alias: " << slave.alias << endl;
+
+ cout
+ << "State: " << slaveState(slave.state) << endl
+ << "Flag: " << (slave.error_flag ? 'E' : '+') << endl
+ << "Identity:" << endl
+ << " Vendor Id: 0x"
+ << hex << setfill('0')
+ << setw(8) << slave.vendor_id << endl
+ << " Product code: 0x"
+ << setw(8) << slave.product_code << endl
+ << " Revision number: 0x"
+ << setw(8) << slave.revision_number << endl
+ << " Serial number: 0x"
+ << setw(8) << slave.serial_number << endl;
+
+ if (slave.mailbox_protocols) {
+ cout << "Mailboxes:" << endl
+ << " RX: 0x"
+ << hex << setw(4) << slave.rx_mailbox_offset << "/"
+ << dec << slave.rx_mailbox_size
+ << ", TX: 0x"
+ << hex << setw(4) << slave.tx_mailbox_offset << "/"
+ << dec << slave.tx_mailbox_size << endl
+ << " Supported protocols: ";
+
+ if (slave.mailbox_protocols & EC_MBOX_AOE) {
+ protoList.push_back("AoE");
+ }
+ if (slave.mailbox_protocols & EC_MBOX_EOE) {
+ protoList.push_back("EoE");
+ }
+ if (slave.mailbox_protocols & EC_MBOX_COE) {
+ protoList.push_back("CoE");
+ }
+ if (slave.mailbox_protocols & EC_MBOX_FOE) {
+ protoList.push_back("FoE");
+ }
+ if (slave.mailbox_protocols & EC_MBOX_SOE) {
+ protoList.push_back("SoE");
+ }
+ if (slave.mailbox_protocols & EC_MBOX_VOE) {
+ protoList.push_back("VoE");
+ }
+
+ for (protoIter = protoList.begin(); protoIter != protoList.end();
+ protoIter++) {
+ if (protoIter != protoList.begin())
+ cout << ", ";
+ cout << *protoIter;
+ }
+ cout << endl;
+ }
+
+ if (slave.has_general_category) {
+ cout << "General:" << endl
+ << " Group: " << slave.group << endl
+ << " Image name: " << slave.image << endl
+ << " Order number: " << slave.order << endl
+ << " Device name: " << slave.name << endl;
+
+ if (slave.mailbox_protocols & EC_MBOX_COE) {
+ cout << " CoE details:" << endl
+ << " Enable Sdo: "
+ << (slave.coe_details.enable_sdo ? "yes" : "no") << endl
+ << " Enable Sdo Info: "
+ << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl
+ << " Enable Pdo Assign: "
+ << (slave.coe_details.enable_pdo_assign
+ ? "yes" : "no") << endl
+ << " Enable Pdo Configuration: "
+ << (slave.coe_details.enable_pdo_configuration
+ ? "yes" : "no") << endl
+ << " Enable Upload at startup: "
+ << (slave.coe_details.enable_upload_at_startup
+ ? "yes" : "no") << endl
+ << " Enable Sdo complete access: "
+ << (slave.coe_details.enable_sdo_complete_access
+ ? "yes" : "no") << endl;
+ }
+
+ cout << " Flags:" << endl
+ << " Enable SafeOp: "
+ << (slave.general_flags.enable_safeop ? "yes" : "no") << endl
+ << " Enable notLRW: "
+ << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl
+ << " Current consumption: "
+ << dec << slave.current_on_ebus << " mA" << endl;
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_states.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_states =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void command_states(void)
+{
+ string stateStr;
+ uint8_t state;
+
+ if (commandArgs.size() != 1) {
+ stringstream err;
+ err << "'state' takes exactly one argument!";
+ throw MasterDeviceException(err.str());
+ }
+
+ stateStr = commandArgs[0];
+ transform(stateStr.begin(), stateStr.end(),
+ stateStr.begin(), (int (*) (int)) std::toupper);
+
+ if (stateStr == "INIT") {
+ state = 0x01;
+ } else if (stateStr == "PREOP") {
+ state = 0x02;
+ } else if (stateStr == "SAFEOP") {
+ state = 0x04;
+ } else if (stateStr == "OP") {
+ state = 0x08;
+ } else {
+ stringstream err;
+ err << "Invalid state '" << commandArgs[0] << "'!";
+ throw MasterDeviceException(err.str());
+ }
+
+ masterDev.open(MasterDevice::ReadWrite);
+
+ if (slavePosition == -1) {
+ unsigned int i, numSlaves = masterDev.slaveCount();
+ for (i = 0; i < numSlaves; i++)
+ masterDev.requestState(i, state);
+ } else {
+ masterDev.requestState(slavePosition, state);
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/cmd_xml.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#include "globals.h"
+
+/****************************************************************************/
+
+const char *help_xml =
+ "[OPTIONS]\n"
+ "\n"
+ "\n"
+ "Command-specific options:\n";
+
+/****************************************************************************/
+
+void generateSlaveXml(uint16_t);
+
+/****************************************************************************/
+
+void command_xml(void)
+{
+ masterDev.open(MasterDevice::Read);
+
+ if (slavePosition == -1) {
+ unsigned int numSlaves = masterDev.slaveCount(), i;
+
+ for (i = 0; i < numSlaves; i++) {
+ generateSlaveXml(i);
+ }
+ } else {
+ generateSlaveXml(slavePosition);
+ }
+}
+
+/****************************************************************************/
+
+void generateSlaveXml(uint16_t slavePosition)
+{
+ ec_ioctl_slave_t slave;
+ ec_ioctl_slave_sync_t sync;
+ ec_ioctl_slave_sync_pdo_t pdo;
+ string pdoType;
+ ec_ioctl_slave_sync_pdo_entry_t entry;
+ unsigned int i, j, k;
+
+ masterDev.getSlave(&slave, slavePosition);
+
+ cout
+ << "<?xml version=\"1.0\" ?>" << endl
+ << " <EtherCATInfo>" << endl
+ << " <!-- Slave " << slave.position << " -->" << endl
+ << " <Vendor>" << endl
+ << " <Id>" << slave.vendor_id << "</Id>" << endl
+ << " </Vendor>" << endl
+ << " <Descriptions>" << endl
+ << " <Devices>" << endl
+ << " <Device>" << endl
+ << " <Type ProductCode=\"#x"
+ << hex << setfill('0') << setw(8) << slave.product_code
+ << "\" RevisionNo=\"#x"
+ << hex << setfill('0') << setw(8) << slave.revision_number
+ << "\">" << slave.order << "</Type>" << endl;
+
+ if (strlen(slave.name)) {
+ cout
+ << " <Name><![CDATA["
+ << slave.name
+ << "]]></Name>" << endl;
+ }
+
+ for (i = 0; i < slave.sync_count; i++) {
+ masterDev.getSync(&sync, slavePosition, i);
+
+ cout
+ << " <Sm Enable=\"" << dec << (unsigned int) sync.enable
+ << "\" StartAddress=\"" << sync.physical_start_address
+ << "\" ControlByte=\"" << (unsigned int) sync.control_register
+ << "\" DefaultSize=\"" << sync.default_size
+ << "\" />" << endl;
+ }
+
+ for (i = 0; i < slave.sync_count; i++) {
+ masterDev.getSync(&sync, slavePosition, i);
+
+ for (j = 0; j < sync.pdo_count; j++) {
+ masterDev.getPdo(&pdo, slavePosition, i, j);
+ pdoType = (sync.control_register & 0x04 ? "R" : "T");
+ pdoType += "xPdo";
+
+ cout
+ << " <" << pdoType
+ << " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl
+ << " <Index>#x"
+ << hex << setfill('0') << setw(4) << pdo.index
+ << "</Index>" << endl
+ << " <Name>" << pdo.name << "</Name>" << endl;
+
+ for (k = 0; k < pdo.entry_count; k++) {
+ masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
+
+ cout
+ << " <Entry>" << endl
+ << " <Index>#x"
+ << hex << setfill('0') << setw(4) << entry.index
+ << "</Index>" << endl;
+ if (entry.index)
+ cout
+ << " <SubIndex>"
+ << dec << (unsigned int) entry.subindex
+ << "</SubIndex>" << endl;
+
+ cout
+ << " <BitLen>"
+ << dec << (unsigned int) entry.bit_length
+ << "</BitLen>" << endl;
+
+ if (entry.index) {
+ cout
+ << " <Name>" << entry.name
+ << "</Name>" << endl
+ << " <DataType>";
+
+ if (entry.bit_length == 1) {
+ cout << "BOOL";
+ } else if (!(entry.bit_length % 8)) {
+ if (entry.bit_length <= 64)
+ cout << "UINT" << (unsigned int) entry.bit_length;
+ else
+ cout << "STRING("
+ << (unsigned int) (entry.bit_length / 8)
+ << ")";
+ } else {
+ cerr << "Invalid bit length "
+ << (unsigned int) entry.bit_length << endl;
+ }
+
+ cout << "</DataType>" << endl;
+ }
+
+ cout << " </Entry>" << endl;
+ }
+
+ cout
+ << " </" << pdoType << ">" << endl;
+ }
+ }
+
+ cout
+ << " </Device>" << endl
+ << " </Devices>" << endl
+ << " </Descriptions>" << endl
+ << "</EtherCATInfo>" << endl;
+}
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/coe_datatypes.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ *
+ * $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;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/coe_datatypes.h Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,25 @@
+/*****************************************************************************
+ *
+ * $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);
+
+/*****************************************************************************/
--- a/tool/globals.h Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/globals.h Tue Jul 22 14:17:20 2008 +0000
@@ -22,6 +22,7 @@
};
extern string commandName;
+extern unsigned int masterIndex;
extern int slavePosition;
extern int domainIndex;
extern vector<string> commandArgs;
@@ -87,3 +88,10 @@
#endif
/****************************************************************************/
+
+enum {BreakAfterBytes = 16};
+enum {DefaultBufferSize = 1024};
+
+void printRawData(const uint8_t *, unsigned int);
+
+/****************************************************************************/
--- a/tool/main.cpp Tue Jul 22 11:38:21 2008 +0000
+++ b/tool/main.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -8,8 +8,10 @@
#include <libgen.h> // basename()
#include <iostream>
+#include <iomanip>
#include <string>
#include <vector>
+#include <list>
using namespace std;
#include "globals.h"
@@ -36,6 +38,7 @@
const char *name;
void (*func)(void);
const char *helpString;
+ const char *briefDesc;
int execute(void) const;
void displayHelp(void) const;
@@ -43,72 +46,73 @@
/*****************************************************************************/
-#define COMMAND(name) \
+#define DEFINE_EXTERN_COMMAND(name) \
void command_##name(void); \
extern const char *help_##name
-#define INIT_COMMAND(name) {#name, command_##name, help_##name}
-
-COMMAND(alias);
-COMMAND(config);
+#define INIT_COMMAND(name, desc) \
+ {#name, command_##name, help_##name, desc}
+
+DEFINE_EXTERN_COMMAND(alias);
+DEFINE_EXTERN_COMMAND(config);
+DEFINE_EXTERN_COMMAND(data);
+DEFINE_EXTERN_COMMAND(debug);
+DEFINE_EXTERN_COMMAND(domains);
+DEFINE_EXTERN_COMMAND(master);
+DEFINE_EXTERN_COMMAND(pdos);
+DEFINE_EXTERN_COMMAND(sdos);
+DEFINE_EXTERN_COMMAND(sdo_download);
+DEFINE_EXTERN_COMMAND(sdo_upload);
+DEFINE_EXTERN_COMMAND(slaves);
+DEFINE_EXTERN_COMMAND(sii_read);
+DEFINE_EXTERN_COMMAND(sii_write);
+DEFINE_EXTERN_COMMAND(states);
+DEFINE_EXTERN_COMMAND(xml);
static const Command commands[] = {
- INIT_COMMAND(alias),
- INIT_COMMAND(config),
+ INIT_COMMAND(alias, "Write alias addresses."),
+ INIT_COMMAND(config, "Show bus configuration."),
+ INIT_COMMAND(data, "Output binary domain process data."),
+ INIT_COMMAND(debug, "Set the master's debug level."),
+ INIT_COMMAND(domains, "Show domain information."),
+ INIT_COMMAND(master, "Show master information."),
+ INIT_COMMAND(pdos, "List Pdo assignment/mapping."),
+ INIT_COMMAND(sdos, "List Sdo dictionaries."),
+ INIT_COMMAND(sdo_download, "Write an Sdo entry."),
+ INIT_COMMAND(sdo_upload, "Read an Sdo entry."),
+ INIT_COMMAND(slaves, "Show slaves."),
+ INIT_COMMAND(sii_read, "Output a slave's SII contents."),
+ INIT_COMMAND(sii_write, "Write slave's SII contents."),
+ INIT_COMMAND(states, "Request slave states."),
+ INIT_COMMAND(xml, "Generate slave information xmls."),
};
-#if 0
- } else if (command == "data") {
- master.outputData(domainIndex);
- } else if (command == "debug") {
- master.setDebug(commandArgs);
- } else if (command == "domain") {
- master.showDomains(domainIndex);
- } else if (command == "master") {
- master.showMaster();
- } else if (command == "pdos") {
- master.listPdos(slavePosition);
- } else if (command == "sdos") {
- master.listSdos(slavePosition);
- } else if (command == "sdo_download" || command == "sd") {
- master.sdoDownload(slavePosition, dataTypeStr, commandArgs);
- } else if (command == "sdo_upload" || command == "su") {
- master.sdoUpload(slavePosition, dataTypeStr, commandArgs);
- } else if (command == "slave" || command == "slaves"
- || command == "list" || command == "ls") {
- master.showSlaves(slavePosition);
- } else if (command == "sii_read" || command == "sr") {
- master.siiRead(slavePosition);
- } else if (command == "sii_write" || command == "sw") {
- master.siiWrite(slavePosition, force, commandArgs);
- } else if (command == "state") {
- master.requestStates(slavePosition, commandArgs);
- } else if (command == "xml") {
- master.generateXml(slavePosition);
-#endif
+static const Command *cmdEnd = commands + sizeof(commands) / sizeof(Command);
/*****************************************************************************/
void printUsage()
{
+ const Command *cmd;
+ size_t maxWidth = 0;
+
+ for (cmd = commands; cmd < cmdEnd; cmd++) {
+ if (strlen(cmd->name) > maxWidth) {
+ maxWidth = strlen(cmd->name);
+ }
+ }
+
cerr
<< "Usage: " << binaryBaseName << " <COMMAND> [OPTIONS]" << endl
- << "Commands:" << endl
- << " alias Write alias addresses." << endl
- << " config Show bus configuration." << endl
- << " data Output binary domain process data." << endl
- << " debug Set the master's debug level." << endl
- << " domain Show domain information." << endl
- << " master Show master information." << endl
- << " pdos List Pdo assignment/mapping." << endl
- << " sdo_download Write an Sdo entry." << endl
- << " sdos List Sdo dictionaries." << endl
- << " sdo_upload Read an Sdo entry." << endl
- << " sii_read Output a slave's SII contents." << endl
- << " sii_write Write slave's SII contents." << endl
- << " slaves Show slaves." << endl
- << " state Request slave states." << endl
- << " xml Generate slave information xmls." << endl
+ << "Commands:" << endl;
+
+ cerr << left;
+ for (cmd = commands; cmd < cmdEnd; cmd++) {
+ cerr << " " << setw(maxWidth) << cmd->name
+ << " " << cmd->briefDesc << endl;
+ }
+
+ cerr
<< "Commands can be generously abbreviated." << endl
<< "Global options:" << endl
<< " --master -m <master> Index of the master to use. Default: 0"
@@ -117,8 +121,6 @@
<< endl
<< " or 'all' for all slaves (default)."
<< endl
- << " --domain -d <index> Positive numerical index,"
- << endl
<< " or 'all' for all domains (default)."
<< endl
<< " --type -t <type> Forced Sdo data type." << endl
@@ -289,12 +291,11 @@
list<const Command *> getMatchingCommands(const string &cmdStr)
{
- const Command *cmd, *endCmd =
- commands + sizeof(commands) / sizeof(Command);
+ const Command *cmd;
list<const Command *> res;
// find matching commands
- for (cmd = commands; cmd < endCmd; cmd++) {
+ for (cmd = commands; cmd < cmdEnd; cmd++) {
if (abbrevMatch(cmdStr, cmd->name)) {
res.push_back(cmd);
}
@@ -345,3 +346,19 @@
}
/****************************************************************************/
+
+void printRawData(
+ const uint8_t *data,
+ unsigned int size
+ )
+{
+ cout << hex << setfill('0');
+ while (size--) {
+ cout << "0x" << setw(2) << (unsigned int) *data++;
+ if (size)
+ cout << " ";
+ }
+ cout << endl;
+}
+
+/****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/sii_crc.cpp Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include "sii_crc.h"
+
+/*****************************************************************************/
+
+/** Calculates the SII checksum field.
+ *
+ * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
+ * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
+ *
+ * The below code was originally generated with PYCRC
+ * http://www.tty1.net/pycrc
+ *
+ * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
+ * --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
+ *
+ * \return CRC8
+ */
+uint8_t calcSiiCrc(
+ const uint8_t *data, /**< pointer to data */
+ size_t length /**< number of bytes in \a data */
+ )
+{
+ unsigned int i;
+ uint8_t bit, byte, crc = 0x48;
+
+ while (length--) {
+ byte = *data++;
+ for (i = 0; i < 8; i++) {
+ bit = crc & 0x80;
+ crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
+ if (bit) crc ^= 0x07;
+ }
+ }
+
+ for (i = 0; i < 8; i++) {
+ bit = crc & 0x80;
+ crc <<= 1;
+ if (bit) crc ^= 0x07;
+ }
+
+ return crc;
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/sii_crc.h Tue Jul 22 14:17:20 2008 +0000
@@ -0,0 +1,11 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ ****************************************************************************/
+
+#include <iostream>
+
+uint8_t calcSiiCrc(const uint8_t *, size_t);
+
+/*****************************************************************************/