TODO.
--- a/TODO Thu Jul 09 14:08:16 2009 +0000
+++ b/TODO Fri Jul 10 09:36:50 2009 +0000
@@ -21,6 +21,7 @@
- Check if register 0x0980 is working, to avoid clearing it when
configuring.
- Create an interface to query the System Time Difference registers.
+* Remove byte-swapping functions from user space.
* EoE:
- Only execute one EoE handler per cycle.
- Replace locking callbacks.
--- a/include/ecrt.h Thu Jul 09 14:08:16 2009 +0000
+++ b/include/ecrt.h Fri Jul 10 09:36:50 2009 +0000
@@ -192,6 +192,22 @@
/*****************************************************************************/
+#ifndef __KERNEL__
+
+/** Master information.
+ *
+ * This is used as an output parameter of ecrt_master().
+ *
+ * \see ecrt_master().
+ */
+typedef struct {
+ unsigned int slave_count; /**< Number of slaves in the bus. */
+ unsigned int link_up : 1; /**< \a true, if the network link is up. */
+ uint64_t app_time; /**< Application time. */
+} ec_master_info_t;
+
+/*****************************************************************************/
+
/** Slave information.
*
* This is used as an output parameter of ecrt_master_slave().
@@ -213,6 +229,8 @@
char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */
} ec_slave_info_t;
+#endif // #ifndef __KERNEL__
+
/*****************************************************************************/
/** Domain working counter interpretation.
@@ -374,6 +392,52 @@
ec_master_t *master /**< EtherCAT master */
);
+
+#ifndef __KERNEL__
+
+/** Opens an EtherCAT master for userspace access.
+ *
+ * This function has to be the first function an application has to call to
+ * use EtherCAT. The function takes the index of the master as its argument.
+ * The first master has index 0, the n-th master has index n - 1. The number
+ * of masters has to be specified when loading the master module.
+ *
+ * \return Pointer to the opened master, otherwise \a NULL.
+ */
+ec_master_t *ecrt_open_master(
+ unsigned int master_index /**< Index of the master to request. */
+ );
+
+/** Reserves an EtherCAT master for realtime operation.
+ *
+ * Before an application can use PDO/domain registration functions or SDO
+ * request functions on the master, it has to reserve one for exclusive use.
+ *
+ * \return 0 in case of success, else < 0
+ *
+ */
+
+int ecrt_reserve_master(
+ ec_master_t *master /**< EtherCAT master */
+ );
+
+/** Obtains master information.
+ *
+ * No memory is allocated on the heap in
+ * this function.
+ *
+ * \attention The pointer to this structure must point to a valid variable.
+ *
+ * \return 0 in case of success, else < 0
+ */
+int ecrt_master(
+ ec_master_t *master, /**< EtherCAT master */
+ ec_master_info_t *master_info /**< Structure that will output the
+ information */
+ );
+
+#endif // #ifndef __KERNEL__
+
/******************************************************************************
* Master methods
*****************************************************************************/
@@ -468,7 +532,7 @@
information */
);
-#endif /* ifndef __KERNEL__ */
+#endif /* #ifndef __KERNEL__ */
/** Finishes the configuration phase and prepares for cyclic operation.
*
@@ -603,7 +667,7 @@
uint32_t *abort_code /**< Abort code of the SDO upload. */
);
-#endif /* ifndef __KERNEL__ */
+#endif /* #ifndef __KERNEL__ */
/******************************************************************************
* Slave configuration methods
--- a/lib/common.c Thu Jul 09 14:08:16 2009 +0000
+++ b/lib/common.c Fri Jul 10 09:36:50 2009 +0000
@@ -50,37 +50,15 @@
/*****************************************************************************/
-#define MAX_PATH_LEN 64
-
ec_master_t *ecrt_request_master(unsigned int master_index)
{
- char path[MAX_PATH_LEN];
- ec_master_t *master;
-
- master = malloc(sizeof(ec_master_t));
- if (!master) {
- fprintf(stderr, "Failed to allocate memory.\n");
- return 0;
- }
-
- master->process_data = NULL;
- master->process_data_size = 0;
-
- snprintf(path, MAX_PATH_LEN - 1, "/dev/EtherCAT%u", master_index);
-
- master->fd = open(path, O_RDWR);
- if (master->fd == -1) {
- fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
- free(master);
- return 0;
- }
-
- if (ioctl(master->fd, EC_IOCTL_REQUEST, NULL) == -1) {
- fprintf(stderr, "Failed to request master %u: %s\n",
- master_index, strerror(errno));
- close(master->fd);
- free(master);
- return 0;
+ ec_master_t *master = ecrt_open_master(master_index);
+ if (master) {
+ if (ecrt_master_reserve(master) < 0) {
+ close(master->fd);
+ free(master);
+ master = 0;
+ }
}
return master;
@@ -88,6 +66,36 @@
/*****************************************************************************/
+#define MAX_PATH_LEN 64
+
+ec_master_t *ecrt_open_master(unsigned int master_index)
+{
+ char path[MAX_PATH_LEN];
+ ec_master_t *master;
+
+ master = malloc(sizeof(ec_master_t));
+ if (!master) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ return 0;
+ }
+
+ master->process_data = NULL;
+ master->process_data_size = 0;
+
+ snprintf(path, MAX_PATH_LEN - 1, "/dev/EtherCAT%u", master_index);
+
+ master->fd = open(path, O_RDWR);
+ if (master->fd == -1) {
+ fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
+ free(master);
+ return 0;
+ }
+
+ return master;
+}
+
+/*****************************************************************************/
+
void ecrt_release_master(ec_master_t *master)
{
if (master->process_data) {
--- a/lib/master.c Thu Jul 09 14:08:16 2009 +0000
+++ b/lib/master.c Fri Jul 10 09:36:50 2009 +0000
@@ -42,6 +42,17 @@
/*****************************************************************************/
+int ecrt_master_reserve(ec_master_t *master)
+{
+ if (ioctl(master->fd, EC_IOCTL_REQUEST, NULL) == -1) {
+ fprintf(stderr, "Failed to reserve master: %s\n",
+ strerror(errno));
+ return -1;
+ }
+}
+
+/*****************************************************************************/
+
ec_domain_t *ecrt_master_create_domain(ec_master_t *master)
{
ec_domain_t *domain;
@@ -101,6 +112,25 @@
return sc;
}
+
+/*****************************************************************************/
+
+int ecrt_master(ec_master_t* master,
+ ec_master_info_t *master_info)
+{
+ ec_ioctl_master_t data;
+ if (ioctl(master->fd, EC_IOCTL_MASTER, &data) < 0) {
+ fprintf(stderr, "Failed to get master info: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ master_info->slave_count = data.slave_count;
+ master_info->link_up = data.devices[0].link_state;
+ master_info->app_time = data.app_time;
+ return 0;
+}
+
+
/*****************************************************************************/
int ecrt_master_slave(ec_master_t *master, uint16_t position,
--- a/master/fsm_coe.c Thu Jul 09 14:08:16 2009 +0000
+++ b/master/fsm_coe.c Fri Jul 10 09:36:50 2009 +0000
@@ -1105,7 +1105,7 @@
if (slave->master->debug_level) {
EC_DBG("Expedited download request:\n");
- ec_print_data(data, 10);
+ ec_print_data(data, 10 + request->data_size);
}
}
else { // request->data_size > 4, use normal transfer type
@@ -1662,7 +1662,7 @@
data_size, fsm->complete_size);
data = ec_slave_mbox_prepare_send(slave, datagram,
- 0x03, 3);
+ 0x03, 10);
if (IS_ERR(data)) {
fsm->state = ec_fsm_coe_error;
return;
@@ -1674,7 +1674,7 @@
if (master->debug_level) {
EC_DBG("Upload segment request:\n");
- ec_print_data(data, 3);
+ ec_print_data(data, 10);
}
fsm->retries = EC_FSM_RETRIES;
@@ -1876,7 +1876,7 @@
last_segment = EC_READ_U8(data + 2) & 0x01;
seg_size = (EC_READ_U8(data + 2) & 0xE) >> 1;
if (rec_size > 10) {
- data_size = rec_size - 10;
+ data_size = rec_size - 3; // Header of segment upload is smaller then normal upload
} else { // == 10
/* seg_size contains the number of trailing bytes to ignore. */
data_size = rec_size - seg_size;
@@ -1890,13 +1890,13 @@
return;
}
- memcpy(request->data + request->data_size, data + 10, data_size);
+ memcpy(request->data + request->data_size, data + 3, data_size);
request->data_size += data_size;
if (!last_segment) {
fsm->toggle = !fsm->toggle;
- data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3);
+ data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10);
if (IS_ERR(data)) {
fsm->state = ec_fsm_coe_error;
return;
@@ -1908,7 +1908,7 @@
if (master->debug_level) {
EC_DBG("Upload segment request:\n");
- ec_print_data(data, 3);
+ ec_print_data(data, 10);
}
fsm->retries = EC_FSM_RETRIES;