Implemented emergency register requests to analyze a broken bus.

This commit is contained in:
Florian Pose 2013-05-13 20:21:19 +02:00
parent a0e44766ec
commit b0eace9ef1
12 changed files with 124 additions and 21 deletions

View File

@ -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;

View File

@ -1144,6 +1144,12 @@ static ATTRIBUTES int ec_ioctl_slave_reg_write(
return -EINTR;
}
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);
@ -1154,6 +1160,7 @@ static ATTRIBUTES int ec_ioctl_slave_reg_write(
// schedule request.
list_add_tail(&request.list, &slave->reg_requests);
}
up(&master->master_sem);

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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;
}

View File

@ -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. */
};
/*****************************************************************************/

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -69,9 +69,11 @@ string CommandRegWrite::helpString(const string &binaryBaseName) const
<< endl
<< "Command-specific options:" << endl
<< " --alias -a <alias>" << endl
<< " --position -p <pos> Slave selection. See the help of" << 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 (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;
}
// send data to master
try {

View File

@ -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) {