# HG changeset patch # User Florian Pose # Date 1213087730 0 # Node ID c07dd38243ba09245af3bf402bd04c3741d55722 # Parent 405cc2d033e0ffdbbf45c39abc85ce834340e17d Implemented SII writing (including alias writing) via ethercat command. diff -r 405cc2d033e0 -r c07dd38243ba TODO --- a/TODO Mon Jun 09 14:32:16 2008 +0000 +++ b/TODO Tue Jun 10 08:48:50 2008 +0000 @@ -9,7 +9,6 @@ Version 1.4.0: * Replace all Sysfs files via the new ethercat tool. - - Slave alias write - Slave info (flags, mailbox, general) - Config info (alias, position, type, Pdos, Sdos) * Slaves as array. @@ -26,6 +25,7 @@ * Check for sizes of uploaded Sdos when reading mapping from CoE. * Attach Pdo names from SII or Coe dictioary to Pdos read via CoE. * Make scanning and configuration run parallel (each). +* List of commands that require a slave. Future issues: diff -r 405cc2d033e0 -r c07dd38243ba master/cdev.c --- a/master/cdev.c Mon Jun 09 14:32:16 2008 +0000 +++ b/master/cdev.c Tue Jun 10 08:48:50 2008 +0000 @@ -763,7 +763,7 @@ case EC_IOCTL_SII_READ: { - ec_ioctl_sii_read_t data; + ec_ioctl_sii_t data; const ec_slave_t *slave; if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { @@ -795,6 +795,54 @@ break; } + case EC_IOCTL_SII_WRITE: + { + ec_ioctl_sii_t data; + ec_slave_t *slave; + unsigned int byte_size; + uint16_t *words; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + retval = -EFAULT; + break; + } + + if (!(slave = ec_master_find_slave( + master, 0, data.slave_position))) { + EC_ERR("Slave %u does not exist!\n", data.slave_position); + retval = -EINVAL; + break; + } + + if (!data.nwords) + break; + + byte_size = sizeof(uint16_t) * data.nwords; + if (!(words = kmalloc(byte_size, GFP_KERNEL))) { + EC_ERR("Failed to allocate %u bytes for SII contents.\n", + byte_size); + retval = -ENOMEM; + break; + } + + if (copy_from_user(words, + (void __user *) data.words, byte_size)) { + retval = -EFAULT; + kfree(words); + break; + } + + if (ec_slave_write_sii(slave, + data.offset, data.nwords, words)) { + retval = -EIO; + kfree(words); + break; + } + + kfree(words); + break; + } + default: retval = -ENOTTY; } diff -r 405cc2d033e0 -r c07dd38243ba master/ioctl.h --- a/master/ioctl.h Mon Jun 09 14:32:16 2008 +0000 +++ b/master/ioctl.h Tue Jun 10 08:48:50 2008 +0000 @@ -67,7 +67,8 @@ #define EC_IOCTL_SDO_ENTRY EC_IOWR(0x0c, ec_ioctl_sdo_entry_t) #define EC_IOCTL_SDO_UPLOAD EC_IOWR(0x0d, ec_ioctl_sdo_upload_t) #define EC_IOCTL_SDO_DOWNLOAD EC_IOW(0x0e, ec_ioctl_sdo_download_t) -#define EC_IOCTL_SII_READ EC_IOWR(0x0f, ec_ioctl_sii_read_t) +#define EC_IOCTL_SII_READ EC_IOWR(0x0f, ec_ioctl_sii_t) +#define EC_IOCTL_SII_WRITE EC_IOW(0x10, ec_ioctl_sii_t) /*****************************************************************************/ @@ -264,7 +265,7 @@ uint16_t offset; uint32_t nwords; uint16_t *words; -} ec_ioctl_sii_read_t; +} ec_ioctl_sii_t; /*****************************************************************************/ diff -r 405cc2d033e0 -r c07dd38243ba master/slave.c --- a/master/slave.c Mon Jun 09 14:32:16 2008 +0000 +++ b/master/slave.c Tue Jun 10 08:48:50 2008 +0000 @@ -57,8 +57,6 @@ void ec_slave_clear(struct kobject *); void ec_slave_sdos_clear(struct kobject *); ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *); -ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *, - const char *, size_t); char *ec_slave_sii_string(ec_slave_t *, unsigned int); /*****************************************************************************/ @@ -66,19 +64,14 @@ /** \cond */ EC_SYSFS_READ_ATTR(info); -EC_SYSFS_READ_WRITE_ATTR(sii); -EC_SYSFS_READ_WRITE_ATTR(alias); static struct attribute *def_attrs[] = { &attr_info, - &attr_sii, - &attr_alias, NULL, }; static struct sysfs_ops sysfs_ops = { .show = ec_show_slave_attribute, - .store = ec_store_slave_attribute }; static struct kobj_type ktype_ec_slave = { @@ -848,217 +841,59 @@ /*****************************************************************************/ /** - * Schedules an SII write request. - * \return 0 case of success, otherwise error code. - */ - -int ec_slave_schedule_sii_writing( - ec_sii_write_request_t *request /**< SII write request */ - ) -{ - ec_master_t *master = request->slave->master; - - request->state = EC_REQUEST_QUEUED; - - // schedule SII write request. - down(&master->sii_sem); - list_add_tail(&request->list, &master->sii_requests); - up(&master->sii_sem); - - // wait for processing through FSM - if (wait_event_interruptible(master->sii_queue, - request->state != EC_REQUEST_QUEUED)) { - // interrupted by signal - down(&master->sii_sem); - if (request->state == EC_REQUEST_QUEUED) { - list_del(&request->list); - up(&master->sii_sem); - return -EINTR; - } - // request already processing: interrupt not possible. - up(&master->sii_sem); - } - - // wait until master FSM has finished processing - wait_event(master->sii_queue, - request->state != EC_REQUEST_BUSY); - - return request->state == EC_REQUEST_SUCCESS ? 0 : -EIO; -} - -/*****************************************************************************/ - -/** - * 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 ec_slave_sii_crc( - 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 complete SII contents to a slave. - * \return data size written in case of success, otherwise error code. - */ - -ssize_t ec_slave_write_sii(ec_slave_t *slave, /**< EtherCAT slave */ - const uint8_t *data, /**< new SII data */ - size_t size /**< size of data in bytes */ - ) -{ + * Writes SII contents to a slave. + * \return Zero on success, otherwise error code. + */ + +int ec_slave_write_sii( + ec_slave_t *slave, /**< EtherCAT slave */ + uint16_t offset, /**< SII word offset. */ + unsigned int nwords, /**< Number of words. */ + const uint16_t *words /**< New SII data. */ + ) +{ + ec_master_t *master = slave->master; ec_sii_write_request_t request; - const uint16_t *cat_header; - uint16_t cat_type, cat_size; - int ret; - uint8_t crc; - - if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME - EC_ERR("Writing SIIs only allowed in idle mode!\n"); - return -EBUSY; - } - - if (size % 2) { - EC_ERR("SII data size is odd (%u bytes)! SII data must be" - " word-aligned. Dropping.\n", size); - return -EINVAL; - } // init SII write request INIT_LIST_HEAD(&request.list); request.slave = slave; - request.words = (const uint16_t *) data; - request.offset = 0; - request.nwords = size / 2; - - if (request.nwords < 0x0041) { - EC_ERR("SII data too short (%u words)! Mimimum is" - " 40 fixed words + 1 delimiter. Dropping.\n", - request.nwords); - return -EINVAL; - } - - // calculate checksum - crc = ec_slave_sii_crc(data, 14); // CRC over words 0 to 6 - if (crc != data[14]) { - EC_WARN("SII CRC incorrect. Must be 0x%02x.\n", crc); - } - - cat_header = request.words + EC_FIRST_SII_CATEGORY_OFFSET; - cat_type = EC_READ_U16(cat_header); - while (cat_type != 0xFFFF) { // cycle through categories - if (cat_header + 1 > request.words + request.nwords) { - EC_ERR("SII data corrupted! Dropping.\n"); - return -EINVAL; - } - cat_size = EC_READ_U16(cat_header + 1); - if (cat_header + cat_size + 2 > request.words + request.nwords) { - EC_ERR("SII data corrupted! Dropping.\n"); - return -EINVAL; - } - cat_header += cat_size + 2; - cat_type = EC_READ_U16(cat_header); - } - - // SII data ok. schedule writing. - if ((ret = ec_slave_schedule_sii_writing(&request))) - return ret; // error code - - return size; // success -} - -/*****************************************************************************/ - -/** - * Writes the Secondary slave address (alias) to the slave's SII. - * \return data size written in case of success, otherwise error code. - */ - -ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */ - const uint8_t *data, /**< alias string */ - size_t size /**< size of data in bytes */ - ) -{ - ec_sii_write_request_t request; - char *remainder; - uint16_t alias; - int ret; - uint8_t sii_data[16], crc; - - if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME - EC_ERR("Writing to SII is only allowed in idle mode!\n"); - return -EBUSY; - } - - alias = simple_strtoul(data, &remainder, 0); - if (remainder == (char *) data || (*remainder && *remainder != '\n')) { - EC_ERR("Invalid alias value! Dropping.\n"); - return -EINVAL; - } - - if (!slave->sii_words || slave->sii_nwords < 8) { - EC_ERR("Failed to read SII contents from slave %u.\n", - slave->ring_position); - return -EINVAL; - } - - // copy first 7 words of recent SII contents - memcpy(sii_data, (uint8_t *) slave->sii_words, 14); - - // write new alias address in word 4 - EC_WRITE_U16(sii_data + 8, alias); - - // calculate new checksum over words 0 to 6 - crc = ec_slave_sii_crc(sii_data, 14); - EC_WRITE_U16(sii_data + 14, crc); - - // init SII write request - INIT_LIST_HEAD(&request.list); - request.slave = slave; - request.words = (const uint16_t *) sii_data; - request.offset = 0x0000; - request.nwords = 8; - - if ((ret = ec_slave_schedule_sii_writing(&request))) - return ret; // error code - - slave->sii.alias = alias; // FIXME: do this in state machine - - return size; // success + request.words = words; + request.offset = offset; + request.nwords = nwords; + request.state = EC_REQUEST_QUEUED; + + // schedule SII write request. + down(&master->sii_sem); + list_add_tail(&request.list, &master->sii_requests); + up(&master->sii_sem); + + // wait for processing through FSM + if (wait_event_interruptible(master->sii_queue, + request.state != EC_REQUEST_QUEUED)) { + // interrupted by signal + down(&master->sii_sem); + if (request.state == EC_REQUEST_QUEUED) { + list_del(&request.list); + up(&master->sii_sem); + return -EINTR; + } + // request already processing: interrupt not possible. + up(&master->sii_sem); + } + + // wait until master FSM has finished processing + wait_event(master->sii_queue, + request.state != EC_REQUEST_BUSY); + + if (request.state == EC_REQUEST_SUCCESS) { + if (offset <= 4 && offset + nwords > 4) { // alias was written + slave->sii.alias = EC_READ_U16(words + 4); + } + return 0; + } else { + return -EIO; + } } /*****************************************************************************/ @@ -1074,25 +909,9 @@ ) { ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); - unsigned int sii_size; if (attr == &attr_info) { return ec_slave_info(slave, buffer); - } else if (attr == &attr_sii) { - if (slave->sii_words) { - sii_size = slave->sii_nwords * 2; - if (sii_size > PAGE_SIZE) { - EC_ERR("SII contents of slave %u exceed 1 page (%u/%u).\n", - slave->ring_position, sii_size, - (int) PAGE_SIZE); - } - else { - memcpy(buffer, (uint8_t *) slave->sii_words, sii_size); - return sii_size; - } - } - } else if (attr == &attr_alias) { - return sprintf(buffer, "%u\n", slave->sii.alias); } return 0; @@ -1100,30 +919,6 @@ /*****************************************************************************/ -/** - Formats attribute data for SysFS write access. - \return number of bytes processed, or negative error code -*/ - -ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */ - struct attribute *attr, /**< attribute */ - const char *buffer, /**< memory with data */ - size_t size /**< size of data to store */ - ) -{ - ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); - - if (attr == &attr_sii) { - return ec_slave_write_sii(slave, buffer, size); - } else if (attr == &attr_alias) { - return ec_slave_write_alias(slave, buffer, size); - } - - return -EIO; -} - -/*****************************************************************************/ - /** Get the sync manager for either Rx- or Tx-Pdos. * * \todo This seems not to be correct in every case... diff -r 405cc2d033e0 -r c07dd38243ba master/slave.h --- a/master/slave.h Mon Jun 09 14:32:16 2008 +0000 +++ b/master/slave.h Tue Jun 10 08:48:50 2008 +0000 @@ -228,6 +228,9 @@ uint16_t ec_slave_sdo_count(const ec_slave_t *); const ec_pdo_t *ec_slave_find_pdo(const ec_slave_t *, uint16_t); +int ec_slave_write_sii(ec_slave_t *, uint16_t, unsigned int, + const uint16_t *); + /*****************************************************************************/ #endif diff -r 405cc2d033e0 -r c07dd38243ba tools/Master.cpp --- a/tools/Master.cpp Mon Jun 09 14:32:16 2008 +0000 +++ b/tools/Master.cpp Tue Jun 10 08:48:50 2008 +0000 @@ -13,6 +13,7 @@ #include #include #include +#include #include // toupper() using namespace std; @@ -116,6 +117,60 @@ index = i; } +/*****************************************************************************/ + +/** + * Writes the Secondary slave address (alias) to the slave's SII. + */ +void Master::writeAlias( + int slavePosition, + bool force, + const vector &commandArgs + ) +{ + ec_ioctl_sii_t data; + ec_ioctl_slave_t slave; + unsigned int i; + uint16_t alias; + stringstream err, strAlias; + int number; + + if (commandArgs.size() != 1) { + stringstream err; + err << "'alias' takes exactly one argument!"; + throw MasterException(err.str()); + } + + strAlias << commandArgs[0]; + strAlias >> hex >> number; + if (strAlias.fail() || number < 0x0000 || number > 0xffff) { + err << "Invalid alias '" << commandArgs[0] << "'!"; + throw MasterException(err.str()); + } + alias = number; + + if (slavePosition == -1) { + unsigned int numSlaves, i; + + if (!force) { + err << "This will write the alias addresses of all slaves to 0x" + << hex << setfill('0') << setw(4) << alias << "! " + << "Please specify --force to proceed."; + throw MasterException(err.str()); + } + + open(ReadWrite); + numSlaves = slaveCount(); + + for (i = 0; i < numSlaves; i++) { + writeSlaveAlias(i, alias); + } + } else { + open(ReadWrite); + writeSlaveAlias(slavePosition, alias); + } +} + /****************************************************************************/ void Master::outputData(int domainIndex) @@ -197,14 +252,17 @@ aliasIndex = 0; for (i = 0; i < numSlaves; i++) { getSlave(&slave, i); - cout << setw(2) << i << " "; + cout << setfill(' ') << setw(2) << i << " "; if (slave.alias) { lastAlias = slave.alias; aliasIndex = 0; } if (lastAlias) { - cout << setw(10) << "#" << lastAlias << ":" << aliasIndex; + cout << "#" + << hex << setfill('0') << setw(4) << lastAlias + << ":" << dec << aliasIndex; + aliasIndex++; } cout << " " << slaveState(slave.state) << " "; @@ -212,8 +270,9 @@ if (strlen(slave.name)) { cout << slave.name; } else { - cout << "0x" << hex << setfill('0') << slave.vendor_id - << ":0x" << slave.product_code; + cout << hex << setfill('0') + << setw(8) << slave.vendor_id << ":" + << setw(8) << slave.product_code << dec; } cout << endl; @@ -608,7 +667,7 @@ void Master::siiRead(int slavePosition) { - ec_ioctl_sii_read_t data; + ec_ioctl_sii_t data; ec_ioctl_slave_t slave; unsigned int i; @@ -647,6 +706,102 @@ /****************************************************************************/ +void Master::siiWrite( + int slavePosition, + bool force, + const vector &commandArgs + ) +{ + stringstream err; + ec_ioctl_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 MasterException(err.str()); + } + data.slave_position = slavePosition; + + if (commandArgs.size() != 1) { + err << "'ssi_write' takes exactly one argument!"; + throw MasterException(err.str()); + } + + file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary); + if (file.fail()) { + err << "Failed to open '" << commandArgs[0] << "'!"; + throw MasterException(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 MasterException(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 MasterException(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 MasterException(err.str()); + } + + // cycle through categories to detect corruption + categoryHeader = data.words + 0x0040; + 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 MasterException(err.str()); + } + categorySize = le16tocpu(*(categoryHeader + 1)); + if (categoryHeader + categorySize + 2 > data.words + data.nwords) { + err << "SII data seem to be corrupted! " + "Use --force to write anyway."; + throw MasterException(err.str()); + } + categoryHeader += categorySize + 2; + categoryType = le16tocpu(*categoryHeader); + } + } + + // send data to master + open(ReadWrite); + data.offset = 0; + if (ioctl(fd, EC_IOCTL_SII_WRITE, &data) < 0) { + stringstream err; + err << "Failed to write SII: " << strerror(errno); + throw MasterException(err.str()); + } +} + +/****************************************************************************/ + void Master::requestStates( int slavePosition, const vector &commandArgs @@ -744,6 +899,62 @@ ::close(fd); } +/*****************************************************************************/ + +/** + * Writes the Secondary slave address (alias) to the slave's SII. + */ +void Master::writeSlaveAlias( + uint16_t slavePosition, + uint16_t alias + ) +{ + ec_ioctl_sii_t data; + ec_ioctl_slave_t slave; + stringstream err; + uint8_t crc; + + open(ReadWrite); + + getSlave(&slave, slavePosition); + + if (slave.sii_nwords < 8) { + err << "Current SII contents are too small to set an alias " + << "(" << slave.sii_nwords << " words)!"; + throw MasterException(err.str()); + } + + data.slave_position = slavePosition; + data.offset = 0; + data.nwords = 8; + data.words = new uint16_t[data.nwords]; + + // read first 8 SII words + if (ioctl(fd, EC_IOCTL_SII_READ, &data) < 0) { + delete [] data.words; + err << "Failed to read SII: " << strerror(errno); + throw MasterException(err.str()); + } + + // write new alias address in word 4 + data.words[4] = cputole16(alias); + + // calculate checksum over words 0 to 6 + crc = calcSiiCrc((const uint8_t *) data.words, 14); + + // write new checksum into first byte of word 7 + *(uint8_t *) (data.words + 7) = crc; + + // write first 8 words with new alias and checksum + if (ioctl(fd, EC_IOCTL_SII_WRITE, &data) < 0) { + delete [] data.words; + err << "Failed to write SII: " << strerror(errno); + throw MasterException(err.str()); + } + + delete [] data.words; +} + /****************************************************************************/ void Master::outputDomainData(unsigned int domainIndex) @@ -1330,4 +1541,46 @@ cout << endl; } -/****************************************************************************/ +/*****************************************************************************/ + +/** + * 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 Master::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; +} + +/*****************************************************************************/ diff -r 405cc2d033e0 -r c07dd38243ba tools/Master.h --- a/tools/Master.h Mon Jun 09 14:32:16 2008 +0000 +++ b/tools/Master.h Tue Jun 10 08:48:50 2008 +0000 @@ -41,6 +41,7 @@ void setIndex(unsigned int); + void writeAlias(int, bool, const vector &); void outputData(int); void setDebug(const vector &); void showDomains(int); @@ -51,6 +52,7 @@ void sdoDownload(int, const string &, const vector &); void sdoUpload(int, const string &, const vector &); void siiRead(int); + void siiWrite(int, bool, const vector &); void requestStates(int, const vector &); void generateXml(int); @@ -59,6 +61,7 @@ void open(Permissions); void close(); + void writeSlaveAlias(uint16_t, uint16_t); void outputDomainData(unsigned int); void showDomain(unsigned int); void listSlavePdos(uint16_t, bool = false, bool = false); @@ -83,6 +86,7 @@ static string slaveState(uint8_t); static void printRawData(const uint8_t *, unsigned int); + static uint8_t calcSiiCrc(const uint8_t *, unsigned int); private: enum {DefaultBufferSize = 1024}; diff -r 405cc2d033e0 -r c07dd38243ba tools/main.cpp --- a/tools/main.cpp Mon Jun 09 14:32:16 2008 +0000 +++ b/tools/main.cpp Tue Jun 10 08:48:50 2008 +0000 @@ -24,6 +24,7 @@ vector commandArgs; static bool quiet = false; string dataTypeStr; +bool force = false; /*****************************************************************************/ @@ -32,6 +33,7 @@ cerr << "Usage: ethercat [OPTIONS]" << endl << "Commands:" << endl + << " alias Write alias address(es)." << endl << " data Output binary domain process data." << endl << " debug Set the master debug level." << endl << " domain Show domain information." << endl @@ -42,6 +44,7 @@ << " sdo_download (sd) Write an Sdo entry." << endl << " sdo_upload (su) Read an Sdo entry." << endl << " sii_read (sr) Output a slave's SII contents." << endl + << " sii_write (sw) Write slave's SII contents." << endl << " state Request slave states." << endl << " xml Generate slave information xmls." << endl << "Global options:" << endl @@ -56,6 +59,7 @@ << " or 'all' for all domains (default)." << endl << " --type -t Forced Sdo data type." << endl + << " --force -f Force action." << endl << " --quiet -q Show less output." << endl << " --help -h Show this help." << endl; } @@ -73,13 +77,14 @@ {"slave", required_argument, NULL, 's'}, {"domain", required_argument, NULL, 'd'}, {"type", required_argument, NULL, 't'}, + {"force", no_argument, NULL, 'f'}, {"quiet", no_argument, NULL, 'q'}, {"help", no_argument, NULL, 'h'}, {} }; do { - c = getopt_long(argc, argv, "m:s:d:t:qh", longOptions, &optionIndex); + c = getopt_long(argc, argv, "m:s:d:t:fqh", longOptions, &optionIndex); switch (c) { case 'm': @@ -127,6 +132,10 @@ dataTypeStr = optarg; break; + case 'f': + force = true; + break; + case 'q': quiet = true; break; @@ -166,7 +175,9 @@ try { master.setIndex(masterIndex); - if (command == "data") { + if (command == "alias") { + master.writeAlias(slavePosition, force, commandArgs); + } else if (command == "data") { master.outputData(domainIndex); } else if (command == "debug") { master.setDebug(commandArgs); @@ -186,6 +197,8 @@ master.sdoUpload(slavePosition, dataTypeStr, commandArgs); } 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") {