# HG changeset patch # User Florian Pose # Date 1333748105 -7200 # Node ID e898451c054aa8fb814bd2fcc3e04380c9aeb9fc # Parent 593272e5a169f9dc04844278781b612d151d4da2 Slave scanning and configuration on all links. diff -r 593272e5a169 -r e898451c054a master/cdev.c --- a/master/cdev.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/cdev.c Fri Apr 06 23:35:05 2012 +0200 @@ -294,6 +294,7 @@ return -EINVAL; } + data.device_index = slave->device_index; data.vendor_id = slave->sii.vendor_id; data.product_code = slave->sii.product_code; data.revision_number = slave->sii.revision_number; diff -r 593272e5a169 -r e898451c054a master/datagram_pair.c --- a/master/datagram_pair.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/datagram_pair.c Fri Apr 06 23:35:05 2012 +0200 @@ -52,17 +52,18 @@ const unsigned int used[] /**< input/output use count. */ ) { - unsigned int dev_idx; + ec_device_index_t dev_idx; int ret; INIT_LIST_HEAD(&pair->list); pair->domain = domain; - for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) { + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { ec_datagram_init(&pair->datagrams[dev_idx]); snprintf(pair->datagrams[dev_idx].name, EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index, - logical_offset, dev_idx ? "backup" : "main"); + logical_offset, ec_device_names[dev_idx]); + pair->datagrams[dev_idx].device_index = dev_idx; } pair->expected_working_counter = 0U; diff -r 593272e5a169 -r e898451c054a master/domain.c --- a/master/domain.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/domain.c Fri Apr 06 23:35:05 2012 +0200 @@ -585,7 +585,7 @@ void ecrt_domain_queue(ec_domain_t *domain) { ec_datagram_pair_t *datagram_pair; - unsigned int dev_idx; + ec_device_index_t dev_idx; list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) { @@ -599,9 +599,9 @@ datagram_pair->datagrams[EC_DEVICE_MAIN].data, datagram_pair->datagrams[EC_DEVICE_MAIN].data_size); - for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) { + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { ec_master_queue_datagram(domain->master, - &datagram_pair->datagrams[dev_idx], dev_idx); + &datagram_pair->datagrams[dev_idx]); } } } diff -r 593272e5a169 -r e898451c054a master/fsm_master.c --- a/master/fsm_master.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/fsm_master.c Fri Apr 06 23:35:05 2012 +0200 @@ -67,6 +67,7 @@ void ec_fsm_master_state_sdo_request(ec_fsm_master_t *); void ec_fsm_master_state_reg_request(ec_fsm_master_t *); +void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *); void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *); /*****************************************************************************/ @@ -79,14 +80,19 @@ ec_datagram_t *datagram /**< Datagram object to use. */ ) { + ec_device_index_t dev_idx; + fsm->master = master; fsm->datagram = datagram; fsm->state = ec_fsm_master_state_start; fsm->idle = 0; - fsm->link_state = 0; - fsm->slaves_responding = 0; + fsm->dev_idx = EC_DEVICE_MAIN; + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { + fsm->link_state[dev_idx] = 0; + fsm->slaves_responding[dev_idx] = 0; + fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN; + } fsm->rescan_required = 0; - fsm->slave_states = EC_SLAVE_STATE_UNKNOWN; // init sub-state-machines ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram); @@ -159,6 +165,7 @@ ec_fsm_master_t *fsm /**< Master state machine. */ ) { + fsm->dev_idx = EC_DEVICE_MAIN; fsm->state = ec_fsm_master_state_start; fsm->state(fsm); // execute immediately } @@ -178,6 +185,7 @@ fsm->idle = 1; ec_datagram_brd(fsm->datagram, 0x0130, 2); ec_datagram_zero(fsm->datagram); + fsm->datagram->device_index = fsm->dev_idx; fsm->state = ec_fsm_master_state_broadcast; } @@ -196,48 +204,58 @@ ec_slave_t *slave; ec_master_t *master = fsm->master; - if (datagram->state == EC_DATAGRAM_TIMED_OUT) - return; // always retry - // bus topology change? - if (datagram->working_counter != fsm->slaves_responding) { + if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) { fsm->rescan_required = 1; - fsm->slaves_responding = datagram->working_counter; - EC_MASTER_INFO(master, "%u slave(s) responding.\n", - fsm->slaves_responding); - } - - if (fsm->link_state && !master->devices[EC_DEVICE_MAIN].link_state) { - // link went down + fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter; + EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n", + fsm->slaves_responding[fsm->dev_idx], + ec_device_names[fsm->dev_idx]); + } + + if (fsm->link_state[fsm->dev_idx] && + !master->devices[fsm->dev_idx].link_state) { + ec_device_index_t dev_idx; + EC_MASTER_DBG(master, 1, "Master state machine detected " - "link down. Clearing slave list.\n"); + "link down on %s device. Clearing slave list.\n", + ec_device_names[fsm->dev_idx]); #ifdef EC_EOE ec_master_eoe_stop(master); ec_master_clear_eoe_handlers(master); #endif ec_master_clear_slaves(master); - fsm->slave_states = 0x00; - fsm->slaves_responding = 0; /* reset to trigger rescan on next link - up. */ - } - fsm->link_state = master->devices[EC_DEVICE_MAIN].link_state; - - if (datagram->state != EC_DATAGRAM_RECEIVED) { - ec_fsm_master_restart(fsm); - return; - } - - if (fsm->slaves_responding) { + + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { + fsm->slave_states[dev_idx] = 0x00; + fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on + next link up. */ + } + } + fsm->link_state[fsm->dev_idx] = master->devices[fsm->dev_idx].link_state; + + if (datagram->state == EC_DATAGRAM_RECEIVED && + fsm->slaves_responding[fsm->dev_idx]) { uint8_t states = EC_READ_U8(datagram->data); - if (states != fsm->slave_states) { // slave states changed? + if (states != fsm->slave_states[fsm->dev_idx]) { + // slave states changed char state_str[EC_STATE_STRING_SIZE]; - fsm->slave_states = states; - ec_state_string(fsm->slave_states, state_str, 1); - EC_MASTER_INFO(master, "Slave states: %s.\n", state_str); + fsm->slave_states[fsm->dev_idx] = states; + ec_state_string(states, state_str, 1); + EC_MASTER_INFO(master, "Slave states on %s device: %s.\n", + ec_device_names[fsm->dev_idx], state_str); } } else { - fsm->slave_states = 0x00; + fsm->slave_states[fsm->dev_idx] = 0x00; + } + + fsm->dev_idx++; + if (fsm->dev_idx < EC_NUM_DEVICES) { + // check number of responding slaves on next device + fsm->state = ec_fsm_master_state_start; + fsm->state(fsm); // execute immediately + return; } if (fsm->rescan_required) { @@ -245,6 +263,9 @@ if (!master->allow_scan) { up(&master->scan_sem); } else { + unsigned int count = 0, next_dev_slave, ring_position; + ec_device_index_t dev_idx; + master->scan_busy = 1; up(&master->scan_sem); @@ -259,9 +280,12 @@ #endif ec_master_clear_slaves(master); - master->slave_count = fsm->slaves_responding; - - if (!master->slave_count) { + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; + dev_idx++) { + count += fsm->slaves_responding[dev_idx]; + } + + if (!count) { // no slaves present -> finish state machine. master->scan_busy = 0; wake_up_interruptible(&master->scan_queue); @@ -269,12 +293,11 @@ return; } - size = sizeof(ec_slave_t) * master->slave_count; + size = sizeof(ec_slave_t) * count; if (!(master->slaves = (ec_slave_t *) kmalloc(size, GFP_KERNEL))) { EC_MASTER_ERR(master, "Failed to allocate %u bytes" " of slave memory!\n", size); - master->slave_count = 0; // TODO avoid retrying scan! master->scan_busy = 0; wake_up_interruptible(&master->scan_queue); ec_fsm_master_restart(fsm); @@ -282,21 +305,35 @@ } // init slaves - for (i = 0; i < master->slave_count; i++) { + dev_idx = EC_DEVICE_MAIN; + next_dev_slave = fsm->slaves_responding[dev_idx]; + ring_position = 0; + for (i = 0; i < count; i++, ring_position++) { slave = master->slaves + i; - ec_slave_init(slave, master, i, i + 1); + while (i >= next_dev_slave) { + dev_idx++; + next_dev_slave += fsm->slaves_responding[dev_idx]; + ring_position = 0; + } + + ec_slave_init(slave, master, dev_idx, ring_position, i + 1); // do not force reconfiguration in operation phase to avoid // unnecesssary process data interruptions - if (master->phase != EC_OPERATION) + if (master->phase != EC_OPERATION) { slave->force_config = 1; + } } - - // broadcast clear all station addresses - ec_datagram_bwr(datagram, 0x0010, 2); - EC_WRITE_U16(datagram->data, 0x0000); - fsm->retries = EC_FSM_RETRIES; - fsm->state = ec_fsm_master_state_clear_addresses; + master->slave_count = count; + + /* start with first device with slaves responding; at least one + * has responding slaves, otherwise count would be zero. */ + fsm->dev_idx = EC_DEVICE_MAIN; + while (!fsm->slaves_responding[fsm->dev_idx]) { + fsm->dev_idx++; + } + + ec_fsm_master_enter_clear_addresses(fsm); return; } } @@ -318,6 +355,7 @@ ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); ec_datagram_zero(datagram); + fsm->datagram->device_index = fsm->slave->device_index; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_read_state; } @@ -411,6 +449,7 @@ request->offset, request->length); memcpy(fsm->datagram->data, request->data, request->length); } + fsm->datagram->device_index = request->slave->device_index; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_reg_request; return 1; @@ -518,6 +557,7 @@ fsm->state = ec_fsm_master_state_sdo_dictionary; ec_fsm_coe_dictionary(&fsm->fsm_coe, slave); ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately + fsm->datagram->device_index = fsm->slave->device_index; return; } @@ -550,6 +590,7 @@ ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2); ec_datagram_zero(fsm->datagram); + fsm->datagram->device_index = fsm->slave->device_index; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_read_state; return; @@ -607,6 +648,7 @@ fsm->state = ec_fsm_master_state_configure_slave; ec_fsm_slave_config_start(&fsm->fsm_slave_config, slave); fsm->state(fsm); // execute immediately + fsm->datagram->device_index = fsm->slave->device_index; return; } @@ -680,8 +722,9 @@ { ec_slave_t *slave = fsm->slave; - if (ec_fsm_change_exec(&fsm->fsm_change)) - return; + if (ec_fsm_change_exec(&fsm->fsm_change)) { + return; + } if (!ec_fsm_change_success(&fsm->fsm_change)) { fsm->slave->error_flag = 1; @@ -693,6 +736,22 @@ /*****************************************************************************/ +/** Start clearing slave addresses. + */ +void ec_fsm_master_enter_clear_addresses( + ec_fsm_master_t *fsm /**< Master state machine. */ + ) +{ + // broadcast clear all station addresses + ec_datagram_bwr(fsm->datagram, 0x0010, 2); + EC_WRITE_U16(fsm->datagram->data, 0x0000); + fsm->datagram->device_index = fsm->dev_idx; + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_master_state_clear_addresses; +} + +/*****************************************************************************/ + /** Master state: CLEAR ADDRESSES. */ void ec_fsm_master_state_clear_addresses( @@ -702,12 +761,14 @@ ec_master_t *master = fsm->master; ec_datagram_t *datagram = fsm->datagram; - if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) - return; + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { + return; + } if (datagram->state != EC_DATAGRAM_RECEIVED) { EC_MASTER_ERR(master, "Failed to receive address" - " clearing datagram: "); + " clearing datagram on %s link: ", + ec_device_names[fsm->dev_idx]); ec_datagram_print_state(datagram); master->scan_busy = 0; wake_up_interruptible(&master->scan_queue); @@ -715,17 +776,20 @@ return; } - if (datagram->working_counter != master->slave_count) { - EC_MASTER_WARN(master, "Failed to clear all station addresses:" + if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) { + EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:" " Cleared %u of %u", - datagram->working_counter, master->slave_count); + ec_device_names[fsm->dev_idx], datagram->working_counter, + fsm->slaves_responding[fsm->dev_idx]); } EC_MASTER_DBG(master, 1, "Sending broadcast-write" - " to measure transmission delays.\n"); + " to measure transmission delays on %s link.\n", + ec_device_names[fsm->dev_idx]); ec_datagram_bwr(datagram, 0x0900, 1); ec_datagram_zero(datagram); + fsm->datagram->device_index = fsm->dev_idx; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_dc_measure_delays; } @@ -745,7 +809,8 @@ return; if (datagram->state != EC_DATAGRAM_RECEIVED) { - EC_MASTER_ERR(master, "Failed to receive delay measuring datagram: "); + EC_MASTER_ERR(master, "Failed to receive delay measuring datagram" + " on %s link: ", ec_device_names[fsm->dev_idx]); ec_datagram_print_state(datagram); master->scan_busy = 0; wake_up_interruptible(&master->scan_queue); @@ -753,16 +818,30 @@ return; } - EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring.\n", - datagram->working_counter); + EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring" + " on %s link.\n", + datagram->working_counter, ec_device_names[fsm->dev_idx]); + + do { + fsm->dev_idx++; + } while (fsm->dev_idx < EC_NUM_DEVICES && + !fsm->slaves_responding[fsm->dev_idx]); + if (fsm->dev_idx < EC_NUM_DEVICES) { + ec_fsm_master_enter_clear_addresses(fsm); + return; + } EC_MASTER_INFO(master, "Scanning bus.\n"); // begin scanning of slaves fsm->slave = master->slaves; + EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n", + fsm->slave->ring_position, + ec_device_names[fsm->slave->device_index]); 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 + fsm->datagram->device_index = fsm->slave->device_index; } /*****************************************************************************/ @@ -779,8 +858,10 @@ #ifdef EC_EOE ec_slave_t *slave = fsm->slave; #endif - if (ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan)) - return; + + if (ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan)) { + return; + } #ifdef EC_EOE if (slave->sii.mailbox_protocols & EC_MBOX_EOE) { @@ -800,8 +881,12 @@ // another slave to fetch? fsm->slave++; if (fsm->slave < master->slaves + master->slave_count) { + EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n", + fsm->slave->ring_position, + ec_device_names[fsm->slave->device_index]); ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave); ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately + fsm->datagram->device_index = fsm->slave->device_index; return; } @@ -843,8 +928,9 @@ { ec_master_t *master = fsm->master; - if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config)) - return; + if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config)) { + return; + } fsm->slave->force_config = 0; @@ -886,6 +972,7 @@ // and time offset (0x0920, 64 bit) ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, 0x0910, 24); + fsm->datagram->device_index = fsm->slave->device_index; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_dc_read_offset; return; @@ -1031,6 +1118,7 @@ ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12); EC_WRITE_U64(datagram->data, new_offset); EC_WRITE_U32(datagram->data + 8, slave->transmission_delay); + fsm->datagram->device_index = slave->device_index; fsm->retries = EC_FSM_RETRIES; fsm->state = ec_fsm_master_state_dc_write_offset; } @@ -1135,7 +1223,9 @@ ec_slave_t *slave = fsm->slave; ec_master_t *master = fsm->master; - if (ec_fsm_coe_exec(&fsm->fsm_coe)) return; + if (ec_fsm_coe_exec(&fsm->fsm_coe)) { + return; + } if (!ec_fsm_coe_success(&fsm->fsm_coe)) { ec_fsm_master_restart(fsm); diff -r 593272e5a169 -r e898451c054a master/fsm_master.h --- a/master/fsm_master.h Fri Apr 06 23:30:35 2012 +0200 +++ b/master/fsm_master.h Fri Apr 06 23:35:05 2012 +0200 @@ -115,12 +115,19 @@ unsigned int retries; /**< retries on datagram timeout. */ void (*state)(ec_fsm_master_t *); /**< master state function */ + ec_device_index_t dev_idx; /**< Current device index (for scanning etc.). + */ int idle; /**< state machine is in idle phase */ unsigned long scan_jiffies; /**< beginning of slave scanning */ - uint8_t link_state; /**< Last main device link state. */ - unsigned int slaves_responding; /**< number of responding slaves */ + uint8_t link_state[EC_NUM_DEVICES]; /**< Last link state for every device. + */ + unsigned int slaves_responding[EC_NUM_DEVICES]; /**< Number of responding + slaves for every device. + */ unsigned int rescan_required; /**< A bus rescan is required. */ - ec_slave_state_t slave_states; /**< states of responding slaves */ + ec_slave_state_t slave_states[EC_NUM_DEVICES]; /**< AL states of + responding slaves for + every device. */ ec_slave_t *slave; /**< current slave */ ec_sii_write_request_t *sii_request; /**< SII write request */ off_t sii_index; /**< index to SII write request data */ diff -r 593272e5a169 -r e898451c054a master/fsm_slave.c --- a/master/fsm_slave.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/fsm_slave.c Fri Apr 06 23:35:05 2012 +0200 @@ -206,8 +206,7 @@ fsm->state = ec_fsm_slave_state_sdo_request; ec_fsm_coe_transfer(&fsm->fsm_coe, slave, &request->req); ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return 1; } return 0; @@ -225,8 +224,7 @@ ec_sdo_request_t *request = fsm->sdo_request; if (ec_fsm_coe_exec(&fsm->fsm_coe)) { - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return; } if (!ec_fsm_coe_success(&fsm->fsm_coe)) { @@ -281,8 +279,7 @@ fsm->state = ec_fsm_slave_state_foe_request; ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req); ec_fsm_foe_exec(&fsm->fsm_foe); - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return 1; } return 0; @@ -300,8 +297,7 @@ ec_foe_request_t *request = fsm->foe_request; if (ec_fsm_foe_exec(&fsm->fsm_foe)) { - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return; } @@ -369,8 +365,7 @@ fsm->state = ec_fsm_slave_state_soe_request; ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &req->req); ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return 1; } return 0; @@ -388,8 +383,7 @@ ec_soe_request_t *request = fsm->soe_request; if (ec_fsm_soe_exec(&fsm->fsm_soe)) { - ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); return; } diff -r 593272e5a169 -r e898451c054a master/fsm_slave_config.c --- a/master/fsm_slave_config.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/fsm_slave_config.c Fri Apr 06 23:35:05 2012 +0200 @@ -744,7 +744,7 @@ ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy); ec_fsm_soe_exec(fsm_soe); // execute immediately ec_master_queue_external_datagram(slave->master, - fsm_soe->datagram, EC_DEVICE_MAIN); + fsm_soe->datagram); return; } } @@ -765,8 +765,7 @@ ec_fsm_soe_t *fsm_soe = &slave->fsm.fsm_soe; if (ec_fsm_soe_exec(fsm_soe)) { - ec_master_queue_external_datagram(slave->master, fsm_soe->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(slave->master, fsm_soe->datagram); return; } @@ -792,7 +791,7 @@ ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy); ec_fsm_soe_exec(fsm_soe); // execute immediately ec_master_queue_external_datagram(slave->master, - fsm_soe->datagram, EC_DEVICE_MAIN); + fsm_soe->datagram); return; } } @@ -1474,7 +1473,7 @@ ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy); ec_fsm_soe_exec(fsm_soe); // execute immediately ec_master_queue_external_datagram(slave->master, - fsm_soe->datagram, EC_DEVICE_MAIN); + fsm_soe->datagram); return; } } @@ -1495,8 +1494,7 @@ ec_fsm_soe_t *fsm_soe = &slave->fsm.fsm_soe; if (ec_fsm_soe_exec(fsm_soe)) { - ec_master_queue_external_datagram(slave->master, fsm_soe->datagram, - EC_DEVICE_MAIN); + ec_master_queue_external_datagram(slave->master, fsm_soe->datagram); return; } @@ -1522,7 +1520,7 @@ ec_fsm_soe_transfer(fsm_soe, fsm->slave, &fsm->soe_request_copy); ec_fsm_soe_exec(fsm_soe); // execute immediately ec_master_queue_external_datagram(slave->master, - fsm_soe->datagram, EC_DEVICE_MAIN); + fsm_soe->datagram); return; } } diff -r 593272e5a169 -r e898451c054a master/globals.h --- a/master/globals.h Fri Apr 06 23:30:35 2012 +0200 +++ b/master/globals.h Fri Apr 06 23:35:05 2012 +0200 @@ -204,6 +204,8 @@ EC_NUM_DEVICES /**< Number of devices. */ } ec_device_index_t; +extern const char *ec_device_names[EC_NUM_DEVICES]; + /*****************************************************************************/ /** Convenience macro for printing EtherCAT-specific information to syslog. diff -r 593272e5a169 -r e898451c054a master/ioctl.h --- a/master/ioctl.h Fri Apr 06 23:30:35 2012 +0200 +++ b/master/ioctl.h Fri Apr 06 23:35:05 2012 +0200 @@ -56,7 +56,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 16 +#define EC_IOCTL_VERSION_MAGIC 17 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -195,6 +195,7 @@ uint16_t position; // outputs + unsigned int device_index; uint32_t vendor_id; uint32_t product_code; uint32_t revision_number; diff -r 593272e5a169 -r e898451c054a master/master.c --- a/master/master.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/master.c Fri Apr 06 23:35:05 2012 +0200 @@ -554,6 +554,7 @@ ) { int ret; + ec_device_index_t dev_idx; EC_MASTER_DBG(master, 1, "ORPHANED -> IDLE.\n"); @@ -564,7 +565,9 @@ master->phase = EC_IDLE; // reset number of responding slaves to trigger scanning - master->fsm.slaves_responding = 0; + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { + master->fsm.slaves_responding[dev_idx] = 0; + } ret = ec_master_thread_start(master, ec_master_idle_thread, "EtherCAT-IDLE"); @@ -727,8 +730,7 @@ datagram->cycles_sent = 0; #endif datagram->jiffies_sent = 0; - ec_master_queue_datagram(master, datagram, - datagram->device_index); + ec_master_queue_datagram(master, datagram); } else { if (datagram->data_size > master->max_queue_size) { list_del_init(&datagram->queue); @@ -800,8 +802,7 @@ */ void ec_master_queue_external_datagram( ec_master_t *master, /**< EtherCAT master */ - ec_datagram_t *datagram, /**< datagram */ - ec_device_index_t device_index /**< Device index. */ + ec_datagram_t *datagram /**< datagram */ ) { ec_datagram_t *queued_datagram; @@ -824,7 +825,6 @@ list_add_tail(&datagram->queue, &master->external_datagram_queue); datagram->state = EC_DATAGRAM_QUEUED; - datagram->device_index = device_index; #ifdef EC_HAVE_CYCLES datagram->cycles_sent = get_cycles(); #endif @@ -840,8 +840,7 @@ */ void ec_master_queue_datagram( ec_master_t *master, /**< EtherCAT master */ - ec_datagram_t *datagram, /**< datagram */ - ec_device_index_t device_index /**< Device index. */ + ec_datagram_t *datagram /**< datagram */ ) { ec_datagram_t *queued_datagram; @@ -881,7 +880,6 @@ list_add_tail(&datagram->queue, &master->datagram_queue); datagram->state = EC_DATAGRAM_QUEUED; - datagram->device_index = device_index; } /*****************************************************************************/ @@ -1388,8 +1386,7 @@ // queue and send down(&master->io_sem); if (fsm_exec) { - ec_master_queue_datagram(master, &master->fsm_datagram, - EC_DEVICE_MAIN); + ec_master_queue_datagram(master, &master->fsm_datagram); } ecrt_master_send(master); #ifdef EC_USE_HRTIMER @@ -2231,42 +2228,41 @@ void ecrt_master_send(ec_master_t *master) { ec_datagram_t *datagram, *n; - unsigned int i; + ec_device_index_t dev_idx; if (master->injection_seq_rt != master->injection_seq_fsm) { - // inject datagrams produced by master & slave FSMs - ec_master_queue_datagram(master, &master->fsm_datagram, - EC_DEVICE_MAIN); + // inject datagrams produced by master and slave FSMs + ec_master_queue_datagram(master, &master->fsm_datagram); master->injection_seq_rt = master->injection_seq_fsm; } ec_master_inject_external_datagrams(master); - for (i = 0; i < EC_NUM_DEVICES; i++) { - if (unlikely(!master->devices[i].link_state)) { + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { + if (unlikely(!master->devices[dev_idx].link_state)) { // link is down, no datagram can be sent list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { - if (datagram->device_index == i) { + if (datagram->device_index == dev_idx) { datagram->state = EC_DATAGRAM_ERROR; list_del_init(&datagram->queue); } } - if (!master->devices[i].dev) { + if (!master->devices[dev_idx].dev) { continue; } // query link state - ec_device_poll(&master->devices[i]); + ec_device_poll(&master->devices[dev_idx]); // clear frame statistics - ec_device_clear_stats(&master->devices[i]); + ec_device_clear_stats(&master->devices[dev_idx]); continue; } // send frames - ec_master_send_datagrams(master, i); + ec_master_send_datagrams(master, dev_idx); } } @@ -2327,7 +2323,7 @@ list_for_each_entry_safe(datagram, next, &master->ext_datagram_queue, queue) { list_del(&datagram->queue); - ec_master_queue_datagram(master, datagram, EC_DEVICE_MAIN); + ec_master_queue_datagram(master, datagram); } ecrt_master_send(master); @@ -2491,9 +2487,22 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state) { - state->slaves_responding = master->fsm.slaves_responding; - state->al_states = master->fsm.slave_states; - state->link_up = master->devices[EC_DEVICE_MAIN].link_state; + ec_device_index_t dev_idx; + + state->slaves_responding = 0U; + state->al_states = 0; + state->link_up = 0U; + + for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) { + /* Announce sum of responding slaves on all links. */ + state->slaves_responding += master->fsm.slaves_responding[dev_idx]; + + /* Binary-or slave states of all links. */ + state->al_states |= master->fsm.slave_states[dev_idx]; + + /* Signal link up if at least one device has link. */ + state->link_up |= master->devices[dev_idx].link_state; + } } /*****************************************************************************/ @@ -2513,8 +2522,7 @@ void ecrt_master_sync_reference_clock(ec_master_t *master) { EC_WRITE_U32(master->ref_sync_datagram.data, master->app_time); - ec_master_queue_datagram(master, &master->ref_sync_datagram, - EC_DEVICE_MAIN); + ec_master_queue_datagram(master, &master->ref_sync_datagram); } /*****************************************************************************/ @@ -2522,8 +2530,7 @@ void ecrt_master_sync_slave_clocks(ec_master_t *master) { ec_datagram_zero(&master->sync_datagram); - ec_master_queue_datagram(master, &master->sync_datagram, - EC_DEVICE_MAIN); + ec_master_queue_datagram(master, &master->sync_datagram); } /*****************************************************************************/ @@ -2531,8 +2538,7 @@ void ecrt_master_sync_monitor_queue(ec_master_t *master) { ec_datagram_zero(&master->sync_mon_datagram); - ec_master_queue_datagram(master, &master->sync_mon_datagram, - EC_DEVICE_MAIN); + ec_master_queue_datagram(master, &master->sync_mon_datagram); } /*****************************************************************************/ diff -r 593272e5a169 -r e898451c054a master/master.h --- a/master/master.h Fri Apr 06 23:30:35 2012 +0200 +++ b/master/master.h Fri Apr 06 23:35:05 2012 +0200 @@ -297,11 +297,9 @@ // 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 *, - ec_device_index_t); +void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *); void ec_master_queue_datagram_ext(ec_master_t *, ec_datagram_t *); -void ec_master_queue_external_datagram(ec_master_t *, ec_datagram_t *, - ec_device_index_t); +void ec_master_queue_external_datagram(ec_master_t *, ec_datagram_t *); void ec_master_inject_external_datagrams(ec_master_t *); // misc. diff -r 593272e5a169 -r e898451c054a master/module.c --- a/master/module.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/module.c Fri Apr 06 23:35:05 2012 +0200 @@ -453,7 +453,7 @@ /** Device names. */ -static const char *ec_device_names[EC_NUM_DEVICES] = { +const char *ec_device_names[EC_NUM_DEVICES] = { "main", "backup" }; diff -r 593272e5a169 -r e898451c054a master/slave.c --- a/master/slave.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/slave.c Fri Apr 06 23:35:05 2012 +0200 @@ -62,6 +62,7 @@ void ec_slave_init( ec_slave_t *slave, /**< EtherCAT slave */ ec_master_t *master, /**< EtherCAT master */ + ec_device_index_t dev_idx, /**< Device index. */ uint16_t ring_position, /**< ring position */ uint16_t station_address /**< station address to configure */ ) @@ -70,6 +71,7 @@ int ret; slave->master = master; + slave->device_index = dev_idx; slave->ring_position = ring_position; slave->station_address = station_address; slave->effective_alias = 0x0000; diff -r 593272e5a169 -r e898451c054a master/slave.h --- a/master/slave.h Fri Apr 06 23:30:35 2012 +0200 +++ b/master/slave.h Fri Apr 06 23:35:05 2012 +0200 @@ -174,6 +174,8 @@ struct ec_slave { ec_master_t *master; /**< Master owning the slave. */ + ec_device_index_t device_index; /**< Index of device the slave responds + on. */ // addresses uint16_t ring_position; /**< Ring position. */ @@ -238,7 +240,8 @@ /*****************************************************************************/ // slave construction/destruction -void ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t); +void ec_slave_init(ec_slave_t *, ec_master_t *, ec_device_index_t, + uint16_t, uint16_t); void ec_slave_clear(ec_slave_t *); void ec_slave_clear_sync_managers(ec_slave_t *); diff -r 593272e5a169 -r e898451c054a master/voe_handler.c --- a/master/voe_handler.c Fri Apr 06 23:30:35 2012 +0200 +++ b/master/voe_handler.c Fri Apr 06 23:35:05 2012 +0200 @@ -190,9 +190,9 @@ { if (voe->config->slave) { // FIXME locking? voe->state(voe); - if (voe->request_state == EC_INT_REQUEST_BUSY) - ec_master_queue_datagram(voe->config->master, &voe->datagram, - EC_DEVICE_MAIN); + if (voe->request_state == EC_INT_REQUEST_BUSY) { + ec_master_queue_datagram(voe->config->master, &voe->datagram); + } } else { voe->state = ec_voe_handler_state_error; voe->request_state = EC_INT_REQUEST_FAILURE; diff -r 593272e5a169 -r e898451c054a tool/CommandSlaves.cpp --- a/tool/CommandSlaves.cpp Fri Apr 06 23:30:35 2012 +0200 +++ b/tool/CommandSlaves.cpp Fri Apr 06 23:35:05 2012 +0200 @@ -144,7 +144,7 @@ ) { ec_ioctl_master_t master; - unsigned int i; + unsigned int i, lastDevice; ec_ioctl_slave_t slave; uint16_t lastAlias, aliasIndex; Info info; @@ -184,6 +184,7 @@ info.state = alStateString(slave.al_state); info.flag = (slave.error_flag ? 'E' : '+'); + info.device = slave.device_index; if (strlen(slave.name)) { info.name = slave.name; @@ -215,7 +216,12 @@ cout << "Master" << dec << m.getIndex() << endl; } + lastDevice = EC_DEVICE_MAIN; for (iter = infoList.begin(); iter != infoList.end(); iter++) { + if (iter->device != lastDevice) { + lastDevice = iter->device; + cout << "xxx LINK FAILURE xxx" << endl; + } cout << indent << setfill(' ') << right << setw(maxPosWidth) << iter->pos << " " << setw(maxAliasWidth) << iter->alias @@ -245,6 +251,7 @@ cout << "Alias: " << si->alias << endl; cout + << "Device: " << (si->device_index ? "Backup" : "Main") << endl << "State: " << alStateString(si->al_state) << endl << "Flag: " << (si->error_flag ? 'E' : '+') << endl << "Identity:" << endl @@ -332,7 +339,8 @@ } cout << " " << setw(10); if (!si->ports[i].link.loop_closed) { - cout << si->ports[i].receive_time - si->ports[0].receive_time; + cout << si->ports[i].receive_time - + si->ports[0].receive_time; } else { cout << "-"; } @@ -406,7 +414,8 @@ << " Enable SDO: " << (si->coe_details.enable_sdo ? "yes" : "no") << endl << " Enable SDO Info: " - << (si->coe_details.enable_sdo_info ? "yes" : "no") << endl + << (si->coe_details.enable_sdo_info ? "yes" : "no") + << endl << " Enable PDO Assign: " << (si->coe_details.enable_pdo_assign ? "yes" : "no") << endl diff -r 593272e5a169 -r e898451c054a tool/CommandSlaves.h --- a/tool/CommandSlaves.h Fri Apr 06 23:30:35 2012 +0200 +++ b/tool/CommandSlaves.h Fri Apr 06 23:35:05 2012 +0200 @@ -51,6 +51,7 @@ string state; string flag; string name; + unsigned int device; }; void listSlaves(MasterDevice &, const SlaveList &, bool);