diff -r 05622513f627 -r 9dc190591c0f master/fsm.c --- a/master/fsm.c Mon Jun 26 16:07:07 2006 +0000 +++ b/master/fsm.c Wed Aug 02 12:25:25 2006 +0000 @@ -46,32 +46,30 @@ void ec_fsm_master_start(ec_fsm_t *); void ec_fsm_master_broadcast(ec_fsm_t *); -void ec_fsm_master_proc_states(ec_fsm_t *); -void ec_fsm_master_scan(ec_fsm_t *); -void ec_fsm_master_states(ec_fsm_t *); +void ec_fsm_master_read_states(ec_fsm_t *); void ec_fsm_master_validate_vendor(ec_fsm_t *); void ec_fsm_master_validate_product(ec_fsm_t *); -void ec_fsm_master_reconfigure(ec_fsm_t *); -void ec_fsm_master_address(ec_fsm_t *); -void ec_fsm_master_conf(ec_fsm_t *); -void ec_fsm_master_eeprom(ec_fsm_t *); - -void ec_fsm_slave_start_reading(ec_fsm_t *); -void ec_fsm_slave_read_status(ec_fsm_t *); -void ec_fsm_slave_read_base(ec_fsm_t *); -void ec_fsm_slave_read_dl(ec_fsm_t *); -void ec_fsm_slave_eeprom_size(ec_fsm_t *); -void ec_fsm_slave_fetch_eeprom(ec_fsm_t *); -void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *); -void ec_fsm_slave_end(ec_fsm_t *); - -void ec_fsm_slave_conf(ec_fsm_t *); -void ec_fsm_slave_sync(ec_fsm_t *); -void ec_fsm_slave_preop(ec_fsm_t *); -void ec_fsm_slave_fmmu(ec_fsm_t *); -void ec_fsm_slave_saveop(ec_fsm_t *); -void ec_fsm_slave_op(ec_fsm_t *); -void ec_fsm_slave_op2(ec_fsm_t *); +void ec_fsm_master_rewrite_addresses(ec_fsm_t *); +void ec_fsm_master_configure_slave(ec_fsm_t *); +void ec_fsm_master_scan_slaves(ec_fsm_t *); +void ec_fsm_master_write_eeprom(ec_fsm_t *); + +void ec_fsm_slavescan_start(ec_fsm_t *); +void ec_fsm_slavescan_address(ec_fsm_t *); +void ec_fsm_slavescan_state(ec_fsm_t *); +void ec_fsm_slavescan_base(ec_fsm_t *); +void ec_fsm_slavescan_datalink(ec_fsm_t *); +void ec_fsm_slavescan_eeprom_size(ec_fsm_t *); +void ec_fsm_slavescan_eeprom_data(ec_fsm_t *); +void ec_fsm_slavescan_end(ec_fsm_t *); + +void ec_fsm_slaveconf_init(ec_fsm_t *); +void ec_fsm_slaveconf_sync(ec_fsm_t *); +void ec_fsm_slaveconf_preop(ec_fsm_t *); +void ec_fsm_slaveconf_fmmu(ec_fsm_t *); +void ec_fsm_slaveconf_saveop(ec_fsm_t *); +void ec_fsm_slaveconf_op(ec_fsm_t *); +void ec_fsm_slaveconf_end(ec_fsm_t *); void ec_fsm_sii_start_reading(ec_fsm_t *); void ec_fsm_sii_read_check(ec_fsm_t *); @@ -87,7 +85,7 @@ void ec_fsm_change_status(ec_fsm_t *); void ec_fsm_change_code(ec_fsm_t *); void ec_fsm_change_ack(ec_fsm_t *); -void ec_fsm_change_ack2(ec_fsm_t *); +void ec_fsm_change_check_ack(ec_fsm_t *); void ec_fsm_change_end(ec_fsm_t *); void ec_fsm_change_error(ec_fsm_t *); @@ -99,7 +97,7 @@ int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ ec_master_t *master /**< EtherCAT master */ - ) + ) { fsm->master = master; fsm->master_state = ec_fsm_master_start; @@ -107,9 +105,9 @@ fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; fsm->master_validation = 0; - ec_command_init(&fsm->command); - if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { - EC_ERR("FSM failed to allocate FSM command.\n"); + ec_datagram_init(&fsm->datagram); + if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) { + EC_ERR("Failed to allocate FSM datagram.\n"); return -1; } @@ -124,7 +122,7 @@ void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_clear(&fsm->command); + ec_datagram_clear(&fsm->datagram); } /*****************************************************************************/ @@ -162,8 +160,8 @@ void ec_fsm_master_start(ec_fsm_t *fsm) { - ec_command_brd(&fsm->command, 0x0130, 2); - ec_master_queue_command(fsm->master, &fsm->command); + ec_datagram_brd(&fsm->datagram, 0x0130, 2); + ec_master_queue_datagram(fsm->master, &fsm->datagram); fsm->master_state = ec_fsm_master_broadcast; } @@ -176,12 +174,12 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; unsigned int topology_change, states_change, i; ec_slave_t *slave; ec_master_t *master = fsm->master; - if (command->state != EC_CMD_RECEIVED) { + if (datagram->state != EC_CMD_RECEIVED) { if (!master->device->link_state) { fsm->master_slaves_responding = 0; list_for_each_entry(slave, &master->slaves, list) { @@ -193,12 +191,12 @@ return; } - topology_change = (command->working_counter != + topology_change = (datagram->working_counter != fsm->master_slaves_responding); - states_change = (EC_READ_U8(command->data) != fsm->master_slave_states); - - fsm->master_slave_states = EC_READ_U8(command->data); - fsm->master_slaves_responding = command->working_counter; + states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states); + + fsm->master_slave_states = EC_READ_U8(datagram->data); + fsm->master_slaves_responding = datagram->working_counter; if (topology_change) { EC_INFO("%i slave%s responding.\n", @@ -221,8 +219,8 @@ printk(".\n"); } - // topology change in free-run mode: clear all slaves and scan the bus - if (topology_change && master->mode == EC_MASTER_MODE_FREERUN) { + // 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); @@ -264,17 +262,84 @@ // begin scanning of slaves fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); - fsm->slave_state = ec_fsm_slave_start_reading; - fsm->master_state = ec_fsm_master_scan; + fsm->slave_state = ec_fsm_slavescan_start; + fsm->master_state = ec_fsm_master_scan_slaves; fsm->master_state(fsm); // execute immediately return; } // fetch state from each slave fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); - ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); - ec_master_queue_command(master, &fsm->command); - fsm->master_state = ec_fsm_master_states; + ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2); + ec_master_queue_datagram(master, &fsm->datagram); + fsm->master_state = ec_fsm_master_read_states; +} + +/*****************************************************************************/ + +/** + Master action: PROC_STATES. + Processes the slave states. +*/ + +void ec_fsm_master_action_process_states(ec_fsm_t *fsm + /**< finite state machine */ + ) +{ + ec_master_t *master = fsm->master; + ec_slave_t *slave; + + // check if any slaves are not in the state, they're supposed to be + list_for_each_entry(slave, &master->slaves, list) { + if (slave->error_flag || + !slave->online || + slave->requested_state == EC_SLAVE_STATE_UNKNOWN || + slave->current_state == slave->requested_state) continue; + + EC_INFO("Changing state of slave %i from ", slave->ring_position); + ec_print_states(slave->current_state); + printk(" to "); + ec_print_states(slave->requested_state); + printk(".\n"); + + fsm->slave = slave; + fsm->slave_state = ec_fsm_slaveconf_init; + fsm->change_new = EC_SLAVE_STATE_INIT; + fsm->change_state = ec_fsm_change_start; + fsm->master_state = ec_fsm_master_configure_slave; + fsm->master_state(fsm); // execute immediately + return; + } + + if (master->mode == EC_MASTER_MODE_IDLE) { + // nothing to configure. check for pending EEPROM write operations. + list_for_each_entry(slave, &master->slaves, list) { + if (!slave->new_eeprom_data) continue; + + if (!slave->online || slave->error_flag) { + kfree(slave->new_eeprom_data); + slave->new_eeprom_data = NULL; + EC_ERR("Discarding EEPROM data, slave %i not ready.\n", + slave->ring_position); + continue; + } + + // found pending EEPROM write operation. execute it! + EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); + fsm->sii_offset = 0x0000; + memcpy(fsm->sii_value, slave->new_eeprom_data, 2); + fsm->sii_mode = 1; + fsm->sii_state = ec_fsm_sii_start_writing; + fsm->slave = slave; + fsm->master_state = ec_fsm_master_write_eeprom; + fsm->master_state(fsm); // execute immediately + return; + } + } + + // nothing to do. restart master state machine. + fsm->master_state = ec_fsm_master_start; + fsm->master_state(fsm); // execute immediately } /*****************************************************************************/ @@ -289,37 +354,38 @@ ec_master_t *master = fsm->master; ec_slave_t *slave = fsm->slave; - // have all states been read? - if (slave->list.next == &master->slaves) { - - // check, if a bus validation has to be done - if (fsm->master_validation) { - fsm->master_validation = 0; - list_for_each_entry(slave, &master->slaves, list) { - if (slave->online) continue; - - // At least one slave is offline. validate! - EC_INFO("Validating bus.\n"); - fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_validate_vendor; - fsm->sii_offset = 0x0008; // vendor ID - fsm->sii_mode = 0; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute immediately - return; - } + // is there another slave to query? + if (slave->list.next != &master->slaves) { + // process next slave + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, + 0x0130, 2); + ec_master_queue_datagram(master, &fsm->datagram); + fsm->master_state = ec_fsm_master_read_states; + return; + } + + // all slave states read + + // check, if a bus validation has to be done + if (fsm->master_validation) { + fsm->master_validation = 0; + list_for_each_entry(slave, &master->slaves, list) { + if (slave->online) continue; + + // At least one slave is offline. validate! + EC_INFO("Validating bus.\n"); + fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); + fsm->master_state = ec_fsm_master_validate_vendor; + fsm->sii_offset = 0x0008; // vendor ID + fsm->sii_mode = 0; + fsm->sii_state = ec_fsm_sii_start_reading; + fsm->sii_state(fsm); // execute immediately + return; } - - fsm->master_state = ec_fsm_master_proc_states; - fsm->master_state(fsm); // execute immediately - return; - } - - // process next slave - fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); - ec_master_queue_command(master, &fsm->command); - fsm->master_state = ec_fsm_master_states; + } + + ec_fsm_master_action_process_states(fsm); } /*****************************************************************************/ @@ -329,20 +395,20 @@ Fetches the AL- and online state of a slave. */ -void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_slave_t *slave = fsm->slave; - ec_command_t *command = &fsm->command; +void ec_fsm_master_read_states(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_slave_t *slave = fsm->slave; + ec_datagram_t *datagram = &fsm->datagram; uint8_t new_state; - if (command->state != EC_CMD_RECEIVED) { + if (datagram->state != EC_CMD_RECEIVED) { fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; } // did the slave not respond to its station address? - if (command->working_counter != 1) { + if (datagram->working_counter != 1) { if (slave->online) { slave->online = 0; EC_INFO("Slave %i: offline.\n", slave->ring_position); @@ -352,10 +418,10 @@ } // slave responded - new_state = EC_READ_U8(command->data); + new_state = EC_READ_U8(datagram->data); if (!slave->online) { // slave was offline before slave->online = 1; - slave->state_error = 0; + slave->error_flag = 0; // clear error flag slave->current_state = new_state; EC_INFO("Slave %i: online (", slave->ring_position); ec_print_states(new_state); @@ -376,62 +442,6 @@ /*****************************************************************************/ /** - Master state: PROC_STATES. - Processes the slave states. -*/ - -void ec_fsm_master_proc_states(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_master_t *master = fsm->master; - ec_slave_t *slave; - - // check if any slaves are not in the state, they're supposed to be - list_for_each_entry(slave, &master->slaves, list) { - if (slave->state_error || !slave->online || - slave->requested_state == EC_SLAVE_STATE_UNKNOWN || - slave->current_state == slave->requested_state) continue; - - EC_INFO("Changing state of slave %i from ", slave->ring_position); - ec_print_states(slave->current_state); - printk(" to "); - ec_print_states(slave->requested_state); - printk(".\n"); - - fsm->slave = slave; - fsm->slave_state = ec_fsm_slave_conf; - fsm->change_new = EC_SLAVE_STATE_INIT; - fsm->change_state = ec_fsm_change_start; - fsm->master_state = ec_fsm_master_conf; - fsm->master_state(fsm); // execute immediately - return; - } - - if (master->mode == EC_MASTER_MODE_FREERUN) { - // nothing to configure. check for pending EEPROM write operations. - list_for_each_entry(slave, &master->slaves, list) { - if (!slave->new_eeprom_data) continue; - - // found pending EEPROM write operation. execute it! - EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); - fsm->sii_offset = 0x0000; - memcpy(fsm->sii_value, slave->new_eeprom_data, 2); - fsm->sii_mode = 1; - fsm->sii_state = ec_fsm_sii_start_writing; - fsm->slave = slave; - fsm->master_state = ec_fsm_master_eeprom; - fsm->master_state(fsm); // execute immediately - return; - } - } - - // nothing to do. restart master state machine. - fsm->master_state = ec_fsm_master_start; - fsm->master_state(fsm); // execute immediately -} - -/*****************************************************************************/ - -/** Master state: VALIDATE_VENDOR. Validates the vendor ID of a slave. */ @@ -443,6 +453,7 @@ fsm->sii_state(fsm); // execute SII state machine if (fsm->sii_state == ec_fsm_sii_error) { + 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; @@ -470,62 +481,14 @@ /*****************************************************************************/ /** - Master state: VALIDATE_PRODUCT. - Validates the product ID of a slave. -*/ - -void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_slave_t *slave = fsm->slave; - - fsm->sii_state(fsm); // execute SII state machine - - if (fsm->sii_state == ec_fsm_sii_error) { - 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 - return; - } - - if (fsm->sii_state != ec_fsm_sii_end) return; - - if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { - 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->sii_value)); - fsm->master_state = ec_fsm_master_start; - fsm->master_state(fsm); // execute immediately - return; - } - - // have all states been validated? - if (slave->list.next == &fsm->master->slaves) { - fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_reconfigure; - return; - } - - // validate next slave - fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_validate_vendor; - fsm->sii_offset = 0x0008; // vendor ID - fsm->sii_mode = 0; - fsm->sii_state = ec_fsm_sii_start_reading; - fsm->sii_state(fsm); // execute immediately -} - -/*****************************************************************************/ - -/** - Master state: RECONFIGURE. + Master action: ADDRESS. Looks for slave, that have lost their configuration and writes their station address, so that they can be reconfigured later. */ -void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; +void ec_fsm_master_action_addresses(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; while (fsm->slave->online) { if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? @@ -540,10 +503,60 @@ EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); // write station address - ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); - EC_WRITE_U16(command->data, fsm->slave->station_address); - ec_master_queue_command(fsm->master, command); - fsm->master_state = ec_fsm_master_address; + ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); + EC_WRITE_U16(datagram->data, fsm->slave->station_address); + ec_master_queue_datagram(fsm->master, datagram); + fsm->master_state = ec_fsm_master_rewrite_addresses; +} + +/*****************************************************************************/ + +/** + Master state: VALIDATE_PRODUCT. + Validates the product ID of a slave. +*/ + +void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_slave_t *slave = fsm->slave; + + fsm->sii_state(fsm); // execute SII state machine + + if (fsm->sii_state == ec_fsm_sii_error) { + 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 + return; + } + + if (fsm->sii_state != ec_fsm_sii_end) return; + + if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { + 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->sii_value)); + fsm->master_state = ec_fsm_master_start; + fsm->master_state(fsm); // execute immediately + return; + } + + // have all states been validated? + if (slave->list.next == &fsm->master->slaves) { + fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); + // start writing addresses to offline slaves + ec_fsm_master_action_addresses(fsm); + return; + } + + // validate next slave + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + fsm->master_state = ec_fsm_master_validate_vendor; + fsm->sii_offset = 0x0008; // vendor ID + fsm->sii_mode = 0; + fsm->sii_state = ec_fsm_sii_start_reading; + fsm->sii_state(fsm); // execute immediately } /*****************************************************************************/ @@ -553,12 +566,14 @@ Checks, if the new station address has been written to the slave. */ -void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_slave_t *slave = fsm->slave; - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { +void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm + /**< finite state machine */ + ) +{ + ec_slave_t *slave = fsm->slave; + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { EC_ERR("Failed to write station address on slave %i.\n", slave->ring_position); } @@ -571,8 +586,8 @@ // check next slave fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - fsm->master_state = ec_fsm_master_reconfigure; - fsm->master_state(fsm); // execute immediately + // Write new station address to slave + ec_fsm_master_action_addresses(fsm); } /*****************************************************************************/ @@ -582,7 +597,7 @@ Executes the sub-statemachine for the scanning of a slave. */ -void ec_fsm_master_scan(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */) { ec_master_t *master = fsm->master; ec_slave_t *slave = fsm->slave; @@ -592,7 +607,7 @@ fsm->slave_state(fsm); // execute slave state machine - if (fsm->slave_state != ec_fsm_slave_end) return; + if (fsm->slave_state != ec_fsm_slavescan_end) return; // have all slaves been fetched? if (slave->list.next == &master->slaves) { @@ -619,7 +634,7 @@ } if (!slave->type) { - EC_WARN("FSM: Unknown slave device (vendor 0x%08X," + EC_WARN("Unknown slave device (vendor 0x%08X," " code 0x%08X) at position %i.\n", slave->sii_vendor_id, slave->sii_product_code, slave->ring_position); @@ -636,7 +651,9 @@ } // determine initial state. - if ((slave->type && slave->type->special == EC_TYPE_BUS_COUPLER)) { + if ((slave->type && + (slave->type->special == EC_TYPE_BUS_COUPLER || + slave->type->special == EC_TYPE_INFRA))) { slave->requested_state = EC_SLAVE_STATE_OP; } else { @@ -645,7 +662,7 @@ else slave->requested_state = EC_SLAVE_STATE_INIT; } - slave->state_error = 0; + slave->error_flag = 0; // calculate coupler-based slave address slave->coupler_index = current_coupler_index; @@ -653,7 +670,7 @@ coupler_subindex++; } - if (master->mode == EC_MASTER_MODE_FREERUN) { + if (master->mode == EC_MASTER_MODE_IDLE) { // start EoE processing ec_master_eoe_start(master); } @@ -665,7 +682,7 @@ // process next slave fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - fsm->slave_state = ec_fsm_slave_start_reading; + fsm->slave_state = ec_fsm_slavescan_start; fsm->slave_state(fsm); // execute immediately } @@ -676,12 +693,14 @@ Starts configuring a slave. */ -void ec_fsm_master_conf(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_configure_slave(ec_fsm_t *fsm + /**< finite state machine */ + ) { fsm->slave_state(fsm); // execute slave's state machine - if (fsm->slave_state != ec_fsm_slave_end) return; - fsm->master_state = ec_fsm_master_proc_states; - fsm->master_state(fsm); // execute immediately + if (fsm->slave_state != ec_fsm_slaveconf_end) return; + + ec_fsm_master_action_process_states(fsm); } /*****************************************************************************/ @@ -690,13 +709,14 @@ Master state: EEPROM. */ -void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; fsm->sii_state(fsm); // execute SII state machine if (fsm->sii_state == ec_fsm_sii_error) { + fsm->slave->error_flag = 1; EC_ERR("Failed to write EEPROM contents to slave %i.\n", slave->ring_position); kfree(slave->new_eeprom_data); @@ -722,13 +742,13 @@ slave->new_eeprom_data = NULL; // restart master state machine. - fsm->master_state = ec_fsm_master_start; + fsm->master_state = ec_fsm_master_start; // TODO: Evaluate new contents! fsm->master_state(fsm); // execute immediately return; } /****************************************************************************** - * slave state machine + * slave scan sub state machine *****************************************************************************/ /** @@ -737,126 +757,129 @@ slave, according to its ring position. */ -void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; +void ec_fsm_slavescan_start(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; // write station address - ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); - EC_WRITE_U16(command->data, fsm->slave->station_address); - ec_master_queue_command(fsm->master, command); - fsm->slave_state = ec_fsm_slave_read_status; -} - -/*****************************************************************************/ - -/** - Slave state: READ_STATUS. -*/ - -void ec_fsm_slave_read_status(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("FSM failed to write station address of slave %i.\n", + ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); + EC_WRITE_U16(datagram->data, fsm->slave->station_address); + ec_master_queue_datagram(fsm->master, datagram); + fsm->slave_state = ec_fsm_slavescan_address; +} + +/*****************************************************************************/ + +/** + Slave state: ADDRESS. +*/ + +void ec_fsm_slavescan_address(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; + EC_ERR("Failed to write station address of slave %i.\n", fsm->slave->ring_position); - fsm->slave_state = ec_fsm_slave_end; - return; - } - - // read AL status - ec_command_nprd(command, fsm->slave->station_address, 0x0130, 2); - ec_master_queue_command(fsm->master, command); - fsm->slave_state = ec_fsm_slave_read_base; -} - -/*****************************************************************************/ - -/** - Slave state: READ_BASE. -*/ - -void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("FSM failed to read AL status of slave %i.\n", + return; + } + + // Read AL state + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2); + ec_master_queue_datagram(fsm->master, datagram); + fsm->slave_state = ec_fsm_slavescan_state; +} + +/*****************************************************************************/ + +/** + Slave state: STATE. +*/ + +void ec_fsm_slavescan_state(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; + EC_ERR("Failed to read AL state of slave %i.\n", fsm->slave->ring_position); - fsm->slave_state = ec_fsm_slave_end; - return; - } - - slave->current_state = EC_READ_U8(command->data); + return; + } + + slave->current_state = EC_READ_U8(datagram->data); if (slave->current_state & EC_ACK) { - EC_WARN("Slave %i has status error bit set (0x%02X)!\n", + EC_WARN("Slave %i has state error bit set (0x%02X)!\n", slave->ring_position, slave->current_state); slave->current_state &= 0x0F; } // read base data - ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6); - ec_master_queue_command(fsm->master, command); - fsm->slave_state = ec_fsm_slave_read_dl; -} - -/*****************************************************************************/ - -/** - Slave state: READ_DL. -*/ - -void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("FSM failed to read base data of slave %i.\n", + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6); + ec_master_queue_datagram(fsm->master, datagram); + fsm->slave_state = ec_fsm_slavescan_base; +} + +/*****************************************************************************/ + +/** + Slave state: BASE. +*/ + +void ec_fsm_slavescan_base(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; + EC_ERR("Failed to read base data of slave %i.\n", slave->ring_position); - fsm->slave_state = ec_fsm_slave_end; - return; - } - - slave->base_type = EC_READ_U8 (command->data); - slave->base_revision = EC_READ_U8 (command->data + 1); - slave->base_build = EC_READ_U16(command->data + 2); - slave->base_fmmu_count = EC_READ_U8 (command->data + 4); - slave->base_sync_count = EC_READ_U8 (command->data + 5); + return; + } + + slave->base_type = EC_READ_U8 (datagram->data); + slave->base_revision = EC_READ_U8 (datagram->data + 1); + slave->base_build = EC_READ_U16(datagram->data + 2); + slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4); + slave->base_sync_count = EC_READ_U8 (datagram->data + 5); if (slave->base_fmmu_count > EC_MAX_FMMUS) slave->base_fmmu_count = EC_MAX_FMMUS; // read data link status - ec_command_nprd(command, slave->station_address, 0x0110, 2); - ec_master_queue_command(slave->master, command); - fsm->slave_state = ec_fsm_slave_eeprom_size; -} - -/*****************************************************************************/ - -/** - Slave state: EEPROM_SIZE. - Read the actual size of the EEPROM to allocate the EEPROM image. -*/ - -void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; + ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2); + ec_master_queue_datagram(slave->master, datagram); + fsm->slave_state = ec_fsm_slavescan_datalink; +} + +/*****************************************************************************/ + +/** + Slave state: DATALINK. +*/ + +void ec_fsm_slavescan_datalink(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; uint16_t dl_status; unsigned int i; - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("FSM failed to read DL status of slave %i.\n", + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; + EC_ERR("Failed to read DL status of slave %i.\n", slave->ring_position); - fsm->slave_state = ec_fsm_slave_end; - return; - } - - dl_status = EC_READ_U16(command->data); + return; + } + + 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; @@ -868,17 +891,17 @@ fsm->sii_offset = 0x0040; // first category header fsm->sii_mode = 1; fsm->sii_state = ec_fsm_sii_start_reading; - fsm->slave_state = ec_fsm_slave_fetch_eeprom; + fsm->slave_state = ec_fsm_slavescan_eeprom_size; fsm->slave_state(fsm); // execute state immediately } /*****************************************************************************/ /** - Slave state: FETCH_EEPROM. -*/ - -void ec_fsm_slave_fetch_eeprom(ec_fsm_t *fsm /**< finite state machine */) + Slave state: EEPROM_SIZE. +*/ + +void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; uint16_t cat_type, cat_size; @@ -887,7 +910,8 @@ fsm->sii_state(fsm); if (fsm->sii_state == ec_fsm_sii_error) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; EC_ERR("Failed to read EEPROM size of slave %i.\n", slave->ring_position); return; @@ -915,9 +939,10 @@ if (!(slave->eeprom_data = (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; EC_ERR("Failed to allocate EEPROM data on slave %i.\n", slave->ring_position); - fsm->slave_state = ec_fsm_slave_end; return; } @@ -926,17 +951,17 @@ fsm->sii_offset = 0x0000; fsm->sii_mode = 1; fsm->sii_state = ec_fsm_sii_start_reading; - fsm->slave_state = ec_fsm_slave_fetch_eeprom2; + fsm->slave_state = ec_fsm_slavescan_eeprom_data; fsm->slave_state(fsm); // execute state immediately } /*****************************************************************************/ /** - Slave state: FETCH_EEPROM2. -*/ - -void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *fsm /**< finite state machine */) + Slave state: EEPROM_DATA. +*/ + +void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; uint16_t *cat_word, cat_type, cat_size; @@ -945,7 +970,8 @@ fsm->sii_state(fsm); if (fsm->sii_state == ec_fsm_sii_error) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", slave->ring_position); return; @@ -1033,26 +1059,45 @@ cat_word += cat_size + 2; } - end: - fsm->slave_state = ec_fsm_slave_end; -} - -/*****************************************************************************/ - -/** - Slave state: CONF. -*/ - -void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_slave_t *slave = fsm->slave; - ec_master_t *master = fsm->master; - ec_command_t *command = &fsm->command; + fsm->slave_state = ec_fsm_slavescan_end; + +end: + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slavescan_end; +} + +/*****************************************************************************/ + +/** + Slave state: END. + End state of the slave state machine. +*/ + +void ec_fsm_slavescan_end(ec_fsm_t *fsm /**< finite state machine */) +{ +} + +/****************************************************************************** + * slave configuration sub state machine + *****************************************************************************/ + +/** + Slave state: INIT. +*/ + +void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_slave_t *slave = fsm->slave; + ec_datagram_t *datagram = &fsm->datagram; + const ec_sync_t *sync; + ec_eeprom_sync_t *eeprom_sync, mbox_sync; + unsigned int j; fsm->change_state(fsm); // execute state change state machine if (fsm->change_state == ec_fsm_change_error) { - fsm->slave_state = ec_fsm_slave_end; + slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; return; } @@ -1060,7 +1105,7 @@ // slave is now in INIT if (slave->current_state == slave->requested_state) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave_state = ec_fsm_slaveconf_end; // successful return; } @@ -1071,150 +1116,114 @@ // check and reset CRC fault counters //ec_slave_check_crc(slave); - - if (!slave->base_fmmu_count) { // no fmmus - fsm->slave_state = ec_fsm_slave_sync; - fsm->slave_state(fsm); // execute immediately - return; - } - - // reset FMMUs - ec_command_npwr(command, slave->station_address, 0x0600, - EC_FMMU_SIZE * slave->base_fmmu_count); - memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); - ec_master_queue_command(master, command); - fsm->slave_state = ec_fsm_slave_sync; -} - -/*****************************************************************************/ - -/** - Slave state: SYNC. - Configure sync managers. -*/ - -void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - unsigned int j; - const ec_sync_t *sync; - ec_eeprom_sync_t *eeprom_sync, mbox_sync; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("Failed to reset FMMUs of slave %i.\n", - slave->ring_position); - slave->state_error = 1; - fsm->slave_state = ec_fsm_slave_end; - return; - } + // TODO! if (!slave->base_sync_count) { // no sync managers - fsm->slave_state = ec_fsm_slave_preop; - fsm->slave_state(fsm); // execute immediately + fsm->slave_state = ec_fsm_slaveconf_preop; + fsm->change_new = EC_SLAVE_STATE_PREOP; + fsm->change_state = ec_fsm_change_start; + fsm->change_state(fsm); // execute immediately return; } // configure sync managers - ec_command_npwr(command, slave->station_address, 0x0800, - EC_SYNC_SIZE * slave->base_sync_count); - memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); + ec_datagram_npwr(datagram, slave->station_address, 0x0800, + EC_SYNC_SIZE * slave->base_sync_count); + memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); + + // does the slave supply sync manager configurations in its EEPROM? + if (!list_empty(&slave->eeprom_syncs)) { + list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { + if (eeprom_sync->index >= slave->base_sync_count) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; + EC_ERR("Invalid sync manager configuration found!"); + return; + } + ec_eeprom_sync_config(eeprom_sync, slave, + datagram->data + EC_SYNC_SIZE + * eeprom_sync->index); + } + } // known slave type, take type's SM information - if (slave->type) { + else if (slave->type) { for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { sync = slave->type->sync_managers[j]; - ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j); + ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j); } } // unknown type, but slave has mailbox else if (slave->sii_mailbox_protocols) { - // does it supply sync manager configurations in its EEPROM? - if (!list_empty(&slave->eeprom_syncs)) { - list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { - if (eeprom_sync->index >= slave->base_sync_count) { - EC_ERR("Invalid sync manager configuration found!"); - fsm->slave_state = ec_fsm_slave_end; - return; - } - ec_eeprom_sync_config(eeprom_sync, - command->data + EC_SYNC_SIZE - * eeprom_sync->index); - } - } - - // no sync manager information; guess mailbox settings - else { - mbox_sync.physical_start_address = - slave->sii_rx_mailbox_offset; - mbox_sync.length = slave->sii_rx_mailbox_size; - mbox_sync.control_register = 0x26; - mbox_sync.enable = 1; - ec_eeprom_sync_config(&mbox_sync, command->data); - - mbox_sync.physical_start_address = - slave->sii_tx_mailbox_offset; - mbox_sync.length = slave->sii_tx_mailbox_size; - mbox_sync.control_register = 0x22; - mbox_sync.enable = 1; - ec_eeprom_sync_config(&mbox_sync, - command->data + EC_SYNC_SIZE); - } + // guess mailbox settings + mbox_sync.physical_start_address = + slave->sii_rx_mailbox_offset; + mbox_sync.length = slave->sii_rx_mailbox_size; + mbox_sync.control_register = 0x26; + mbox_sync.enable = 1; + ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); + + mbox_sync.physical_start_address = + slave->sii_tx_mailbox_offset; + mbox_sync.length = slave->sii_tx_mailbox_size; + mbox_sync.control_register = 0x22; + mbox_sync.enable = 1; + ec_eeprom_sync_config(&mbox_sync, slave, + datagram->data + EC_SYNC_SIZE); EC_INFO("Mailbox configured for unknown slave %i\n", slave->ring_position); } - ec_master_queue_command(fsm->master, command); - fsm->slave_state = ec_fsm_slave_preop; -} - -/*****************************************************************************/ - -/** - Slave state: PREOP. - Change slave state to PREOP. -*/ - -void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { + ec_master_queue_datagram(fsm->master, datagram); + fsm->slave_state = ec_fsm_slaveconf_sync; +} + +/*****************************************************************************/ + +/** + Slave state: SYNC. +*/ + +void ec_fsm_slaveconf_sync(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; EC_ERR("Failed to set sync managers on slave %i.\n", slave->ring_position); - slave->state_error = 1; - fsm->slave_state = ec_fsm_slave_end; - return; - } - + return; + } + + fsm->slave_state = ec_fsm_slaveconf_preop; fsm->change_new = EC_SLAVE_STATE_PREOP; fsm->change_state = ec_fsm_change_start; - fsm->slave_state = ec_fsm_slave_fmmu; fsm->change_state(fsm); // execute immediately } /*****************************************************************************/ /** - Slave state: FMMU. - Configure FMMUs. -*/ - -void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */) + Slave state: PREOP. +*/ + +void ec_fsm_slaveconf_preop(ec_fsm_t *fsm /**< finite state machine */) { ec_slave_t *slave = fsm->slave; ec_master_t *master = fsm->master; - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; unsigned int j; fsm->change_state(fsm); // execute state change state machine if (fsm->change_state == ec_fsm_change_error) { - fsm->slave_state = ec_fsm_slave_end; + slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; return; } @@ -1222,57 +1231,57 @@ // slave is now in PREOP if (slave->current_state == slave->requested_state) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave_state = ec_fsm_slaveconf_end; // successful return; } // stop activation here for slaves without type if (!slave->type) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave_state = ec_fsm_slaveconf_end; // successful return; } if (!slave->base_fmmu_count) { - fsm->slave_state = ec_fsm_slave_saveop; - fsm->slave_state(fsm); // execute immediately + fsm->slave_state = ec_fsm_slaveconf_saveop; + fsm->change_new = EC_SLAVE_STATE_SAVEOP; + fsm->change_state = ec_fsm_change_start; + fsm->change_state(fsm); // execute immediately return; } // configure FMMUs - ec_command_npwr(command, slave->station_address, - 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); - memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); + ec_datagram_npwr(datagram, slave->station_address, + 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); + memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); for (j = 0; j < slave->fmmu_count; j++) { ec_fmmu_config(&slave->fmmus[j], slave, - command->data + EC_FMMU_SIZE * j); - } - - ec_master_queue_command(master, command); - fsm->slave_state = ec_fsm_slave_saveop; -} - -/*****************************************************************************/ - -/** - Slave state: SAVEOP. - Set slave state to SAVEOP. -*/ - -void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - - if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED || - command->working_counter != 1)) { - EC_ERR("FSM failed to set FMMUs on slave %i.\n", + datagram->data + EC_FMMU_SIZE * j); + } + + ec_master_queue_datagram(master, datagram); + fsm->slave_state = ec_fsm_slaveconf_fmmu; +} + +/*****************************************************************************/ + +/** + Slave state: FMMU. +*/ + +void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; + EC_ERR("Failed to set FMMUs on slave %i.\n", fsm->slave->ring_position); - fsm->slave->state_error = 1; - fsm->slave_state = ec_fsm_slave_end; return; } // set state to SAVEOP - fsm->slave_state = ec_fsm_slave_op; + fsm->slave_state = ec_fsm_slaveconf_saveop; fsm->change_new = EC_SLAVE_STATE_SAVEOP; fsm->change_state = ec_fsm_change_start; fsm->change_state(fsm); // execute immediately @@ -1281,16 +1290,16 @@ /*****************************************************************************/ /** - Slave state: OP. - Set slave state to OP. -*/ - -void ec_fsm_slave_op(ec_fsm_t *fsm /**< finite state machine */) + Slave state: SAVEOP. +*/ + +void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm /**< finite state machine */) { fsm->change_state(fsm); // execute state change state machine if (fsm->change_state == ec_fsm_change_error) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; return; } @@ -1298,12 +1307,12 @@ // slave is now in SAVEOP if (fsm->slave->current_state == fsm->slave->requested_state) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave_state = ec_fsm_slaveconf_end; // successful return; } // set state to OP - fsm->slave_state = ec_fsm_slave_op2; + fsm->slave_state = ec_fsm_slaveconf_op; fsm->change_new = EC_SLAVE_STATE_OP; fsm->change_state = ec_fsm_change_start; fsm->change_state(fsm); // execute immediately @@ -1312,23 +1321,23 @@ /*****************************************************************************/ /** - Slave state: OP2 - Executes the change state machine, until the OP state is set. -*/ - -void ec_fsm_slave_op2(ec_fsm_t *fsm /**< finite state machine */) + Slave state: OP +*/ + +void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */) { fsm->change_state(fsm); // execute state change state machine if (fsm->change_state == ec_fsm_change_error) { - fsm->slave_state = ec_fsm_slave_end; + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_slaveconf_end; return; } if (fsm->change_state != ec_fsm_change_end) return; // slave is now in OP - fsm->slave_state = ec_fsm_slave_end; + fsm->slave_state = ec_fsm_slaveconf_end; // successful } /*****************************************************************************/ @@ -1338,12 +1347,12 @@ End state of the slave state machine. */ -void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */) +void ec_fsm_slaveconf_end(ec_fsm_t *fsm /**< finite state machine */) { } /****************************************************************************** - * SII state machine + * SII sub state machine *****************************************************************************/ /** @@ -1353,20 +1362,20 @@ void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; // initiate read operation if (fsm->sii_mode) { - ec_command_npwr(command, fsm->slave->station_address, 0x502, 4); + ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); } else { - ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4); - } - - EC_WRITE_U8 (command->data, 0x00); // read-only access - EC_WRITE_U8 (command->data + 1, 0x01); // request read operation - EC_WRITE_U16(command->data + 2, fsm->sii_offset); - ec_master_queue_command(fsm->master, command); + ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); + } + + EC_WRITE_U8 (datagram->data, 0x00); // read-only access + EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation + EC_WRITE_U16(datagram->data + 2, fsm->sii_offset); + ec_master_queue_datagram(fsm->master, datagram); fsm->sii_state = ec_fsm_sii_read_check; } @@ -1374,30 +1383,30 @@ /** SII state: READ_CHECK. - Checks, if the SII-read-command has been sent and issues a fetch command. + Checks, if the SII-read-datagram has been sent and issues a fetch datagram. */ void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("SII: Reception of read command failed.\n"); + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + EC_ERR("SII: Reception of read datagram failed.\n"); fsm->sii_state = ec_fsm_sii_error; return; } fsm->sii_start = get_cycles(); - // issue check/fetch command + // issue check/fetch datagram if (fsm->sii_mode) { - ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); } else { - ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); - } - - ec_master_queue_command(fsm->master, command); + ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); + } + + ec_master_queue_datagram(fsm->master, datagram); fsm->sii_state = ec_fsm_sii_read_fetch; } @@ -1405,55 +1414,55 @@ /** SII state: READ_FETCH. - Fetches the result of an SII-read command. + Fetches the result of an SII-read datagram. */ void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("SII: Reception of check/fetch command failed.\n"); + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + EC_ERR("SII: Reception of check/fetch datagram failed.\n"); fsm->sii_state = ec_fsm_sii_error; return; } // check "busy bit" - if (EC_READ_U8(command->data + 1) & 0x81) { + if (EC_READ_U8(datagram->data + 1) & 0x81) { // still busy... timeout? if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { EC_ERR("SII: Timeout.\n"); fsm->sii_state = ec_fsm_sii_error; #if 0 EC_DBG("SII busy: %02X %02X %02X %02X\n", - EC_READ_U8(command->data + 0), - EC_READ_U8(command->data + 1), - EC_READ_U8(command->data + 2), - EC_READ_U8(command->data + 3)); + EC_READ_U8(datagram->data + 0), + EC_READ_U8(datagram->data + 1), + EC_READ_U8(datagram->data + 2), + EC_READ_U8(datagram->data + 3)); #endif } - // issue check/fetch command again + // issue check/fetch datagram again if (fsm->sii_mode) { - ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); } else { - ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); + ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); } - ec_master_queue_command(fsm->master, command); + ec_master_queue_datagram(fsm->master, datagram); return; } #if 0 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", - EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1), - EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3), - EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), - EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); + EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1), + EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3), + EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7), + EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9)); #endif // SII value received. - memcpy(fsm->sii_value, command->data + 6, 4); + memcpy(fsm->sii_value, datagram->data + 6, 4); fsm->sii_state = ec_fsm_sii_end; } @@ -1466,15 +1475,15 @@ void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; // initiate write operation - ec_command_npwr(command, fsm->slave->station_address, 0x502, 8); - EC_WRITE_U8 (command->data, 0x01); // enable write access - EC_WRITE_U8 (command->data + 1, 0x02); // request write operation - EC_WRITE_U32(command->data + 2, fsm->sii_offset); - memcpy(command->data + 6, fsm->sii_value, 2); - ec_master_queue_command(fsm->master, command); + ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8); + EC_WRITE_U8 (datagram->data, 0x01); // enable write access + EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation + EC_WRITE_U32(datagram->data + 2, fsm->sii_offset); + memcpy(datagram->data + 6, fsm->sii_value, 2); + ec_master_queue_datagram(fsm->master, datagram); fsm->sii_state = ec_fsm_sii_write_check; } @@ -1486,19 +1495,19 @@ void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("SII: Reception of write command failed.\n"); + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + EC_ERR("SII: Reception of write datagram failed.\n"); fsm->sii_state = ec_fsm_sii_error; return; } fsm->sii_start = get_cycles(); - // issue check/fetch command - ec_command_nprd(command, fsm->slave->station_address, 0x502, 2); - ec_master_queue_command(fsm->master, command); + // issue check/fetch datagram + ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); + ec_master_queue_datagram(fsm->master, datagram); fsm->sii_state = ec_fsm_sii_write_check2; } @@ -1510,25 +1519,25 @@ void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("SII: Reception of write check command failed.\n"); + ec_datagram_t *datagram = &fsm->datagram; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + EC_ERR("SII: Reception of write check datagram failed.\n"); fsm->sii_state = ec_fsm_sii_error; return; } - if (EC_READ_U8(command->data + 1) & 0x82) { + if (EC_READ_U8(datagram->data + 1) & 0x82) { // still busy... timeout? if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { EC_ERR("SII: Write timeout.\n"); fsm->sii_state = ec_fsm_sii_error; } - // issue check/fetch command again - ec_master_queue_command(fsm->master, command); - } - else if (EC_READ_U8(command->data + 1) & 0x40) { + // issue check/fetch datagram again + ec_master_queue_datagram(fsm->master, datagram); + } + else if (EC_READ_U8(datagram->data + 1) & 0x40) { EC_ERR("SII: Write operation failed!\n"); fsm->sii_state = ec_fsm_sii_error; } @@ -1560,7 +1569,7 @@ } /****************************************************************************** - * state change state machine + * state change sub state machine *****************************************************************************/ /** @@ -1569,13 +1578,13 @@ void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; // write new state to slave - ec_command_npwr(command, slave->station_address, 0x0120, 2); - EC_WRITE_U16(command->data, fsm->change_new); - ec_master_queue_command(fsm->master, command); + ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); + EC_WRITE_U16(datagram->data, fsm->change_new); + ec_master_queue_datagram(fsm->master, datagram); fsm->change_state = ec_fsm_change_check; } @@ -1587,53 +1596,50 @@ void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED) { - EC_ERR("Failed to send state command to slave %i!\n", + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED) { + fsm->change_state = ec_fsm_change_error; + EC_ERR("Failed to send state datagram to slave %i!\n", fsm->slave->ring_position); - slave->state_error = 1; + return; + } + + if (datagram->working_counter != 1) { fsm->change_state = ec_fsm_change_error; - return; - } - - if (command->working_counter != 1) { EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" " respond.\n", fsm->change_new, fsm->slave->ring_position); - slave->state_error = 1; + return; + } + + fsm->change_start = get_cycles(); + + // read AL status from slave + ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); + ec_master_queue_datagram(fsm->master, datagram); + fsm->change_state = ec_fsm_change_status; +} + +/*****************************************************************************/ + +/** + Change state: STATUS. +*/ + +void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { fsm->change_state = ec_fsm_change_error; - return; - } - - fsm->change_start = get_cycles(); - - // read AL status from slave - ec_command_nprd(command, slave->station_address, 0x0130, 2); - ec_master_queue_command(fsm->master, command); - fsm->change_state = ec_fsm_change_status; -} - -/*****************************************************************************/ - -/** - Change state: STATUS. -*/ - -void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { EC_ERR("Failed to check state 0x%02X on slave %i.\n", fsm->change_new, slave->ring_position); - slave->state_error = 1; - fsm->change_state = ec_fsm_change_error; - return; - } - - slave->current_state = EC_READ_U8(command->data); + return; + } + + slave->current_state = EC_READ_U8(datagram->data); if (slave->current_state == fsm->change_new) { // state has been set successfully @@ -1648,15 +1654,14 @@ " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, slave->current_state); // fetch AL status error code - ec_command_nprd(command, slave->station_address, 0x0134, 2); - ec_master_queue_command(fsm->master, command); + ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2); + ec_master_queue_datagram(fsm->master, datagram); fsm->change_state = ec_fsm_change_code; return; } if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { // timeout while checking - slave->state_error = 1; fsm->change_state = ec_fsm_change_error; EC_ERR("Timeout while setting state 0x%02X on slave %i.\n", fsm->change_new, slave->ring_position); @@ -1664,8 +1669,8 @@ } // still old state: check again - ec_command_nprd(command, slave->station_address, 0x0130, 2); - ec_master_queue_command(fsm->master, command); + ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); + ec_master_queue_datagram(fsm->master, datagram); } /*****************************************************************************/ @@ -1687,10 +1692,24 @@ {0x0019, "No valid outputs"}, {0x001A, "Synchronisation error"}, {0x001B, "Sync manager watchdog"}, + {0x001C, "Invalid sync manager types"}, + {0x001D, "Invalid output configuration"}, + {0x001E, "Invalid input configuration"}, + {0x001F, "Invalid watchdog configuration"}, {0x0020, "Slave needs cold start"}, {0x0021, "Slave needs INIT"}, {0x0022, "Slave needs PREOP"}, {0x0023, "Slave needs SAVEOP"}, + {0x0030, "Invalid DC SYNCH configuration"}, + {0x0031, "Invalid DC latch configuration"}, + {0x0032, "PLL error"}, + {0x0033, "Invalid DC IO error"}, + {0x0034, "Invalid DC timeout error"}, + {0x0042, "MBOX EOE"}, + {0x0043, "MBOX COE"}, + {0x0044, "MBOX FOE"}, + {0x0045, "MBOX SOE"}, + {0x004F, "MBOX VOE"}, {} }; @@ -1702,19 +1721,18 @@ void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; + ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; uint32_t code; const ec_code_msg_t *al_msg; - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("Reception of AL status code command failed.\n"); - slave->state_error = 1; + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { fsm->change_state = ec_fsm_change_error; - return; - } - - if ((code = EC_READ_U16(command->data))) { + EC_ERR("Reception of AL status code datagram failed.\n"); + return; + } + + if ((code = EC_READ_U16(datagram->data))) { for (al_msg = al_status_messages; al_msg->code; al_msg++) { if (al_msg->code != code) continue; EC_ERR("AL status message 0x%04X: \"%s\".\n", @@ -1726,9 +1744,9 @@ } // acknowledge "old" slave state - ec_command_npwr(command, slave->station_address, 0x0120, 2); - EC_WRITE_U16(command->data, slave->current_state); - ec_master_queue_command(fsm->master, command); + ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); + EC_WRITE_U16(datagram->data, slave->current_state); + ec_master_queue_datagram(fsm->master, datagram); fsm->change_state = ec_fsm_change_ack; } @@ -1740,55 +1758,62 @@ void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) { - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("Reception of state ack command failed.\n"); - slave->state_error = 1; + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { fsm->change_state = ec_fsm_change_error; - return; - } + EC_ERR("Reception of state ack datagram failed.\n"); + return; + } + + fsm->change_start = get_cycles(); // read new AL status - ec_command_nprd(command, slave->station_address, 0x0130, 2); - ec_master_queue_command(fsm->master, command); - fsm->change_state = ec_fsm_change_ack2; -} - -/*****************************************************************************/ - -/** - Change state: ACK. - Acknowledge 2. -*/ - -void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */) -{ - ec_command_t *command = &fsm->command; - ec_slave_t *slave = fsm->slave; - - if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { - EC_ERR("Reception of state ack check command failed.\n"); - slave->state_error = 1; + ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); + ec_master_queue_datagram(fsm->master, datagram); + fsm->change_state = ec_fsm_change_check_ack; +} + +/*****************************************************************************/ + +/** + Change state: CHECK ACK. +*/ + +void ec_fsm_change_check_ack(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + ec_slave_t *slave = fsm->slave; + ec_slave_state_t ack_state; + + if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { fsm->change_state = ec_fsm_change_error; - return; - } - - slave->current_state = EC_READ_U8(command->data); - - if (slave->current_state == fsm->change_new) { + EC_ERR("Reception of state ack check datagram failed.\n"); + return; + } + + ack_state = EC_READ_U8(datagram->data); + + if (ack_state == slave->current_state) { + fsm->change_state = ec_fsm_change_error; EC_INFO("Acknowleged state 0x%02X on slave %i.\n", slave->current_state, slave->ring_position); - slave->state_error = 1; + return; + } + + if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { + // timeout while checking + slave->current_state = EC_SLAVE_STATE_UNKNOWN; fsm->change_state = ec_fsm_change_error; - return; - } - - EC_WARN("Failed to acknowledge state 0x%02X on slave %i" - " - Timeout!\n", fsm->change_new, slave->ring_position); - slave->state_error = 1; - fsm->change_state = ec_fsm_change_error; + EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n", + fsm->change_new, slave->ring_position); + return; + } + + // reread new AL status + ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2); + ec_master_queue_datagram(fsm->master, datagram); } /*****************************************************************************/