# HG changeset patch # User Florian Pose # Date 1213263145 0 # Node ID 5746fdd1ca2edc5c591f58e393bd0c583e22bbdd # Parent 14307580deb6507005ebdab8731a08ccaee8fcf3 Store slaves in an array instead of a list. diff -r 14307580deb6 -r 5746fdd1ca2e TODO --- 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(). diff -r 14307580deb6 -r 5746fdd1ca2e master/fsm_master.c --- 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; diff -r 14307580deb6 -r 5746fdd1ca2e master/fsm_slave_scan.c --- 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 diff -r 14307580deb6 -r 5746fdd1ca2e master/globals.h --- 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 diff -r 14307580deb6 -r 5746fdd1ca2e master/master.c --- 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; + } } /*****************************************************************************/ diff -r 14307580deb6 -r 5746fdd1ca2e master/master.h --- 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. */ diff -r 14307580deb6 -r 5746fdd1ca2e master/slave.c --- 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; - } } /*****************************************************************************/ diff -r 14307580deb6 -r 5746fdd1ca2e master/slave.h --- 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. */ }; /*****************************************************************************/