Merge
authorFlorian Pose <fp@igh-essen.com>
Fri, 21 Aug 2009 09:46:29 +0200
changeset 1534 4844a8433915
parent 1533 bd150d066ea2 (current diff)
parent 1532 b1d1317f1c7a (diff)
child 1535 0c484ee12d89
Merge
--- a/TODO	Fri Aug 21 09:45:53 2009 +0200
+++ b/TODO	Fri Aug 21 09:46:29 2009 +0200
@@ -50,6 +50,10 @@
 * Check for Enable SDO Complete Access flag.
 * Implement CompleteAccess for command-line tool.
 * Implement CompleteAccess for SDO uploads.
+* Implement identifier parameter for cstruct command.
+* Implement sync delimiter for cstruct command.
+* Change SDO index at runtime for SDO request.
+* Implement ecrt_slave_config_request_state().
 
 Future issues:
 
--- a/include/ecrt.h	Fri Aug 21 09:45:53 2009 +0200
+++ b/include/ecrt.h	Fri Aug 21 09:46:29 2009 +0200
@@ -55,6 +55,7 @@
  *   ecrt_slave_config_sync_manager()).
  * - Added ecrt_slave_config_complete_sdo() method to download an SDO during
  *   configuration via CompleteAccess.
+ * - Added ecrt_master_deactivate() to remove the bus configuration.
  * - Added ecrt_open_master() and ecrt_master_reserve() separation for
  *   userspace.
  * - Added bus information interface (methods ecrt_master(),
@@ -682,6 +683,18 @@
         ec_master_t *master /**< EtherCAT master. */
         );
 
+/** Deactivates the master.
+ *
+ * Removes the bus configuration. All objects created by
+ * ecrt_master_create_domain(), ecrt_master_slave_config(), ecrt_domain_data()
+ * ecrt_slave_config_create_sdo_request() and
+ * ecrt_slave_config_create_voe_handler() are freed, so pointers to them
+ * become invalid.
+ */
+void ecrt_master_deactivate(
+        ec_master_t *master /**< EtherCAT master. */
+        );
+
 /** Sends all datagrams in the queue.
  *
  * This method takes all datagrams, that have been queued for transmission,
--- a/lib/master.c	Fri Aug 21 09:45:53 2009 +0200
+++ b/lib/master.c	Fri Aug 21 09:46:29 2009 +0200
@@ -335,6 +335,16 @@
 
 /*****************************************************************************/
 
+void ecrt_master_deactivate(ec_master_t *master)
+{
+    if (ioctl(master->fd, EC_IOCTL_DEACTIVATE, NULL) == -1) {
+        fprintf(stderr, "Failed to deactivate master: %s\n", strerror(errno));
+        return;
+    }
+}
+
+/*****************************************************************************/
+
 void ecrt_master_send(ec_master_t *master)
 {
     if (ioctl(master->fd, EC_IOCTL_SEND, NULL) == -1) {
--- a/master/cdev.c	Fri Aug 21 09:45:53 2009 +0200
+++ b/master/cdev.c	Fri Aug 21 09:46:29 2009 +0200
@@ -175,6 +175,7 @@
     data.eoe_handler_count = ec_master_eoe_handler_count(master);
 #endif
     data.phase = (uint8_t) master->phase;
+    data.active = (uint8_t) master->active;
     data.scan_busy = master->scan_busy;
     up(&master->master_sem);
 
@@ -1647,6 +1648,23 @@
 
 /*****************************************************************************/
 
+/** Deactivates the master.
+ */
+int ec_cdev_ioctl_deactivate(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    if (unlikely(!priv->requested))
+        return -EPERM;
+
+    ecrt_master_deactivate(master);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Send frames.
  */
 int ec_cdev_ioctl_send(
@@ -3262,6 +3280,10 @@
             if (!(filp->f_mode & FMODE_WRITE))
                 return -EPERM;
             return ec_cdev_ioctl_activate(master, arg, priv);
+        case EC_IOCTL_DEACTIVATE:
+            if (!(filp->f_mode & FMODE_WRITE))
+                return -EPERM;
+            return ec_cdev_ioctl_deactivate(master, arg, priv);
         case EC_IOCTL_SEND:
             if (!(filp->f_mode & FMODE_WRITE))
                 return -EPERM;
--- a/master/ioctl.h	Fri Aug 21 09:45:53 2009 +0200
+++ b/master/ioctl.h	Fri Aug 21 09:46:29 2009 +0200
@@ -86,40 +86,41 @@
 #define EC_IOCTL_CREATE_DOMAIN          EC_IO(0x1a)
 #define EC_IOCTL_CREATE_SLAVE_CONFIG  EC_IOWR(0x1b, ec_ioctl_config_t)
 #define EC_IOCTL_ACTIVATE              EC_IOR(0x1c, size_t)
-#define EC_IOCTL_SEND                   EC_IO(0x1d)
-#define EC_IOCTL_RECEIVE                EC_IO(0x1e)
-#define EC_IOCTL_MASTER_STATE          EC_IOR(0x1f, ec_master_state_t)
-#define EC_IOCTL_APP_TIME              EC_IOW(0x20, ec_ioctl_app_time_t)
-#define EC_IOCTL_SYNC_REF               EC_IO(0x21)
-#define EC_IOCTL_SYNC_SLAVES            EC_IO(0x22)
-#define EC_IOCTL_SC_SYNC               EC_IOW(0x23, ec_ioctl_config_t)
-#define EC_IOCTL_SC_WATCHDOG           EC_IOW(0x24, ec_ioctl_config_t)
-#define EC_IOCTL_SC_ADD_PDO            EC_IOW(0x25, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_CLEAR_PDOS         EC_IOW(0x26, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_ADD_ENTRY          EC_IOW(0x27, ec_ioctl_add_pdo_entry_t)
-#define EC_IOCTL_SC_CLEAR_ENTRIES      EC_IOW(0x28, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_REG_PDO_ENTRY     EC_IOWR(0x29, ec_ioctl_reg_pdo_entry_t)
-#define EC_IOCTL_SC_DC                 EC_IOW(0x2a, ec_ioctl_config_t)
-#define EC_IOCTL_SC_SDO                EC_IOW(0x2b, ec_ioctl_sc_sdo_t)
-#define EC_IOCTL_SC_SDO_REQUEST       EC_IOWR(0x2c, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SC_VOE               EC_IOWR(0x2d, ec_ioctl_voe_t)
-#define EC_IOCTL_SC_STATE             EC_IOWR(0x2e, ec_ioctl_sc_state_t)
-#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x2f)
-#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x20)
-#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x31)
-#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x32, ec_ioctl_domain_state_t)
-#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x33, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x34, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x35, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x36, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x37, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x38, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x39, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ              EC_IOW(0x3a, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x3b, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x3c, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x3d, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_DATA             EC_IOWR(0x3e, ec_ioctl_voe_t)
+#define EC_IOCTL_DEACTIVATE             EC_IO(0x1d)
+#define EC_IOCTL_SEND                   EC_IO(0x1e)
+#define EC_IOCTL_RECEIVE                EC_IO(0x1f)
+#define EC_IOCTL_MASTER_STATE          EC_IOR(0x20, ec_master_state_t)
+#define EC_IOCTL_APP_TIME              EC_IOW(0x21, ec_ioctl_app_time_t)
+#define EC_IOCTL_SYNC_REF               EC_IO(0x22)
+#define EC_IOCTL_SYNC_SLAVES            EC_IO(0x23)
+#define EC_IOCTL_SC_SYNC               EC_IOW(0x24, ec_ioctl_config_t)
+#define EC_IOCTL_SC_WATCHDOG           EC_IOW(0x25, ec_ioctl_config_t)
+#define EC_IOCTL_SC_ADD_PDO            EC_IOW(0x26, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_CLEAR_PDOS         EC_IOW(0x27, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_ADD_ENTRY          EC_IOW(0x28, ec_ioctl_add_pdo_entry_t)
+#define EC_IOCTL_SC_CLEAR_ENTRIES      EC_IOW(0x29, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_REG_PDO_ENTRY     EC_IOWR(0x2a, ec_ioctl_reg_pdo_entry_t)
+#define EC_IOCTL_SC_DC                 EC_IOW(0x2b, ec_ioctl_config_t)
+#define EC_IOCTL_SC_SDO                EC_IOW(0x2c, ec_ioctl_sc_sdo_t)
+#define EC_IOCTL_SC_SDO_REQUEST       EC_IOWR(0x2d, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SC_VOE               EC_IOWR(0x2e, ec_ioctl_voe_t)
+#define EC_IOCTL_SC_STATE             EC_IOWR(0x2f, ec_ioctl_sc_state_t)
+#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x20)
+#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x31)
+#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x32)
+#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x33, ec_ioctl_domain_state_t)
+#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x34, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x35, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x36, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x37, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x38, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x39, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x3a, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ              EC_IOW(0x3b, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x3c, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x3d, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x3e, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_DATA             EC_IOWR(0x3f, ec_ioctl_voe_t)
 
 /*****************************************************************************/
 
@@ -135,6 +136,7 @@
     uint32_t eoe_handler_count;
 #endif
     uint8_t phase;
+    uint8_t active;
     uint8_t scan_busy;
     struct {
         uint8_t address[6];
--- a/master/master.c	Fri Aug 21 09:45:53 2009 +0200
+++ b/master/master.c	Fri Aug 21 09:46:29 2009 +0200
@@ -121,6 +121,7 @@
     init_MUTEX(&master->device_sem);
 
     master->phase = EC_ORPHANED;
+    master->active = 0;
     master->injection_seq_fsm = 0;
     master->injection_seq_rt = 0;
 
@@ -592,67 +593,17 @@
 
 /** Transition function from OPERATION to IDLE phase.
  */
-void ec_master_leave_operation_phase(ec_master_t *master
-                                    /**< EtherCAT master */)
-{
-    ec_slave_t *slave;
-#ifdef EC_EOE
-    ec_eoe_t *eoe;
-#endif
+void ec_master_leave_operation_phase(
+        ec_master_t *master /**< EtherCAT master */
+        )
+{
+    if (master->active)
+        ecrt_master_deactivate(master);
 
     if (master->debug_level)
         EC_DBG("OPERATION -> IDLE.\n");
 
     master->phase = EC_IDLE;
-
-#ifdef EC_EOE
-    ec_master_eoe_stop(master);
-#endif
-    ec_master_thread_stop(master);
-    
-    master->send_cb = ec_master_internal_send_cb;
-    master->receive_cb = ec_master_internal_receive_cb;
-    master->cb_data = master;
-    
-    down(&master->master_sem);
-    ec_master_clear_domains(master);
-    ec_master_clear_slave_configs(master);
-    up(&master->master_sem);
-
-    for (slave = master->slaves;
-            slave < master->slaves + master->slave_count;
-            slave++) {
-
-        // set states for all slaves
-        ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
-
-        // mark for reconfiguration, because the master could have no
-        // possibility for a reconfiguration between two sequential operation
-        // phases.
-        slave->force_config = 1;
-    }
-
-#ifdef EC_EOE
-    // ... but leave EoE slaves in OP
-    list_for_each_entry(eoe, &master->eoe_handlers, list) {
-        if (ec_eoe_is_open(eoe))
-            ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
-    }
-#endif
-
-    master->app_time = 0ULL;
-    master->app_start_time = 0ULL;
-    master->has_start_time = 0;
-
-    if (ec_master_thread_start(master, ec_master_idle_thread,
-                "EtherCAT-IDLE"))
-        EC_WARN("Failed to restart master thread!\n");
-#ifdef EC_EOE
-    ec_master_eoe_start(master);
-#endif
-
-    master->allow_scan = 1;
-    master->allow_config = 1;
 }
 
 /*****************************************************************************/
@@ -1635,6 +1586,11 @@
     if (master->debug_level)
         EC_DBG("ecrt_master_activate(master = 0x%x)\n", (u32) master);
 
+    if (master->active) {
+        EC_WARN("%s: Master already active!\n", __func__);
+        return 0;
+    }
+
     down(&master->master_sem);
 
     // finish all domains
@@ -1684,11 +1640,80 @@
 
     master->allow_config = 1; // request the current configuration
     master->allow_scan = 1; // allow re-scanning on topology change
+    master->active = 1;
     return 0;
 }
 
 /*****************************************************************************/
 
+void ecrt_master_deactivate(ec_master_t *master)
+{
+    ec_slave_t *slave;
+#ifdef EC_EOE
+    ec_eoe_t *eoe;
+#endif
+
+    if (master->debug_level)
+        EC_DBG("ecrt_master_deactivate(master = 0x%x)\n", (u32) master);
+
+    if (!master->active) {
+        EC_WARN("%s: Master not active.\n", __func__);
+        return;
+    }
+
+#ifdef EC_EOE
+    ec_master_eoe_stop(master);
+#endif
+    ec_master_thread_stop(master);
+    
+    master->send_cb = ec_master_internal_send_cb;
+    master->receive_cb = ec_master_internal_receive_cb;
+    master->cb_data = master;
+    
+    down(&master->master_sem);
+    ec_master_clear_domains(master);
+    ec_master_clear_slave_configs(master);
+    up(&master->master_sem);
+
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
+
+        // set states for all slaves
+        ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+
+        // mark for reconfiguration, because the master could have no
+        // possibility for a reconfiguration between two sequential operation
+        // phases.
+        slave->force_config = 1;
+    }
+
+#ifdef EC_EOE
+    // ... but leave EoE slaves in OP
+    list_for_each_entry(eoe, &master->eoe_handlers, list) {
+        if (ec_eoe_is_open(eoe))
+            ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
+    }
+#endif
+
+    master->app_time = 0ULL;
+    master->app_start_time = 0ULL;
+    master->has_start_time = 0;
+
+    if (ec_master_thread_start(master, ec_master_idle_thread,
+                "EtherCAT-IDLE"))
+        EC_WARN("Failed to restart master thread!\n");
+#ifdef EC_EOE
+    ec_master_eoe_start(master);
+#endif
+
+    master->allow_scan = 1;
+    master->allow_config = 1;
+    master->active = 0;
+}
+
+/*****************************************************************************/
+
 void ecrt_master_send(ec_master_t *master)
 {
     ec_datagram_t *datagram, *n;
@@ -1903,6 +1928,7 @@
 
 EXPORT_SYMBOL(ecrt_master_create_domain);
 EXPORT_SYMBOL(ecrt_master_activate);
+EXPORT_SYMBOL(ecrt_master_deactivate);
 EXPORT_SYMBOL(ecrt_master_send);
 EXPORT_SYMBOL(ecrt_master_send_ext);
 EXPORT_SYMBOL(ecrt_master_receive);
--- a/master/master.h	Fri Aug 21 09:45:53 2009 +0200
+++ b/master/master.h	Fri Aug 21 09:46:29 2009 +0200
@@ -108,6 +108,7 @@
     ec_fsm_master_t fsm; /**< Master state machine. */
     ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */
     ec_master_phase_t phase; /**< Master phase. */
+    unsigned int active; /**< Master has been activated. */
     unsigned int injection_seq_fsm; /**< Datagram injection sequence number
                                       for the FSM side. */
     unsigned int injection_seq_rt; /**< Datagram injection sequence number
--- a/tool/CommandMaster.cpp	Fri Aug 21 09:45:53 2009 +0200
+++ b/tool/CommandMaster.cpp	Fri Aug 21 09:46:29 2009 +0200
@@ -91,6 +91,7 @@
     }
 
     cout << endl
+        << "  Active: " << (data.active ? "yes" : "no") << endl
         << "  Slaves: " << data.slave_count << endl
         << "  Ethernet devices:" << endl;