Improved exceptions and commandName usage.

This commit is contained in:
Florian Pose 2008-07-23 08:06:10 +00:00
parent 206990db10
commit ca217cf27d
14 changed files with 100 additions and 106 deletions

22
TODO
View File

@ -11,22 +11,22 @@ Version 1.4.0:
* Read Pdo mapping for unknown Pdos before configuring them.
* Attach Pdo names from SII or Coe dictioary to Pdos read via CoE.
* Update documentation.
* Add -a and -p switches for 'ethercat config' command.
* Add a -n (numeric) switch to ethercat command.
* Add help pages for every ethercat command.
* Show Pdos in 'ethercat slave -v'.
* Allow master requesting when in ORPHANED phase
* Get original driver for r8169.
* Race in jiffies frame timeout?
* Accept files from stdin.
* Show attached slave position.
* Display attached device's MAC address instead of ff's.
* Use commandName in error messages.
* Data type abbreviations.
* ethercat tool:
- Add help pages for each command.
- Add -a and -p switches for config command.
- Show attached slave position.
- Show Pdos in 'ethercat slave -v'.
- Accept files from stdin.
- Display attached device's MAC address instead of ff's.
- Data type abbreviations.
- Add a -n (numeric) switch.
Future issues:
* Distributed clocks.
* Allow master requesting when in ORPHANED phase
* Move master threads, slave handlers and state machines into a user
space daemon.
* Implement user space realtime interface via cdev.
@ -43,7 +43,7 @@ Future issues:
Smaller issues:
* Stop master thread at ecrt_master_request() to get rid of allow_* flags.
* Stop master thread at ecrt_master_request() to get rid of allow_* flags?
* Evaluate SII Size field (0x003E) to determine maximum SII memory size.
* Unite fsm_pdo_mapping, fsm_pdo_config and fsm_coe_map.
* Clear sync managers in INIT.

View File

@ -51,7 +51,7 @@ void MasterDevice::open(Permissions perm)
stringstream err;
err << "Failed to open master device " << deviceName.str() << ": "
<< strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
}
@ -83,7 +83,7 @@ void MasterDevice::getMaster(ec_ioctl_master_t *data)
if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) {
stringstream err;
err << "Failed to get master information: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -96,7 +96,7 @@ void MasterDevice::getConfig(ec_ioctl_config_t *data, unsigned int index)
if (ioctl(fd, EC_IOCTL_CONFIG, data) < 0) {
stringstream err;
err << "Failed to get slave configuration: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -116,7 +116,7 @@ void MasterDevice::getConfigPdo(
if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) {
stringstream err;
err << "Failed to get slave config Pdo: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -138,7 +138,7 @@ void MasterDevice::getConfigPdoEntry(
if (ioctl(fd, EC_IOCTL_CONFIG_PDO_ENTRY, data) < 0) {
stringstream err;
err << "Failed to get slave config Pdo entry: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -156,7 +156,7 @@ void MasterDevice::getConfigSdo(
if (ioctl(fd, EC_IOCTL_CONFIG_SDO, data) < 0) {
stringstream err;
err << "Failed to get slave config Sdo: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -173,7 +173,7 @@ void MasterDevice::getDomain(ec_ioctl_domain_t *data, unsigned int index)
err << "Domain " << index << " does not exist!";
else
err << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -189,7 +189,7 @@ void MasterDevice::getData(ec_ioctl_domain_data_t *data,
if (ioctl(fd, EC_IOCTL_DOMAIN_DATA, data) < 0) {
stringstream err;
err << "Failed to get domain data: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -206,7 +206,7 @@ void MasterDevice::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex)
err << "Slave " << slaveIndex << " does not exist!";
else
err << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -224,7 +224,7 @@ void MasterDevice::getFmmu(
if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) {
stringstream err;
err << "Failed to get domain FMMU: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -242,7 +242,7 @@ void MasterDevice::getSync(
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC, sync)) {
stringstream err;
err << "Failed to get sync manager: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -262,7 +262,7 @@ void MasterDevice::getPdo(
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO, pdo)) {
stringstream err;
err << "Failed to get Pdo: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -284,7 +284,7 @@ void MasterDevice::getPdoEntry(
if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO_ENTRY, entry)) {
stringstream err;
err << "Failed to get Pdo entry: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -302,7 +302,7 @@ void MasterDevice::getSdo(
if (ioctl(fd, EC_IOCTL_SLAVE_SDO, sdo)) {
stringstream err;
err << "Failed to get Sdo: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -322,7 +322,7 @@ void MasterDevice::getSdoEntry(
if (ioctl(fd, EC_IOCTL_SLAVE_SDO_ENTRY, entry)) {
stringstream err;
err << "Failed to get Sdo entry: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -335,7 +335,7 @@ void MasterDevice::readSii(
if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, data) < 0) {
stringstream err;
err << "Failed to read SII: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -348,7 +348,7 @@ void MasterDevice::writeSii(
if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, data) < 0) {
stringstream err;
err << "Failed to write SII: " << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -359,7 +359,7 @@ 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());
throw MasterDeviceException(err);
}
}
@ -376,7 +376,7 @@ void MasterDevice::sdoDownload(ec_ioctl_slave_sdo_download_t *data)
} else {
err << strerror(errno);
}
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -393,7 +393,7 @@ void MasterDevice::sdoUpload(ec_ioctl_slave_sdo_upload_t *data)
} else {
err << strerror(errno);
}
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}
@ -416,7 +416,7 @@ void MasterDevice::requestState(
err << "Slave " << slavePosition << " does not exist!";
else
err << strerror(errno);
throw MasterDeviceException(err.str());
throw MasterDeviceException(err);
}
}

View File

@ -8,6 +8,7 @@
#define __EC_MASTER_H__
#include <stdexcept>
#include <sstream>
using namespace std;
#include "../include/ecrt.h"
@ -18,11 +19,13 @@ using namespace std;
class MasterDeviceException:
public runtime_error
{
public:
friend class MasterDevice;
protected:
/** Constructor with std::string parameter. */
MasterDeviceException(
const string &s /**< Message. */
): runtime_error(s) {}
const stringstream &s /**< Message. */
): runtime_error(s.str()) {}
};
/****************************************************************************/

View File

@ -66,7 +66,7 @@ void command_alias(void)
if (!force) {
err << "This will write the alias addresses of all slaves to "
<< alias << "! Please specify --force to proceed.";
throw ExecutionFailureException(err);
throw CommandException(err);
}
masterDev.open(MasterDevice::ReadWrite);
@ -100,7 +100,7 @@ void writeSlaveAlias(
if (slave.sii_nwords < 8) {
err << "Current SII contents are too small to set an alias "
<< "(" << slave.sii_nwords << " words)!";
throw ExecutionFailureException(err);
throw CommandException(err);
}
// read first 8 SII words
@ -114,7 +114,7 @@ void writeSlaveAlias(
} catch (MasterDeviceException &e) {
delete [] data.words;
err << "Failed to read SII: " << e.what();
throw ExecutionFailureException(err);
throw CommandException(err);
}
// write new alias address in word 4
@ -132,7 +132,7 @@ void writeSlaveAlias(
} catch (MasterDeviceException &e) {
delete [] data.words;
err << "Failed to read SII: " << e.what();
throw ExecutionFailureException(err);
throw CommandException(err);
}
delete [] data.words;

View File

@ -36,8 +36,8 @@ void command_debug(void)
if (commandArgs.size() != 1) {
stringstream err;
err << "'debug' takes exactly one argument!";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' takes exactly one argument!";
throw InvalidUsageException(err);
}
str << commandArgs[0];
@ -47,7 +47,7 @@ void command_debug(void)
if (str.fail()) {
stringstream err;
err << "Invalid debug level '" << commandArgs[0] << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
masterDev.open(MasterDevice::ReadWrite);

View File

@ -119,9 +119,9 @@ void showDomain(unsigned int domainIndex)
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());
err << "Fmmu information corrupted!";
throw CommandException(err);
}
cout << " " << hex << setfill('0');

View File

@ -30,14 +30,15 @@ void command_download(void)
const CoEDataType *dataType = NULL;
if (slavePosition < 0) {
err << "'sdo_download' requires a slave! Please specify --slave.";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' requires a slave! "
<< "Please specify --slave.";
throw InvalidUsageException(err);
}
data.slave_position = slavePosition;
if (commandArgs.size() != 3) {
err << "'sdo_download' takes 3 arguments!";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' takes 3 arguments!";
throw InvalidUsageException(err);
}
strIndex << commandArgs[0];
@ -46,7 +47,7 @@ void command_download(void)
>> data.sdo_index;
if (strIndex.fail()) {
err << "Invalid Sdo index '" << commandArgs[0] << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
strSubIndex << commandArgs[1];
@ -55,14 +56,14 @@ void command_download(void)
>> number;
if (strSubIndex.fail() || number > 0xff) {
err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
data.sdo_entry_subindex = number;
if (dataTypeStr != "") { // data type specified
if (!(dataType = findDataType(dataTypeStr))) {
err << "Invalid data type '" << dataTypeStr << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
} else { // no data type specified: fetch from dictionary
ec_ioctl_slave_sdo_entry_t entry;
@ -75,13 +76,13 @@ void command_download(void)
} catch (MasterDeviceException &e) {
err << "Failed to determine Sdo entry data type. "
<< "Please specify --type.";
throw ExecutionFailureException(err);
throw CommandException(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);
throw CommandException(err);
}
}
@ -148,7 +149,7 @@ void command_download(void)
case 0x0009: // string
if (strValue.str().size() >= data.data_size) {
err << "String too large";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
data.data_size = strValue.str().size();
strValue >> (char *) data.data;
@ -157,13 +158,13 @@ void command_download(void)
default:
delete [] data.data;
err << "Unknown data type 0x" << hex << dataType->coeCode;
throw MasterDeviceException(err.str());
throw CommandException(err);
}
} catch (ios::failure &e) {
delete [] data.data;
err << "Invalid value argument '" << commandArgs[2]
<< "' for type '" << dataType->name << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
masterDev.open(MasterDevice::ReadWrite);

View File

@ -36,12 +36,10 @@ void command_master(void)
<< " 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());
case 0: cout << "Waiting for device..."; break;
case 1: cout << "Idle"; break;
case 2: cout << "Operation"; break;
default: cout << "???";
}
cout << endl

View File

@ -66,9 +66,9 @@ void command_sii_read(void)
stringstream err;
if (slavePosition < 0) {
stringstream err;
err << "'sii_read' requires a slave! Please specify --slave.";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' requires a slave! "
<< "Please specify --slave.";
throw InvalidUsageException(err);
}
data.slave_position = slavePosition;
@ -113,7 +113,7 @@ void command_sii_read(void)
if (categoryHeader + 1 > data.words + data.nwords) {
err << "SII data seem to be corrupted!";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
categorySize = le16tocpu(*(categoryHeader + 1));
cout << ", " << dec << categorySize << " words" << flush;
@ -121,7 +121,7 @@ void command_sii_read(void)
if (categoryHeader + 2 + categorySize
> data.words + data.nwords) {
err << "SII data seem to be corrupted!";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
cout << hex;
@ -139,7 +139,7 @@ void command_sii_read(void)
if (categoryHeader + 2 + categorySize + 1
> data.words + data.nwords) {
err << "SII data seem to be corrupted!";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
categoryHeader += 2 + categorySize;
categoryType = le16tocpu(*categoryHeader);

View File

@ -34,20 +34,21 @@ void command_sii_write(void)
uint8_t crc;
if (slavePosition < 0) {
err << "'sii_write' requires a slave! Please specify --slave.";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' requires a slave! "
<< "Please specify --slave.";
throw InvalidUsageException(err);
}
data.slave_position = slavePosition;
if (commandArgs.size() != 1) {
err << "'ssi_write' takes exactly one argument!";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' takes exactly one argument!";
throw InvalidUsageException(err);
}
file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary);
if (file.fail()) {
err << "Failed to open '" << commandArgs[0] << "'!";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
// get length of file
@ -56,16 +57,15 @@ void command_sii_write(void)
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());
throw CommandException(err);
}
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());
throw CommandException(err);
}
// allocate buffer and read file into buffer
@ -80,7 +80,7 @@ void command_sii_write(void)
err << "CRC incorrect. Must be 0x"
<< hex << setfill('0') << setw(2) << (unsigned int) crc
<< ". Use --force to write anyway.";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
// cycle through categories to detect corruption
@ -90,14 +90,14 @@ void command_sii_write(void)
if (categoryHeader + 1 > data.words + data.nwords) {
err << "SII data seem to be corrupted! "
<< "Use --force to write anyway.";
throw MasterDeviceException(err.str());
throw CommandException(err);
}
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());
throw CommandException(err);
}
categoryHeader += 2 + categorySize;
categoryType = le16tocpu(*categoryHeader);

View File

@ -22,13 +22,13 @@ const char *help_states =
void command_states(void)
{
stringstream err;
string stateStr;
uint8_t state;
if (commandArgs.size() != 1) {
stringstream err;
err << "'state' takes exactly one argument!";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' takes exactly one argument!";
throw InvalidUsageException(err);
}
stateStr = commandArgs[0];
@ -44,9 +44,8 @@ void command_states(void)
} else if (stateStr == "OP") {
state = 0x08;
} else {
stringstream err;
err << "Invalid state '" << commandArgs[0] << "'!";
throw MasterDeviceException(err.str());
throw InvalidUsageException(err);
}
masterDev.open(MasterDevice::ReadWrite);

View File

@ -24,23 +24,22 @@ const char *help_upload =
void command_upload(void)
{
stringstream strIndex, strSubIndex;
stringstream err, 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());
err << "'" << commandName << "' requires a slave! "
<< "Please specify --slave.";
throw InvalidUsageException(err);
}
data.slave_position = slavePosition;
if (commandArgs.size() != 2) {
stringstream err;
err << "'sdo_upload' takes two arguments!";
throw MasterDeviceException(err.str());
err << "'" << commandName << "' takes two arguments!";
throw InvalidUsageException(err);
}
strIndex << commandArgs[0];
@ -48,9 +47,8 @@ void command_upload(void)
>> 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());
throw InvalidUsageException(err);
}
strSubIndex << commandArgs[1];
@ -58,17 +56,15 @@ void command_upload(void)
>> 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());
throw InvalidUsageException(err);
}
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());
throw InvalidUsageException(err);
}
} else { // no data type specified: fetch from dictionary
ec_ioctl_slave_sdo_entry_t entry;
@ -79,17 +75,15 @@ void command_upload(void)
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);
throw CommandException(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);
throw CommandException(err);
}
}
@ -113,11 +107,10 @@ void command_upload(void)
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());
throw CommandException(err);
}
cout << setfill('0');

View File

@ -46,12 +46,12 @@ class InvalidUsageException:
/****************************************************************************/
class ExecutionFailureException:
class CommandException:
public runtime_error
{
public:
/** Constructor with std::string parameter. */
ExecutionFailureException(
CommandException(
const stringstream &s /**< Message. */
): runtime_error(s.str()) {}
};

View File

@ -251,7 +251,7 @@ int Command::execute() const
cerr << e.what() << endl << endl;
displayHelp();
return 1;
} catch (ExecutionFailureException &e) {
} catch (CommandException &e) {
cerr << e.what() << endl;
return 1;
} catch (MasterDeviceException &e) {