--- a/TODO Thu Jun 19 08:06:49 2008 +0000
+++ b/TODO Thu Jun 19 09:24:22 2008 +0000
@@ -16,8 +16,7 @@
* Update documentation.
* Attach Pdo names from SII or Coe dictioary to Pdos read via CoE.
* Add a -n (numeric) switch to ethercat command.
-* Remove Eoe cylces and Idle cycles.
-* Store Sdo abort code in sdo_request_t and output it in user space.
+* Remove Eoe cycles and Idle cycles.
Future issues:
--- a/master/cdev.c Thu Jun 19 08:06:49 2008 +0000
+++ b/master/cdev.c Thu Jun 19 09:24:22 2008 +0000
@@ -628,6 +628,7 @@
if (request.req.state == EC_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->sdo_sem);
+ ec_sdo_request_clear(&request.req);
retval = -EINTR;
break;
}
@@ -637,27 +638,31 @@
// wait until master FSM has finished processing
wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
+
+ data.abort_code = request.req.abort_code;
if (request.req.state != EC_REQUEST_SUCCESS) {
+ data.data_size = 0;
retval = -EIO;
- break;
- }
-
- if (request.req.data_size > data.target_size) {
- EC_ERR("Buffer too small.\n");
- retval = -EOVERFLOW;
- break;
- }
- data.data_size = request.req.data_size;
-
- if (copy_to_user((void __user *) data.target,
- request.req.data, data.data_size)) {
- retval = -EFAULT;
- break;
- }
+ } else {
+ if (request.req.data_size > data.target_size) {
+ EC_ERR("Buffer too small.\n");
+ ec_sdo_request_clear(&request.req);
+ retval = -EOVERFLOW;
+ break;
+ }
+ data.data_size = request.req.data_size;
+
+ if (copy_to_user((void __user *) data.target,
+ request.req.data, data.data_size)) {
+ ec_sdo_request_clear(&request.req);
+ retval = -EFAULT;
+ break;
+ }
+ }
+
if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
retval = -EFAULT;
- break;
}
ec_sdo_request_clear(&request.req);
@@ -721,6 +726,7 @@
if (request.req.state == EC_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->sdo_sem);
+ ec_sdo_request_clear(&request.req);
retval = -EINTR;
break;
}
@@ -731,9 +737,14 @@
// wait until master FSM has finished processing
wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
+ data.abort_code = request.req.abort_code;
+
if (request.req.state != EC_REQUEST_SUCCESS) {
retval = -EIO;
- break;
+ }
+
+ if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
+ retval = -EFAULT;
}
ec_sdo_request_clear(&request.req);
--- a/master/fsm_coe.c Thu Jun 19 08:06:49 2008 +0000
+++ b/master/fsm_coe.c Thu Jun 19 09:24:22 2008 +0000
@@ -430,11 +430,23 @@
return;
}
+ if (rec_size < 3) {
+ EC_ERR("Received corrupted Sdo dictionary response (size %u).\n",
+ rec_size);
+ fsm->state = ec_fsm_coe_error;
+ return;
+ }
+
if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("Sdo information error response at slave %u!\n",
slave->ring_position);
- ec_canopen_abort_msg(EC_READ_U32(data + 6));
+ if (rec_size < 10) {
+ EC_ERR("Incomplete Sdo information error response:\n");
+ ec_print_data(data, rec_size);
+ } else {
+ ec_canopen_abort_msg(EC_READ_U32(data + 6));
+ }
fsm->state = ec_fsm_coe_error;
return;
}
@@ -448,8 +460,8 @@
return;
}
- if (rec_size < 8) {
- EC_ERR("Invalid data size!\n");
+ if (rec_size < 8 || rec_size % 2) {
+ EC_ERR("Invalid data size %u!\n", rec_size);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_coe_error;
return;
@@ -656,6 +668,13 @@
return;
}
+ if (rec_size < 3) {
+ EC_ERR("Received corrupted Sdo description response (size %u).\n",
+ rec_size);
+ fsm->state = ec_fsm_coe_error;
+ return;
+ }
+
if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("Sdo information error response at slave %u while"
@@ -666,6 +685,13 @@
return;
}
+ if (rec_size < 8) {
+ EC_ERR("Received corrupted Sdo description response (size %u).\n",
+ rec_size);
+ fsm->state = ec_fsm_coe_error;
+ return;
+ }
+
if (EC_READ_U16(data) >> 12 != 0x8 || // Sdo information
(EC_READ_U8 (data + 2) & 0x7F) != 0x04 || // Object desc. response
EC_READ_U16(data + 6) != sdo->index) { // Sdo index
@@ -872,6 +898,13 @@
return;
}
+ if (rec_size < 3) {
+ EC_ERR("Received corrupted Sdo entry description response "
+ "(size %u).\n", rec_size);
+ fsm->state = ec_fsm_coe_error;
+ return;
+ }
+
if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("Sdo information error response at slave %u while"
@@ -882,6 +915,13 @@
return;
}
+ if (rec_size < 9) {
+ EC_ERR("Received corrupted Sdo entry description response "
+ "(size %u).\n", rec_size);
+ fsm->state = ec_fsm_coe_error;
+ return;
+ }
+
if (EC_READ_U16(data) >> 12 != 0x8 || // Sdo information
(EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
EC_READ_U16(data + 6) != sdo->index || // Sdo index
@@ -895,7 +935,7 @@
}
if (rec_size < 16) {
- EC_ERR("Invalid data size!\n");
+ EC_ERR("Invalid data size %u!\n", rec_size);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_coe_error;
return;
@@ -1191,7 +1231,7 @@
if (rec_size < 6) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Received data is too small (%u bytes):\n", rec_size);
+ EC_ERR("Received data are too small (%u bytes):\n", rec_size);
ec_print_data(data, rec_size);
return;
}
@@ -1205,9 +1245,10 @@
if (rec_size < 10) {
EC_ERR("Incomplete Abort command:\n");
ec_print_data(data, rec_size);
- }
- else
- ec_canopen_abort_msg(EC_READ_U32(data + 6));
+ } else {
+ fsm->request->abort_code = EC_READ_U32(data + 6);
+ ec_canopen_abort_msg(fsm->request->abort_code);
+ }
return;
}
@@ -1446,10 +1487,12 @@
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
EC_ERR("Sdo upload 0x%04X:%02X aborted on slave %u.\n",
request->index, request->subindex, slave->ring_position);
- if (rec_size >= 10)
- ec_canopen_abort_msg(EC_READ_U32(data + 6));
- else
+ if (rec_size >= 10) {
+ request->abort_code = EC_READ_U32(data + 6);
+ ec_canopen_abort_msg(request->abort_code);
+ } else {
EC_ERR("No abort message.\n");
+ }
fsm->state = ec_fsm_coe_error;
return;
}
@@ -1737,7 +1780,8 @@
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
EC_ERR("Sdo upload 0x%04X:%02X aborted on slave %u.\n",
request->index, request->subindex, slave->ring_position);
- ec_canopen_abort_msg(EC_READ_U32(data + 6));
+ request->abort_code = EC_READ_U32(data + 6);
+ ec_canopen_abort_msg(request->abort_code);
fsm->state = ec_fsm_coe_error;
return;
}
--- a/master/ioctl.h Thu Jun 19 08:06:49 2008 +0000
+++ b/master/ioctl.h Thu Jun 19 09:24:22 2008 +0000
@@ -67,7 +67,7 @@
#define EC_IOCTL_SDO EC_IOWR(0x0a, ec_ioctl_sdo_t)
#define EC_IOCTL_SDO_ENTRY EC_IOWR(0x0b, ec_ioctl_sdo_entry_t)
#define EC_IOCTL_SDO_UPLOAD EC_IOWR(0x0c, ec_ioctl_sdo_upload_t)
-#define EC_IOCTL_SDO_DOWNLOAD EC_IOW(0x0d, ec_ioctl_sdo_download_t)
+#define EC_IOCTL_SDO_DOWNLOAD EC_IOWR(0x0d, ec_ioctl_sdo_download_t)
#define EC_IOCTL_SII_READ EC_IOWR(0x0e, ec_ioctl_sii_t)
#define EC_IOCTL_SII_WRITE EC_IOW(0x0f, ec_ioctl_sii_t)
#define EC_IOCTL_CONFIG EC_IOWR(0x10, ec_ioctl_config_t)
@@ -253,6 +253,7 @@
// outputs
uint32_t data_size;
+ uint32_t abort_code;
} ec_ioctl_sdo_upload_t;
/*****************************************************************************/
@@ -264,6 +265,9 @@
uint8_t sdo_entry_subindex;
uint32_t data_size;
uint8_t *data;
+
+ // outputs
+ uint32_t abort_code;
} ec_ioctl_sdo_download_t;
/*****************************************************************************/
--- a/master/sdo_request.c Thu Jun 19 08:06:49 2008 +0000
+++ b/master/sdo_request.c Thu Jun 19 09:24:22 2008 +0000
@@ -73,6 +73,7 @@
req->issue_timeout = 0; // no timeout
req->response_timeout = 0; // immediate response required
req->state = EC_REQUEST_INIT;
+ req->abort_code = 0x00000000;
}
/*****************************************************************************/
@@ -211,6 +212,7 @@
{
req->dir = EC_DIR_INPUT;
req->state = EC_REQUEST_QUEUED;
+ req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}
@@ -220,6 +222,7 @@
{
req->dir = EC_DIR_OUTPUT;
req->state = EC_REQUEST_QUEUED;
+ req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}
--- a/master/sdo_request.h Thu Jun 19 08:06:49 2008 +0000
+++ b/master/sdo_request.h Thu Jun 19 09:24:22 2008 +0000
@@ -69,6 +69,7 @@
unsigned long jiffies_start; /**< Jiffies, when the request was issued. */
unsigned long jiffies_sent; /**< Jiffies, when the upload/download
request was sent. */
+ uint32_t abort_code; /**< Sdo request abort code. Zero on success. */
};
/*****************************************************************************/
--- a/tools/Master.cpp Thu Jun 19 08:06:49 2008 +0000
+++ b/tools/Master.cpp Thu Jun 19 09:24:22 2008 +0000
@@ -656,7 +656,13 @@
if (ioctl(fd, EC_IOCTL_SDO_DOWNLOAD, &data) < 0) {
stringstream err;
- err << "Failed to download Sdo: " << strerror(errno);
+ err << "Failed to download Sdo: ";
+ if (errno == EIO && data.abort_code) {
+ err << "Abort code 0x" << hex << setfill('0') << setw(8)
+ << data.abort_code;
+ } else {
+ err << strerror(errno);
+ }
delete [] data.data;
throw MasterException(err.str());
}
@@ -751,7 +757,13 @@
if (ioctl(fd, EC_IOCTL_SDO_UPLOAD, &data) < 0) {
stringstream err;
- err << "Failed to upload Sdo: " << strerror(errno);
+ err << "Failed to upload Sdo: ";
+ if (errno == EIO && data.abort_code) {
+ err << "Abort code 0x" << hex << setfill('0') << setw(8)
+ << data.abort_code;
+ } else {
+ err << strerror(errno);
+ }
delete [] data.target;
close();
throw MasterException(err.str());