Store slaves in an array instead of a list.
--- a/TODO Thu Jun 12 09:19:06 2008 +0000
+++ b/TODO Thu Jun 12 09:32:25 2008 +0000
@@ -8,7 +8,6 @@
Version 1.4.0:
-* Slaves as array.
* Remove the end state of the master state machine.
* Supply new ec_master_state_t.
* Implement ecrt_slave_config_state().
--- a/master/fsm_master.c Thu Jun 12 09:19:06 2008 +0000
+++ b/master/fsm_master.c Thu Jun 12 09:32:25 2008 +0000
@@ -241,26 +241,26 @@
return;
}
+ if (!(master->slaves = (ec_slave_t *)
+ kmalloc(sizeof(ec_slave_t) * master->slave_count,
+ GFP_KERNEL))) {
+ EC_ERR("Failed to allocate slave memory!\n");
+ master->slave_count = 0; // FIXME avoid scanning!
+ master->scan_busy = 0;
+ wake_up_interruptible(&master->scan_queue);
+ fsm->state = ec_fsm_master_state_error;
+ 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 %u!\n", i);
- ec_master_clear_slaves(master);
- master->scan_busy = 0;
- wake_up_interruptible(&master->scan_queue);
- fsm->state = ec_fsm_master_state_error;
- return;
- }
-
+ slave = master->slaves + i;
ec_slave_init(slave, master, i, i + 1);
// do not force reconfiguration in operation mode to avoid
// unnecesssary process data interruptions
if (master->mode != EC_MASTER_MODE_OPERATION)
slave->force_config = 1;
-
- list_add_tail(&slave->list, &master->slaves);
}
// broadcast clear all station addresses
@@ -272,15 +272,15 @@
}
}
- if (list_empty(&master->slaves)) {
- fsm->state = ec_fsm_master_state_end;
- } else {
+ if (master->slave_count) {
// fetch state from first slave
- fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+ fsm->slave = master->slaves;
ec_datagram_fprd(fsm->datagram, fsm->slave->station_address,
0x0130, 2);
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_master_state_read_state;
+ } else {
+ fsm->state = ec_fsm_master_state_end;
}
}
@@ -338,12 +338,14 @@
)
{
ec_master_t *master = fsm->master;
+ ec_slave_t *slave;
+ ec_sdo_request_t *req;
ec_master_sdo_request_t *request;
- ec_sdo_request_t *req;
- ec_slave_t *slave;
// search for internal requests to be processed
- list_for_each_entry(slave, &master->slaves, list) {
+ for (slave = master->slaves;
+ slave < master->slaves + master->slave_count;
+ slave++) {
if (!slave->config)
continue;
list_for_each_entry(req, &slave->config->sdo_requests, list) {
@@ -437,7 +439,9 @@
return;
// check, if slaves have an Sdo dictionary to read out.
- list_for_each_entry(slave, &master->slaves, list) {
+ for (slave = master->slaves;
+ slave < master->slaves + master->slave_count;
+ slave++) {
if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
|| slave->sdo_dictionary_fetched
|| slave->current_state == EC_SLAVE_STATE_INIT
@@ -476,15 +480,14 @@
)
{
ec_master_t *master = fsm->master;
- ec_slave_t *slave = fsm->slave;
// is there another slave to query?
- if (slave->list.next != &master->slaves) {
+ fsm->slave++;
+ if (fsm->slave < master->slaves + master->slave_count) {
// fetch state from next slave
fsm->idle = 1;
- fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
- ec_datagram_fprd(fsm->datagram, fsm->slave->station_address,
- 0x0130, 2);
+ ec_datagram_fprd(fsm->datagram,
+ fsm->slave->station_address, 0x0130, 2);
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_master_state_read_state;
return;
@@ -654,7 +657,7 @@
EC_INFO("Scanning bus.\n");
// begin scanning of slaves
- fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+ fsm->slave = master->slaves;
fsm->state = ec_fsm_master_state_scan_slave;
ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
@@ -694,8 +697,8 @@
#endif
// another slave to fetch?
- if (slave->list.next != &master->slaves) {
- fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
+ fsm->slave++;
+ if (slave < master->slaves + master->slave_count) {
ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
return;
--- a/master/fsm_slave_scan.c Thu Jun 12 09:19:06 2008 +0000
+++ b/master/fsm_slave_scan.c Thu Jun 12 09:32:25 2008 +0000
@@ -338,10 +338,10 @@
}
dl_status = EC_READ_U16(datagram->data);
- for (i = 0; i < 4; i++) {
- slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
- slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
- slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
+ for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+ slave->ports[i].dl_link = dl_status & (1 << (4 + i)) ? 1 : 0;
+ slave->ports[i].dl_loop = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
+ slave->ports[i].dl_signal = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
}
// Start fetching SII size
--- a/master/globals.h Thu Jun 12 09:19:06 2008 +0000
+++ b/master/globals.h Thu Jun 12 09:32:25 2008 +0000
@@ -99,6 +99,9 @@
/** Size of an FMMU configuration page. */
#define EC_FMMU_PAGE_SIZE 16
+/** Maximum number of slave ports. */
+#define EC_SLAVE_MAX_PORTS 4
+
/** Slave state mask.
*
* Apply this mask to a slave state byte to get the slave state without
--- a/master/master.c Thu Jun 12 09:19:06 2008 +0000
+++ b/master/master.c Thu Jun 12 09:32:25 2008 +0000
@@ -92,7 +92,7 @@
master->injection_seq_fsm = 0;
master->injection_seq_rt = 0;
- INIT_LIST_HEAD(&master->slaves);
+ master->slaves = NULL;
master->slave_count = 0;
INIT_LIST_HEAD(&master->configs);
@@ -245,15 +245,20 @@
*/
void ec_master_clear_slaves(ec_master_t *master)
{
- ec_slave_t *slave, *next;
-
- list_for_each_entry_safe(slave, next, &master->slaves, list) {
- list_del(&slave->list);
+ ec_slave_t *slave;
+
+ for (slave = master->slaves;
+ slave < master->slaves + master->slave_count;
+ slave++) {
ec_slave_clear(slave);
kfree(slave);
}
- master->slave_count = 0;
+ if (master->slave_count) {
+ kfree(master->slaves);
+ master->slaves = NULL;
+ master->slave_count = 0;
+ }
}
/*****************************************************************************/
@@ -413,7 +418,9 @@
}
// set states for all slaves
- list_for_each_entry(slave, &master->slaves, list) {
+ for (slave = master->slaves;
+ slave < master->slaves + master->slave_count;
+ slave++) {
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
}
#ifdef EC_EOE
@@ -466,7 +473,9 @@
ec_master_clear_slave_configs(master);
// set states for all slaves
- list_for_each_entry(slave, &master->slaves, list) {
+ for (slave = master->slaves;
+ slave < master->slaves + master->slave_count;
+ slave++) {
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
}
#ifdef EC_EOE
@@ -1013,23 +1022,25 @@
uint16_t position /**< Slave position. */
)
{
- ec_slave_t *slave;
- unsigned int alias_found = 0, relative_position = 0;
-
- list_for_each_entry(slave, &master->slaves, list) {
- if (!alias_found) {
- if (alias && slave->sii.alias != alias)
+ ec_slave_t *slave = master->slaves;
+
+ if (alias) {
+ // find slave with the given alias
+ for (; slave < master->slaves + master->slave_count;
+ slave++) {
+ if (slave->sii.alias != alias)
continue;
- alias_found = 1;
- relative_position = 0;
}
- if (relative_position == position) {
- return slave;
- }
- relative_position++;
+ if (slave == master->slaves + master->slave_count)
+ return NULL;
}
- return NULL;
+ slave += position;
+ if (slave < master->slaves + master->slave_count) {
+ return slave;
+ } else {
+ return NULL;
+ }
}
/*****************************************************************************/
--- a/master/master.h Thu Jun 12 09:19:06 2008 +0000
+++ b/master/master.h Thu Jun 12 09:32:25 2008 +0000
@@ -99,8 +99,8 @@
unsigned int injection_seq_rt; /**< datagram injection sequence number
for the realtime side */
- struct list_head slaves; /**< list of slaves on the bus */
- unsigned int slave_count; /**< number of slaves on the bus */
+ ec_slave_t *slaves; /**< Array of slaves on the bus. */
+ unsigned int slave_count; /**< Number of slaves on the bus. */
struct list_head configs; /**< Bus configuration list. */
unsigned int configs_attached; /**< Slave configurations were attached. */
--- a/master/slave.c Thu Jun 12 09:19:06 2008 +0000
+++ b/master/slave.c Thu Jun 12 09:32:25 2008 +0000
@@ -72,11 +72,10 @@
{
unsigned int i;
+ slave->master = master;
slave->ring_position = ring_position;
slave->station_address = station_address;
- slave->master = master;
-
slave->config = NULL;
slave->requested_state = EC_SLAVE_STATE_PREOP;
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
@@ -88,6 +87,13 @@
slave->base_build = 0;
slave->base_fmmu_count = 0;
+ for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+ slave->ports[i].dl_link = 0;
+ slave->ports[i].dl_loop = 0;
+ slave->ports[i].dl_signal = 0;
+ slave->sii.physical_layer[i] = 0xFF;
+ }
+
slave->sii_words = NULL;
slave->sii_nwords = 0;
@@ -123,13 +129,6 @@
slave->sdo_dictionary_fetched = 0;
slave->jiffies_preop = 0;
-
- for (i = 0; i < 4; i++) {
- slave->dl_link[i] = 0;
- slave->dl_loop[i] = 0;
- slave->dl_signal[i] = 0;
- slave->sii.physical_layer[i] = 0xFF;
- }
}
/*****************************************************************************/
--- a/master/slave.h Thu Jun 12 09:19:06 2008 +0000
+++ b/master/slave.h Thu Jun 12 09:32:25 2008 +0000
@@ -71,39 +71,48 @@
// Strings
char **strings; /**< Strings in SII categories. */
- unsigned int string_count; /**< number of SII strings */
+ unsigned int string_count; /**< Number of SII strings. */
// General
unsigned int has_general; /**< General category present. */
- char *group; /**< slave group acc. to SII */
- char *image; /**< slave image name acc. to SII */
- char *order; /**< slave order number acc. to SII */
- char *name; /**< slave name acc. to SII */
- uint8_t physical_layer[4]; /**< port media */
+ char *group; /**< Group name. */
+ char *image; /**< Image name. */
+ char *order; /**< Order number. */
+ char *name; /**< Slave name. */
+ uint8_t physical_layer[EC_SLAVE_MAX_PORTS]; /**< Port media. */
ec_sii_coe_details_t coe_details; /**< CoE detail flags. */
ec_sii_general_flags_t general_flags; /**< General flags. */
- int16_t current_on_ebus; /**< power consumption */
+ int16_t current_on_ebus; /**< Power consumption in mA. */
// SyncM
- ec_sync_t *syncs; /**< SII SYNC MANAGER categories */
- unsigned int sync_count; /**< number of sync managers in SII */
+ ec_sync_t *syncs; /**< SYNC MANAGER categories. */
+ unsigned int sync_count; /**< Number of sync managers. */
// [RT]XPDO
- struct list_head pdos; /**< SII [RT]XPDO categories */
+ struct list_head pdos; /**< SII [RT]XPDO categories. */
} ec_sii_t;
/*****************************************************************************/
+/** EtherCAT slave port information.
+ */
+typedef struct {
+ uint8_t dl_link; /**< Link detected. */
+ uint8_t dl_loop; /**< Loop closed. */
+ uint8_t dl_signal; /**< Detected signal on RX port. */
+} ec_slave_port_t;
+
+/*****************************************************************************/
+
/** EtherCAT slave.
*/
struct ec_slave
{
- struct list_head list; /**< list item */
- ec_master_t *master; /**< master owning the slave */
+ ec_master_t *master; /**< Master owning the slave. */
// addresses
- uint16_t ring_position; /**< ring position */
- uint16_t station_address; /**< configured station address */
+ uint16_t ring_position; /**< Ring position. */
+ uint16_t station_address; /**< Configured station address. */
// configuration
ec_slave_config_t *config; /**< Current configuration. */
@@ -113,26 +122,24 @@
unsigned int force_config; /**< Force (re-)configuration. */
// base data
- uint8_t base_type; /**< slave type */
- uint8_t base_revision; /**< revision */
- uint16_t base_build; /**< build number */
- uint16_t base_fmmu_count; /**< number of supported FMMUs */
+ uint8_t base_type; /**< Slave type. */
+ uint8_t base_revision; /**< Revision. */
+ uint16_t base_build; /**< Build number. */
+ uint16_t base_fmmu_count; /**< Number of supported FMMUs. */
// data link status
- uint8_t dl_link[4]; /**< link detected */
- uint8_t dl_loop[4]; /**< loop closed */
- uint8_t dl_signal[4]; /**< detected signal on RX port */
+ ec_slave_port_t ports[EC_SLAVE_MAX_PORTS];
// SII
uint16_t *sii_words; /**< Complete SII image. */
size_t sii_nwords; /**< Size of the SII contents in words. */
- // slave information interface
- ec_sii_t sii; /**< SII data. */
+ // Slave information interface
+ ec_sii_t sii; /**< Extracted SII data. */
struct list_head sdo_dictionary; /**< Sdo dictionary list */
- uint8_t sdo_dictionary_fetched; /**< dictionary has been fetched */
- unsigned long jiffies_preop; /**< time, the slave went to PREOP */
+ uint8_t sdo_dictionary_fetched; /**< Dictionary has been fetched. */
+ unsigned long jiffies_preop; /**< Time, the slave went to PREOP. */
};
/*****************************************************************************/