Implemented SII writing (including alias writing) via ethercat command.
--- 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:
--- 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;
}
--- 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;
/*****************************************************************************/
--- 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...
--- 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
--- 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 <iostream>
#include <iomanip>
#include <sstream>
+#include <fstream>
#include <cctype> // 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<string> &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<string> &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<string> &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;
+}
+
+/*****************************************************************************/
--- 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<string> &);
void outputData(int);
void setDebug(const vector<string> &);
void showDomains(int);
@@ -51,6 +52,7 @@
void sdoDownload(int, const string &, const vector<string> &);
void sdoUpload(int, const string &, const vector<string> &);
void siiRead(int);
+ void siiWrite(int, bool, const vector<string> &);
void requestStates(int, const vector<string> &);
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};
--- 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<string> commandArgs;
static bool quiet = false;
string dataTypeStr;
+bool force = false;
/*****************************************************************************/
@@ -32,6 +33,7 @@
cerr
<< "Usage: ethercat <COMMAND> [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 <type> 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") {