Implemented CompleteAccess for SDO downloads.
authorFlorian Pose <fp@igh-essen.com>
Thu, 13 Aug 2009 13:53:56 +0200
changeset 1526 66edd310830c
parent 1525 ee18735e534f
child 1527 ec71329743a1
Implemented CompleteAccess for SDO downloads.
NEWS
TODO
include/ecrt.h
lib/slave_config.c
master/cdev.c
master/fsm_coe.c
master/ioctl.h
master/sdo_request.c
master/sdo_request.h
master/slave_config.c
tool/CommandConfig.cpp
--- a/NEWS	Thu Aug 13 10:13:02 2009 +0200
+++ b/NEWS	Thu Aug 13 13:53:56 2009 +0200
@@ -61,6 +61,7 @@
 * Added 'ethercat eoe' command to display Ethernet over EtherCAT statistics.
 * Added 'ethercat cstruct' command to output PDO information in C language.
 * Significantly improved EoE bandwidth by running EoE processing in a kthread.
+* Implemented CompleteAccess for SDO downloads.
 
 Changes in 1.4.0:
 
--- a/TODO	Thu Aug 13 10:13:02 2009 +0200
+++ b/TODO	Thu Aug 13 13:53:56 2009 +0200
@@ -47,6 +47,9 @@
 * Document ec_fsm_foe members.
 * Test KBUILD_EXTRA_SYMBOLS.
 * Remove default buffer size in SDO upload.
+* Check for Enable SDO Complete Access flag.
+* Implement CompleteAccess for command-line tool.
+* Implement CompleteAccess for SDO uploads.
 
 Future issues:
 
--- a/include/ecrt.h	Thu Aug 13 10:13:02 2009 +0200
+++ b/include/ecrt.h	Thu Aug 13 13:53:56 2009 +0200
@@ -53,6 +53,8 @@
  * - Added watchdog configuration (method ecrt_slave_config_watchdog(),
  *   #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and
  *   ecrt_slave_config_sync_manager()).
+ * - Added ecrt_slave_config_complete_sdo() method to download an SDO during
+ *   configuration via CompleteAccess.
  * - Added ecrt_open_master() and ecrt_master_reserve() separation for
  *   userspace.
  * - Added bus information interface (methods ecrt_master(),
@@ -1032,6 +1034,23 @@
         uint32_t value /**< Value to set. */
         );
 
+/** Add configuration data for a complete SDO.
+ *
+ * The SDO data are transferred via CompleteAccess. Data for the first
+ * subindex (0) have to be included.
+ *
+ * \see ecrt_slave_config_sdo().
+ *
+ * \retval  0 Success.
+ * \retval <0 Error code.
+ */
+int ecrt_slave_config_complete_sdo(
+        ec_slave_config_t *sc, /**< Slave configuration. */
+        uint16_t index, /**< Index of the SDO to configure. */
+        const uint8_t *data, /**< Pointer to the data. */
+        size_t size /**< Size of the \a data. */
+        );
+
 /** Create an SDO request to exchange SDOs during realtime operation.
  *
  * The created SDO request object is freed automatically when the master is
--- a/lib/slave_config.c	Thu Aug 13 10:13:02 2009 +0200
+++ b/lib/slave_config.c	Thu Aug 13 13:53:56 2009 +0200
@@ -294,6 +294,29 @@
     data.subindex = subindex;
     data.data = sdo_data;
     data.size = size;
+    data.complete_access = 0;
+
+    if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
+        fprintf(stderr, "Failed to configure SDO.\n");
+        return -1; // FIXME
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
+        const uint8_t *sdo_data, size_t size)
+{
+    ec_ioctl_sc_sdo_t data;
+
+    data.config_index = sc->index;
+    data.index = index;
+    data.subindex = 0;
+    data.data = sdo_data;
+    data.size = size;
+    data.complete_access = 1;
 
     if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
         fprintf(stderr, "Failed to configure SDO.\n");
--- a/master/cdev.c	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/cdev.c	Thu Aug 13 13:53:56 2009 +0200
@@ -1434,7 +1434,8 @@
     data.index = req->index;
     data.subindex = req->subindex;
     data.size = req->data_size;
-    memcpy(&data.data, req->data, min((u32) data.size, (u32) 4));
+    memcpy(&data.data, req->data,
+            min((u32) data.size, (u32) EC_MAX_SDO_DATA_SIZE));
 
     up(&master->master_sem);
 
@@ -2120,8 +2121,12 @@
 
     up(&master->master_sem); // FIXME
 
-    ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
-            data.size);
+    if (data.complete_access) {
+        ret = ecrt_slave_config_complete_sdo(sc, data.index, sdo_data, data.size);
+    } else {
+        ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
+                data.size);
+    }
     kfree(sdo_data);
     return ret;
 }
--- a/master/fsm_coe.c	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/fsm_coe.c	Thu Aug 13 13:53:56 2009 +0200
@@ -1074,8 +1074,14 @@
     uint8_t size;
 
     if (fsm->slave->master->debug_level) {
-        EC_DBG("Downloading SDO 0x%04X:%02X to slave %u.\n",
-               request->index, request->subindex, slave->ring_position);
+        char subidxstr[10];
+        if (request->complete_access) {
+            subidxstr[0] = 0x00;
+        } else {
+            sprintf(subidxstr, ":%02X", request->subindex);
+        }
+        EC_DBG("Downloading SDO 0x%04X%s to slave %u.\n",
+                request->index, subidxstr, slave->ring_position);
         ec_print_data(request->data, request->data_size);
     }
 
@@ -1097,9 +1103,11 @@
         EC_WRITE_U16(data, 0x2 << 12); // SDO request
         EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited
                     | size << 2
+                    | ((request->complete_access ? 1 : 0) << 4) 
                     | 0x1 << 5)); // Download request
         EC_WRITE_U16(data + 3, request->index);
-        EC_WRITE_U8 (data + 5, request->subindex);
+        EC_WRITE_U8 (data + 5,
+                request->complete_access ? 0x00 : request->subindex);
         memcpy(data + 6, request->data, request->data_size);
         memset(data + 6 + request->data_size, 0x00, 4 - request->data_size);
 
@@ -1110,7 +1118,7 @@
     }
     else { // request->data_size > 4, use normal transfer type
         if (slave->configured_rx_mailbox_size < 6 + 10 + request->data_size) {
-            EC_ERR("SDO fragmenting not supported yet!\n");
+            EC_ERR("SDO fragmenting not supported yet!\n"); // FIXME
             fsm->state = ec_fsm_coe_error;
             return;
         }
@@ -1124,9 +1132,11 @@
 
         EC_WRITE_U16(data, 0x2 << 12); // SDO request
         EC_WRITE_U8 (data + 2, (0x1 // size indicator, normal
+                    | ((request->complete_access ? 1 : 0) << 4) 
                     | 0x1 << 5)); // Download request
         EC_WRITE_U16(data + 3, request->index);
-        EC_WRITE_U8 (data + 5, request->subindex);
+        EC_WRITE_U8 (data + 5,
+                request->complete_access ? 0x00 : request->subindex);
         EC_WRITE_U32(data + 6, request->data_size);
         memcpy(data + 10, request->data, request->data_size);
 
@@ -1311,12 +1321,18 @@
 
     if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
-        fsm->state = ec_fsm_coe_error;
-        EC_ERR("SDO download 0x%04X:%02X (%u bytes) aborted on slave %u.\n",
-               request->index, request->subindex, request->data_size,
-               slave->ring_position);
+        char subidxstr[10];
+        fsm->state = ec_fsm_coe_error;
+        if (request->complete_access) {
+            subidxstr[0] = 0x00;
+        } else {
+            sprintf(subidxstr, ":%02X", request->subindex);
+        }
+        EC_ERR("SDO download 0x%04X%s (%u bytes) aborted on slave %u.\n",
+                request->index, subidxstr, request->data_size,
+                slave->ring_position);
         if (rec_size < 10) {
-            EC_ERR("Incomplete Abort command:\n");
+            EC_ERR("Incomplete abort command:\n");
             ec_print_data(data, rec_size);
         } else {
             fsm->request->abort_code = EC_READ_U32(data + 6);
--- a/master/ioctl.h	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/ioctl.h	Thu Aug 13 13:53:56 2009 +0200
@@ -438,6 +438,11 @@
 
 /*****************************************************************************/
 
+/** Maximum size for displayed SDO data.
+ * \todo Make this dynamic.
+ */
+#define EC_MAX_SDO_DATA_SIZE 1024
+
 typedef struct {
     // inputs
     uint32_t config_index;
@@ -447,7 +452,7 @@
     uint16_t index;
     uint8_t subindex;
     uint32_t size;
-    uint8_t data[4];
+    uint8_t data[EC_MAX_SDO_DATA_SIZE];
 } ec_ioctl_config_sdo_t;
 
 /*****************************************************************************/
@@ -505,6 +510,7 @@
     uint8_t subindex;
     const uint8_t *data;
     size_t size;
+    uint8_t complete_access;
 } ec_ioctl_sc_sdo_t;
 
 /*****************************************************************************/
--- a/master/sdo_request.c	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/sdo_request.c	Thu Aug 13 13:53:56 2009 +0200
@@ -56,6 +56,7 @@
         ec_sdo_request_t *req /**< SDO request. */
         )
 {
+    req->complete_access = 0;
     req->data = NULL;
     req->mem_size = 0;
     req->data_size = 0;
@@ -88,6 +89,7 @@
         const ec_sdo_request_t *other /**< Other SDO request to copy from. */
         )
 {
+    req->complete_access = other->complete_access;
     req->index = other->index;
     req->subindex = other->subindex;
     return ec_sdo_request_copy_data(req, other->data, other->data_size);
--- a/master/sdo_request.h	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/sdo_request.h	Thu Aug 13 13:53:56 2009 +0200
@@ -52,6 +52,7 @@
     uint8_t *data; /**< Pointer to SDO data. */
     size_t mem_size; /**< Size of SDO data memory. */
     size_t data_size; /**< Size of SDO data. */
+    uint8_t complete_access; /**< SDO shall be transferred completely. */
     uint32_t issue_timeout; /**< Maximum time in ms, the processing of the
                               request may take. */
     uint32_t response_timeout; /**< Maximum time in ms, the transfer is
--- a/master/slave_config.c	Thu Aug 13 10:13:02 2009 +0200
+++ b/master/slave_config.c	Thu Aug 13 13:53:56 2009 +0200
@@ -794,6 +794,48 @@
 
 /*****************************************************************************/
 
+int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
+        const uint8_t *data, size_t size)
+{
+    ec_slave_t *slave = sc->slave;
+    ec_sdo_request_t *req;
+    int ret;
+
+    if (sc->master->debug_level)
+        EC_DBG("ecrt_slave_config_complete_sdo(sc = 0x%x, index = 0x%04X, "
+                "data = 0x%x, size = %u)\n", (u32) sc,
+                index, (u32) data, size);
+
+    if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
+        EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
+        return -EPROTONOSUPPORT; // protocol not supported
+    }
+
+    if (!(req = (ec_sdo_request_t *)
+          kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate memory for SDO configuration!\n");
+        return -ENOMEM;
+    }
+
+    ec_sdo_request_init(req);
+    ec_sdo_request_address(req, index, 0);
+    req->complete_access = 1;
+
+    ret = ec_sdo_request_copy_data(req, data, size);
+    if (ret < 0) {
+        ec_sdo_request_clear(req);
+        kfree(req);
+        return ret;
+    }
+        
+    down(&sc->master->master_sem);
+    list_add_tail(&req->list, &sc->sdo_configs);
+    up(&sc->master->master_sem);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Same as ecrt_slave_config_create_sdo_request(), but with ERR_PTR() return
  * value.
  */
@@ -923,6 +965,7 @@
 EXPORT_SYMBOL(ecrt_slave_config_sdo8);
 EXPORT_SYMBOL(ecrt_slave_config_sdo16);
 EXPORT_SYMBOL(ecrt_slave_config_sdo32);
+EXPORT_SYMBOL(ecrt_slave_config_complete_sdo);
 EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request);
 EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler);
 EXPORT_SYMBOL(ecrt_slave_config_state);
--- a/tool/CommandConfig.cpp	Thu Aug 13 10:13:02 2009 +0200
+++ b/tool/CommandConfig.cpp	Thu Aug 13 13:53:56 2009 +0200
@@ -131,7 +131,7 @@
 		)
 {
     ConfigList::const_iterator configIter;
-    unsigned int j, k, l;
+    unsigned int i, j, k, l;
     ec_ioctl_slave_t slave;
     ec_ioctl_config_pdo_t pdo;
     ec_ioctl_config_pdo_entry_t entry;
@@ -217,26 +217,23 @@
                     << hex << setfill('0')
                     << setw(4) << sdo.index << ":"
                     << setw(2) << (unsigned int) sdo.subindex
-                    << ", " << dec << sdo.size << " byte: " << hex;
-
-                switch (sdo.size) {
-                    case 1:
-                        cout << "0x" << setw(2)
-                            << (unsigned int) *(uint8_t *) &sdo.data;
-                        break;
-                    case 2:
-                        cout << "0x" << setw(4)
-                            << le16_to_cpup(&sdo.data);
-                        break;
-                    case 4:
-                        cout << "0x" << setw(8)
-                            << le32_to_cpup(&sdo.data);
-                        break;
-                    default:
-                        cout << "???";
+                    << ", " << dec << sdo.size << " byte" << endl;
+
+                cout << "    " << hex;
+                for (i = 0; i < min((uint32_t) sdo.size,
+                            (uint32_t) EC_MAX_SDO_DATA_SIZE); i++) {
+                    cout << setw(2) << (unsigned int) sdo.data[i];
+                    if ((i + 1) % 16 == 0 && i < sdo.size - 1) {
+                        cout << endl << "    ";
+                    } else {
+                        cout << " ";
+                    }
                 }
 
                 cout << endl;
+                if (sdo.size > EC_MAX_SDO_DATA_SIZE) {
+                    cout << "    ..." << endl;
+                }
             }
         } else {
             cout << "  None." << endl;