Added interface to read/write register contents; re-worked register requests.
--- a/include/ecrt.h Wed Nov 14 22:08:32 2012 +0100
+++ b/include/ecrt.h Wed Nov 14 22:12:57 2012 +0100
@@ -52,6 +52,10 @@
* ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(),
* ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and
* the defines EC_HAVE_EMERGENCY and EC_COE_EMERGENCY_MSG_SIZE.
+ * - Added interface for direct EtherCAT register access: Added data type
+ * ec_reg_request_t and methods ecrt_slave_config_create_reg_request(),
+ * ecrt_reg_request_data(), ecrt_reg_request_state(),
+ * ecrt_reg_request_write() and ecrt_reg_request_read().
*
* Changes in version 1.5:
*
@@ -207,6 +211,9 @@
struct ec_voe_handler;
typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */
+struct ec_reg_request;
+typedef struct ec_reg_request ec_reg_request_t; /**< \see ec_sdo_request. */
+
/*****************************************************************************/
/** Master state.
@@ -1375,6 +1382,20 @@
size_t size /**< Data size to reserve. */
);
+/** Create a register request to exchange EtherCAT register contents during
+ * realtime operation.
+ *
+ * This interface should not be used to take over master functionality,
+ * instead it is intended for debugging and monitoring reasons.
+ *
+ * The created register request object is freed automatically when the master
+ * is released.
+ */
+ec_reg_request_t *ecrt_slave_config_create_reg_request(
+ ec_slave_config_t *sc, /**< Slave configuration. */
+ size_t size /**< Data size to reserve. */
+ );
+
/** Outputs the state of the slave configuration.
*
* Stores the state information in the given \a state structure. The state
@@ -1745,6 +1766,75 @@
ec_voe_handler_t *voe /**< VoE handler. */
);
+/*****************************************************************************
+ * Register request methods.
+ ****************************************************************************/
+
+/** Access to the register request's data.
+ *
+ * This function returns a pointer to the request's internal memory.
+ *
+ * - After a read operation was successful, integer data can be evaluated using
+ * the EC_READ_*() macros as usual. Example:
+ * \code
+ * uint16_t value = EC_READ_U16(ecrt_reg_request_data(reg_request)));
+ * \endcode
+ * - If a write operation shall be triggered, the data have to be written to
+ * the internal memory. Use the EC_WRITE_*() macros, if you are writing
+ * integer data. Be sure, that the data fit into the memory. The memory size
+ * is a parameter of ecrt_slave_config_create_reg_request().
+ * \code
+ * EC_WRITE_U16(ecrt_reg_request_data(reg_request), 0xFFFF);
+ * \endcode
+ *
+ * \return Pointer to the internal memory.
+ */
+uint8_t *ecrt_reg_request_data(
+ ec_reg_request_t *req /**< Register request. */
+ );
+
+/** Get the current state of the register request.
+ *
+ * \return Request state.
+ */
+#ifdef __KERNEL__
+ec_request_state_t ecrt_reg_request_state(
+ const ec_reg_request_t *req /**< Register request. */
+ );
+#else
+ec_request_state_t ecrt_reg_request_state(
+ ec_reg_request_t *req /**< Register request. */
+ );
+#endif
+
+/** Schedule an register write operation.
+ *
+ * \attention This method may not be called while ecrt_reg_request_state()
+ * returns EC_REQUEST_BUSY.
+ *
+ * \attention The \a size parameter is truncated to the size given at request
+ * creation.
+ */
+void ecrt_reg_request_write(
+ ec_reg_request_t *req, /**< Register request. */
+ uint16_t address, /**< Register address. */
+ size_t size /**< Size to write. */
+ );
+
+/** Schedule a register read operation.
+ *
+ * \attention This method may not be called while ecrt_reg_request_state()
+ * returns EC_REQUEST_BUSY.
+ *
+ * \attention The \a size parameter is truncated to the size given at request
+ * creation.
+ */
+void ecrt_reg_request_read(
+ ec_reg_request_t *req, /**< Register request. */
+ uint16_t address, /**< Register address. */
+ size_t size /**< Size to write. */
+ );
+
/*****************************************************************************/
#ifdef __cplusplus
--- a/lib/Makefile.am Wed Nov 14 22:08:32 2012 +0100
+++ b/lib/Makefile.am Wed Nov 14 22:12:57 2012 +0100
@@ -36,6 +36,7 @@
common.c \
domain.c \
master.c \
+ reg_request.c \
sdo_request.c \
slave_config.c \
voe_handler.c
@@ -43,6 +44,7 @@
noinst_HEADERS = \
domain.h \
master.h \
+ reg_request.h \
sdo_request.h \
slave_config.h \
voe_handler.h
--- a/lib/master.c Wed Nov 14 22:08:32 2012 +0100
+++ b/lib/master.c Wed Nov 14 22:12:57 2012 +0100
@@ -192,6 +192,7 @@
sc->alias = alias;
sc->position = position;
sc->first_sdo_request = NULL;
+ sc->first_reg_request = NULL;
sc->first_voe_handler = NULL;
ec_master_add_slave_config(master, sc);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/reg_request.c Wed Nov 14 22:12:57 2012 +0100
@@ -0,0 +1,138 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT master userspace library.
+ *
+ * The IgH EtherCAT master userspace library is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License as published by the Free Software Foundation; version 2.1
+ * of the License.
+ *
+ * The IgH EtherCAT master userspace library is distributed in the hope that
+ * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the IgH EtherCAT master userspace library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ *****************************************************************************/
+
+/** \file
+ * EtherCAT register request functions.
+ */
+
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ioctl.h"
+#include "reg_request.h"
+#include "slave_config.h"
+#include "master.h"
+
+/*****************************************************************************/
+
+void ec_reg_request_clear(ec_reg_request_t *reg)
+{
+ if (reg->data) {
+ free(reg->data);
+ }
+}
+
+/*****************************************************************************
+ * Application interface.
+ ****************************************************************************/
+
+uint8_t *ecrt_reg_request_data(ec_reg_request_t *reg)
+{
+ return reg->data;
+}
+
+/*****************************************************************************/
+
+ec_request_state_t ecrt_reg_request_state(ec_reg_request_t *reg)
+{
+ ec_ioctl_reg_request_t io;
+ int ret;
+
+ io.config_index = reg->config->index;
+ io.request_index = reg->index;
+
+ ret = ioctl(reg->config->master->fd, EC_IOCTL_REG_REQUEST_STATE, &io);
+ if (EC_IOCTL_IS_ERROR(ret)) {
+ fprintf(stderr, "Failed to get register request state: %s\n",
+ strerror(EC_IOCTL_ERRNO(ret)));
+ return EC_REQUEST_ERROR;
+ }
+
+ if (io.new_data) { // new data waiting to be copied
+
+ io.data = reg->data;
+ io.mem_size = reg->mem_size;
+
+ ret = ioctl(reg->config->master->fd,
+ EC_IOCTL_REG_REQUEST_DATA, &io);
+ if (EC_IOCTL_IS_ERROR(ret)) {
+ fprintf(stderr, "Failed to get register data: %s\n",
+ strerror(EC_IOCTL_ERRNO(ret)));
+ return EC_REQUEST_ERROR;
+ }
+ }
+
+ return io.state;
+}
+
+/*****************************************************************************/
+
+void ecrt_reg_request_write(ec_reg_request_t *reg, uint16_t address,
+ size_t size)
+{
+ ec_ioctl_reg_request_t io;
+ int ret;
+
+ io.config_index = reg->config->index;
+ io.request_index = reg->index;
+ io.data = reg->data;
+ io.address = address;
+ io.transfer_size = size;
+
+ ret = ioctl(reg->config->master->fd, EC_IOCTL_REG_REQUEST_WRITE, &io);
+ if (EC_IOCTL_IS_ERROR(ret)) {
+ fprintf(stderr, "Failed to command an register write operation: %s\n",
+ strerror(EC_IOCTL_ERRNO(ret)));
+ }
+}
+
+/*****************************************************************************/
+
+void ecrt_reg_request_read(ec_reg_request_t *reg, uint16_t address,
+ size_t size)
+{
+ ec_ioctl_reg_request_t io;
+ int ret;
+
+ io.config_index = reg->config->index;
+ io.request_index = reg->index;
+ io.address = address;
+ io.transfer_size = size;
+
+ ret = ioctl(reg->config->master->fd, EC_IOCTL_REG_REQUEST_READ, &io);
+ if (EC_IOCTL_IS_ERROR(ret)) {
+ fprintf(stderr, "Failed to command an register read operation: %s\n",
+ strerror(EC_IOCTL_ERRNO(ret)));
+ }
+}
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/reg_request.h Wed Nov 14 22:12:57 2012 +0100
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT master userspace library.
+ *
+ * The IgH EtherCAT master userspace library is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License as published by the Free Software Foundation; version 2.1
+ * of the License.
+ *
+ * The IgH EtherCAT master userspace library is distributed in the hope that
+ * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the IgH EtherCAT master userspace library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ *****************************************************************************/
+
+#include "include/ecrt.h"
+
+/*****************************************************************************/
+
+struct ec_reg_request {
+ ec_reg_request_t *next; /**< List header. */
+ ec_slave_config_t *config; /**< Parent slave configuration. */
+ unsigned int index; /**< Request index (identifier). */
+ uint8_t *data; /**< Data memory. */
+ size_t mem_size; /**< Size of \a data. */
+};
+
+/*****************************************************************************/
+
+void ec_reg_request_clear(ec_reg_request_t *);
+
+/*****************************************************************************/
--- a/lib/slave_config.c Wed Nov 14 22:08:32 2012 +0100
+++ b/lib/slave_config.c Wed Nov 14 22:12:57 2012 +0100
@@ -37,6 +37,7 @@
#include "slave_config.h"
#include "domain.h"
#include "sdo_request.h"
+#include "reg_request.h"
#include "voe_handler.h"
#include "master.h"
@@ -45,6 +46,7 @@
void ec_slave_config_clear(ec_slave_config_t *sc)
{
ec_sdo_request_t *r, *next_r;
+ ec_reg_request_t *e, *next_e;
ec_voe_handler_t *v, *next_v;
r = sc->first_sdo_request;
@@ -54,6 +56,12 @@
r = next_r;
}
+ e = sc->first_reg_request;
+ while (e) {
+ next_e = e->next;
+ ec_reg_request_clear(e);
+ e = next_e;
+ }
v = sc->first_voe_handler;
while (v) {
@@ -551,6 +559,71 @@
/*****************************************************************************/
+void ec_slave_config_add_reg_request(ec_slave_config_t *sc,
+ ec_reg_request_t *reg)
+{
+ if (sc->first_reg_request) {
+ ec_reg_request_t *r = sc->first_reg_request;
+ while (r->next) {
+ r = r->next;
+ }
+ r->next = reg;
+ } else {
+ sc->first_reg_request = reg;
+ }
+}
+
+/*****************************************************************************/
+
+ec_reg_request_t *ecrt_slave_config_create_reg_request(ec_slave_config_t *sc,
+ size_t size)
+{
+ ec_ioctl_reg_request_t io;
+ ec_reg_request_t *reg;
+ int ret;
+
+ reg = malloc(sizeof(ec_reg_request_t));
+ if (!reg) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ return NULL;
+ }
+
+ if (size) {
+ reg->data = malloc(size);
+ if (!reg->data) {
+ fprintf(stderr, "Failed to allocate %u bytes of register data"
+ " memory.\n", size);
+ free(reg);
+ return 0;
+ }
+ } else {
+ reg->data = NULL;
+ }
+
+ io.config_index = sc->index;
+ io.mem_size = size;
+
+ ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_REQUEST, &io);
+ if (EC_IOCTL_IS_ERROR(ret)) {
+ fprintf(stderr, "Failed to create register request: %s\n",
+ strerror(EC_IOCTL_ERRNO(ret)));
+ ec_reg_request_clear(reg);
+ free(reg);
+ return NULL;
+ }
+
+ reg->next = NULL;
+ reg->config = sc;
+ reg->index = io.request_index;
+ reg->mem_size = size;
+
+ ec_slave_config_add_reg_request(sc, reg);
+
+ return reg;
+}
+
+/*****************************************************************************/
+
void ec_slave_config_add_voe_handler(ec_slave_config_t *sc,
ec_voe_handler_t *voe)
{
--- a/lib/slave_config.h Wed Nov 14 22:08:32 2012 +0100
+++ b/lib/slave_config.h Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT master userspace library.
*
@@ -39,6 +39,7 @@
uint16_t alias;
uint16_t position;
ec_sdo_request_t *first_sdo_request;
+ ec_reg_request_t *first_reg_request;
ec_voe_handler_t *first_voe_handler;
};
--- a/master/Kbuild.in Wed Nov 14 22:08:32 2012 +0100
+++ b/master/Kbuild.in Wed Nov 14 22:12:57 2012 +0100
@@ -60,6 +60,7 @@
pdo.o \
pdo_entry.o \
pdo_list.o \
+ reg_request.o \
sdo.o \
sdo_entry.o \
sdo_request.o \
--- a/master/Makefile.am Wed Nov 14 22:08:32 2012 +0100
+++ b/master/Makefile.am Wed Nov 14 22:12:57 2012 +0100
@@ -60,6 +60,7 @@
pdo.c pdo.h \
pdo_entry.c pdo_entry.h \
pdo_list.c pdo_list.h \
+ reg_request.c reg_request.h \
rtdm-ioctl.c \
rtdm.c rtdm.h \
sdo.c sdo.h \
--- a/master/fsm_master.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/fsm_master.c Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -65,7 +65,6 @@
void ec_fsm_master_state_write_sii(ec_fsm_master_t *);
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *);
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *);
-void ec_fsm_master_state_reg_request(ec_fsm_master_t *);
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *);
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *);
@@ -404,62 +403,6 @@
/*****************************************************************************/
-/** Check for pending register requests and process one.
- *
- * \return non-zero, if a register request is processed.
- */
-int ec_fsm_master_action_process_register(
- ec_fsm_master_t *fsm /**< Master state machine. */
- )
-{
- ec_master_t *master = fsm->master;
- ec_reg_request_t *request;
-
- // search the first request to be processed
- while (!list_empty(&master->reg_requests)) {
-
- // get first request
- request = list_entry(master->reg_requests.next,
- ec_reg_request_t, list);
- list_del_init(&request->list); // dequeue
- request->state = EC_INT_REQUEST_BUSY;
-
- // found pending request; process it!
- EC_SLAVE_DBG(request->slave, 1, "Processing register request, "
- "offset 0x%04x, length %zu...\n",
- request->offset, request->length);
-
- if (request->length > fsm->datagram->mem_size) {
- EC_MASTER_ERR(master, "Request length (%zu) exceeds maximum "
- "datagram size (%zu)!\n", request->length,
- fsm->datagram->mem_size);
- request->state = EC_INT_REQUEST_FAILURE;
- wake_up(&master->reg_queue);
- continue;
- }
-
- fsm->reg_request = request;
-
- if (request->dir == EC_DIR_INPUT) {
- ec_datagram_fprd(fsm->datagram, request->slave->station_address,
- request->offset, request->length);
- ec_datagram_zero(fsm->datagram);
- } else {
- ec_datagram_fpwr(fsm->datagram, request->slave->station_address,
- request->offset, request->length);
- memcpy(fsm->datagram->data, request->data, request->length);
- }
- fsm->datagram->device_index = request->slave->device_index;
- fsm->retries = EC_FSM_RETRIES;
- fsm->state = ec_fsm_master_state_reg_request;
- return 1;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
/** Check for pending SDO requests and process one.
*
* \return non-zero, if an SDO request is processed.
@@ -509,7 +452,6 @@
return 0;
}
-
/*****************************************************************************/
/** Master action: IDLE.
@@ -563,12 +505,9 @@
}
// check for pending SII write operations.
- if (ec_fsm_master_action_process_sii(fsm))
+ if (ec_fsm_master_action_process_sii(fsm)) {
return; // SII write request found
-
- // check for pending register requests.
- if (ec_fsm_master_action_process_register(fsm))
- return; // register request processing
+ }
ec_fsm_master_restart(fsm);
}
@@ -1276,64 +1215,11 @@
EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
// check for another SDO request
- if (ec_fsm_master_action_process_sdo(fsm))
+ if (ec_fsm_master_action_process_sdo(fsm)) {
return; // processing another request
+ }
ec_fsm_master_restart(fsm);
}
/*****************************************************************************/
-
-/** Master state: REG REQUEST.
- */
-void ec_fsm_master_state_reg_request(
- ec_fsm_master_t *fsm /**< Master state machine. */
- )
-{
- ec_master_t *master = fsm->master;
- ec_datagram_t *datagram = fsm->datagram;
- ec_reg_request_t *request = fsm->reg_request;
-
- if (datagram->state != EC_DATAGRAM_RECEIVED) {
- EC_MASTER_ERR(master, "Failed to receive register"
- " request datagram: ");
- ec_datagram_print_state(datagram);
- request->state = EC_INT_REQUEST_FAILURE;
- wake_up(&master->reg_queue);
- ec_fsm_master_restart(fsm);
- return;
- }
-
- if (datagram->working_counter == 1) {
- if (request->dir == EC_DIR_INPUT) { // read request
- if (request->data)
- kfree(request->data);
- request->data = kmalloc(request->length, GFP_KERNEL);
- if (!request->data) {
- EC_MASTER_ERR(master, "Failed to allocate %zu bytes"
- " of memory for register data.\n", request->length);
- request->state = EC_INT_REQUEST_FAILURE;
- wake_up(&master->reg_queue);
- ec_fsm_master_restart(fsm);
- return;
- }
- memcpy(request->data, datagram->data, request->length);
- }
-
- request->state = EC_INT_REQUEST_SUCCESS;
- EC_SLAVE_DBG(request->slave, 1, "Register request successful.\n");
- } else {
- request->state = EC_INT_REQUEST_FAILURE;
- EC_MASTER_ERR(master, "Register request failed.\n");
- }
-
- wake_up(&master->reg_queue);
-
- // check for another register request
- if (ec_fsm_master_action_process_register(fsm))
- return; // processing another request
-
- ec_fsm_master_restart(fsm);
-}
-
-/*****************************************************************************/
--- a/master/fsm_master.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/fsm_master.h Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -61,20 +61,6 @@
/*****************************************************************************/
-/** Register request.
- */
-typedef struct {
- struct list_head list; /**< List head. */
- ec_slave_t *slave; /**< EtherCAT slave. */
- ec_direction_t dir; /**< Direction. */
- uint16_t offset; /**< Register address. */
- size_t length; /**< Number of bytes. */
- uint8_t *data; /**< Data to write / memory for read data. */
- ec_internal_request_state_t state; /**< State of the request. */
-} ec_reg_request_t;
-
-/*****************************************************************************/
-
/** Slave/SDO request record for master's SDO request list.
*/
typedef struct {
@@ -132,7 +118,6 @@
ec_sii_write_request_t *sii_request; /**< SII write request */
off_t sii_index; /**< index to SII write request data */
ec_sdo_request_t *sdo_request; /**< SDO request to process. */
- ec_reg_request_t *reg_request; /**< Register request to process. */
ec_fsm_coe_t fsm_coe; /**< CoE state machine */
ec_fsm_pdo_t fsm_pdo; /**< PDO configuration state machine. */
--- a/master/fsm_slave.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/fsm_slave.c Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -36,6 +36,7 @@
#include "globals.h"
#include "master.h"
#include "mailbox.h"
+#include "slave_config.h"
#include "fsm_slave.h"
@@ -45,6 +46,8 @@
void ec_fsm_slave_state_ready(ec_fsm_slave_t *);
int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *);
void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *);
+int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *);
+void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *);
int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *);
void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *);
int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *);
@@ -137,7 +140,6 @@
// do nothing
}
-
/*****************************************************************************/
/** Slave state: READY.
@@ -151,6 +153,11 @@
return;
}
+ // Check for pending external register requests
+ if (ec_fsm_slave_action_process_reg(fsm)) {
+ return;
+ }
+
// Check for pending FoE requests
if (ec_fsm_slave_action_process_foe(fsm)) {
return;
@@ -176,7 +183,8 @@
ec_master_sdo_request_t *request, *next;
// search the first external request to be processed
- list_for_each_entry_safe(request, next, &slave->slave_sdo_requests, list) {
+ list_for_each_entry_safe(request, next,
+ &slave->slave_sdo_requests, list) {
list_del_init(&request->list); // dequeue
if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
@@ -229,6 +237,7 @@
ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
return;
}
+
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
request->state = EC_INT_REQUEST_FAILURE;
@@ -250,6 +259,114 @@
/*****************************************************************************/
+/** Check for pending register requests and process one.
+ *
+ * \return non-zero, if a register request is processed.
+ */
+int ec_fsm_slave_action_process_reg(
+ ec_fsm_slave_t *fsm /**< Slave state machine. */
+ )
+{
+ ec_slave_t *slave = fsm->slave;
+ ec_reg_request_t *reg, *next;
+
+ fsm->reg_request = NULL;
+
+ if (slave->config) {
+ // search the first internal register request to be processed
+ list_for_each_entry(reg, &slave->config->reg_requests, list) {
+ if (reg->state == EC_INT_REQUEST_QUEUED) {
+ fsm->reg_request = reg;
+ break;
+ }
+ }
+ }
+
+ if (!fsm->reg_request) {
+ // search the first external request to be processed
+ list_for_each_entry_safe(reg, next, &slave->reg_requests, list) {
+ list_del_init(®->list); // dequeue
+ fsm->reg_request = reg;
+ break;
+ }
+ }
+
+ if (!fsm->reg_request) { // no register request to process
+ return 0;
+ }
+
+ if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
+ EC_SLAVE_WARN(slave, "Aborting register request,"
+ " slave has error flag set.\n");
+ reg->state = EC_INT_REQUEST_FAILURE;
+ wake_up(&slave->reg_queue);
+ fsm->state = ec_fsm_slave_state_idle;
+ return 1;
+ }
+
+ // Found pending register request. Execute it!
+ EC_SLAVE_DBG(slave, 1, "Processing register request...\n");
+
+ reg->state = EC_INT_REQUEST_BUSY;
+
+ // Start register access
+ if (reg->dir == EC_DIR_INPUT) {
+ ec_datagram_fprd(fsm->datagram, slave->station_address,
+ reg->address, reg->transfer_size);
+ ec_datagram_zero(fsm->datagram);
+ } else {
+ ec_datagram_fpwr(fsm->datagram, slave->station_address,
+ reg->address, reg->transfer_size);
+ memcpy(fsm->datagram->data, reg->data, reg->transfer_size);
+ }
+ fsm->datagram->device_index = slave->device_index;
+ ec_master_queue_external_datagram(slave->master, fsm->datagram);
+ fsm->state = ec_fsm_slave_state_reg_request;
+ return 1;
+}
+
+/*****************************************************************************/
+
+/** Slave state: Register request.
+ */
+void ec_fsm_slave_state_reg_request(
+ ec_fsm_slave_t *fsm /**< Slave state machine. */
+ )
+{
+ ec_slave_t *slave = fsm->slave;
+ ec_reg_request_t *reg = fsm->reg_request;
+
+ if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
+ EC_SLAVE_ERR(slave, "Failed to receive register"
+ " request datagram: ");
+ ec_datagram_print_state(fsm->datagram);
+ reg->state = EC_INT_REQUEST_FAILURE;
+ wake_up(&slave->reg_queue);
+ fsm->state = ec_fsm_slave_state_ready;
+ return;
+ }
+
+ if (fsm->datagram->working_counter == 1) {
+ if (reg->dir == EC_DIR_INPUT) { // read request
+ memcpy(reg->data, fsm->datagram->data, reg->transfer_size);
+ }
+
+ reg->state = EC_INT_REQUEST_SUCCESS;
+ EC_SLAVE_DBG(slave, 1, "Register request successful.\n");
+ } else {
+ reg->state = EC_INT_REQUEST_FAILURE;
+ ec_datagram_print_state(fsm->datagram);
+ EC_SLAVE_ERR(slave, "Register request failed"
+ " (working counter is %u).\n",
+ fsm->datagram->working_counter);
+ }
+
+ wake_up(&slave->reg_queue);
+ fsm->state = ec_fsm_slave_state_ready;
+}
+
+/*****************************************************************************/
+
/** Check for pending FoE requests and process one.
*
* \return non-zero, if an FoE request is processed.
--- a/master/fsm_slave.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/fsm_slave.h Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -29,20 +29,24 @@
/**
\file
- EtherCAT slave request (SDO) state machine.
+ EtherCAT slave request state machine.
*/
/*****************************************************************************/
+
#ifndef __EC_FSM_SLAVE_H__
#define __EC_FSM_SLAVE_H__
#include "globals.h"
#include "datagram.h"
#include "sdo_request.h"
+#include "reg_request.h"
#include "fsm_coe.h"
#include "fsm_foe.h"
#include "fsm_soe.h"
+/*****************************************************************************/
+
typedef struct ec_fsm_slave ec_fsm_slave_t; /**< \see ec_fsm_slave */
/** Finite state machine of an EtherCAT slave.
@@ -53,6 +57,7 @@
void (*state)(ec_fsm_slave_t *); /**< master state function */
ec_sdo_request_t *sdo_request; /**< SDO request to process. */
+ ec_reg_request_t *reg_request; /**< Register request to process. */
ec_foe_request_t *foe_request; /**< FoE request to process. */
off_t foe_index; /**< index to FoE write request data */
ec_soe_request_t *soe_request; /**< SoE request to process. */
--- a/master/ioctl.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/ioctl.c Wed Nov 14 22:12:57 2012 +0100
@@ -977,51 +977,48 @@
void *arg /**< ioctl() argument. */
)
{
- ec_ioctl_slave_reg_t data;
+ ec_ioctl_slave_reg_t io;
ec_slave_t *slave;
- uint8_t *contents;
ec_reg_request_t request;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!data.length)
+ int ret;
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ if (!io.size) {
return 0;
-
- if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for register data.\n", data.length);
- return -ENOMEM;
- }
-
- if (down_interruptible(&master->master_sem))
+ }
+
+ // init register request
+ ret = ec_reg_request_init(&request, io.size);
+ if (ret) {
+ return ret;
+ }
+
+ ecrt_reg_request_read(&request, io.address, io.size);
+
+ if (down_interruptible(&master->master_sem)) {
+ ec_reg_request_clear(&request);
return -EINTR;
+ }
if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- up(&master->master_sem);
+ master, 0, io.slave_position))) {
+ up(&master->master_sem);
+ ec_reg_request_clear(&request);
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
+ io.slave_position);
return -EINVAL;
}
- // init register request
- INIT_LIST_HEAD(&request.list);
- request.slave = slave;
- request.dir = EC_DIR_INPUT;
- request.data = contents;
- request.offset = data.offset;
- request.length = data.length;
- request.state = EC_INT_REQUEST_QUEUED;
-
// schedule request.
- list_add_tail(&request.list, &master->reg_requests);
+ list_add_tail(&request.list, &slave->reg_requests);
up(&master->master_sem);
// wait for processing through FSM
- if (wait_event_interruptible(master->reg_queue,
+ if (wait_event_interruptible(slave->reg_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
@@ -1029,20 +1026,21 @@
// abort request
list_del(&request.list);
up(&master->master_sem);
- kfree(contents);
+ ec_reg_request_clear(&request);
return -EINTR;
}
up(&master->master_sem);
}
// wait until master FSM has finished processing
- wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
+ wait_event(slave->reg_queue, request.state != EC_INT_REQUEST_BUSY);
if (request.state == EC_INT_REQUEST_SUCCESS) {
- if (copy_to_user((void __user *) data.data, contents, data.length))
+ if (copy_to_user((void __user *) io.data, request.data, io.size)) {
return -EFAULT;
- }
- kfree(contents);
+ }
+ }
+ ec_reg_request_clear(&request);
return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
@@ -1056,57 +1054,53 @@
void *arg /**< ioctl() argument. */
)
{
- ec_ioctl_slave_reg_t data;
+ ec_ioctl_slave_reg_t io;
ec_slave_t *slave;
- uint8_t *contents;
ec_reg_request_t request;
-
- if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
- return -EFAULT;
- }
-
- if (!data.length)
+ int ret;
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ if (!io.size) {
return 0;
-
- if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
- EC_MASTER_ERR(master, "Failed to allocate %u bytes"
- " for register data.\n", data.length);
- return -ENOMEM;
- }
-
- if (copy_from_user(contents, (void __user *) data.data, data.length)) {
- kfree(contents);
- return -EFAULT;
- }
-
- if (down_interruptible(&master->master_sem))
+ }
+
+ // init register request
+ ret = ec_reg_request_init(&request, io.size);
+ if (ret) {
+ return ret;
+ }
+
+ if (copy_from_user(request.data, (void __user *) io.data, io.size)) {
+ ec_reg_request_clear(&request);
+ return -EFAULT;
+ }
+
+ ecrt_reg_request_write(&request, io.address, io.size);
+
+ if (down_interruptible(&master->master_sem)) {
+ ec_reg_request_clear(&request);
return -EINTR;
+ }
if (!(slave = ec_master_find_slave(
- master, 0, data.slave_position))) {
- up(&master->master_sem);
+ master, 0, io.slave_position))) {
+ up(&master->master_sem);
+ ec_reg_request_clear(&request);
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
- data.slave_position);
- kfree(contents);
+ io.slave_position);
return -EINVAL;
}
- // init register request
- INIT_LIST_HEAD(&request.list);
- request.slave = slave;
- request.dir = EC_DIR_OUTPUT;
- request.data = contents;
- request.offset = data.offset;
- request.length = data.length;
- request.state = EC_INT_REQUEST_QUEUED;
-
// schedule request.
- list_add_tail(&request.list, &master->reg_requests);
+ list_add_tail(&request.list, &slave->reg_requests);
up(&master->master_sem);
// wait for processing through FSM
- if (wait_event_interruptible(master->reg_queue,
+ if (wait_event_interruptible(slave->reg_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
@@ -1114,16 +1108,16 @@
// abort request
list_del(&request.list);
up(&master->master_sem);
- kfree(contents);
+ ec_reg_request_clear(&request);
return -EINTR;
}
up(&master->master_sem);
}
// wait until master FSM has finished processing
- wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
-
- kfree(contents);
+ wait_event(slave->reg_queue, request.state != EC_INT_REQUEST_BUSY);
+
+ ec_reg_request_clear(&request);
return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
@@ -1608,7 +1602,7 @@
/* Set the memory as external process data memory for the
* domains.
- */
+ */
offset = 0;
list_for_each_entry(domain, &master->domains, list) {
ecrt_domain_external_memory(domain,
@@ -1617,10 +1611,10 @@
}
#ifdef EC_IOCTL_RTDM
- /* RTDM uses a different approach for memory-mapping, which has to be
- * initiated by the kernel.
- */
- ret = ec_rtdm_mmap(ctx, &io.process_data);
+ /* RTDM uses a different approach for memory-mapping, which has to be
+ * initiated by the kernel.
+ */
+ ret = ec_rtdm_mmap(ctx, &io.process_data);
if (ret < 0) {
EC_MASTER_ERR(master, "Failed to map process data"
" memory to user space (code %i).\n", ret);
@@ -2488,6 +2482,58 @@
/*****************************************************************************/
+/** Create a register request.
+ */
+static int ec_ioctl_sc_create_reg_request(
+ ec_master_t *master, /**< EtherCAT master. */
+ void *arg, /**< ioctl() argument. */
+ ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+ )
+{
+ ec_ioctl_reg_request_t io;
+ ec_slave_config_t *sc;
+ ec_reg_request_t *reg;
+
+ if (unlikely(!ctx->requested)) {
+ return -EPERM;
+ }
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ io.request_index = 0;
+
+ if (down_interruptible(&master->master_sem)) {
+ return -EINTR;
+ }
+
+ sc = ec_master_get_config(master, io.config_index);
+ if (!sc) {
+ up(&master->master_sem);
+ return -ENOENT;
+ }
+
+ list_for_each_entry(reg, &sc->reg_requests, list) {
+ io.request_index++;
+ }
+
+ up(&master->master_sem); /** \fixme sc could be invalidated */
+
+ reg = ecrt_slave_config_create_reg_request_err(sc, io.mem_size);
+ if (IS_ERR(reg)) {
+ return PTR_ERR(reg);
+ }
+
+ if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
/** Create a VoE handler.
*/
static int ec_ioctl_sc_create_voe_handler(
@@ -2979,6 +3025,181 @@
/*****************************************************************************/
+/** Read register data.
+ */
+static int ec_ioctl_reg_request_data(
+ ec_master_t *master, /**< EtherCAT master. */
+ void *arg, /**< ioctl() argument. */
+ ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+ )
+{
+ ec_ioctl_reg_request_t io;
+ ec_slave_config_t *sc;
+ ec_reg_request_t *reg;
+
+ if (unlikely(!ctx->requested)) {
+ return -EPERM;
+ }
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ if (io.mem_size <= 0) {
+ return 0;
+ }
+
+ /* no locking of master_sem needed, because neither sc nor reg will not be
+ * deleted in the meantime. */
+
+ if (!(sc = ec_master_get_config(master, io.config_index))) {
+ return -ENOENT;
+ }
+
+ if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
+ return -ENOENT;
+ }
+
+ if (copy_to_user((void __user *) io.data, ecrt_reg_request_data(reg),
+ min(reg->mem_size, io.mem_size))) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+/** Gets an register request's state.
+ */
+static int ec_ioctl_reg_request_state(
+ ec_master_t *master, /**< EtherCAT master. */
+ void *arg, /**< ioctl() argument. */
+ ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+ )
+{
+ ec_ioctl_reg_request_t io;
+ ec_slave_config_t *sc;
+ ec_reg_request_t *reg;
+
+ if (unlikely(!ctx->requested)) {
+ return -EPERM;
+ }
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ /* no locking of master_sem needed, because neither sc nor reg will not be
+ * deleted in the meantime. */
+
+ if (!(sc = ec_master_get_config(master, io.config_index))) {
+ return -ENOENT;
+ }
+
+ if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
+ return -ENOENT;
+ }
+
+ io.state = ecrt_reg_request_state(reg);
+ io.new_data = io.state == EC_REQUEST_SUCCESS && reg->dir == EC_DIR_INPUT;
+
+ if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+/** Starts an register write operation.
+ */
+static int ec_ioctl_reg_request_write(
+ ec_master_t *master, /**< EtherCAT master. */
+ void *arg, /**< ioctl() argument. */
+ ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+ )
+{
+ ec_ioctl_reg_request_t io;
+ ec_slave_config_t *sc;
+ ec_reg_request_t *reg;
+
+ if (unlikely(!ctx->requested)) {
+ return -EPERM;
+ }
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ /* no locking of master_sem needed, because neither sc nor reg will not be
+ * deleted in the meantime. */
+
+ if (!(sc = ec_master_get_config(master, io.config_index))) {
+ return -ENOENT;
+ }
+
+ if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
+ return -ENOENT;
+ }
+
+ if (io.transfer_size > reg->mem_size) {
+ return -EOVERFLOW;
+ }
+
+ if (copy_from_user(reg->data, (void __user *) io.data,
+ io.transfer_size)) {
+ return -EFAULT;
+ }
+
+ ecrt_reg_request_write(reg, io.address, io.transfer_size);
+ return 0;
+}
+
+/*****************************************************************************/
+
+/** Starts an register read operation.
+ */
+static int ec_ioctl_reg_request_read(
+ ec_master_t *master, /**< EtherCAT master. */
+ void *arg, /**< ioctl() argument. */
+ ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+ )
+{
+ ec_ioctl_reg_request_t io;
+ ec_slave_config_t *sc;
+ ec_reg_request_t *reg;
+
+ if (unlikely(!ctx->requested)) {
+ return -EPERM;
+ }
+
+ if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
+ return -EFAULT;
+ }
+
+ /* no locking of master_sem needed, because neither sc nor reg will not be
+ * deleted in the meantime. */
+
+ if (!(sc = ec_master_get_config(master, io.config_index))) {
+ return -ENOENT;
+ }
+
+ if (!(reg = ec_slave_config_find_reg_request(sc, io.request_index))) {
+ return -ENOENT;
+ }
+
+ if (io.transfer_size > reg->mem_size) {
+ return -EOVERFLOW;
+ }
+
+ ecrt_reg_request_read(reg, io.address, io.transfer_size);
+ return 0;
+}
+
+/*****************************************************************************/
+
/** Sets the VoE send header.
*/
static int ec_ioctl_voe_send_header(
@@ -3548,7 +3769,7 @@
/** Called when an ioctl() command is issued.
*/
long EC_IOCTL(ec_master_t *master, ec_ioctl_context_t *ctx,
- unsigned int cmd, void *arg)
+ unsigned int cmd, void *arg)
{
#if DEBUG_LATENCY
cycles_t a = get_cycles(), b;
@@ -3876,6 +4097,13 @@
}
ret = ec_ioctl_sc_create_sdo_request(master, arg, ctx);
break;
+ case EC_IOCTL_SC_REG_REQUEST:
+ if (!ctx->writable) {
+ ret = -EPERM;
+ break;
+ }
+ ret = ec_ioctl_sc_create_reg_request(master, arg, ctx);
+ break;
case EC_IOCTL_SC_VOE:
if (!ctx->writable) {
ret = -EPERM;
@@ -3947,6 +4175,26 @@
case EC_IOCTL_SDO_REQUEST_DATA:
ret = ec_ioctl_sdo_request_data(master, arg, ctx);
break;
+ case EC_IOCTL_REG_REQUEST_DATA:
+ ret = ec_ioctl_reg_request_data(master, arg, ctx);
+ break;
+ case EC_IOCTL_REG_REQUEST_STATE:
+ ret = ec_ioctl_reg_request_state(master, arg, ctx);
+ break;
+ case EC_IOCTL_REG_REQUEST_WRITE:
+ if (!ctx->writable) {
+ ret = -EPERM;
+ break;
+ }
+ ret = ec_ioctl_reg_request_write(master, arg, ctx);
+ break;
+ case EC_IOCTL_REG_REQUEST_READ:
+ if (!ctx->writable) {
+ ret = -EPERM;
+ break;
+ }
+ ret = ec_ioctl_reg_request_read(master, arg, ctx);
+ break;
case EC_IOCTL_VOE_SEND_HEADER:
if (!ctx->writable) {
ret = -EPERM;
--- a/master/ioctl.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/ioctl.h Wed Nov 14 22:12:57 2012 +0100
@@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
-#define EC_IOCTL_VERSION_MAGIC 21
+#define EC_IOCTL_VERSION_MAGIC 22
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@@ -122,27 +122,32 @@
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x38, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x39, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SC_VOE EC_IOWR(0x3b, ec_ioctl_voe_t)
-#define EC_IOCTL_SC_STATE EC_IOWR(0x3c, ec_ioctl_sc_state_t)
-#define EC_IOCTL_SC_IDN EC_IOW(0x3d, ec_ioctl_sc_idn_t)
-#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3e)
-#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3f)
-#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x40)
-#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x41, ec_ioctl_domain_state_t)
-#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x42, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x43, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x44, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x45, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x46, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x47, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x48, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x49, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ EC_IOW(0x4a, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x4b, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_WRITE EC_IOWR(0x4c, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_EXEC EC_IOWR(0x4d, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_DATA EC_IOWR(0x4e, ec_ioctl_voe_t)
-#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4f, size_t)
+#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x3b, ec_ioctl_reg_request_t)
+#define EC_IOCTL_SC_VOE EC_IOWR(0x3c, ec_ioctl_voe_t)
+#define EC_IOCTL_SC_STATE EC_IOWR(0x3d, ec_ioctl_sc_state_t)
+#define EC_IOCTL_SC_IDN EC_IOW(0x3e, ec_ioctl_sc_idn_t)
+#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3f)
+#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x40)
+#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x41)
+#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x42, ec_ioctl_domain_state_t)
+#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x43, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x44, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x45, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x46, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x47, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x48, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x49, ec_ioctl_reg_request_t)
+#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x4a, ec_ioctl_reg_request_t)
+#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x4b, ec_ioctl_reg_request_t)
+#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x4c, ec_ioctl_reg_request_t)
+#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x4d, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x4e, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ EC_IOW(0x4f, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x50, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_WRITE EC_IOWR(0x51, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_EXEC EC_IOWR(0x52, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_DATA EC_IOWR(0x53, ec_ioctl_voe_t)
+#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x54, size_t)
/*****************************************************************************/
@@ -409,8 +414,8 @@
typedef struct {
// inputs
uint16_t slave_position;
- uint16_t offset;
- uint16_t length;
+ uint16_t address;
+ size_t size;
uint8_t *data;
} ec_ioctl_slave_reg_t;
@@ -686,6 +691,22 @@
typedef struct {
// inputs
uint32_t config_index;
+ size_t mem_size;
+
+ // inputs/outputs
+ uint32_t request_index;
+ uint8_t *data;
+ ec_request_state_t state;
+ uint8_t new_data;
+ uint16_t address;
+ size_t transfer_size;
+} ec_ioctl_reg_request_t;
+
+/*****************************************************************************/
+
+typedef struct {
+ // inputs
+ uint32_t config_index;
// inputs/outputs
uint32_t voe_index;
--- a/master/master.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/master.c Wed Nov 14 22:12:57 2012 +0100
@@ -208,9 +208,6 @@
INIT_LIST_HEAD(&master->sii_requests);
init_waitqueue_head(&master->sii_queue);
- INIT_LIST_HEAD(&master->reg_requests);
- init_waitqueue_head(&master->reg_queue);
-
// init devices
ret = ec_device_init(&master->devices[EC_DEVICE_MAIN], master);
if (ret < 0)
@@ -429,16 +426,6 @@
wake_up(&master->sii_queue);
}
- while (!list_empty(&master->reg_requests)) {
- ec_reg_request_t *request =
- list_entry(master->reg_requests.next, ec_reg_request_t, list);
- list_del_init(&request->list); // dequeue
- EC_MASTER_WARN(master, "Discarding register request, slave %u"
- " about to be deleted.\n", request->slave->ring_position);
- request->state = EC_INT_REQUEST_FAILURE;
- wake_up(&master->reg_queue);
- }
-
for (slave = master->slaves;
slave < master->slaves + master->slave_count;
slave++) {
@@ -874,8 +861,8 @@
list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
if (queued_datagram == datagram) {
datagram->skip_count++;
- EC_MASTER_DBG(master, 1, "Skipping re-initialized datagram %p.\n",
- datagram);
+ EC_MASTER_DBG(master, 1,
+ "Datagram %p already queued (skipping).\n", datagram);
datagram->state = EC_DATAGRAM_QUEUED;
return;
}
--- a/master/master.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/master.h Wed Nov 14 22:12:57 2012 +0100
@@ -276,9 +276,6 @@
struct list_head sii_requests; /**< SII write requests. */
wait_queue_head_t sii_queue; /**< Wait queue for SII
write requests from user space. */
-
- struct list_head reg_requests; /**< Register requests. */
- wait_queue_head_t reg_queue; /**< Wait queue for register requests. */
};
/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/reg_request.c Wed Nov 14 22:12:57 2012 +0100
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT Master.
+ *
+ * The IgH EtherCAT Master is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * The IgH EtherCAT Master is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the IgH EtherCAT Master; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ *****************************************************************************/
+
+/** \file
+ * Register request functions.
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+
+#include "reg_request.h"
+
+/*****************************************************************************/
+
+void ec_reg_request_clear_data(ec_reg_request_t *);
+
+/*****************************************************************************/
+
+/** Register request constructor.
+ */
+int ec_reg_request_init(
+ ec_reg_request_t *reg, /**< Register request. */
+ size_t size /**< Memory size. */
+ )
+{
+ if (!(reg->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
+ EC_ERR("Failed to allocate %zu bytes of register memory.\n", size);
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(®->list);
+ reg->mem_size = size;
+ memset(reg->data, 0x00, size);
+ reg->dir = EC_DIR_INVALID;
+ reg->address = 0;
+ reg->transfer_size = 0;
+ reg->state = EC_INT_REQUEST_INIT;
+ return 0;
+}
+
+/*****************************************************************************/
+
+/** Register request destructor.
+ */
+void ec_reg_request_clear(
+ ec_reg_request_t *reg /**< Register request. */
+ )
+{
+ if (reg->data) {
+ kfree(reg->data);
+ }
+}
+
+/*****************************************************************************
+ * Application interface.
+ ****************************************************************************/
+
+uint8_t *ecrt_reg_request_data(ec_reg_request_t *reg)
+{
+ return reg->data;
+}
+
+/*****************************************************************************/
+
+ec_request_state_t ecrt_reg_request_state(const ec_reg_request_t *reg)
+{
+ return ec_request_state_translation_table[reg->state];
+}
+
+/*****************************************************************************/
+
+void ecrt_reg_request_write(ec_reg_request_t *reg, uint16_t address,
+ size_t size)
+{
+ reg->dir = EC_DIR_OUTPUT;
+ reg->address = address;
+ reg->transfer_size = min(size, reg->mem_size);
+ reg->state = EC_INT_REQUEST_QUEUED;
+}
+
+/*****************************************************************************/
+
+void ecrt_reg_request_read(ec_reg_request_t *reg, uint16_t address,
+ size_t size)
+{
+ reg->dir = EC_DIR_INPUT;
+ reg->address = address;
+ reg->transfer_size = min(size, reg->mem_size);
+ reg->state = EC_INT_REQUEST_QUEUED;
+}
+
+/*****************************************************************************/
+
+/** \cond */
+
+EXPORT_SYMBOL(ecrt_reg_request_data);
+EXPORT_SYMBOL(ecrt_reg_request_state);
+EXPORT_SYMBOL(ecrt_reg_request_write);
+EXPORT_SYMBOL(ecrt_reg_request_read);
+
+/** \endcond */
+
+/*****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/reg_request.h Wed Nov 14 22:12:57 2012 +0100
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2012 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT Master.
+ *
+ * The IgH EtherCAT Master is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * The IgH EtherCAT Master is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the IgH EtherCAT Master; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ *****************************************************************************/
+
+/**
+ \file
+ EtherCAT register request structure.
+*/
+
+/*****************************************************************************/
+
+#ifndef __EC_REG_REQUEST_H__
+#define __EC_REG_REQUEST_H__
+
+#include <linux/list.h>
+
+#include "globals.h"
+
+/*****************************************************************************/
+
+/** Register request.
+ */
+struct ec_reg_request {
+ struct list_head list; /**< List item. */
+ size_t mem_size; /**< Size of data memory. */
+ uint8_t *data; /**< Pointer to data memory. */
+ ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means writing to the
+ slave, EC_DIR_INPUT means reading from the slave. */
+ uint16_t address; /**< Register address. */
+ size_t transfer_size; /*< Size of the data to transfer. */
+ ec_internal_request_state_t state; /**< Request state. */
+};
+
+/*****************************************************************************/
+
+int ec_reg_request_init(ec_reg_request_t *, size_t);
+void ec_reg_request_clear(ec_reg_request_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/master/slave.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/slave.c Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -155,6 +155,9 @@
INIT_LIST_HEAD(&slave->slave_sdo_requests);
init_waitqueue_head(&slave->sdo_queue);
+ INIT_LIST_HEAD(&slave->reg_requests);
+ init_waitqueue_head(&slave->reg_queue);
+
INIT_LIST_HEAD(&slave->foe_requests);
init_waitqueue_head(&slave->foe_queue);
@@ -202,6 +205,16 @@
wake_up(&slave->sdo_queue);
}
+ while (!list_empty(&slave->reg_requests)) {
+ ec_reg_request_t *reg =
+ list_entry(slave->reg_requests.next, ec_reg_request_t, list);
+ list_del_init(®->list); // dequeue
+ EC_SLAVE_WARN(slave, "Discarding register request,"
+ " slave about to be deleted.\n");
+ reg->state = EC_INT_REQUEST_FAILURE;
+ wake_up(&slave->reg_queue);
+ }
+
while (!list_empty(&slave->foe_requests)) {
ec_master_foe_request_t *request =
list_entry(slave->foe_requests.next,
@@ -224,8 +237,9 @@
wake_up(&slave->soe_queue);
}
- if (slave->config)
+ if (slave->config) {
ec_slave_config_detach(slave->config);
+ }
// free all SDOs
list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
@@ -251,8 +265,10 @@
kfree(pdo);
}
- if (slave->sii_words)
+ if (slave->sii_words) {
kfree(slave->sii_words);
+ }
+
ec_fsm_slave_clear(&slave->fsm);
ec_datagram_clear(&slave->fsm_datagram);
}
--- a/master/slave.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/slave.h Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -227,6 +227,9 @@
struct list_head slave_sdo_requests; /**< SDO access requests. */
wait_queue_head_t sdo_queue; /**< Wait queue for SDO access requests
from user space. */
+ struct list_head reg_requests; /**< Register access requests. */
+ wait_queue_head_t reg_queue; /**< Wait queue for register access requests
+ from user space. */
struct list_head foe_requests; /**< FoE write requests. */
wait_queue_head_t foe_queue; /**< Wait queue for FoE requests from user
space. */
--- a/master/slave_config.c Wed Nov 14 22:08:32 2012 +0100
+++ b/master/slave_config.c Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -86,6 +86,7 @@
INIT_LIST_HEAD(&sc->sdo_configs);
INIT_LIST_HEAD(&sc->sdo_requests);
+ INIT_LIST_HEAD(&sc->reg_requests);
INIT_LIST_HEAD(&sc->voe_handlers);
INIT_LIST_HEAD(&sc->soe_configs);
@@ -105,6 +106,7 @@
unsigned int i;
ec_sdo_request_t *req, *next_req;
ec_voe_handler_t *voe, *next_voe;
+ ec_reg_request_t *reg, *next_reg;
ec_soe_request_t *soe, *next_soe;
ec_slave_config_detach(sc);
@@ -127,6 +129,13 @@
kfree(req);
}
+ // free all register requests
+ list_for_each_entry_safe(reg, next_reg, &sc->reg_requests, list) {
+ list_del(®->list);
+ ec_reg_request_clear(reg);
+ kfree(reg);
+ }
+
// free all VoE handlers
list_for_each_entry_safe(voe, next_voe, &sc->voe_handlers, list) {
list_del(&voe->list);
@@ -429,7 +438,7 @@
/*****************************************************************************/
-/** Finds a VoE handler via its position in the list.
+/** Finds a CoE handler via its position in the list.
*/
ec_sdo_request_t *ec_slave_config_find_sdo_request(
ec_slave_config_t *sc, /**< Slave configuration. */
@@ -449,6 +458,26 @@
/*****************************************************************************/
+/** Finds a register handler via its position in the list.
+ */
+ec_reg_request_t *ec_slave_config_find_reg_request(
+ ec_slave_config_t *sc, /**< Slave configuration. */
+ unsigned int pos /**< Position in the list. */
+ )
+{
+ ec_reg_request_t *reg;
+
+ list_for_each_entry(reg, &sc->reg_requests, list) {
+ if (pos--)
+ continue;
+ return reg;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
/** Finds a VoE handler via its position in the list.
*/
ec_voe_handler_t *ec_slave_config_find_voe_handler(
@@ -965,6 +994,49 @@
/*****************************************************************************/
+/** Same as ecrt_slave_config_create_reg_request(), but with ERR_PTR() return
+ * value.
+ */
+ec_reg_request_t *ecrt_slave_config_create_reg_request_err(
+ ec_slave_config_t *sc, size_t size)
+{
+ ec_reg_request_t *reg;
+ int ret;
+
+ EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, size = %zu)\n",
+ __func__, sc, size);
+
+ if (!(reg = (ec_reg_request_t *)
+ kmalloc(sizeof(ec_reg_request_t), GFP_KERNEL))) {
+ EC_CONFIG_ERR(sc, "Failed to allocate register request memory!\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ret = ec_reg_request_init(reg, size);
+ if (ret) {
+ kfree(reg);
+ return ERR_PTR(ret);
+ }
+
+ down(&sc->master->master_sem);
+ list_add_tail(®->list, &sc->reg_requests);
+ up(&sc->master->master_sem);
+
+ return reg;
+}
+
+/*****************************************************************************/
+
+ec_reg_request_t *ecrt_slave_config_create_reg_request(
+ ec_slave_config_t *sc, size_t size)
+{
+ ec_reg_request_t *reg =
+ ecrt_slave_config_create_reg_request_err(sc, size);
+ return IS_ERR(reg) ? NULL : reg;
+}
+
+/*****************************************************************************/
+
/** Same as ecrt_slave_config_create_voe_handler(), but with ERR_PTR() return
* value.
*/
@@ -1101,6 +1173,7 @@
EXPORT_SYMBOL(ecrt_slave_config_emerg_overruns);
EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request);
EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler);
+EXPORT_SYMBOL(ecrt_slave_config_create_reg_request);
EXPORT_SYMBOL(ecrt_slave_config_state);
EXPORT_SYMBOL(ecrt_slave_config_idn);
--- a/master/slave_config.h Wed Nov 14 22:08:32 2012 +0100
+++ b/master/slave_config.h Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -141,6 +141,7 @@
struct list_head sdo_configs; /**< List of SDO configurations. */
struct list_head sdo_requests; /**< List of SDO requests. */
struct list_head voe_handlers; /**< List of VoE handlers. */
+ struct list_head reg_requests; /**< List of register requests. */
struct list_head soe_configs; /**< List of SoE configurations. */
ec_coe_emerg_ring_t emerg_ring; /**< CoE emergency ring buffer. */
@@ -165,6 +166,8 @@
const ec_slave_config_t *, unsigned int);
ec_sdo_request_t *ec_slave_config_find_sdo_request(ec_slave_config_t *,
unsigned int);
+ec_reg_request_t *ec_slave_config_find_reg_request(ec_slave_config_t *,
+ unsigned int);
ec_voe_handler_t *ec_slave_config_find_voe_handler(ec_slave_config_t *,
unsigned int);
@@ -172,6 +175,8 @@
ec_slave_config_t *, uint16_t, uint8_t, size_t);
ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err(
ec_slave_config_t *, size_t);
+ec_reg_request_t *ecrt_slave_config_create_reg_request_err(
+ ec_slave_config_t *, size_t);
/*****************************************************************************/
--- a/tool/CommandRegRead.cpp Wed Nov 14 22:08:32 2012 +0100
+++ b/tool/CommandRegRead.cpp Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -48,20 +48,20 @@
stringstream str;
str << binaryBaseName << " " << getName()
- << " [OPTIONS] <OFFSET> [LENGTH]" << endl
+ << " [OPTIONS] <ADDRESS> [SIZE]" << endl
<< endl
<< getBriefDescription() << endl
<< endl
<< "This command requires a single slave to be selected." << endl
<< endl
<< "Arguments:" << endl
- << " OFFSET is the register address. Must" << endl
- << " be an unsigned 16 bit number." << endl
- << " LENGTH is the number of bytes to read and must also be" << endl
- << " an unsigned 16 bit number. OFFSET plus LENGTH" << endl
- << " may not exceed 64k. The length is ignored (and" << endl
- << " can be omitted), if a selected data type" << endl
- << " implies a length." << endl
+ << " ADDRESS is the register address. Must" << endl
+ << " be an unsigned 16 bit number." << endl
+ << " SIZE is the number of bytes to read and must also be" << endl
+ << " an unsigned 16 bit number. ADDRESS plus SIZE" << endl
+ << " may not exceed 64k. The size is ignored (and" << endl
+ << " can be omitted), if a selected data type" << endl
+ << " implies a size." << endl
<< endl
<< typeInfo()
<< endl
@@ -81,7 +81,7 @@
void CommandRegRead::execute(const StringVector &args)
{
SlaveList slaves;
- ec_ioctl_slave_reg_t data;
+ ec_ioctl_slave_reg_t io;
stringstream strOffset, err;
const DataType *dataType = NULL;
@@ -93,9 +93,9 @@
strOffset << args[0];
strOffset
>> resetiosflags(ios::basefield) // guess base from prefix
- >> data.offset;
+ >> io.address;
if (strOffset.fail()) {
- err << "Invalid offset '" << args[0] << "'!";
+ err << "Invalid address '" << args[0] << "'!";
throwInvalidUsageException(err);
}
@@ -104,18 +104,18 @@
strLength << args[1];
strLength
>> resetiosflags(ios::basefield) // guess base from prefix
- >> data.length;
+ >> io.size;
if (strLength.fail()) {
- err << "Invalid length '" << args[1] << "'!";
+ err << "Invalid size '" << args[1] << "'!";
throwInvalidUsageException(err);
}
- if (!data.length) {
+ if (!io.size) {
err << "Length may not be zero!";
throwInvalidUsageException(err);
}
- } else { // no length argument given
- data.length = 0;
+ } else { // no size argument given
+ io.size = 0;
}
if (!getDataType().empty()) {
@@ -125,19 +125,19 @@
}
if (dataType->byteSize) {
- // override length argument
- data.length = dataType->byteSize;
+ // override size argument
+ io.size = dataType->byteSize;
}
}
- if (!data.length) {
- err << "The length argument is mandatory, if no datatype is " << endl
- << "specified, or the datatype does not imply a length!";
+ if (!io.size) {
+ err << "The size argument is mandatory, if no datatype is " << endl
+ << "specified, or the datatype does not imply a size!";
throwInvalidUsageException(err);
}
- if ((uint32_t) data.offset + data.length > 0xffff) {
- err << "Offset and length exceeding 64k!";
+ if ((uint32_t) io.address + io.size > 0xffff) {
+ err << "Address and size exceeding 64k!";
throwInvalidUsageException(err);
}
@@ -148,25 +148,25 @@
if (slaves.size() != 1) {
throwSingleSlaveRequired(slaves.size());
}
- data.slave_position = slaves.front().position;
+ io.slave_position = slaves.front().position;
- data.data = new uint8_t[data.length];
+ io.data = new uint8_t[io.size];
try {
- m.readReg(&data);
+ m.readReg(&io);
} catch (MasterDeviceException &e) {
- delete [] data.data;
+ delete [] io.data;
throw e;
}
try {
- outputData(cout, dataType, data.data, data.length);
+ outputData(cout, dataType, io.data, io.size);
} catch (SizeException &e) {
- delete [] data.data;
+ delete [] io.data;
throwCommandException(e.what());
}
- delete [] data.data;
+ delete [] io.data;
}
/*****************************************************************************/
--- a/tool/CommandRegWrite.cpp Wed Nov 14 22:08:32 2012 +0100
+++ b/tool/CommandRegWrite.cpp Wed Nov 14 22:12:57 2012 +0100
@@ -2,7 +2,7 @@
*
* $Id$
*
- * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
+ * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@@ -57,7 +57,7 @@
<< "This command requires a single slave to be selected." << endl
<< endl
<< "Arguments:" << endl
- << " OFFSET is the register address to write to." << endl
+ << " ADDRESS is the register address to write to." << endl
<< " DATA depends on whether a datatype was specified" << endl
<< " with the --type option: If not, DATA must be" << endl
<< " either a path to a file with data to write," << endl
@@ -83,7 +83,7 @@
void CommandRegWrite::execute(const StringVector &args)
{
stringstream strOffset, err;
- ec_ioctl_slave_reg_t data;
+ ec_ioctl_slave_reg_t io;
ifstream file;
SlaveList slaves;
@@ -95,22 +95,22 @@
strOffset << args[0];
strOffset
>> resetiosflags(ios::basefield) // guess base from prefix
- >> data.offset;
+ >> io.address;
if (strOffset.fail()) {
- err << "Invalid offset '" << args[0] << "'!";
+ err << "Invalid address '" << args[0] << "'!";
throwInvalidUsageException(err);
}
if (getDataType().empty()) {
if (args[1] == "-") {
- loadRegData(&data, cin);
+ loadRegData(&io, cin);
} else {
file.open(args[1].c_str(), ifstream::in | ifstream::binary);
if (file.fail()) {
err << "Failed to open '" << args[1] << "'!";
throwCommandException(err);
}
- loadRegData(&data, file);
+ loadRegData(&io, file);
file.close();
}
} else {
@@ -123,30 +123,30 @@
}
if (dataType->byteSize) {
- data.length = dataType->byteSize;
+ io.size = dataType->byteSize;
} else {
- data.length = 1024; // FIXME
- }
-
- data.data = new uint8_t[data.length];
+ io.size = 1024; // FIXME
+ }
+
+ io.data = new uint8_t[io.size];
try {
- data.length = interpretAsType(
- dataType, args[1], data.data, data.length);
+ io.size = interpretAsType(
+ dataType, args[1], io.data, io.size);
} catch (SizeException &e) {
- delete [] data.data;
+ delete [] io.data;
throwCommandException(e.what());
} catch (ios::failure &e) {
- delete [] data.data;
+ delete [] io.data;
err << "Invalid value argument '" << args[1]
<< "' for type '" << dataType->name << "'!";
throwInvalidUsageException(err);
}
}
- if ((uint32_t) data.offset + data.length > 0xffff) {
- err << "Offset and length exceeding 64k!";
- delete [] data.data;
+ if ((uint32_t) io.address + io.size > 0xffff) {
+ err << "Address and size exceeding 64k!";
+ delete [] io.data;
throwInvalidUsageException(err);
}
@@ -154,22 +154,22 @@
try {
m.open(MasterDevice::ReadWrite);
} catch (MasterDeviceException &e) {
- delete [] data.data;
+ delete [] io.data;
throw e;
}
slaves = selectedSlaves(m);
if (slaves.size() != 1) {
- delete [] data.data;
+ delete [] io.data;
throwSingleSlaveRequired(slaves.size());
}
- data.slave_position = slaves.front().position;
+ io.slave_position = slaves.front().position;
// send data to master
try {
- m.writeReg(&data);
+ m.writeReg(&io);
} catch (MasterDeviceException &e) {
- delete [] data.data;
+ delete [] io.data;
throw e;
}
@@ -177,13 +177,13 @@
cerr << "Register writing finished." << endl;
}
- delete [] data.data;
+ delete [] io.data;
}
/*****************************************************************************/
void CommandRegWrite::loadRegData(
- ec_ioctl_slave_reg_t *data,
+ ec_ioctl_slave_reg_t *io,
const istream &in
)
{
@@ -201,11 +201,11 @@
err << "Invalid data size " << contents.size() << "!";
throwInvalidUsageException(err);
}
- data->length = contents.size();
+ io->size = contents.size();
// allocate buffer and read file into buffer
- data->data = new uint8_t[data->length];
- contents.copy((char *) data->data, contents.size());
-}
-
-/*****************************************************************************/
+ io->data = new uint8_t[io->size];
+ contents.copy((char *) io->data, contents.size());
+}
+
+/*****************************************************************************/