# HG changeset patch # User Florian Pose # Date 1161880166 0 # Node ID 8fede404c01fb8c10adf948b7f4af185aec0a364 # Parent 3b7eec3291121b4542e2c100b491d7a7eff9a5c3 Persistent slave lists. diff -r 3b7eec329112 -r 8fede404c01f examples/mini/mini.c --- 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"))) diff -r 3b7eec329112 -r 8fede404c01f master/datagram.c --- 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; diff -r 3b7eec329112 -r 8fede404c01f master/domain.c --- 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); } /*****************************************************************************/ diff -r 3b7eec329112 -r 8fede404c01f master/domain.h --- 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 *); /*****************************************************************************/ diff -r 3b7eec329112 -r 8fede404c01f master/ethernet.c --- 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; } diff -r 3b7eec329112 -r 8fede404c01f master/fsm.c --- 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 */) +{ +} + +/*****************************************************************************/ diff -r 3b7eec329112 -r 8fede404c01f master/fsm.h --- 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 *); /*****************************************************************************/ diff -r 3b7eec329112 -r 8fede404c01f master/fsm_coe.c --- 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; } diff -r 3b7eec329112 -r 8fede404c01f master/master.c --- 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); } diff -r 3b7eec329112 -r 8fede404c01f master/master.h --- 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 *); /*****************************************************************************/ diff -r 3b7eec329112 -r 8fede404c01f master/module.c --- 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; } diff -r 3b7eec329112 -r 8fede404c01f master/slave.c --- 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) { diff -r 3b7eec329112 -r 8fede404c01f master/slave.h --- 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 *);