Implemented SoE write state machine and soe_write command.

This commit is contained in:
Florian Pose 2010-03-05 15:32:56 +01:00
parent 3c1cf99c44
commit ffca1fa780
12 changed files with 552 additions and 48 deletions

3
TODO
View File

@ -30,9 +30,10 @@ Version 1.5.0:
* Implement indent in 'ethercat ma'
* Add master index to log messages.
* Implement 0xXXXX:YY format for specifying SDOs.
* Lookup CoE codes for 64bit data types.
* Lookup codes for 64bit data types.
* Move data type usage string into DataTypeHandler.
* Implement interpretation of SoE '[SP]-x-yyy' strings.
* Implement reading from stream for soe_write.
Future issues:

View File

@ -3254,26 +3254,26 @@ int ec_cdev_ioctl_slave_soe_read(
unsigned long arg /**< ioctl() argument. */
)
{
ec_ioctl_slave_soe_t data;
ec_ioctl_slave_soe_read_t ioctl;
ec_master_soe_request_t request;
int retval;
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
return -EFAULT;
}
ec_soe_request_init(&request.req);
ec_soe_request_set_idn(&request.req, data.idn);
ec_soe_request_set_idn(&request.req, ioctl.idn);
ec_soe_request_read(&request.req);
if (down_interruptible(&master->master_sem))
return -EINTR;
if (!(request.slave = ec_master_find_slave(
master, 0, data.slave_position))) {
master, 0, ioctl.slave_position))) {
up(&master->master_sem);
ec_soe_request_clear(&request.req);
EC_ERR("Slave %u does not exist!\n", data.slave_position);
EC_ERR("Slave %u does not exist!\n", ioctl.slave_position);
return -EINVAL;
}
@ -3306,31 +3306,31 @@ int ec_cdev_ioctl_slave_soe_read(
wait_event(request.slave->soe_queue,
request.req.state != EC_INT_REQUEST_BUSY);
data.error_code = request.req.error_code;
ioctl.error_code = request.req.error_code;
if (master->debug_level) {
EC_DBG("Read %zd bytes via SoE.\n", request.req.data_size);
}
if (request.req.state != EC_INT_REQUEST_SUCCESS) {
data.data_size = 0;
ioctl.data_size = 0;
retval = -EIO;
} else {
if (request.req.data_size > data.mem_size) {
if (request.req.data_size > ioctl.mem_size) {
EC_ERR("Buffer too small.\n");
ec_soe_request_clear(&request.req);
return -EOVERFLOW;
}
data.data_size = request.req.data_size;
if (copy_to_user((void __user *) data.data,
request.req.data, data.data_size)) {
ioctl.data_size = request.req.data_size;
if (copy_to_user((void __user *) ioctl.data,
request.req.data, ioctl.data_size)) {
ec_soe_request_clear(&request.req);
return -EFAULT;
}
retval = 0;
}
if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
retval = -EFAULT;
}
@ -3352,38 +3352,38 @@ int ec_cdev_ioctl_slave_soe_write(
unsigned long arg /**< ioctl() argument. */
)
{
ec_ioctl_slave_soe_t data;
ec_ioctl_slave_soe_write_t ioctl;
ec_master_soe_request_t request;
int retval;
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
return -EFAULT;
}
INIT_LIST_HEAD(&request.list);
ec_soe_request_init(&request.req);
ec_soe_request_set_idn(&request.req, data.idn);
ec_soe_request_set_idn(&request.req, ioctl.idn);
if (ec_soe_request_alloc(&request.req, data.mem_size)) {
if (ec_soe_request_alloc(&request.req, ioctl.data_size)) {
ec_soe_request_clear(&request.req);
return -ENOMEM;
}
if (copy_from_user(request.req.data,
(void __user *) data.data, data.mem_size)) {
(void __user *) ioctl.data, ioctl.data_size)) {
ec_soe_request_clear(&request.req);
return -EFAULT;
}
request.req.data_size = data.mem_size;
request.req.data_size = ioctl.data_size;
ec_soe_request_write(&request.req);
if (down_interruptible(&master->master_sem))
return -EINTR;
if (!(request.slave = ec_master_find_slave(
master, 0, data.slave_position))) {
master, 0, ioctl.slave_position))) {
up(&master->master_sem);
EC_ERR("Slave %u does not exist!\n", data.slave_position);
EC_ERR("Slave %u does not exist!\n", ioctl.slave_position);
ec_soe_request_clear(&request.req);
return -EINVAL;
}
@ -3416,11 +3416,9 @@ int ec_cdev_ioctl_slave_soe_write(
wait_event(request.slave->soe_queue,
request.req.state != EC_INT_REQUEST_BUSY);
//data.result = request.req.result;
retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
if (__copy_to_user((void __user *) arg, &ioctl, sizeof(ioctl))) {
retval = -EFAULT;
}

View File

@ -45,11 +45,15 @@
*/
#define EC_MBOX_TYPE_SOE 0x05
#define EC_SOE_OPCODE_READ_REQUEST 0x01
#define EC_SOE_OPCODE_READ_RESPONSE 0x02
#define EC_SOE_OPCODE_READ_REQUEST 0x01
#define EC_SOE_OPCODE_READ_RESPONSE 0x02
#define EC_SOE_OPCODE_WRITE_REQUEST 0x03
#define EC_SOE_OPCODE_WRITE_RESPONSE 0x04
#define EC_SOE_READ_REQUEST_SIZE 0x04
#define EC_SOE_READ_RESPONSE_SIZE 0x04
#define EC_SOE_READ_REQUEST_SIZE 0x04
#define EC_SOE_READ_RESPONSE_SIZE 0x04
#define EC_SOE_WRITE_REQUEST_SIZE 0x04
#define EC_SOE_WRITE_RESPONSE_SIZE 0x04
#define EC_SOE_RESPONSE_TIMEOUT 1000
@ -60,6 +64,11 @@ void ec_fsm_soe_read_request(ec_fsm_soe_t *);
void ec_fsm_soe_read_check(ec_fsm_soe_t *);
void ec_fsm_soe_read_response(ec_fsm_soe_t *);
void ec_fsm_soe_write_start(ec_fsm_soe_t *);
void ec_fsm_soe_write_request(ec_fsm_soe_t *);
void ec_fsm_soe_write_check(ec_fsm_soe_t *);
void ec_fsm_soe_write_response(ec_fsm_soe_t *);
void ec_fsm_soe_end(ec_fsm_soe_t *);
void ec_fsm_soe_error(ec_fsm_soe_t *);
@ -99,7 +108,7 @@ void ec_fsm_soe_transfer(
fsm->slave = slave;
fsm->request = request;
if (request->dir == EC_DIR_OUTPUT) {
//fsm->state = ec_fsm_soe_write_start;
fsm->state = ec_fsm_soe_write_start;
} else {
fsm->state = ec_fsm_soe_read_start;
}
@ -370,6 +379,241 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
fsm->state = ec_fsm_soe_end; // success
}
/******************************************************************************
* SoE write state machine
*****************************************************************************/
/** SoE state: WRITE START.
*/
void ec_fsm_soe_write_start(ec_fsm_soe_t *fsm /**< finite state machine */)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
ec_soe_request_t *request = fsm->request;
uint8_t *data;
if (master->debug_level)
EC_DBG("Writing IDN 0x%04X to slave %u.\n",
request->idn, slave->ring_position);
if (!(slave->sii.mailbox_protocols & EC_MBOX_SOE)) {
EC_ERR("Slave %u does not support SoE!\n", slave->ring_position);
fsm->state = ec_fsm_soe_error;
return;
}
data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE,
EC_SOE_WRITE_REQUEST_SIZE + request->data_size);
if (IS_ERR(data)) {
fsm->state = ec_fsm_soe_error;
return;
}
EC_WRITE_U8(data, EC_SOE_OPCODE_WRITE_REQUEST);
EC_WRITE_U8(data + 1, 1 << 6); // only value included
EC_WRITE_U16(data + 2, request->idn);
memcpy(data + 4, request->data, request->data_size);
if (master->debug_level) {
EC_DBG("SCC write request:\n");
ec_print_data(data, EC_SOE_WRITE_REQUEST_SIZE + request->data_size);
}
fsm->request->jiffies_sent = jiffies;
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_soe_write_request;
}
/*****************************************************************************/
/** SoE state: WRITE REQUEST.
*/
void ec_fsm_soe_write_request(ec_fsm_soe_t *fsm /**< finite state machine */)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
unsigned long diff_ms;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return; // FIXME: check for response first?
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Failed to receive SoE write request for slave %u: ",
slave->ring_position);
ec_datagram_print_state(datagram);
return;
}
diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
if (datagram->working_counter != 1) {
if (!datagram->working_counter) {
if (diff_ms < EC_SOE_RESPONSE_TIMEOUT) {
// no response; send request datagram again
return;
}
}
fsm->state = ec_fsm_soe_error;
EC_ERR("Reception of SoE write request for IDN 0x%04x failed"
" after %u ms on slave %u: ",
fsm->request->idn, (u32) diff_ms,
fsm->slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
fsm->jiffies_start = datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_soe_write_check;
}
/*****************************************************************************/
/** CoE state: WRITE CHECK.
*/
void ec_fsm_soe_write_check(ec_fsm_soe_t *fsm /**< finite state machine */)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Failed to receive SoE mailbox check datagram from slave %u: ",
slave->ring_position);
ec_datagram_print_state(datagram);
return;
}
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Reception of SoE mailbox check datagram failed on slave %u: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
if (!ec_slave_mbox_check(datagram)) {
unsigned long diff_ms =
(datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
if (diff_ms >= EC_SOE_RESPONSE_TIMEOUT) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Timeout after %u ms while waiting for IDN 0x%04x"
" write response on slave %u.\n", (u32) diff_ms,
fsm->request->idn, slave->ring_position);
return;
}
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
return;
}
// Fetch response
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_soe_write_response;
}
/*****************************************************************************/
/** SoE state: WRITE RESPONSE.
*/
void ec_fsm_soe_write_response(ec_fsm_soe_t *fsm /**< finite state machine */)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
uint8_t *data, mbox_prot, opcode, error_flag;
uint16_t idn;
size_t rec_size;
ec_soe_request_t *req = fsm->request;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return; // FIXME: request again?
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Failed to receive SoE write response datagram for"
" slave %u: ", slave->ring_position);
ec_datagram_print_state(datagram);
return;
}
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Reception of SoE write response failed on slave %u: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size);
if (IS_ERR(data)) {
fsm->state = ec_fsm_soe_error;
return;
}
if (master->debug_level) {
EC_DBG("SCC write response:\n");
ec_print_data(data, rec_size);
}
if (mbox_prot != EC_MBOX_TYPE_SOE) {
fsm->state = ec_fsm_soe_error;
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
return;
}
if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE) {
fsm->state = ec_fsm_soe_error;
EC_ERR("Received currupted SoE write response (%zu bytes)!\n",
rec_size);
ec_print_data(data, rec_size);
return;
}
opcode = EC_READ_U8(data) & 0x3;
if (opcode != EC_SOE_OPCODE_WRITE_RESPONSE) {
EC_ERR("Received no write response (opcode %x).\n", opcode);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_soe_error;
return;
}
idn = EC_READ_U16(data + 2);
if (idn != req->idn) {
EC_ERR("Received response for wrong IDN 0x%04x.\n", idn);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_soe_error;
return;
}
error_flag = (EC_READ_U8(data) >> 4) & 1;
if (error_flag) {
req->error_code = EC_READ_U16(data + rec_size - 2);
EC_ERR("Received error response: 0x%04x.\n",
req->error_code);
fsm->state = ec_fsm_soe_error;
return;
} else {
req->error_code = 0x0000;
}
if (master->debug_level) {
EC_DBG("IDN data:\n");
ec_print_data(req->data, req->data_size);
}
fsm->state = ec_fsm_soe_end; // success
}
/*****************************************************************************/
/** State: ERROR.

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 2
#define EC_IOCTL_VERSION_MAGIC 3
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -80,8 +80,8 @@
#define EC_IOCTL_SLAVE_REG_WRITE EC_IOW(0x12, ec_ioctl_slave_reg_t)
#define EC_IOCTL_SLAVE_FOE_READ EC_IOWR(0x13, ec_ioctl_slave_foe_t)
#define EC_IOCTL_SLAVE_FOE_WRITE EC_IOW(0x14, ec_ioctl_slave_foe_t)
#define EC_IOCTL_SLAVE_SOE_READ EC_IOWR(0x15, ec_ioctl_slave_soe_t)
#define EC_IOCTL_SLAVE_SOE_WRITE EC_IOWR(0x16, ec_ioctl_slave_soe_t)
#define EC_IOCTL_SLAVE_SOE_READ EC_IOWR(0x15, ec_ioctl_slave_soe_read_t)
#define EC_IOCTL_SLAVE_SOE_WRITE EC_IOWR(0x16, ec_ioctl_slave_soe_write_t)
#define EC_IOCTL_CONFIG EC_IOWR(0x17, ec_ioctl_config_t)
#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x18, ec_ioctl_config_pdo_t)
#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x19, ec_ioctl_config_pdo_entry_t)
@ -413,9 +413,21 @@ typedef struct {
// outputs
uint32_t data_size;
uint32_t result;
uint16_t error_code;
} ec_ioctl_slave_soe_t;
} ec_ioctl_slave_soe_read_t;
/*****************************************************************************/
typedef struct {
// inputs
uint16_t slave_position;
uint16_t idn;
uint32_t data_size;
uint8_t *data;
// outputs
uint16_t error_code;
} ec_ioctl_slave_soe_write_t;
/*****************************************************************************/

View File

@ -74,7 +74,7 @@ void CommandSoeRead::execute(const StringVector &args)
SlaveList slaves;
stringstream err, strIdn;
const DataType *dataType = NULL;
ec_ioctl_slave_soe_t data;
ec_ioctl_slave_soe_read_t ioctl;
if (args.size() != 1) {
err << "'" << getName() << "' takes one argument!";
@ -84,7 +84,7 @@ void CommandSoeRead::execute(const StringVector &args)
strIdn << args[0];
strIdn
>> resetiosflags(ios::basefield) // guess base from prefix
>> data.idn;
>> ioctl.idn;
if (strIdn.fail()) {
err << "Invalid IDN '" << args[0] << "'!";
throwInvalidUsageException(err);
@ -100,7 +100,7 @@ void CommandSoeRead::execute(const StringVector &args)
if (slaves.size() != 1) {
throwSingleSlaveRequired(slaves.size());
}
data.slave_position = slaves.front().position;
ioctl.slave_position = slaves.front().position;
if (getDataType().empty()) {
dataType = findDataType("raw"); // FIXME
@ -112,35 +112,35 @@ void CommandSoeRead::execute(const StringVector &args)
}
if (dataType->byteSize) {
data.mem_size = dataType->byteSize;
ioctl.mem_size = dataType->byteSize;
} else {
data.mem_size = 1024;
ioctl.mem_size = 1024;
}
data.data = new uint8_t[data.mem_size + 1];
ioctl.data = new uint8_t[ioctl.mem_size + 1];
try {
m.readSoe(&data);
m.readSoe(&ioctl);
} catch (MasterDeviceSoeException &e) {
delete [] data.data;
delete [] ioctl.data;
err << "SoE read command aborted with code 0x"
<< setfill('0') << hex << setw(4) << e.errorCode;
throwCommandException(err);
} catch (MasterDeviceException &e) {
delete [] data.data;
delete [] ioctl.data;
throw e;
}
m.close();
try {
outputData(cout, dataType, data.data, data.data_size);
outputData(cout, dataType, ioctl.data, ioctl.data_size);
} catch (SizeException &e) {
delete [] data.data;
delete [] ioctl.data;
throwCommandException(e.what());
}
delete [] data.data;
delete [] ioctl.data;
}
/*****************************************************************************/

160
tool/CommandSoeWrite.cpp Normal file
View File

@ -0,0 +1,160 @@
/*****************************************************************************
*
* $Id$
*
* Copyright (C) 2006-2009 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.
*
****************************************************************************/
#include <iostream>
#include <iomanip>
using namespace std;
#include "CommandSoeWrite.h"
#include "MasterDevice.h"
/*****************************************************************************/
CommandSoeWrite::CommandSoeWrite():
Command("soe_write", "Write an SoE IDN to a slave.")
{
}
/*****************************************************************************/
string CommandSoeWrite::helpString() const
{
stringstream str;
str << getName() << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl
<< endl
<< getBriefDescription() << endl
<< endl
<< "This command requires a single slave to be selected." << endl
<< endl
<< "Arguments:" << endl
<< " IDN is the IDN and must be an unsigned" << endl
<< " 16 bit number." << endl
<< " VALUE is the value to write and is interpreted" << endl
<< " as the given datatype (see above)." << endl
<< endl
<< "Command-specific options:" << endl
<< " --alias -a <alias>" << endl
<< " --position -p <pos> Slave selection. See the help of" << endl
<< " the 'slaves' command." << endl
<< " --type -t <type> Data type (see above)." << endl
<< endl
<< numericInfo();
return str.str();
}
/****************************************************************************/
void CommandSoeWrite::execute(const StringVector &args)
{
stringstream strIdn, err;
const DataType *dataType = NULL;
ec_ioctl_slave_soe_write_t ioctl;
SlaveList slaves;
size_t memSize;
if (args.size() != 2) {
err << "'" << getName() << "' takes 2 arguments!";
throwInvalidUsageException(err);
}
strIdn << args[0];
strIdn
>> resetiosflags(ios::basefield) // guess base from prefix
>> ioctl.idn;
if (strIdn.fail()) {
err << "Invalid IDN '" << args[0] << "'!";
throwInvalidUsageException(err);
}
if (getMasterIndices().size() != 1) {
err << getName() << " requires to select a single master!";
throwInvalidUsageException(err);
}
MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::ReadWrite);
slaves = selectedSlaves(m);
if (slaves.size() != 1) {
throwSingleSlaveRequired(slaves.size());
}
ioctl.slave_position = slaves.front().position;
if (!getDataType().empty()) { // data type specified
if (!(dataType = findDataType(getDataType()))) {
err << "Invalid data type '" << getDataType() << "'!";
throwInvalidUsageException(err);
}
} else { // no data type specified
err << "Please specify a data type.";
throwInvalidUsageException(err); // FIXME read from stream
}
if (dataType->byteSize) {
memSize = dataType->byteSize;
} else {
// guess string type size
memSize = args[1].size();
if (!memSize) {
err << "Empty argument not allowed.";
throwInvalidUsageException(err);
}
}
ioctl.data = new uint8_t[memSize + 1];
try {
ioctl.data_size = interpretAsType(
dataType, args[1], ioctl.data, memSize);
} catch (SizeException &e) {
delete [] ioctl.data;
throwCommandException(e.what());
} catch (ios::failure &e) {
delete [] ioctl.data;
err << "Invalid value argument '" << args[1]
<< "' for type '" << dataType->name << "'!";
throwInvalidUsageException(err);
}
try {
m.writeSoe(&ioctl);
} catch (MasterDeviceSoeException &e) {
delete [] ioctl.data;
err << "SoE write command aborted with code 0x"
<< setfill('0') << hex << setw(4) << e.errorCode << ".";
throwCommandException(err);
} catch (MasterDeviceException &e) {
delete [] ioctl.data;
throw e;
}
delete [] ioctl.data;
}
/*****************************************************************************/

51
tool/CommandSoeWrite.h Normal file
View File

@ -0,0 +1,51 @@
/*****************************************************************************
*
* $Id$
*
* Copyright (C) 2006-2009 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.
*
****************************************************************************/
#ifndef __COMMANDSOEWRITE_H__
#define __COMMANDSOEWRITE_H__
#include "Command.h"
#include "DataTypeHandler.h"
/****************************************************************************/
class CommandSoeWrite:
public Command,
public DataTypeHandler
{
public:
CommandSoeWrite();
string helpString() const;
void execute(const StringVector &);
};
/****************************************************************************/
#endif

View File

@ -27,6 +27,12 @@
*
****************************************************************************/
#define DEBUG 0
#if DEBUG
#include <iostream>
#endif
#include <iomanip>
#include <sstream>
using namespace std;
@ -81,10 +87,18 @@ size_t DataTypeHandler::interpretAsType(
stringstream str;
size_t dataSize = type->byteSize;
#if DEBUG
cerr << __func__ << "(targetSize=" << targetSize << ")" << endl;
#endif
str << source;
str >> resetiosflags(ios::basefield); // guess base from prefix
str.exceptions(ios::failbit);
#if DEBUG
cerr << "code=" << type->code << endl;
#endif
switch (type->code) {
case 0x0002: // int8
{
@ -151,6 +165,10 @@ size_t DataTypeHandler::interpretAsType(
}
}
#if DEBUG
printRawData(cerr, (const uint8_t *) target, dataSize);
#endif
return dataSize;
}

View File

@ -56,6 +56,7 @@ ethercat_SOURCES = \
CommandSiiWrite.cpp \
CommandSlaves.cpp \
CommandSoeRead.cpp \
CommandSoeWrite.cpp \
CommandStates.cpp \
CommandUpload.cpp \
CommandVersion.cpp \
@ -95,6 +96,7 @@ noinst_HEADERS = \
CommandSiiWrite.h \
CommandSlaves.h \
CommandSoeRead.h \
CommandSoeWrite.h \
CommandStates.h \
CommandUpload.h \
CommandVersion.h \

View File

@ -528,7 +528,7 @@ void MasterDevice::getEoeHandler(
/****************************************************************************/
void MasterDevice::readSoe(ec_ioctl_slave_soe_t *data)
void MasterDevice::readSoe(ec_ioctl_slave_soe_read_t *data)
{
if (ioctl(fd, EC_IOCTL_SLAVE_SOE_READ, data) < 0) {
if (errno == EIO && data->error_code) {
@ -541,4 +541,19 @@ void MasterDevice::readSoe(ec_ioctl_slave_soe_t *data)
}
}
/****************************************************************************/
void MasterDevice::writeSoe(ec_ioctl_slave_soe_write_t *data)
{
if (ioctl(fd, EC_IOCTL_SLAVE_SOE_WRITE, data) < 0) {
if (errno == EIO && data->error_code) {
throw MasterDeviceSoeException(data->error_code);
} else {
stringstream err;
err << "Failed to write IDN: " << strerror(errno);
throw MasterDeviceException(err);
}
}
}
/*****************************************************************************/

View File

@ -140,7 +140,8 @@ class MasterDevice
#ifdef EC_EOE
void getEoeHandler(ec_ioctl_eoe_handler_t *, uint16_t);
#endif
void readSoe(ec_ioctl_slave_soe_t *);
void readSoe(ec_ioctl_slave_soe_read_t *);
void writeSoe(ec_ioctl_slave_soe_write_t *);
unsigned int getMasterCount() const {return masterCount;}

View File

@ -57,6 +57,7 @@ using namespace std;
#include "CommandSiiWrite.h"
#include "CommandSlaves.h"
#include "CommandSoeRead.h"
#include "CommandSoeWrite.h"
#include "CommandStates.h"
#include "CommandUpload.h"
#include "CommandVersion.h"
@ -337,6 +338,7 @@ int main(int argc, char **argv)
commandList.push_back(new CommandSiiWrite());
commandList.push_back(new CommandSlaves());
commandList.push_back(new CommandSoeRead());
commandList.push_back(new CommandSoeWrite());
commandList.push_back(new CommandStates());
commandList.push_back(new CommandUpload());
commandList.push_back(new CommandVersion());