Added phy commands.
This commit is contained in:
parent
568505a4df
commit
d975aafa18
162
master/cdev.c
162
master/cdev.c
|
|
@ -986,6 +986,162 @@ int ec_cdev_ioctl_slave_sii_write(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Read a slave's physical memory.
|
||||
*/
|
||||
int ec_cdev_ioctl_slave_phy_read(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
unsigned long arg /**< ioctl() argument. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_slave_phy_t data;
|
||||
ec_slave_t *slave;
|
||||
uint8_t *contents;
|
||||
ec_phy_request_t request;
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!data.length)
|
||||
return 0;
|
||||
|
||||
if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %u bytes for phy data.\n", data.length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (down_interruptible(&master->master_sem))
|
||||
return -EINTR;
|
||||
|
||||
if (!(slave = ec_master_find_slave(
|
||||
master, 0, data.slave_position))) {
|
||||
up(&master->master_sem);
|
||||
EC_ERR("Slave %u does not exist!\n", data.slave_position);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// init phy 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_REQUEST_QUEUED;
|
||||
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &master->phy_requests);
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
// wait for processing through FSM
|
||||
if (wait_event_interruptible(master->phy_queue,
|
||||
request.state != EC_REQUEST_QUEUED)) {
|
||||
// interrupted by signal
|
||||
down(&master->master_sem);
|
||||
if (request.state == EC_REQUEST_QUEUED) {
|
||||
// abort request
|
||||
list_del(&request.list);
|
||||
up(&master->master_sem);
|
||||
kfree(contents);
|
||||
return -EINTR;
|
||||
}
|
||||
up(&master->master_sem);
|
||||
}
|
||||
|
||||
// wait until master FSM has finished processing
|
||||
wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
|
||||
|
||||
if (request.state == EC_REQUEST_SUCCESS) {
|
||||
if (copy_to_user((void __user *) data.data, contents, data.length))
|
||||
return -EFAULT;
|
||||
}
|
||||
kfree(contents);
|
||||
|
||||
return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Write a slave's physical memory.
|
||||
*/
|
||||
int ec_cdev_ioctl_slave_phy_write(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
unsigned long arg /**< ioctl() argument. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_slave_phy_t data;
|
||||
ec_slave_t *slave;
|
||||
uint8_t *contents;
|
||||
ec_phy_request_t request;
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!data.length)
|
||||
return 0;
|
||||
|
||||
if (!(contents = kmalloc(data.length, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %u bytes for phy 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))
|
||||
return -EINTR;
|
||||
|
||||
if (!(slave = ec_master_find_slave(
|
||||
master, 0, data.slave_position))) {
|
||||
up(&master->master_sem);
|
||||
EC_ERR("Slave %u does not exist!\n", data.slave_position);
|
||||
kfree(contents);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// init phy 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_REQUEST_QUEUED;
|
||||
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &master->phy_requests);
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
// wait for processing through FSM
|
||||
if (wait_event_interruptible(master->phy_queue,
|
||||
request.state != EC_REQUEST_QUEUED)) {
|
||||
// interrupted by signal
|
||||
down(&master->master_sem);
|
||||
if (request.state == EC_REQUEST_QUEUED) {
|
||||
// abort request
|
||||
list_del(&request.list);
|
||||
up(&master->master_sem);
|
||||
kfree(contents);
|
||||
return -EINTR;
|
||||
}
|
||||
up(&master->master_sem);
|
||||
}
|
||||
|
||||
// wait until master FSM has finished processing
|
||||
wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
|
||||
|
||||
kfree(contents);
|
||||
|
||||
return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Get slave configuration information.
|
||||
*/
|
||||
int ec_cdev_ioctl_config(
|
||||
|
|
@ -1282,6 +1438,12 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
return ec_cdev_ioctl_slave_sii_write(master, arg);
|
||||
case EC_IOCTL_SLAVE_PHY_READ:
|
||||
return ec_cdev_ioctl_slave_phy_read(master, arg);
|
||||
case EC_IOCTL_SLAVE_PHY_WRITE:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
return ec_cdev_ioctl_slave_phy_write(master, arg);
|
||||
case EC_IOCTL_CONFIG:
|
||||
return ec_cdev_ioctl_config(master, arg);
|
||||
case EC_IOCTL_CONFIG_PDO:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ void ec_fsm_master_state_scan_slave(ec_fsm_master_t *);
|
|||
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_phy_request(ec_fsm_master_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -324,6 +325,59 @@ int ec_fsm_master_action_process_sii(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Check for pending phy requests and process one.
|
||||
*
|
||||
* \return non-zero, if a phy request is processed.
|
||||
*/
|
||||
int ec_fsm_master_action_process_phy(
|
||||
ec_fsm_master_t *fsm /**< Master state machine. */
|
||||
)
|
||||
{
|
||||
ec_master_t *master = fsm->master;
|
||||
ec_phy_request_t *request;
|
||||
|
||||
// search the first request to be processed
|
||||
while (1) {
|
||||
if (list_empty(&master->phy_requests))
|
||||
break;
|
||||
|
||||
// get first request
|
||||
request = list_entry(master->phy_requests.next,
|
||||
ec_phy_request_t, list);
|
||||
list_del_init(&request->list); // dequeue
|
||||
request->state = EC_REQUEST_BUSY;
|
||||
|
||||
// found pending request; process it!
|
||||
if (master->debug_level)
|
||||
EC_DBG("Processing phy request for slave %u...\n",
|
||||
request->slave->ring_position);
|
||||
fsm->phy_request = request;
|
||||
|
||||
if (request->dir == EC_DIR_INPUT) {
|
||||
ec_datagram_fprd(fsm->datagram, request->slave->station_address,
|
||||
request->offset, request->length);
|
||||
} else {
|
||||
if (request->length > fsm->datagram->mem_size) {
|
||||
EC_ERR("Request length (%u) exceeds maximum datagram size (%u)!\n",
|
||||
request->length, fsm->datagram->mem_size);
|
||||
request->state = EC_REQUEST_FAILURE;
|
||||
wake_up(&master->phy_queue);
|
||||
continue;
|
||||
}
|
||||
ec_datagram_fpwr(fsm->datagram, request->slave->station_address,
|
||||
request->offset, request->length);
|
||||
memcpy(fsm->datagram->data, request->data, request->length);
|
||||
}
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_master_state_phy_request;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Check for pending Sdo requests and process one.
|
||||
*
|
||||
* \return non-zero, if an Sdo request is processed.
|
||||
|
|
@ -460,6 +514,10 @@ void ec_fsm_master_action_idle(
|
|||
if (ec_fsm_master_action_process_sii(fsm))
|
||||
return; // SII write request found
|
||||
|
||||
// check for pending phy requests.
|
||||
if (ec_fsm_master_action_process_phy(fsm))
|
||||
return; // phy request processing
|
||||
|
||||
ec_fsm_master_restart(fsm);
|
||||
}
|
||||
|
||||
|
|
@ -862,3 +920,49 @@ void ec_fsm_master_state_sdo_request(
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Master state: PHY.
|
||||
*/
|
||||
void ec_fsm_master_state_phy_request(
|
||||
ec_fsm_master_t *fsm /**< Master state machine. */
|
||||
)
|
||||
{
|
||||
ec_master_t *master = fsm->master;
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_phy_request_t *request = fsm->phy_request;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
EC_ERR("Failed to receive phy request datagram (state %u).\n",
|
||||
datagram->state);
|
||||
request->state = EC_REQUEST_FAILURE;
|
||||
wake_up(&master->phy_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
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_ERR("Failed to allocate %u bytes of memory for phy request.\n",
|
||||
request->length);
|
||||
request->state = EC_REQUEST_FAILURE;
|
||||
wake_up(&master->phy_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
}
|
||||
memcpy(request->data, datagram->data, request->length);
|
||||
}
|
||||
|
||||
request->state = EC_REQUEST_SUCCESS;
|
||||
wake_up(&master->phy_queue);
|
||||
|
||||
// check for another PHY request
|
||||
if (ec_fsm_master_action_process_phy(fsm))
|
||||
return; // processing another request
|
||||
|
||||
ec_fsm_master_restart(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -65,6 +65,20 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Physical memory request.
|
||||
*/
|
||||
typedef struct {
|
||||
struct list_head list; /**< List head. */
|
||||
ec_slave_t *slave; /**< EtherCAT slave. */
|
||||
ec_direction_t dir; /**< Direction. */
|
||||
uint16_t offset; /**< Physical memory offset. */
|
||||
size_t length; /**< Number of bytes. */
|
||||
uint8_t *data;
|
||||
ec_request_state_t state; /**< State of the request. */
|
||||
} ec_phy_request_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave/Sdo request record for master's Sdo request list.
|
||||
*/
|
||||
typedef struct {
|
||||
|
|
@ -94,6 +108,7 @@ struct ec_fsm_master {
|
|||
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_phy_request_t *phy_request; /**< Physical memory request to process. */
|
||||
|
||||
ec_fsm_coe_t fsm_coe; /**< CoE state machine */
|
||||
ec_fsm_pdo_t fsm_pdo; /**< Pdo configuration state machine. */
|
||||
|
|
|
|||
|
|
@ -72,10 +72,12 @@
|
|||
#define EC_IOCTL_SLAVE_SDO_DOWNLOAD EC_IOWR(0x0d, ec_ioctl_slave_sdo_download_t)
|
||||
#define EC_IOCTL_SLAVE_SII_READ EC_IOWR(0x0e, ec_ioctl_slave_sii_t)
|
||||
#define EC_IOCTL_SLAVE_SII_WRITE EC_IOW(0x0f, ec_ioctl_slave_sii_t)
|
||||
#define EC_IOCTL_CONFIG EC_IOWR(0x10, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x11, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x12, ec_ioctl_config_pdo_entry_t)
|
||||
#define EC_IOCTL_CONFIG_SDO EC_IOWR(0x13, ec_ioctl_config_sdo_t)
|
||||
#define EC_IOCTL_SLAVE_PHY_READ EC_IOWR(0x10, ec_ioctl_slave_phy_t)
|
||||
#define EC_IOCTL_SLAVE_PHY_WRITE EC_IOW(0x11, ec_ioctl_slave_phy_t)
|
||||
#define EC_IOCTL_CONFIG EC_IOWR(0x12, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x13, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x14, ec_ioctl_config_pdo_entry_t)
|
||||
#define EC_IOCTL_CONFIG_SDO EC_IOWR(0x15, ec_ioctl_config_sdo_t)
|
||||
|
||||
#define EC_IOCTL_STRING_SIZE 64
|
||||
|
||||
|
|
@ -286,6 +288,16 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint16_t slave_position;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
uint8_t *data;
|
||||
} ec_ioctl_slave_phy_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
INIT_LIST_HEAD(&master->slave_sdo_requests);
|
||||
init_waitqueue_head(&master->sdo_queue);
|
||||
|
||||
INIT_LIST_HEAD(&master->phy_requests);
|
||||
init_waitqueue_head(&master->phy_queue);
|
||||
|
||||
// init devices
|
||||
if (ec_device_init(&master->main_device, master))
|
||||
goto out_return;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,9 @@ struct ec_master {
|
|||
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 phy_requests; /**< Physical memory requests. */
|
||||
wait_queue_head_t phy_queue; /**< Wait queue for phy requests. */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "CommandPhyRead.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
CommandPhyRead::CommandPhyRead():
|
||||
Command("phy_read", "Output a slave's physical memory contents.")
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
string CommandPhyRead::helpString() const
|
||||
{
|
||||
stringstream str;
|
||||
|
||||
str << getName() << " [OPTIONS] <OFFSET> <LENGTH>" << endl
|
||||
<< endl
|
||||
<< getBriefDescription() << endl
|
||||
<< endl
|
||||
<< "This command requires a single slave to be selected." << endl
|
||||
<< endl
|
||||
<< "Arguments:" << endl
|
||||
<< " OFFSET is the physical memory 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." << endl
|
||||
<< endl
|
||||
<< "Command-specific options:" << endl
|
||||
<< " --alias -a <alias>" << endl
|
||||
<< " --position -p <pos> Slave selection. See the help of" << endl
|
||||
<< " the 'slaves' command." << endl
|
||||
<< endl
|
||||
<< numericInfo();
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void CommandPhyRead::execute(MasterDevice &m, const StringVector &args)
|
||||
{
|
||||
SlaveList slaves;
|
||||
ec_ioctl_slave_phy_t data;
|
||||
stringstream strOffset, strLength, err;
|
||||
uint16_t i;
|
||||
|
||||
if (args.size() != 2) {
|
||||
err << "'" << getName() << "' takes two arguments!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
strOffset << args[0];
|
||||
strOffset
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> data.offset;
|
||||
if (strOffset.fail()) {
|
||||
err << "Invalid offset '" << args[0] << "'!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
strLength << args[1];
|
||||
strLength
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> data.length;
|
||||
if (strLength.fail()) {
|
||||
err << "Invalid length '" << args[1] << "'!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
if (!data.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((uint32_t) data.offset + data.length > 0xffff) {
|
||||
err << "Offset and length exceeding 64k!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
m.open(MasterDevice::Read);
|
||||
slaves = selectedSlaves(m);
|
||||
|
||||
if (slaves.size() != 1) {
|
||||
throwSingleSlaveRequired(slaves.size());
|
||||
}
|
||||
data.slave_position = slaves.front().position;
|
||||
|
||||
data.data = new uint8_t[data.length];
|
||||
|
||||
try {
|
||||
m.readPhy(&data);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] data.data;
|
||||
throw e;
|
||||
}
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
cout << data.data[i];
|
||||
}
|
||||
|
||||
delete [] data.data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __COMMANDPHYREAD_H__
|
||||
#define __COMMANDPHYREAD_H__
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
class CommandPhyRead:
|
||||
public Command
|
||||
{
|
||||
public:
|
||||
CommandPhyRead();
|
||||
|
||||
string helpString() const;
|
||||
void execute(MasterDevice &, const StringVector &);
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
#include "CommandPhyWrite.h"
|
||||
#include "sii_crc.h"
|
||||
#include "byteorder.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
CommandPhyWrite::CommandPhyWrite():
|
||||
Command("phy_write", "Write data to a slave's physical memory.")
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
string CommandPhyWrite::helpString() const
|
||||
{
|
||||
stringstream str;
|
||||
|
||||
str << getName() << " [OPTIONS] <OFFSET> <FILENAME>" << endl
|
||||
<< endl
|
||||
<< getBriefDescription() << endl
|
||||
<< endl
|
||||
<< "This command requires a single slave to be selected." << endl
|
||||
<< endl
|
||||
<< "Arguments:" << endl
|
||||
<< " OFFSET must be the physical memory offset to start." << endl
|
||||
<< " FILENAME must be a path to a file with data to write." << endl
|
||||
<< " If it is '-', data are read from stdin." << endl
|
||||
<< endl
|
||||
<< "Command-specific options:" << endl
|
||||
<< " --alias -a <alias>" << endl
|
||||
<< " --position -p <pos> Slave selection. See the help of" << endl
|
||||
<< " the 'slaves' command." << endl
|
||||
<< endl
|
||||
<< numericInfo();
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void CommandPhyWrite::execute(MasterDevice &m, const StringVector &args)
|
||||
{
|
||||
stringstream strOffset, err;
|
||||
ec_ioctl_slave_phy_t data;
|
||||
ifstream file;
|
||||
SlaveList slaves;
|
||||
|
||||
if (args.size() != 2) {
|
||||
err << "'" << getName() << "' takes exactly one argument!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
strOffset << args[0];
|
||||
strOffset
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> data.offset;
|
||||
if (strOffset.fail()) {
|
||||
err << "Invalid offset '" << args[0] << "'!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
if (args[1] == "-") {
|
||||
loadPhyData(&data, cin);
|
||||
} else {
|
||||
file.open(args[1].c_str(), ifstream::in | ifstream::binary);
|
||||
if (file.fail()) {
|
||||
err << "Failed to open '" << args[0] << "'!";
|
||||
throwCommandException(err);
|
||||
}
|
||||
loadPhyData(&data, file);
|
||||
file.close();
|
||||
}
|
||||
|
||||
if ((uint32_t) data.offset + data.length > 0xffff) {
|
||||
err << "Offset and length exceeding 64k!";
|
||||
delete [] data.data;
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
|
||||
try {
|
||||
m.open(MasterDevice::ReadWrite);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] data.data;
|
||||
throw e;
|
||||
}
|
||||
|
||||
slaves = selectedSlaves(m);
|
||||
if (slaves.size() != 1) {
|
||||
delete [] data.data;
|
||||
throwSingleSlaveRequired(slaves.size());
|
||||
}
|
||||
data.slave_position = slaves.front().position;
|
||||
|
||||
// send data to master
|
||||
try {
|
||||
m.writePhy(&data);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] data.data;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (getVerbosity() == Verbose) {
|
||||
cerr << "Physical memory writing finished." << endl;
|
||||
}
|
||||
|
||||
delete [] data.data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void CommandPhyWrite::loadPhyData(
|
||||
ec_ioctl_slave_phy_t *data,
|
||||
const istream &in
|
||||
)
|
||||
{
|
||||
stringstream err;
|
||||
ostringstream tmp;
|
||||
|
||||
tmp << in.rdbuf();
|
||||
string const &contents = tmp.str();
|
||||
|
||||
if (getVerbosity() == Verbose) {
|
||||
cerr << "Read " << contents.size() << " bytes of data." << endl;
|
||||
}
|
||||
|
||||
if (contents.size() > 0xffff) {
|
||||
err << "Invalid data size " << contents.size() << "!";
|
||||
throwInvalidUsageException(err);
|
||||
}
|
||||
data->length = contents.size();
|
||||
|
||||
// allocate buffer and read file into buffer
|
||||
data->data = new uint8_t[data->length];
|
||||
contents.copy((char *) data->data, contents.size());
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __COMMANDPHYWRITE_H__
|
||||
#define __COMMANDPHYWRITE_H__
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
class CommandPhyWrite:
|
||||
public Command
|
||||
{
|
||||
public:
|
||||
CommandPhyWrite();
|
||||
|
||||
string helpString() const;
|
||||
void execute(MasterDevice &, const StringVector &);
|
||||
|
||||
private:
|
||||
void loadPhyData(ec_ioctl_slave_phy_t *, const istream &);
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
@ -45,6 +45,8 @@ ethercat_SOURCES = \
|
|||
CommandDownload.cpp \
|
||||
CommandMaster.cpp \
|
||||
CommandPdos.cpp \
|
||||
CommandPhyRead.cpp \
|
||||
CommandPhyWrite.cpp \
|
||||
CommandSdos.cpp \
|
||||
CommandSiiRead.cpp \
|
||||
CommandSiiWrite.cpp \
|
||||
|
|
@ -68,6 +70,8 @@ noinst_HEADERS = \
|
|||
CommandDownload.h \
|
||||
CommandMaster.h \
|
||||
CommandPdos.h \
|
||||
CommandPhyRead.h \
|
||||
CommandPhyWrite.h \
|
||||
CommandSdos.h \
|
||||
CommandSiiRead.h \
|
||||
CommandSiiWrite.h \
|
||||
|
|
|
|||
|
|
@ -344,6 +344,32 @@ void MasterDevice::writeSii(
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::readPhy(
|
||||
ec_ioctl_slave_phy_t *data
|
||||
)
|
||||
{
|
||||
if (ioctl(fd, EC_IOCTL_SLAVE_PHY_READ, data) < 0) {
|
||||
stringstream err;
|
||||
err << "Failed to read physical memory: " << strerror(errno);
|
||||
throw MasterDeviceException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::writePhy(
|
||||
ec_ioctl_slave_phy_t *data
|
||||
)
|
||||
{
|
||||
if (ioctl(fd, EC_IOCTL_SLAVE_PHY_WRITE, data) < 0) {
|
||||
stringstream err;
|
||||
err << "Failed to write physical memory: " << strerror(errno);
|
||||
throw MasterDeviceException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::setDebug(unsigned int debugLevel)
|
||||
{
|
||||
if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ class MasterDevice
|
|||
void getSdoEntry(ec_ioctl_slave_sdo_entry_t *, uint16_t, int, uint8_t);
|
||||
void readSii(ec_ioctl_slave_sii_t *);
|
||||
void writeSii(ec_ioctl_slave_sii_t *);
|
||||
void readPhy(ec_ioctl_slave_phy_t *);
|
||||
void writePhy(ec_ioctl_slave_phy_t *);
|
||||
void setDebug(unsigned int);
|
||||
void sdoDownload(ec_ioctl_slave_sdo_download_t *);
|
||||
void sdoUpload(ec_ioctl_slave_sdo_upload_t *);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ using namespace std;
|
|||
#include "CommandDownload.h"
|
||||
#include "CommandMaster.h"
|
||||
#include "CommandPdos.h"
|
||||
#include "CommandPhyRead.h"
|
||||
#include "CommandPhyWrite.h"
|
||||
#include "CommandSdos.h"
|
||||
#include "CommandSiiRead.h"
|
||||
#include "CommandSiiWrite.h"
|
||||
|
|
@ -263,6 +265,8 @@ int main(int argc, char **argv)
|
|||
commandList.push_back(new CommandDownload());
|
||||
commandList.push_back(new CommandMaster());
|
||||
commandList.push_back(new CommandPdos());
|
||||
commandList.push_back(new CommandPhyRead());
|
||||
commandList.push_back(new CommandPhyWrite());
|
||||
commandList.push_back(new CommandSdos());
|
||||
commandList.push_back(new CommandSiiRead());
|
||||
commandList.push_back(new CommandSiiWrite());
|
||||
|
|
|
|||
Loading…
Reference in New Issue