Slave information via 'ethercat slave'.
authorFlorian Pose <fp@igh-essen.com>
Wed, 11 Jun 2008 13:01:21 +0000
changeset 989 816663ca9370
parent 988 a47c5a3c143d
child 990 4f223f3df05a
Slave information via 'ethercat slave'.
TODO
master/cdev.c
master/globals.h
master/ioctl.h
master/slave.h
tools/Master.cpp
tools/Master.h
tools/main.cpp
--- a/TODO	Tue Jun 10 12:52:08 2008 +0000
+++ b/TODO	Wed Jun 11 13:01:21 2008 +0000
@@ -9,7 +9,6 @@
 Version 1.4.0:
 
 * Replace all Sysfs files via the new ethercat tool.
-    - Slave info (mailbox, general) 
     - Config info (alias, position, type, Pdos, Sdos)
 * Slaves as array.
 * Remove the end state of the master state machine.
--- a/master/cdev.c	Tue Jun 10 12:52:08 2008 +0000
+++ b/master/cdev.c	Wed Jun 11 13:01:21 2008 +0000
@@ -192,6 +192,15 @@
                 data.revision_number = slave->sii.revision_number;
                 data.serial_number = slave->sii.serial_number;
                 data.alias = slave->sii.alias;
+                data.rx_mailbox_offset = slave->sii.rx_mailbox_offset;
+                data.rx_mailbox_size = slave->sii.rx_mailbox_size;
+                data.tx_mailbox_offset = slave->sii.tx_mailbox_offset;
+                data.tx_mailbox_size = slave->sii.tx_mailbox_size;
+                data.mailbox_protocols = slave->sii.mailbox_protocols;
+                data.has_general_category = slave->sii.has_general;
+                data.coe_details = slave->sii.coe_details;
+                data.general_flags = slave->sii.general_flags;
+                data.current_on_ebus = slave->sii.current_on_ebus;
                 data.state = slave->current_state;
                 data.error_flag = slave->error_flag;
 
--- a/master/globals.h	Tue Jun 10 12:52:08 2008 +0000
+++ b/master/globals.h	Wed Jun 11 13:01:21 2008 +0000
@@ -99,6 +99,59 @@
 /** Size of an FMMU configuration page. */
 #define EC_FMMU_PAGE_SIZE 16
 
+/** Slave state mask.
+ *
+ * Apply this mask to a slave state byte to get the slave state without
+ * the error flag.
+ */
+#define EC_SLAVE_STATE_MASK 0x0F
+
+/** State of an EtherCAT slave.
+ */
+typedef enum {
+    EC_SLAVE_STATE_UNKNOWN = 0x00,
+    /**< unknown state */
+    EC_SLAVE_STATE_INIT = 0x01,
+    /**< INIT state (no mailbox communication, no IO) */
+    EC_SLAVE_STATE_PREOP = 0x02,
+    /**< PREOP state (mailbox communication, no IO) */
+    EC_SLAVE_STATE_SAFEOP = 0x04,
+    /**< SAFEOP (mailbox communication and input update) */
+    EC_SLAVE_STATE_OP = 0x08,
+    /**< OP (mailbox communication and input/output update) */
+    EC_SLAVE_STATE_ACK_ERR = 0x10
+    /**< Acknowledge/Error bit (no actual state) */
+} ec_slave_state_t;
+
+/** Supported mailbox protocols.
+ */
+enum {
+    EC_MBOX_AOE = 0x01, /**< ADS-over-EtherCAT */
+    EC_MBOX_EOE = 0x02, /**< Ethernet-over-EtherCAT */
+    EC_MBOX_COE = 0x04, /**< CANopen-over-EtherCAT */
+    EC_MBOX_FOE = 0x08, /**< File-Access-over-EtherCAT */
+    EC_MBOX_SOE = 0x10, /**< Servo-Profile-over-EtherCAT */
+    EC_MBOX_VOE = 0x20  /**< Vendor specific */
+};
+
+/** Slave information interface CANopen-over-EtherCAT details flags.
+ */
+typedef struct {
+    uint8_t enable_sdo : 1; /**< Enable Sdo access. */
+    uint8_t enable_sdo_info : 1; /**< SDO information service available. */
+    uint8_t enable_pdo_assign : 1; /**< Pdo mapping configurable. */
+    uint8_t enable_pdo_configuration : 1; /**< Pdo configuration possible. */
+    uint8_t enable_upload_at_startup : 1; /**< ?. */
+    uint8_t enable_sdo_complete_access : 1; /**< Complete access possible. */
+} ec_sii_coe_details_t;
+
+/** Slave information interface general flags.
+ */
+typedef struct {
+    uint8_t enable_safeop : 1; /**< ?. */
+    uint8_t enable_not_lrw : 1; /**< Slave does not support LRW. */
+} ec_sii_general_flags_t;
+
 /*****************************************************************************/
 
 /** Convenience macro for printing EtherCAT-specific information to syslog.
--- a/master/ioctl.h	Tue Jun 10 12:52:08 2008 +0000
+++ b/master/ioctl.h	Wed Jun 11 13:01:21 2008 +0000
@@ -43,6 +43,8 @@
 
 #include <linux/ioctl.h>
 
+#include "globals.h"
+
 /*****************************************************************************/
 
 #define EC_IOCTL_TYPE    0xa4
@@ -85,7 +87,7 @@
 
 /*****************************************************************************/
 
-#define EC_IOCTL_SLAVE_NAME_SIZE 99
+#define EC_IOCTL_SLAVE_NAME_SIZE 77
 
 typedef struct {
     // input
@@ -97,6 +99,15 @@
     uint32_t revision_number;
     uint32_t serial_number;
     uint16_t alias;
+    uint16_t rx_mailbox_offset;
+    uint16_t rx_mailbox_size;
+    uint16_t tx_mailbox_offset;
+    uint16_t tx_mailbox_size;
+    uint16_t mailbox_protocols;
+    uint8_t has_general_category;
+    ec_sii_coe_details_t coe_details;
+    ec_sii_general_flags_t general_flags;
+    int16_t current_on_ebus;
     uint8_t state;
     uint8_t error_flag;
     uint8_t sync_count;
--- a/master/slave.h	Tue Jun 10 12:52:08 2008 +0000
+++ b/master/slave.h	Wed Jun 11 13:01:21 2008 +0000
@@ -54,69 +54,6 @@
 
 /*****************************************************************************/
 
-/** Slave state mask.
- *
- * Apply this mask to a slave state byte to get the slave state without
- * the error flag.
- */
-#define EC_SLAVE_STATE_MASK 0x0F
-
-/*****************************************************************************/
-
-/** State of an EtherCAT slave.
- */
-typedef enum {
-    EC_SLAVE_STATE_UNKNOWN = 0x00,
-    /**< unknown state */
-    EC_SLAVE_STATE_INIT = 0x01,
-    /**< INIT state (no mailbox communication, no IO) */
-    EC_SLAVE_STATE_PREOP = 0x02,
-    /**< PREOP state (mailbox communication, no IO) */
-    EC_SLAVE_STATE_SAFEOP = 0x04,
-    /**< SAFEOP (mailbox communication and input update) */
-    EC_SLAVE_STATE_OP = 0x08,
-    /**< OP (mailbox communication and input/output update) */
-    EC_SLAVE_STATE_ACK_ERR = 0x10
-    /**< Acknowledge/Error bit (no actual state) */
-} ec_slave_state_t;
-
-/*****************************************************************************/
-
-/** Supported mailbox protocols.
- */
-enum {
-    EC_MBOX_AOE = 0x01, /**< ADS-over-EtherCAT */
-    EC_MBOX_EOE = 0x02, /**< Ethernet-over-EtherCAT */
-    EC_MBOX_COE = 0x04, /**< CANopen-over-EtherCAT */
-    EC_MBOX_FOE = 0x08, /**< File-Access-over-EtherCAT */
-    EC_MBOX_SOE = 0x10, /**< Servo-Profile-over-EtherCAT */
-    EC_MBOX_VOE = 0x20  /**< Vendor specific */
-};
-
-/*****************************************************************************/
-
-/** Slave information interface CANopen-over-EtherCAT details flags.
- */
-typedef struct {
-    uint8_t enable_sdo : 1; /**< Enable Sdo access. */
-    uint8_t enable_sdo_info : 1; /**< SDO information service available. */
-    uint8_t enable_pdo_assign : 1; /**< Pdo mapping configurable. */
-    uint8_t enable_pdo_configuration : 1; /**< Pdo configuration possible. */
-    uint8_t enable_upload_at_startup : 1; /**< ?. */
-    uint8_t enable_sdo_complete_access : 1; /**< Complete access possible. */
-} ec_sii_coe_details_t;
-
-/*****************************************************************************/
-
-/** Slave information interface general flags.
- */
-typedef struct {
-    uint8_t enable_safeop : 1; /**< ?. */
-    uint8_t enable_not_lrw : 1; /**< Slave does not support LRW. */
-} ec_sii_general_flags_t;
-
-/*****************************************************************************/
-
 /** Slave information interface data.
  */
 typedef struct {
--- a/tools/Master.cpp	Tue Jun 10 12:52:08 2008 +0000
+++ b/tools/Master.cpp	Wed Jun 11 13:01:21 2008 +0000
@@ -713,6 +713,23 @@
 
 /****************************************************************************/
 
+void Master::showSlaves(int slavePosition)
+{
+    open(Read);
+
+    if (slavePosition == -1) {
+        unsigned int numSlaves = slaveCount(), i;
+
+        for (i = 0; i < numSlaves; i++) {
+            showSlave(i);
+        }
+    } else {
+        showSlave(slavePosition);
+    }
+}
+
+/****************************************************************************/
+
 void Master::siiRead(int slavePosition)
 {
     ec_ioctl_sii_t data;
@@ -1199,6 +1216,103 @@
 
 /****************************************************************************/
 
+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
+        << "Alias: 0x" << hex << setfill('0') << setw(4) << slave.alias << endl
+        << "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
+            << "  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 << sizeof(slave);
+    }
+    cout << endl;
+}
+
+/****************************************************************************/
+
 void Master::generateSlaveXml(uint16_t slavePosition)
 {
     ec_ioctl_slave_t slave;
--- a/tools/Master.h	Tue Jun 10 12:52:08 2008 +0000
+++ b/tools/Master.h	Wed Jun 11 13:01:21 2008 +0000
@@ -51,6 +51,7 @@
         void listSdos(int, bool = false);
         void sdoDownload(int, const string &, const vector<string> &);
         void sdoUpload(int, const string &, const vector<string> &);
+        void showSlaves(int);
         void siiRead(int);
         void siiWrite(int, bool, const vector<string> &);
         void requestStates(int, const vector<string> &);
@@ -66,6 +67,7 @@
         void showDomain(unsigned int);
         void listSlavePdos(uint16_t, bool = false, bool = false);
         void listSlaveSdos(uint16_t, bool = false, bool = false);
+        void showSlave(uint16_t);
         void generateSlaveXml(uint16_t);
         unsigned int domainCount();
         unsigned int slaveCount();
--- a/tools/main.cpp	Tue Jun 10 12:52:08 2008 +0000
+++ b/tools/main.cpp	Wed Jun 11 13:01:21 2008 +0000
@@ -37,12 +37,13 @@
         << "  data               Output binary domain process data." << endl
         << "  debug              Set the master debug level." << endl
         << "  domain             Show domain information." << endl
-        << "  list (ls, slaves)  List all slaves (former 'lsec')." << endl
+        << "  list (ls)          List all slaves (former 'lsec')." << endl
         << "  master             Show master information." << endl
         << "  pdos               List Pdo mapping." << endl
         << "  sdos               List Sdo dictionaries." << endl
         << "  sdo_download (sd)  Write an Sdo entry." << endl
         << "  sdo_upload (su)    Read an Sdo entry." << endl
+        << "  slave              Show slave information." << 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
@@ -183,7 +184,7 @@
             master.setDebug(commandArgs);
         } else if (command == "domain") {
             master.showDomains(domainIndex);
-		} else if (command == "list" || command == "ls" || command == "slaves") {
+		} else if (command == "list" || command == "ls") {
             master.listSlaves();
 		} else if (command == "master") {
             master.showMaster();
@@ -195,6 +196,8 @@
             master.sdoDownload(slavePosition, dataTypeStr, commandArgs);
         } else if (command == "sdo_upload" || command == "su") {
             master.sdoUpload(slavePosition, dataTypeStr, commandArgs);
+		} else if (command == "slave") {
+            master.showSlaves(slavePosition);
         } else if (command == "sii_read" || command == "sr") {
             master.siiRead(slavePosition);
         } else if (command == "sii_write" || command == "sw") {