Implemented emergency register requests to analyze a broken bus.
This commit is contained in:
parent
a0e44766ec
commit
b0eace9ef1
|
|
@ -198,7 +198,47 @@ void ec_fsm_master_state_start(
|
|||
ec_fsm_master_t *fsm /**< Master state machine. */
|
||||
)
|
||||
{
|
||||
ec_master_t *master = fsm->master;
|
||||
|
||||
fsm->idle = 1;
|
||||
|
||||
// check for emergency requests
|
||||
if (!list_empty(&master->emerg_reg_requests)) {
|
||||
ec_reg_request_t *request;
|
||||
|
||||
// get first request
|
||||
request = list_entry(master->emerg_reg_requests.next,
|
||||
ec_reg_request_t, list);
|
||||
list_del_init(&request->list); // dequeue
|
||||
request->state = EC_INT_REQUEST_BUSY;
|
||||
|
||||
if (request->transfer_size > fsm->datagram->mem_size) {
|
||||
EC_MASTER_ERR(master, "Emergency request data too large!\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up_all(&master->request_queue);
|
||||
fsm->state(fsm); // continue
|
||||
return;
|
||||
}
|
||||
|
||||
if (request->dir != EC_DIR_OUTPUT) {
|
||||
EC_MASTER_ERR(master, "Emergency requests must be"
|
||||
" write requests!\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up_all(&master->request_queue);
|
||||
fsm->state(fsm); // continue
|
||||
return;
|
||||
}
|
||||
|
||||
EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
|
||||
ec_datagram_apwr(fsm->datagram, request->ring_position,
|
||||
request->address, request->transfer_size);
|
||||
memcpy(fsm->datagram->data, request->data, request->transfer_size);
|
||||
fsm->datagram->device_index = EC_DEVICE_MAIN;
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
wake_up_all(&master->request_queue);
|
||||
return;
|
||||
}
|
||||
|
||||
ec_datagram_brd(fsm->datagram, 0x0130, 2);
|
||||
ec_datagram_zero(fsm->datagram);
|
||||
fsm->datagram->device_index = fsm->dev_idx;
|
||||
|
|
|
|||
|
|
@ -1144,16 +1144,23 @@ static ATTRIBUTES int ec_ioctl_slave_reg_write(
|
|||
return -EINTR;
|
||||
}
|
||||
|
||||
if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
|
||||
up(&master->master_sem);
|
||||
ec_reg_request_clear(&request);
|
||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
|
||||
io.slave_position);
|
||||
return -EINVAL;
|
||||
if (io.emergency) {
|
||||
request.ring_position = io.slave_position;
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &master->emerg_reg_requests);
|
||||
}
|
||||
else {
|
||||
if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
|
||||
up(&master->master_sem);
|
||||
ec_reg_request_clear(&request);
|
||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
|
||||
io.slave_position);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &slave->reg_requests);
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &slave->reg_requests);
|
||||
}
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
*
|
||||
* Increment this when changing the ioctl interface!
|
||||
*/
|
||||
#define EC_IOCTL_VERSION_MAGIC 27
|
||||
#define EC_IOCTL_VERSION_MAGIC 28
|
||||
|
||||
// Command-line tool
|
||||
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
|
||||
|
|
@ -419,6 +419,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
// inputs
|
||||
uint16_t slave_position;
|
||||
uint8_t emergency;
|
||||
uint16_t address;
|
||||
size_t size;
|
||||
uint8_t *data;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
master->app_cb_data = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&master->sii_requests);
|
||||
INIT_LIST_HEAD(&master->emerg_reg_requests);
|
||||
|
||||
init_waitqueue_head(&master->request_queue);
|
||||
|
||||
|
|
|
|||
|
|
@ -305,6 +305,8 @@ struct ec_master {
|
|||
void *app_cb_data; /**< Application callback data. */
|
||||
|
||||
struct list_head sii_requests; /**< SII write requests. */
|
||||
struct list_head emerg_reg_requests; /**< Emergency register access
|
||||
requests. */
|
||||
|
||||
wait_queue_head_t request_queue; /**< Wait queue for external requests
|
||||
from user space. */
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ int ec_reg_request_init(
|
|||
reg->address = 0;
|
||||
reg->transfer_size = 0;
|
||||
reg->state = EC_INT_REQUEST_INIT;
|
||||
reg->ring_position = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ struct ec_reg_request {
|
|||
uint16_t address; /**< Register address. */
|
||||
size_t transfer_size; /**< Size of the data to transfer. */
|
||||
ec_internal_request_state_t state; /**< Request state. */
|
||||
uint16_t ring_position; /**< Ring position for emergency requests. */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -150,7 +150,9 @@ class AliasPositionParser:
|
|||
Command::Command(const string &name, const string &briefDesc):
|
||||
name(name),
|
||||
briefDesc(briefDesc),
|
||||
verbosity(Normal)
|
||||
verbosity(Normal),
|
||||
emergency(false),
|
||||
force(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +206,13 @@ void Command::setDataType(const string &t)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void Command::setEmergency(bool e)
|
||||
{
|
||||
emergency = e;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void Command::setForce(bool f)
|
||||
{
|
||||
force = f;
|
||||
|
|
@ -489,6 +498,19 @@ Command::DomainList Command::selectedDomains(MasterDevice &m,
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
int Command::emergencySlave() const
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
stringstream str;
|
||||
str << positions;
|
||||
str >> ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
string Command::alStateString(uint8_t state)
|
||||
{
|
||||
string ret;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ class Command
|
|||
void setDataType(const string &);
|
||||
const string &getDataType() const;
|
||||
|
||||
void setEmergency(bool);
|
||||
bool getEmergency() const;
|
||||
|
||||
void setForce(bool);
|
||||
bool getForce() const;
|
||||
|
||||
|
|
@ -140,6 +143,7 @@ class Command
|
|||
ConfigList selectedConfigs(MasterDevice &);
|
||||
typedef list<ec_ioctl_domain_t> DomainList;
|
||||
DomainList selectedDomains(MasterDevice &, const ec_ioctl_master_t &);
|
||||
int emergencySlave() const;
|
||||
|
||||
static string alStateString(uint8_t);
|
||||
|
||||
|
|
@ -152,6 +156,7 @@ class Command
|
|||
string positions;
|
||||
string domains;
|
||||
string dataType;
|
||||
bool emergency;
|
||||
bool force;
|
||||
string outputFile;
|
||||
string skin;
|
||||
|
|
@ -189,6 +194,13 @@ inline const string &Command::getDataType() const
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
inline bool Command::getEmergency() const
|
||||
{
|
||||
return emergency;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
inline bool Command::getForce() const
|
||||
{
|
||||
return force;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ void CommandRegRead::execute(const StringVector &args)
|
|||
throwSingleSlaveRequired(slaves.size());
|
||||
}
|
||||
io.slave_position = slaves.front().position;
|
||||
io.emergency = false;
|
||||
|
||||
io.data = new uint8_t[io.size];
|
||||
|
||||
|
|
|
|||
|
|
@ -68,10 +68,12 @@ string CommandRegWrite::helpString(const string &binaryBaseName) const
|
|||
<< typeInfo()
|
||||
<< 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
|
||||
<< " --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
|
||||
<< " --emergency -e Send as emergency request." << endl
|
||||
<< endl
|
||||
<< numericInfo();
|
||||
|
||||
|
|
@ -85,7 +87,6 @@ void CommandRegWrite::execute(const StringVector &args)
|
|||
stringstream strOffset, err;
|
||||
ec_ioctl_slave_reg_t io;
|
||||
ifstream file;
|
||||
SlaveList slaves;
|
||||
|
||||
if (args.size() != 2) {
|
||||
err << "'" << getName() << "' takes exactly two arguments!";
|
||||
|
|
@ -158,12 +159,19 @@ void CommandRegWrite::execute(const StringVector &args)
|
|||
throw e;
|
||||
}
|
||||
|
||||
slaves = selectedSlaves(m);
|
||||
if (slaves.size() != 1) {
|
||||
delete [] io.data;
|
||||
throwSingleSlaveRequired(slaves.size());
|
||||
if (getEmergency()) {
|
||||
io.slave_position = emergencySlave();
|
||||
io.emergency = true;
|
||||
}
|
||||
else {
|
||||
SlaveList slaves = selectedSlaves(m);
|
||||
if (slaves.size() != 1) {
|
||||
delete [] io.data;
|
||||
throwSingleSlaveRequired(slaves.size());
|
||||
}
|
||||
io.slave_position = slaves.front().position;
|
||||
io.emergency = false;
|
||||
}
|
||||
io.slave_position = slaves.front().position;
|
||||
|
||||
// send data to master
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ string domains = "-"; // all domains
|
|||
string dataTypeStr;
|
||||
Command::Verbosity verbosity = Command::Normal;
|
||||
bool force = false;
|
||||
bool emergency = false;
|
||||
bool helpRequested = false;
|
||||
string outputFile;
|
||||
string skin;
|
||||
|
|
@ -149,6 +150,7 @@ void getOptions(int argc, char **argv)
|
|||
{"type", required_argument, NULL, 't'},
|
||||
{"output-file", required_argument, NULL, 'o'},
|
||||
{"skin", required_argument, NULL, 's'},
|
||||
{"emergency", no_argument, NULL, 'e'},
|
||||
{"force", no_argument, NULL, 'f'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
|
|
@ -157,7 +159,7 @@ void getOptions(int argc, char **argv)
|
|||
};
|
||||
|
||||
do {
|
||||
c = getopt_long(argc, argv, "m:a:p:d:t:o:s:fqvh", longOptions, NULL);
|
||||
c = getopt_long(argc, argv, "m:a:p:d:t:o:s:efqvh", longOptions, NULL);
|
||||
|
||||
switch (c) {
|
||||
case 'm':
|
||||
|
|
@ -188,6 +190,10 @@ void getOptions(int argc, char **argv)
|
|||
skin = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
emergency = true;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
force = true;
|
||||
break;
|
||||
|
|
@ -315,6 +321,7 @@ int main(int argc, char **argv)
|
|||
cmd->setDataType(dataTypeStr);
|
||||
cmd->setOutputFile(outputFile);
|
||||
cmd->setSkin(skin);
|
||||
cmd->setEmergency(emergency);
|
||||
cmd->setForce(force);
|
||||
cmd->execute(commandArgs);
|
||||
} catch (InvalidUsageException &e) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue