Persistent slave lists.
--- a/examples/mini/mini.c Wed Oct 25 16:53:17 2006 +0000
+++ b/examples/mini/mini.c Thu Oct 26 16:29:26 2006 +0000
@@ -56,13 +56,16 @@
spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
// data fields
+#if 0
void *r_inputs;
void *r_outputs;
-
-#if 0
+#endif
+
+void *r_ana_in;
+
+#if 1
ec_pdo_reg_t domain1_pdos[] = {
- {"2", Beckhoff_EL4132_Output1, &r_ana_out},
- {"3", Beckhoff_EL5001_Value, NULL},
+ {"2", Beckhoff_EL3102_Input1, &r_ana_in},
{}
};
#endif
@@ -82,8 +85,7 @@
// process data
//k_pos = EC_READ_U32(r_ssi);
- EC_WRITE_U8(r_outputs + 2, einaus ? 0xFF : 0x00);
-
+ //EC_WRITE_U8(r_outputs + 2, einaus ? 0xFF : 0x00);
// send
ecrt_master_run(master);
@@ -142,12 +144,14 @@
}
printk(KERN_INFO "Registering PDOs...\n");
-#if 0
+#if 1
if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) {
printk(KERN_ERR "PDO registration failed!\n");
goto out_release_master;
}
#endif
+
+#if 0
if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120,
EC_DIR_OUTPUT, 0, 4, &r_outputs)) {
printk(KERN_ERR "PDO registration failed!\n");
@@ -158,6 +162,7 @@
printk(KERN_ERR "PDO registration failed!\n");
goto out_release_master;
}
+#endif
#if 0
if (!(slave = ecrt_master_get_slave(master, "3")))
--- a/master/datagram.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/datagram.c Thu Oct 26 16:29:26 2006 +0000
@@ -69,6 +69,7 @@
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
+ INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
datagram->type = EC_DATAGRAM_NONE;
datagram->address.logical = 0x00000000;
datagram->data = NULL;
--- a/master/domain.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/domain.c Thu Oct 26 16:29:26 2006 +0000
@@ -139,8 +139,6 @@
domain = container_of(kobj, ec_domain_t, kobj);
- EC_INFO("Clearing domain %i.\n", domain->index);
-
list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
ec_datagram_clear(datagram);
kfree(datagram);
@@ -222,6 +220,9 @@
data_reg->data_ptr = data_ptr;
list_add_tail(&data_reg->list, &domain->data_regs);
+
+ ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
+
return 0;
}
@@ -297,6 +298,9 @@
}
list_add_tail(&data_reg->list, &domain->data_regs);
+
+ ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
+
return 0;
}
@@ -448,7 +452,7 @@
Places all process data datagrams in the masters datagram queue.
*/
-void ec_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
+void ec_domain_queue_datagrams(ec_domain_t *domain /**< EtherCAT domain */)
{
ec_datagram_t *datagram;
@@ -460,6 +464,22 @@
/*****************************************************************************/
/**
+ Dequeues all datagrams from the masters datagram queue.
+*/
+
+void ec_domain_dequeue_datagrams(ec_domain_t *domain /**< EtherCAT domain */)
+{
+ ec_datagram_t *datagram;
+
+ list_for_each_entry(datagram, &domain->datagrams, list) {
+ if (!list_empty(&datagram->queue)) // datagram queued?
+ list_del_init(&datagram->queue);
+ }
+}
+
+/*****************************************************************************/
+
+/**
Formats attribute data for SysFS reading.
\return number of bytes to read
*/
@@ -518,18 +538,15 @@
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
- if (!data_ptr) {
- // data_ptr is NULL => mark slave as "registered" (do not warn)
- slave->registered = 1;
- }
+ if (!data_ptr) return slave;
list_for_each_entry(pdo, &slave->sii_pdos, list) {
list_for_each_entry(entry, &pdo->entries, list) {
if (entry->index != pdo_index
|| entry->subindex != pdo_subindex) continue;
- if (data_ptr) {
- ec_domain_reg_pdo_entry(domain, slave, pdo, entry, data_ptr);
+ if (ec_domain_reg_pdo_entry(domain, slave, pdo, entry, data_ptr)) {
+ return NULL;
}
return slave;
@@ -538,7 +555,6 @@
EC_ERR("Slave %i does not provide PDO 0x%04X:%i.\n",
slave->ring_position, pdo_index, pdo_subindex);
- slave->registered = 0;
return NULL;
}
@@ -609,11 +625,7 @@
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
- if (!data_ptr) {
- // data_ptr is NULL => mark slave as "registered" (do not warn)
- slave->registered = 1;
- return slave;
- }
+ if (!data_ptr) return slave;
if (ec_domain_reg_pdo_range(domain, slave,
direction, offset, length, data_ptr)) {
@@ -666,7 +678,7 @@
domain->working_counter_changes = 0;
}
- ec_domain_queue(domain);
+ ec_domain_queue_datagrams(domain);
}
/*****************************************************************************/
--- a/master/domain.h Wed Oct 25 16:53:17 2006 +0000
+++ b/master/domain.h Thu Oct 26 16:29:26 2006 +0000
@@ -76,8 +76,11 @@
/*****************************************************************************/
int ec_domain_init(ec_domain_t *, ec_master_t *, unsigned int);
+
int ec_domain_alloc(ec_domain_t *, uint32_t);
-void ec_domain_queue(ec_domain_t *);
+
+void ec_domain_queue_datagrams(ec_domain_t *);
+void ec_domain_dequeue_datagrams(ec_domain_t *);
/*****************************************************************************/
--- a/master/ethernet.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/ethernet.c Thu Oct 26 16:29:26 2006 +0000
@@ -629,8 +629,7 @@
if (!eoe->slave)
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
else {
- eoe->slave->requested_state = EC_SLAVE_STATE_OP;
- eoe->slave->error_flag = 0;
+ ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
}
return 0;
}
@@ -652,8 +651,7 @@
if (!eoe->slave)
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
else {
- eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
- eoe->slave->error_flag = 0;
+ ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_PREOP);
}
return 0;
}
--- a/master/fsm.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/fsm.c Thu Oct 26 16:29:26 2006 +0000
@@ -56,13 +56,8 @@
void ec_fsm_master_write_eeprom(ec_fsm_t *);
void ec_fsm_master_sdodict(ec_fsm_t *);
void ec_fsm_master_sdo_request(ec_fsm_t *);
-
-void ec_fsm_startup_start(ec_fsm_t *);
-void ec_fsm_startup_broadcast(ec_fsm_t *);
-void ec_fsm_startup_scan(ec_fsm_t *);
-
-void ec_fsm_configuration_start(ec_fsm_t *);
-void ec_fsm_configuration_conf(ec_fsm_t *);
+void ec_fsm_master_end(ec_fsm_t *);
+void ec_fsm_master_error(ec_fsm_t *);
void ec_fsm_slavescan_start(ec_fsm_t *);
void ec_fsm_slavescan_address(ec_fsm_t *);
@@ -80,8 +75,8 @@
void ec_fsm_slaveconf_saveop(ec_fsm_t *);
void ec_fsm_slaveconf_op(ec_fsm_t *);
-void ec_fsm_end(ec_fsm_t *);
-void ec_fsm_error(ec_fsm_t *);
+void ec_fsm_slave_end(ec_fsm_t *);
+void ec_fsm_slave_error(ec_fsm_t *);
/*****************************************************************************/
@@ -132,19 +127,6 @@
/*****************************************************************************/
/**
- Resets the state machine.
-*/
-
-void ec_fsm_reset(ec_fsm_t *fsm /**< finite state machine */)
-{
- fsm->master_state = ec_fsm_master_start;
- fsm->master_slaves_responding = 0;
- fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
-}
-
-/*****************************************************************************/
-
-/**
Executes the current state of the state machine.
\return false, if state machine has terminated
*/
@@ -153,232 +135,23 @@
{
fsm->master_state(fsm);
- return fsm->master_state != ec_fsm_end &&
- fsm->master_state != ec_fsm_error;
-}
-
-/*****************************************************************************/
-
-/**
- Initializes the master startup state machine.
-*/
-
-void ec_fsm_startup(ec_fsm_t *fsm)
-{
- fsm->master_state = ec_fsm_startup_start;
-}
-
-/*****************************************************************************/
-
-/**
- Returns, if the master startup state machine terminated with success.
- \return non-zero if successful.
-*/
-
-int ec_fsm_startup_success(ec_fsm_t *fsm /**< Finite state machine */)
-{
- return fsm->master_state == ec_fsm_end;
-}
-
-/*****************************************************************************/
-
-/**
- Initializes the master configuration state machine.
-*/
-
-void ec_fsm_configuration(ec_fsm_t *fsm)
-{
- fsm->master_state = ec_fsm_configuration_start;
-}
-
-/*****************************************************************************/
-
-/**
- Returns, if the master confuguration state machine terminated with success.
- \return non-zero if successful.
-*/
-
-int ec_fsm_configuration_success(ec_fsm_t *fsm /**< Finite state machine */)
-{
- return fsm->master_state == ec_fsm_end;
+ return fsm->master_state != ec_fsm_master_end
+ && fsm->master_state != ec_fsm_master_error;
+}
+
+/*****************************************************************************/
+
+/**
+ \return true, if the master state machine terminated gracefully
+*/
+
+int ec_fsm_success(ec_fsm_t *fsm /**< finite state machine */)
+{
+ return fsm->master_state == ec_fsm_master_end;
}
/******************************************************************************
- * master startup state machine
- *****************************************************************************/
-
-/**
- Master state: START.
- Starts with getting slave count and slave states.
-*/
-
-void ec_fsm_startup_start(ec_fsm_t *fsm)
-{
- ec_datagram_brd(&fsm->datagram, 0x0130, 2);
- ec_master_queue_datagram(fsm->master, &fsm->datagram);
- fsm->master_state = ec_fsm_startup_broadcast;
-}
-
-/*****************************************************************************/
-
-/**
- Master state: BROADCAST.
- Processes the broadcast read slave count and slaves states.
-*/
-
-void ec_fsm_startup_broadcast(ec_fsm_t *fsm /**< finite state machine */)
-{
- ec_datagram_t *datagram = &fsm->datagram;
- unsigned int i;
- ec_slave_t *slave;
- ec_master_t *master = fsm->master;
-
- if (datagram->state != EC_DATAGRAM_RECEIVED) {
- EC_ERR("Failed to receive broadcast datagram.\n");
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- EC_INFO("Scanning bus.\n");
-
- ec_master_clear_slaves(master);
-
- master->slave_count = datagram->working_counter;
-
- if (!master->slave_count) {
- // no slaves present -> finish state machine.
- fsm->master_state = ec_fsm_end;
- return;
- }
-
- // init slaves
- for (i = 0; i < master->slave_count; i++) {
- if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
- GFP_KERNEL))) {
- EC_ERR("Failed to allocate slave %i!\n", i);
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- if (ec_slave_init(slave, master, i, i + 1)) {
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- if (kobject_add(&slave->kobj)) {
- EC_ERR("Failed to add kobject.\n");
- kobject_put(&slave->kobj); // free
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- list_add_tail(&slave->list, &master->slaves);
- }
-
- // begin scanning of slaves
- fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
- fsm->slave_state = ec_fsm_slavescan_start;
- fsm->master_state = ec_fsm_startup_scan;
- fsm->master_state(fsm); // execute immediately
- return;
-}
-
-/*****************************************************************************/
-
-/**
- Master state: SCAN.
- Executes the sub-statemachine for the scanning of a slave.
-*/
-
-void ec_fsm_startup_scan(ec_fsm_t *fsm /**< finite state machine */)
-{
- ec_master_t *master = fsm->master;
- ec_slave_t *slave = fsm->slave;
-
- fsm->slave_state(fsm); // execute slave state machine
-
- if (fsm->slave_state == ec_fsm_error) {
- EC_ERR("Slave scanning failed.\n");
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- if (fsm->slave_state != ec_fsm_end) return;
-
- // another slave to scan?
- if (slave->list.next != &master->slaves) {
- fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
- fsm->slave_state = ec_fsm_slavescan_start;
- fsm->slave_state(fsm); // execute immediately
- return;
- }
-
- EC_INFO("Bus scanning completed.\n");
-
- ec_master_calc_addressing(master);
-
- fsm->master_state = ec_fsm_end;
-}
-
-/******************************************************************************
- * master configuration state machine
- *****************************************************************************/
-
-/**
- Master configuration state machine: START.
-*/
-
-void ec_fsm_configuration_start(ec_fsm_t *fsm /**< finite state machine */)
-{
- ec_master_t *master = fsm->master;
-
- if (list_empty(&master->slaves)) {
- fsm->master_state = ec_fsm_end;
- return;
- }
-
- // begin configuring slaves
- fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
- fsm->slave_state = ec_fsm_slaveconf_init;
- ec_fsm_change(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
- fsm->master_state = ec_fsm_configuration_conf;
- fsm->master_state(fsm); // execute immediately
-}
-
-/*****************************************************************************/
-
-/**
- Master state: CONF.
-*/
-
-void ec_fsm_configuration_conf(ec_fsm_t *fsm /**< finite state machine */)
-{
- ec_master_t *master = fsm->master;
- ec_slave_t *slave = fsm->slave;
-
- fsm->slave_state(fsm); // execute slave's state machine
-
- if (fsm->slave_state == ec_fsm_error) {
- fsm->master_state = ec_fsm_error;
- return;
- }
-
- if (fsm->slave_state != ec_fsm_end) return;
-
- // another slave to configure?
- if (slave->list.next != &master->slaves) {
- fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
- fsm->slave_state = ec_fsm_slaveconf_init;
- ec_fsm_change(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
- fsm->master_state(fsm); // execute immediately
- return;
- }
-
- fsm->master_state = ec_fsm_end;
-}
-
-/******************************************************************************
- * operation / idle state machine
+ * operation/idle state machine
*****************************************************************************/
/**
@@ -414,8 +187,10 @@
slave->online = 0;
}
}
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ else {
+ EC_ERR("Failed to receive broadcast datagram.\n");
+ }
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -449,7 +224,6 @@
// topology change in idle mode: clear all slaves and scan the bus
if (topology_change && master->mode == EC_MASTER_MODE_IDLE) {
- EC_INFO("Scanning bus.\n");
ec_master_eoe_stop(master);
ec_master_clear_slaves(master);
@@ -458,8 +232,7 @@
if (!master->slave_count) {
// no slaves present -> finish state machine.
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_end;
return;
}
@@ -469,16 +242,14 @@
GFP_ATOMIC))) {
EC_ERR("Failed to allocate slave %i!\n", i);
ec_master_clear_slaves(master);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
if (ec_slave_init(slave, master, i, i + 1)) {
// freeing of "slave" already done
ec_master_clear_slaves(master);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -486,14 +257,15 @@
EC_ERR("Failed to add kobject.\n");
kobject_put(&slave->kobj); // free
ec_master_clear_slaves(master);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
list_add_tail(&slave->list, &master->slaves);
}
+ EC_INFO("Scanning bus.\n");
+
// begin scanning of slaves
fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
fsm->slave_state = ec_fsm_slavescan_start;
@@ -533,17 +305,18 @@
&& (slave->configured
|| slave->current_state == EC_SLAVE_STATE_INIT))) continue;
- ec_state_string(slave->current_state, old_state);
- ec_state_string(slave->requested_state, new_state);
-
- if (!slave->configured
- && slave->current_state != EC_SLAVE_STATE_INIT) {
- EC_INFO("Reconfiguring slave %i (%s -> %s).\n",
- slave->ring_position, old_state, new_state);
- }
- else if (slave->current_state != slave->requested_state) {
- EC_INFO("Changing state of slave %i (%s -> %s).\n",
- slave->ring_position, old_state, new_state);
+ if (master->debug_level) {
+ ec_state_string(slave->current_state, old_state);
+ if (!slave->configured
+ && slave->current_state != EC_SLAVE_STATE_INIT) {
+ EC_INFO("Reconfiguring slave %i (%s).\n",
+ slave->ring_position, old_state);
+ }
+ else if (slave->current_state != slave->requested_state) {
+ ec_state_string(slave->requested_state, new_state);
+ EC_INFO("Changing state of slave %i (%s -> %s).\n",
+ slave->ring_position, old_state, new_state);
+ }
}
fsm->slave = slave;
@@ -601,8 +374,7 @@
EC_ERR("Failed to add SDO kobj of slave %i.\n",
slave->ring_position);
slave->error_flag = 1;
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -639,9 +411,7 @@
}
}
- // nothing to do. restart master state machine.
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_end;
}
/*****************************************************************************/
@@ -702,8 +472,9 @@
uint8_t new_state;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ EC_ERR("Failed to receive AL state datagram for slave %i!\n",
+ slave->ring_position);
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -756,15 +527,13 @@
fsm->slave->error_flag = 1;
EC_ERR("Failed to validate vendor ID of slave %i.\n",
slave->ring_position);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_vendor_id) {
- EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ EC_ERR("Slave %i has an invalid vendor ID!\n", slave->ring_position);
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -796,7 +565,8 @@
fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
}
- EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
+ if (fsm->master->debug_level)
+ EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position);
// write station address
ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
@@ -822,8 +592,7 @@
fsm->slave->error_flag = 1;
EC_ERR("Failed to validate product code of slave %i.\n",
slave->ring_position);
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -831,8 +600,7 @@
EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
EC_READ_U32(fsm->fsm_sii.value));
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -897,8 +665,8 @@
fsm->slave_state(fsm); // execute slave state machine
- if (fsm->slave_state != ec_fsm_end
- && fsm->slave_state != ec_fsm_error) return;
+ if (fsm->slave_state != ec_fsm_slave_end
+ && fsm->slave_state != ec_fsm_slave_error) return;
// another slave to fetch?
if (slave->list.next != &master->slaves) {
@@ -915,11 +683,10 @@
// set initial states of all slaves to PREOP to make mailbox
// communication possible
list_for_each_entry(slave, &master->slaves, list) {
- slave->requested_state = EC_SLAVE_STATE_PREOP;
- }
-
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+ }
+
+ fsm->master_state = ec_fsm_master_end;
}
/*****************************************************************************/
@@ -935,8 +702,8 @@
{
fsm->slave_state(fsm); // execute slave's state machine
- if (fsm->slave_state != ec_fsm_end
- && fsm->slave_state != ec_fsm_error) return;
+ if (fsm->slave_state != ec_fsm_slave_end
+ && fsm->slave_state != ec_fsm_slave_error) return;
ec_fsm_master_action_process_states(fsm);
}
@@ -959,8 +726,7 @@
slave->ring_position);
kfree(slave->new_eeprom_data);
slave->new_eeprom_data = NULL;
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -999,8 +765,7 @@
if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -1034,8 +799,7 @@
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
request->return_code = -1;
master->sdo_seq_master++;
- fsm->master_state = ec_fsm_master_start;
- fsm->master_state(fsm); // execute immediately
+ fsm->master_state = ec_fsm_master_error;
return;
}
@@ -1049,6 +813,28 @@
fsm->master_state(fsm); // execute immediately
}
+/*****************************************************************************/
+
+/**
+ State: ERROR.
+*/
+
+void ec_fsm_master_error(ec_fsm_t *fsm /**< finite state machine */)
+{
+ fsm->master_state = ec_fsm_master_start;
+}
+
+/*****************************************************************************/
+
+/**
+ State: END.
+*/
+
+void ec_fsm_master_end(ec_fsm_t *fsm /**< finite state machine */)
+{
+ fsm->master_state = ec_fsm_master_start;
+}
+
/******************************************************************************
* slave scan state machine
*****************************************************************************/
@@ -1083,7 +869,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to write station address of slave %i.\n",
fsm->slave->ring_position);
return;
@@ -1109,7 +895,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to read AL state of slave %i.\n",
fsm->slave->ring_position);
return;
@@ -1141,7 +927,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to read base data of slave %i.\n",
slave->ring_position);
return;
@@ -1178,7 +964,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to read DL status of slave %i.\n",
slave->ring_position);
return;
@@ -1214,7 +1000,7 @@
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to read EEPROM size of slave %i.\n",
slave->ring_position);
return;
@@ -1242,7 +1028,7 @@
if (!(slave->eeprom_data =
(uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
slave->ring_position);
return;
@@ -1271,7 +1057,7 @@
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
slave->ring_position);
return;
@@ -1359,13 +1145,13 @@
cat_word += cat_size + 2;
}
- fsm->slave_state = ec_fsm_end;
+ fsm->slave_state = ec_fsm_slave_end;
return;
end:
EC_ERR("Failed to analyze category data.\n");
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
}
/******************************************************************************
@@ -1388,7 +1174,7 @@
if (!ec_fsm_change_success(&fsm->fsm_change)) {
slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
@@ -1400,7 +1186,7 @@
// slave is now in INIT
if (slave->current_state == slave->requested_state) {
- fsm->slave_state = ec_fsm_end; // successful
+ fsm->slave_state = ec_fsm_slave_end; // successful
if (master->debug_level) {
EC_DBG("Finished configuration of slave %i.\n",
slave->ring_position);
@@ -1457,7 +1243,7 @@
if (sync->index >= slave->base_sync_count) {
EC_ERR("Invalid sync manager configuration found!");
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
ec_sync_config(sync, slave,
@@ -1483,7 +1269,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to set sync managers on slave %i.\n",
slave->ring_position);
return;
@@ -1511,7 +1297,7 @@
if (!ec_fsm_change_success(&fsm->fsm_change)) {
slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
@@ -1523,7 +1309,7 @@
}
if (slave->current_state == slave->requested_state) {
- fsm->slave_state = ec_fsm_end; // successful
+ fsm->slave_state = ec_fsm_slave_end; // successful
if (master->debug_level) {
EC_DBG("Finished configuration of slave %i.\n",
slave->ring_position);
@@ -1574,7 +1360,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED
|| datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
EC_ERR("Failed to set FMMUs on slave %i.\n",
fsm->slave->ring_position);
return;
@@ -1608,7 +1394,7 @@
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
@@ -1644,7 +1430,7 @@
if (!ec_fsm_change_success(&fsm->fsm_change)) {
fsm->slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
@@ -1655,7 +1441,7 @@
}
if (fsm->slave->current_state == fsm->slave->requested_state) {
- fsm->slave_state = ec_fsm_end; // successful
+ fsm->slave_state = ec_fsm_slave_end; // successful
if (master->debug_level) {
EC_DBG("Finished configuration of slave %i.\n",
slave->ring_position);
@@ -1684,7 +1470,7 @@
if (!ec_fsm_change_success(&fsm->fsm_change)) {
slave->error_flag = 1;
- fsm->slave_state = ec_fsm_error;
+ fsm->slave_state = ec_fsm_slave_error;
return;
}
@@ -1695,7 +1481,7 @@
EC_DBG("Finished configuration of slave %i.\n", slave->ring_position);
}
- fsm->slave_state = ec_fsm_end; // successful
+ fsm->slave_state = ec_fsm_slave_end; // successful
}
/******************************************************************************
@@ -1706,7 +1492,7 @@
State: ERROR.
*/
-void ec_fsm_error(ec_fsm_t *fsm /**< finite state machine */)
+void ec_fsm_slave_error(ec_fsm_t *fsm /**< finite state machine */)
{
}
@@ -1716,8 +1502,8 @@
State: END.
*/
-void ec_fsm_end(ec_fsm_t *fsm /**< finite state machine */)
-{
-}
-
-/*****************************************************************************/
+void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */)
+{
+}
+
+/*****************************************************************************/
--- a/master/fsm.h Wed Oct 25 16:53:17 2006 +0000
+++ b/master/fsm.h Thu Oct 26 16:29:26 2006 +0000
@@ -84,14 +84,9 @@
int ec_fsm_init(ec_fsm_t *, ec_master_t *);
void ec_fsm_clear(ec_fsm_t *);
-void ec_fsm_reset(ec_fsm_t *);
+
int ec_fsm_exec(ec_fsm_t *);
-
-void ec_fsm_startup(ec_fsm_t *);
-int ec_fsm_startup_success(ec_fsm_t *);
-
-void ec_fsm_configuration(ec_fsm_t *);
-int ec_fsm_configuration_success(ec_fsm_t *);
+int ec_fsm_success(ec_fsm_t *);
/*****************************************************************************/
--- a/master/fsm_coe.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/fsm_coe.c Thu Oct 26 16:29:26 2006 +0000
@@ -360,7 +360,7 @@
}
if (mbox_prot != 0x03) { // CoE
- EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
fsm->state = ec_fsm_coe_error;
return;
}
@@ -549,7 +549,7 @@
}
if (mbox_prot != 0x03) { // CoE
- EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
fsm->state = ec_fsm_coe_error;
return;
}
@@ -722,7 +722,7 @@
}
if (mbox_prot != 0x03) { // CoE
- EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
fsm->state = ec_fsm_coe_error;
return;
}
@@ -970,7 +970,7 @@
}
if (mbox_prot != 0x03) { // CoE
- EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
fsm->state = ec_fsm_coe_error;
return;
}
@@ -1210,8 +1210,10 @@
request->size = 0;
if (complete_size) {
- if (!(request->data = (uint8_t *) kmalloc(complete_size + 1, GFP_ATOMIC))) {
- EC_ERR("Failed to allocate %i bytes of SDO data!\n", complete_size);
+ if (!(request->data = (uint8_t *)
+ kmalloc(complete_size + 1, GFP_ATOMIC))) {
+ EC_ERR("Failed to allocate %i bytes of SDO data!\n",
+ complete_size);
fsm->state = ec_fsm_coe_error;
return;
}
@@ -1228,9 +1230,11 @@
fsm->toggle = 0;
if (data_size < complete_size) {
- EC_WARN("SDO data incomplete (%i / %i).\n", data_size, complete_size);
-
- if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {
+ EC_WARN("SDO data incomplete (%i / %i).\n",
+ data_size, complete_size);
+
+ if (!(data = ec_slave_mbox_prepare_send(slave, datagram,
+ 0x03, 3))) {
fsm->state = ec_fsm_coe_error;
return;
}
@@ -1354,7 +1358,7 @@
}
if (mbox_prot != 0x03) { // CoE
- EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
+ EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
fsm->state = ec_fsm_coe_error;
return;
}
--- a/master/master.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/master.c Thu Oct 26 16:29:26 2006 +0000
@@ -59,6 +59,7 @@
void ec_master_idle_run(void *);
void ec_master_eoe_run(unsigned long);
void ec_master_check_sdo(unsigned long);
+int ec_master_measure_bus_time(ec_master_t *);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
const char *, size_t);
@@ -109,28 +110,55 @@
EC_INFO("Initializing master %i.\n", index);
+ atomic_set(&master->available, 1);
master->index = index;
+
master->device = NULL;
init_MUTEX(&master->device_sem);
- atomic_set(&master->available, 1);
+
+ master->mode = EC_MASTER_MODE_ORPHANED;
+
INIT_LIST_HEAD(&master->slaves);
+ master->slave_count = 0;
+
INIT_LIST_HEAD(&master->datagram_queue);
+ master->datagram_index = 0;
+
INIT_LIST_HEAD(&master->domains);
- INIT_LIST_HEAD(&master->eoe_handlers);
+ master->debug_level = 0;
+
+ master->stats.timeouts = 0;
+ master->stats.corrupted = 0;
+ master->stats.skipped = 0;
+ master->stats.unmatched = 0;
+ master->stats.output_jiffies = 0;
+
INIT_WORK(&master->idle_work, ec_master_idle_run, (void *) master);
+
+ for (i = 0; i < HZ; i++) {
+ master->idle_cycle_times[i] = 0;
+ master->eoe_cycle_times[i] = 0;
+ }
+ master->idle_cycle_time_pos = 0;
+ master->eoe_cycle_time_pos = 0;
+
init_timer(&master->eoe_timer);
master->eoe_timer.function = ec_master_eoe_run;
master->eoe_timer.data = (unsigned long) master;
- master->internal_lock = SPIN_LOCK_UNLOCKED;
master->eoe_running = 0;
master->eoe_checked = 0;
- for (i = 0; i < HZ; i++) {
- master->idle_cycle_times[i] = 0;
- master->eoe_cycle_times[i] = 0;
- }
- master->idle_cycle_time_pos = 0;
- master->eoe_cycle_time_pos = 0;
- master->debug_level = 0;
+ INIT_LIST_HEAD(&master->eoe_handlers);
+
+ master->internal_lock = SPIN_LOCK_UNLOCKED;
+ master->request_cb = NULL;
+ master->release_cb = NULL;
+ master->cb_data = NULL;
+
+ master->eeprom_write_enable = 0;
+
+ master->sdo_request = NULL;
+ master->sdo_seq_user = 0;
+ master->sdo_seq_master = 0;
init_MUTEX(&master->sdo_sem);
init_timer(&master->sdo_timer);
master->sdo_timer.function = ec_master_check_sdo;
@@ -175,7 +203,6 @@
return -1;
}
- ec_master_reset(master);
return 0;
out_clear_eoe:
@@ -203,10 +230,17 @@
{
ec_master_t *master = container_of(kobj, ec_master_t, kobj);
ec_eoe_t *eoe, *next_eoe;
-
- EC_INFO("Clearing master %i...\n", master->index);
-
- ec_master_reset(master);
+ ec_datagram_t *datagram, *next_c;
+
+ ec_master_clear_slaves(master);
+
+ // empty datagram queue
+ list_for_each_entry_safe(datagram, next_c,
+ &master->datagram_queue, queue) {
+ datagram->state = EC_DATAGRAM_ERROR;
+ list_del_init(&datagram->queue);
+ }
+
ec_fsm_clear(&master->fsm);
destroy_workqueue(master->workqueue);
ec_xmldev_clear(&master->xmldev);
@@ -218,11 +252,6 @@
kfree(eoe);
}
- if (master->device) {
- ec_device_clear(master->device);
- kfree(master->device);
- }
-
EC_INFO("Master %i cleared.\n", master->index);
kfree(master);
@@ -231,57 +260,6 @@
/*****************************************************************************/
/**
- Resets the master.
- Note: This function has to be called, everytime ec_master_release() is
- called, to free the slave list, domains etc.
-*/
-
-void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram, *next_c;
- ec_domain_t *domain, *next_d;
-
- ec_master_eoe_stop(master);
- ec_master_idle_stop(master);
- ec_master_flush_sdo_requests(master);
- ec_master_clear_slaves(master);
-
- // empty datagram queue
- list_for_each_entry_safe(datagram, next_c,
- &master->datagram_queue, queue) {
- datagram->state = EC_DATAGRAM_ERROR;
- list_del_init(&datagram->queue);
- }
-
- // clear domains
- list_for_each_entry_safe(domain, next_d, &master->domains, list) {
- list_del(&domain->list);
- kobject_del(&domain->kobj);
- kobject_put(&domain->kobj);
- }
-
- master->datagram_index = 0;
-
- master->stats.timeouts = 0;
- master->stats.corrupted = 0;
- master->stats.skipped = 0;
- master->stats.unmatched = 0;
- master->stats.output_jiffies = 0;
-
- master->mode = EC_MASTER_MODE_ORPHANED;
-
- master->request_cb = NULL;
- master->release_cb = NULL;
- master->cb_data = NULL;
-
- master->eeprom_write_enable = 0;
-
- ec_fsm_reset(&master->fsm);
-}
-
-/*****************************************************************************/
-
-/**
Clears all slaves.
*/
@@ -294,6 +272,7 @@
kobject_del(&slave->kobj);
kobject_put(&slave->kobj);
}
+
master->slave_count = 0;
}
@@ -315,6 +294,123 @@
/*****************************************************************************/
/**
+*/
+
+int ec_master_enter_idle_mode(ec_master_t *master /**< EtherCAT master */)
+{
+ master->mode = EC_MASTER_MODE_IDLE;
+ queue_delayed_work(master->workqueue, &master->idle_work, 1);
+ return 0;
+}
+
+/*****************************************************************************/
+
+/**
+*/
+
+void ec_master_leave_idle_mode(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_master_eoe_stop(master);
+
+ master->mode = EC_MASTER_MODE_ORPHANED;
+ if (!cancel_delayed_work(&master->idle_work)) {
+ flush_workqueue(master->workqueue);
+ }
+
+ ec_master_flush_sdo_requests(master);
+}
+
+/*****************************************************************************/
+
+/**
+*/
+
+int ec_master_enter_operation_mode(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_slave_t *slave;
+ ec_datagram_t *datagram = &master->fsm.datagram;
+
+ master->mode = EC_MASTER_MODE_OPERATION;
+ if (!cancel_delayed_work(&master->idle_work)) {
+ flush_workqueue(master->workqueue);
+ }
+
+ // wait for FSM datagram
+ if (datagram->state == EC_DATAGRAM_SENT) {;
+ while (get_cycles() - datagram->cycles_sent
+ < (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000)) {}
+ ecrt_master_receive(master);
+ }
+
+ // finish running FSM
+ while (ec_fsm_exec(&master->fsm)) {
+ ec_master_sync_io(master);
+ }
+
+ if (!ec_fsm_success(&master->fsm)) {
+ EC_ERR("Master state machine failure!\n");
+ goto out_idle;
+ }
+
+ if (master->debug_level) {
+ if (ec_master_measure_bus_time(master)) {
+ EC_ERR("Bus time measuring failed!\n");
+ goto out_idle;
+ }
+ }
+
+ // set initial slave states
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (ec_slave_is_coupler(slave)) {
+ ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
+ }
+ else {
+ ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+ }
+ }
+
+ return 0;
+
+ out_idle:
+ master->mode = EC_MASTER_MODE_IDLE;
+ queue_delayed_work(master->workqueue, &master->idle_work, 1);
+ return -1;
+}
+
+/*****************************************************************************/
+
+/**
+*/
+
+void ec_master_leave_operation_mode(ec_master_t *master
+ /**< EtherCAT master */)
+{
+ ec_slave_t *slave;
+ ec_domain_t *domain, *next_d;
+
+ // clear domains
+ list_for_each_entry_safe(domain, next_d, &master->domains, list) {
+ ec_domain_dequeue_datagrams(domain);
+ list_del(&domain->list);
+ kobject_del(&domain->kobj);
+ kobject_put(&domain->kobj);
+ }
+
+ master->request_cb = NULL;
+ master->release_cb = NULL;
+ master->cb_data = NULL;
+
+ list_for_each_entry(slave, &master->slaves, list) {
+ ec_slave_reset(slave);
+ }
+
+ master->mode = EC_MASTER_MODE_IDLE;
+ queue_delayed_work(master->workqueue, &master->idle_work, 1);
+}
+
+/*****************************************************************************/
+
+/**
Places a datagram in the datagram queue.
*/
@@ -545,32 +641,6 @@
/*****************************************************************************/
/**
- Scans the EtherCAT bus for slaves.
- Creates a list of slave structures for further processing.
- \return 0 in case of success, else < 0
-*/
-
-int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
-{
- ec_fsm_t *fsm = &master->fsm;
-
- ec_fsm_startup(fsm); // init startup state machine
-
- while (ec_fsm_exec(fsm)) {
- ec_master_sync_io(master);
- }
-
- if (!ec_fsm_startup_success(fsm)) {
- ec_master_clear_slaves(master);
- return -1;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
Output statistics in cyclic mode.
This function outputs statistical data on demand, but not more often than
necessary. The output happens at most once a second.
@@ -607,52 +677,6 @@
/*****************************************************************************/
/**
- Starts the Idle mode.
-*/
-
-void ec_master_idle_start(ec_master_t *master /**< EtherCAT master */)
-{
- if (master->mode == EC_MASTER_MODE_IDLE) return;
-
- if (master->mode == EC_MASTER_MODE_OPERATION) {
- EC_ERR("ec_master_idle_start: Master already running!\n");
- return;
- }
-
- EC_INFO("Starting Idle mode.\n");
-
- master->mode = EC_MASTER_MODE_IDLE;
- ec_fsm_reset(&master->fsm);
- queue_delayed_work(master->workqueue, &master->idle_work, 1);
-}
-
-/*****************************************************************************/
-
-/**
- Stops the Idle mode.
-*/
-
-void ec_master_idle_stop(ec_master_t *master /**< EtherCAT master */)
-{
- if (master->mode != EC_MASTER_MODE_IDLE) return;
-
- ec_master_eoe_stop(master);
-
- EC_INFO("Stopping Idle mode.\n");
- master->mode = EC_MASTER_MODE_ORPHANED; // this is important for the
- // IDLE work function to not
- // queue itself again
-
- if (!cancel_delayed_work(&master->idle_work)) {
- flush_workqueue(master->workqueue);
- }
-
- ec_master_clear_slaves(master);
-}
-
-/*****************************************************************************/
-
-/**
Idle mode function.
*/
@@ -947,16 +971,16 @@
coupled++;
EC_INFO("Coupling device %s to slave %i.\n",
eoe->dev->name, slave->ring_position);
- if (eoe->opened) slave->requested_state = EC_SLAVE_STATE_OP;
- else slave->requested_state = EC_SLAVE_STATE_INIT;
- slave->error_flag = 0;
+ if (eoe->opened)
+ ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
+ else
+ ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
break;
}
if (!found) {
EC_WARN("No EoE handler for slave %i!\n", slave->ring_position);
- slave->requested_state = EC_SLAVE_STATE_INIT;
- slave->error_flag = 0;
+ ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
}
}
@@ -995,8 +1019,7 @@
// decouple all EoE handlers
list_for_each_entry(eoe, &master->eoe_handlers, list) {
if (eoe->slave) {
- eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
- eoe->slave->error_flag = 0;
+ ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_PREOP);
eoe->slave = NULL;
}
}
@@ -1253,27 +1276,23 @@
domain_offset += domain->data_size;
}
- // determine initial states.
- list_for_each_entry(slave, &master->slaves, list) {
- if (ec_slave_is_coupler(slave) || slave->registered) {
- slave->requested_state = EC_SLAVE_STATE_OP;
- }
- else {
- slave->requested_state = EC_SLAVE_STATE_PREOP;
- }
- }
-
- ec_fsm_configuration(fsm); // init configuration state machine
-
+ // execute master FSM until termination
while (ec_fsm_exec(fsm)) {
ec_master_sync_io(master);
}
- if (!ec_fsm_configuration_success(fsm)) {
+ if (!ec_fsm_success(fsm)) {
+ EC_ERR("Error in master state machine.\n");
return -1;
}
- ec_fsm_reset(&master->fsm); // prepare for operation state machine
+ // check, if all slaves have been configured
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (slave->error_flag || !slave->online) {
+ EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
+ return -1;
+ }
+ }
return 0;
}
@@ -1289,13 +1308,21 @@
{
ec_fsm_t *fsm = &master->fsm;
ec_slave_t *slave;
-
+ ec_datagram_t *datagram = &master->fsm.datagram;
+
+ // wait for FSM datagram
+ if (datagram->state == EC_DATAGRAM_SENT) {
+ while (get_cycles() - datagram->cycles_sent
+ < (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000)) {}
+ ecrt_master_receive(master);
+ }
+
+ // set states for all slaves
list_for_each_entry(slave, &master->slaves, list) {
- slave->requested_state = EC_SLAVE_STATE_INIT;
- }
-
- ec_fsm_configuration(fsm); // init configuration state machine
-
+ ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+ }
+
+ // execute master FSM to deactivate slaves
while (ec_fsm_exec(fsm)) {
ec_master_sync_io(master);
}
@@ -1416,7 +1443,7 @@
// queue datagrams of all domains
list_for_each_entry(domain, &master->domains, list)
- ec_domain_queue(domain);
+ ec_domain_queue_datagrams(domain);
ecrt_master_send(master);
@@ -1443,7 +1470,7 @@
// output statistics
ec_master_output_stats(master);
- // execute master state machine
+ // execute master state machine in a loop
ec_fsm_exec(&master->fsm);
}
--- a/master/master.h Wed Oct 25 16:53:17 2006 +0000
+++ b/master/master.h Thu Oct 26 16:29:26 2006 +0000
@@ -148,35 +148,31 @@
/*****************************************************************************/
-// master creation and deletion
+// master creation
int ec_master_init(ec_master_t *, unsigned int, unsigned int, dev_t);
-void ec_master_reset(ec_master_t *);
-// free run
-void ec_master_idle_start(ec_master_t *);
-void ec_master_idle_stop(ec_master_t *);
+// mode transitions
+int ec_master_enter_idle_mode(ec_master_t *);
+void ec_master_leave_idle_mode(ec_master_t *);
+int ec_master_enter_operation_mode(ec_master_t *);
+void ec_master_leave_operation_mode(ec_master_t *);
// EoE
void ec_master_eoe_start(ec_master_t *);
void ec_master_eoe_stop(ec_master_t *);
-// IO
+// datagram IO
void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t);
void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *);
-// slave management
-int ec_master_bus_scan(ec_master_t *);
-
// misc.
void ec_master_output_stats(ec_master_t *);
void ec_master_clear_slaves(ec_master_t *);
-int ec_master_measure_bus_time(ec_master_t *);
+void ec_master_calc_addressing(ec_master_t *);
-// other methods
+// helper functions
void ec_sync_config(const ec_sii_sync_t *, const ec_slave_t *, uint8_t *);
void ec_fmmu_config(const ec_fmmu_t *, const ec_slave_t *, uint8_t *);
-void ec_master_calc_addressing(ec_master_t *);
-void ec_master_flush_sdo_requests(ec_master_t *);
/*****************************************************************************/
--- a/master/module.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/module.c Thu Oct 26 16:29:26 2006 +0000
@@ -384,7 +384,8 @@
return -1;
}
- ec_master_idle_start(master);
+ ec_master_enter_idle_mode(master);
+
return 0;
}
@@ -402,8 +403,7 @@
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return;
- ec_master_idle_stop(master);
- ec_master_flush_sdo_requests(master);
+ ec_master_leave_idle_mode(master);
if (ec_device_close(master->device))
EC_WARN("Failed to close device!\n");
@@ -459,31 +459,19 @@
goto out_module_put;
}
- ec_master_reset(master); // also stops idle mode
- master->mode = EC_MASTER_MODE_OPERATION;
-
- if (ec_master_measure_bus_time(master)) {
- EC_ERR("Bus time measuring failed!\n");
- goto out_reset;
- }
-
- if (ec_master_bus_scan(master)) {
- EC_ERR("Bus scan failed!\n");
- goto out_reset;
+ if (ec_master_enter_operation_mode(master)) {
+ EC_ERR("Failed to enter OPERATION mode!\n");
+ goto out_module_put;
}
EC_INFO("Successfully requested master %i.\n", master_index);
return master;
- out_reset:
- ec_master_reset(master);
- ec_master_idle_start(master);
out_module_put:
module_put(master->device->module);
out_release:
atomic_inc(&master->available);
out_return:
- EC_ERR("Failed to request master %i.\n", master_index);
return NULL;
}
@@ -496,20 +484,12 @@
void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
{
- EC_INFO("Releasing master %i...\n", master->index);
-
- if (atomic_read(&master->available)) {
- EC_ERR("Master %i was never requested!\n", master->index);
- return;
- }
-
- ec_master_reset(master);
- ec_master_idle_start(master);
+ ec_master_leave_operation_mode(master);
module_put(master->device->module);
atomic_inc(&master->available);
- EC_INFO("Successfully released master %i.\n", master->index);
+ EC_INFO("Released master %i.\n", master->index);
return;
}
--- a/master/slave.c Wed Oct 25 16:53:17 2006 +0000
+++ b/master/slave.c Thu Oct 26 16:29:26 2006 +0000
@@ -136,7 +136,6 @@
slave->error_flag = 0;
slave->online = 1;
slave->fmmu_count = 0;
- slave->registered = 0;
slave->coupler_index = 0;
slave->coupler_subindex = 0xFFFF;
@@ -243,7 +242,7 @@
kobject_put(&sdo->kobj);
}
- // free SDO kobject
+ // free SDO kobject FIXME
if (slave->sdo_dictionary_fetched) kobject_del(&slave->sdo_kobj);
kobject_put(&slave->sdo_kobj);
@@ -263,6 +262,30 @@
/*****************************************************************************/
/**
+ Reset slave from operation mode.
+*/
+
+void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */)
+{
+ slave->fmmu_count = 0;
+}
+
+/*****************************************************************************/
+
+/**
+ */
+
+void ec_slave_request_state(ec_slave_t *slave, /**< ETherCAT slave */
+ ec_slave_state_t state /**< new state */
+ )
+{
+ slave->requested_state = state;
+ slave->error_flag = 0;
+}
+
+/*****************************************************************************/
+
+/**
Fetches data from a STRING category.
\return 0 in case of success, else < 0
*/
@@ -514,7 +537,6 @@
fmmu->logical_start_address = 0;
slave->fmmu_count++;
- slave->registered = 1;
return 0;
}
@@ -810,13 +832,13 @@
if (attr == &attr_state) {
char state[EC_STATE_STRING_SIZE];
if (!strcmp(buffer, "INIT\n"))
- slave->requested_state = EC_SLAVE_STATE_INIT;
+ ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
else if (!strcmp(buffer, "PREOP\n"))
- slave->requested_state = EC_SLAVE_STATE_PREOP;
+ ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
else if (!strcmp(buffer, "SAVEOP\n"))
- slave->requested_state = EC_SLAVE_STATE_SAVEOP;
+ ec_slave_request_state(slave, EC_SLAVE_STATE_SAVEOP);
else if (!strcmp(buffer, "OP\n"))
- slave->requested_state = EC_SLAVE_STATE_OP;
+ ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
else {
EC_ERR("Invalid slave state \"%s\"!\n", buffer);
return -EINVAL;
@@ -825,7 +847,6 @@
ec_state_string(slave->requested_state, state);
EC_INFO("Accepted new state %s for slave %i.\n",
state, slave->ring_position);
- slave->error_flag = 0;
return size;
}
else if (attr == &attr_eeprom) {
--- a/master/slave.h Wed Oct 25 16:53:17 2006 +0000
+++ b/master/slave.h Thu Oct 26 16:29:26 2006 +0000
@@ -197,10 +197,9 @@
ec_slave_state_t requested_state; /**< requested slave state */
ec_slave_state_t current_state; /**< current slave state */
- unsigned int configured; /**< the slave is configured by this master */
+ unsigned int configured; /**< the slave was configured by this master */
unsigned int error_flag; /**< stop processing after an error */
unsigned int online; /**< non-zero, if the slave responds. */
- uint8_t registered; /**< true, if slave has been registered */
// addresses
uint16_t ring_position; /**< ring position */
@@ -261,9 +260,13 @@
// slave construction/destruction
int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t);
+void ec_slave_reset(ec_slave_t *);
+
int ec_slave_prepare_fmmu(ec_slave_t *, const ec_domain_t *,
const ec_sii_sync_t *);
+void ec_slave_request_state(ec_slave_t *, ec_slave_state_t);
+
// SII categories
int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *);
void ec_slave_fetch_general(ec_slave_t *, const uint8_t *);