From 5d4b915317bb4922f946b0e4de03ee5b9751d241 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Mon, 26 Jan 2009 13:22:05 +0000 Subject: [PATCH] merge -c1619 branches/1.4-foe: Implemented going to bootstrap state BOOT. --- NEWS | 3 ++ master/cdev.c | 12 +++++--- master/ethernet.c | 8 ++--- master/fsm_change.c | 18 ++++++------ master/fsm_coe.c | 2 +- master/fsm_foe.c | 19 ++++++------ master/fsm_master.c | 6 ++-- master/fsm_slave_config.c | 62 +++++++++++++++++++++++++++++---------- master/fsm_slave_scan.c | 18 ++++++++---- master/globals.h | 4 ++- master/ioctl.h | 12 +++++--- master/mailbox.c | 51 +++++++++++++++++++++++++------- master/module.c | 53 ++++++++++++++++++++++----------- master/slave.c | 26 +++++++++------- master/slave.h | 12 +++++--- tool/Command.cpp | 1 + tool/CommandSlaves.cpp | 16 ++++++---- tool/CommandStates.cpp | 4 ++- 18 files changed, 222 insertions(+), 105 deletions(-) diff --git a/NEWS b/NEWS index 53f67637..84030fba 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ Changes since 1.4.0: physical device. * Improved error case return codes of many functions. * Added 8139too driver for 2.6.25. +* Implemented the File Access over EtherCAT (FoE) mailbox protocol. +* Going to the Bootstrap state is now supported by the state machines and the + command-line tool. Changes in 1.4.0: diff --git a/master/cdev.c b/master/cdev.c index 643970c4..a6fbcd59 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -226,10 +226,14 @@ int ec_cdev_ioctl_slave( data.revision_number = slave->sii.revision_number; data.serial_number = slave->sii.serial_number; data.alias = slave->sii.alias; - data.rx_mailbox_offset = slave->sii.rx_mailbox_offset; - data.rx_mailbox_size = slave->sii.rx_mailbox_size; - data.tx_mailbox_offset = slave->sii.tx_mailbox_offset; - data.tx_mailbox_size = slave->sii.tx_mailbox_size; + data.boot_rx_mailbox_offset = slave->sii.boot_rx_mailbox_offset; + data.boot_rx_mailbox_size = slave->sii.boot_rx_mailbox_size; + data.boot_tx_mailbox_offset = slave->sii.boot_tx_mailbox_offset; + data.boot_tx_mailbox_size = slave->sii.boot_tx_mailbox_size; + data.std_rx_mailbox_offset = slave->sii.std_rx_mailbox_offset; + data.std_rx_mailbox_size = slave->sii.std_rx_mailbox_size; + data.std_tx_mailbox_offset = slave->sii.std_tx_mailbox_offset; + data.std_tx_mailbox_size = slave->sii.std_tx_mailbox_size; data.mailbox_protocols = slave->sii.mailbox_protocols; data.has_general_category = slave->sii.has_general; data.coe_details = slave->sii.coe_details; diff --git a/master/ethernet.c b/master/ethernet.c index d8e37f93..9f26b2da 100644 --- a/master/ethernet.c +++ b/master/ethernet.c @@ -218,6 +218,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */) /** Sends a frame or the next fragment. + \todo bootstrap mailboxes / use configured mailbox sizes */ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */) @@ -231,12 +232,11 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */) remaining_size = eoe->tx_frame->skb->len - eoe->tx_offset; - if (remaining_size <= eoe->slave->sii.tx_mailbox_size - 10) { + if (remaining_size <= eoe->slave->sii.std_tx_mailbox_size - 10) { current_size = remaining_size; last_fragment = 1; - } - else { - current_size = ((eoe->slave->sii.tx_mailbox_size - 10) / 32) * 32; + } else { + current_size = ((eoe->slave->sii.std_tx_mailbox_size - 10) / 32) * 32; last_fragment = 0; } diff --git a/master/fsm_change.c b/master/fsm_change.c index 322385c9..4973a9cb 100644 --- a/master/fsm_change.c +++ b/master/fsm_change.c @@ -187,7 +187,7 @@ void ec_fsm_change_state_check(ec_fsm_change_t *fsm if (datagram->working_counter == 0) { if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) { char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(fsm->requested_state, state_str); + ec_state_string(fsm->requested_state, state_str, 0); fsm->state = ec_fsm_change_state_error; EC_ERR("Failed to set state %s on slave %u: ", state_str, fsm->slave->ring_position); @@ -204,7 +204,7 @@ void ec_fsm_change_state_check(ec_fsm_change_t *fsm if (unlikely(datagram->working_counter > 1)) { char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(fsm->requested_state, state_str); + ec_state_string(fsm->requested_state, state_str, 0); fsm->state = ec_fsm_change_state_error; EC_ERR("Failed to set state %s on slave %u: ", state_str, fsm->slave->ring_position); @@ -247,7 +247,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm if (datagram->working_counter != 1) { char req_state[EC_STATE_STRING_SIZE]; - ec_state_string(fsm->requested_state, req_state); + ec_state_string(fsm->requested_state, req_state, 0); fsm->state = ec_fsm_change_state_error; EC_ERR("Failed to check state %s on slave %u: ", req_state, slave->ring_position); @@ -271,7 +271,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm if (slave->current_state != fsm->old_state) { // state changed char req_state[EC_STATE_STRING_SIZE], cur_state[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, cur_state); + ec_state_string(slave->current_state, cur_state, 0); if ((slave->current_state & 0x0F) != (fsm->old_state & 0x0F)) { // Slave spontaneously changed its state just before the new state @@ -287,7 +287,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm // state change error slave->error_flag = 1; - ec_state_string(fsm->requested_state, req_state); + ec_state_string(fsm->requested_state, req_state, 0); EC_ERR("Failed to set %s state, slave %u refused state change (%s).\n", req_state, slave->ring_position, cur_state); @@ -304,7 +304,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm if (datagram->jiffies_received - fsm->jiffies_start >= HZ) { // 1s // timeout while checking char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(fsm->requested_state, state_str); + ec_state_string(fsm->requested_state, state_str, 0); fsm->state = ec_fsm_change_state_error; EC_ERR("Timeout while setting state %s on slave %u.\n", state_str, slave->ring_position); @@ -326,7 +326,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm const ec_code_msg_t al_status_messages[] = { {0x0001, "Unspecified error"}, - {0x0011, "Invalud requested state change"}, + {0x0011, "Invalid requested state change"}, {0x0012, "Unknown requested state"}, {0x0013, "Bootstrap not supported"}, {0x0014, "No valid firmware"}, @@ -498,7 +498,7 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm if (!(slave->current_state & EC_SLAVE_STATE_ACK_ERR)) { char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, state_str); + ec_state_string(slave->current_state, state_str, 0); if (fsm->mode == EC_FSM_CHANGE_MODE_FULL) { fsm->state = ec_fsm_change_state_error; } @@ -513,7 +513,7 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm if (datagram->jiffies_received - fsm->jiffies_start >= HZ) { // 1s // timeout while checking char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, state_str); + ec_state_string(slave->current_state, state_str, 0); fsm->state = ec_fsm_change_state_error; EC_ERR("Timeout while acknowledging state %s on slave %u.\n", state_str, slave->ring_position); diff --git a/master/fsm_coe.c b/master/fsm_coe.c index f0a8ed3b..2af301e2 100644 --- a/master/fsm_coe.c +++ b/master/fsm_coe.c @@ -1095,7 +1095,7 @@ void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */) } } else { // request->data_size > 4, use normal transfer type - if (slave->sii.rx_mailbox_size < 6 + 10 + request->data_size) { + if (slave->sii.std_rx_mailbox_size < 6 + 10 + request->data_size) { EC_ERR("SDO fragmenting not supported yet!\n"); fsm->state = ec_fsm_coe_error; return; diff --git a/master/fsm_foe.c b/master/fsm_foe.c index 12182042..87ef7331 100644 --- a/master/fsm_foe.c +++ b/master/fsm_foe.c @@ -214,12 +214,13 @@ int ec_foe_prepare_data_send( ec_fsm_foe_t *fsm ) { remaining_size = fsm->tx_buffer_size - fsm->tx_buffer_offset; - if (remaining_size < fsm->slave->sii.tx_mailbox_size - EC_MBOX_HEADER_SIZE - EC_FOE_HEADER_SIZE) { + if (remaining_size < fsm->slave->sii.std_tx_mailbox_size + - EC_MBOX_HEADER_SIZE - EC_FOE_HEADER_SIZE) { current_size = remaining_size; fsm->tx_last_packet = 1; - } - else { - current_size = fsm->slave->sii.tx_mailbox_size - EC_MBOX_HEADER_SIZE - EC_FOE_HEADER_SIZE; + } else { + current_size = fsm->slave->sii.std_tx_mailbox_size + - EC_MBOX_HEADER_SIZE - EC_FOE_HEADER_SIZE; } if (!(data = ec_slave_mbox_prepare_send(fsm->slave, fsm->datagram, @@ -788,12 +789,12 @@ void ec_fsm_foe_state_data_read ( ec_fsm_foe_t *fsm ) { fsm->rx_last_packet = (rec_size + EC_MBOX_HEADER_SIZE + EC_FOE_HEADER_SIZE - != fsm->slave->sii.rx_mailbox_size); + != fsm->slave->sii.std_rx_mailbox_size); if (fsm->rx_last_packet || - (slave->sii.rx_mailbox_size - EC_MBOX_HEADER_SIZE - - EC_FOE_HEADER_SIZE + fsm->rx_buffer_offset) <= fsm->rx_buffer_size) { - // either it was the last packet or a new packet will fit into the delivered buffer + (slave->sii.std_rx_mailbox_size - EC_MBOX_HEADER_SIZE + - EC_FOE_HEADER_SIZE + fsm->rx_buffer_offset) <= fsm->rx_buffer_size) { + // either it was the last packet or a new packet will fit into the delivered buffer #ifdef myDEBUG printk ("last_packet=true\n"); #endif @@ -811,7 +812,7 @@ void ec_fsm_foe_state_data_read ( ec_fsm_foe_t *fsm ) { printk (" rx_buffer_size = %d\n", fsm->rx_buffer_size); printk (" rx_buffer_offset= %d\n", fsm->rx_buffer_offset); printk (" rec_size = %d\n", rec_size); - printk (" rx_mailbox_size = %d\n", slave->sii.rx_mailbox_size); + printk (" rx_mailbox_size = %d\n", slave->sii.std_rx_mailbox_size); printk (" rx_last_packet = %d\n", fsm->rx_last_packet); // fsm->state = ec_fsm_state_wait_next_read; fsm->request->result = FOE_READY; diff --git a/master/fsm_master.c b/master/fsm_master.c index ae51899f..aca58ced 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -201,7 +201,7 @@ void ec_fsm_master_state_broadcast( if (states != fsm->slave_states) { // slave states changed? char state_str[EC_STATE_STRING_SIZE]; fsm->slave_states = states; - ec_state_string(fsm->slave_states, state_str); + ec_state_string(fsm->slave_states, state_str, 1); EC_INFO("Slave states: %s.\n", state_str); } } else { @@ -622,8 +622,8 @@ void ec_fsm_master_action_configure( if (master->debug_level) { char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, old_state); - ec_state_string(slave->requested_state, new_state); + ec_state_string(slave->current_state, old_state, 0); + ec_state_string(slave->requested_state, new_state, 0); EC_DBG("Changing state of slave %u from %s to %s%s.\n", slave->ring_position, old_state, new_state, slave->force_config ? " (forced)" : ""); diff --git a/master/fsm_slave_config.c b/master/fsm_slave_config.c index fe9b6563..2b05d844 100644 --- a/master/fsm_slave_config.c +++ b/master/fsm_slave_config.c @@ -43,7 +43,7 @@ void ec_fsm_slave_config_state_start(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_state_preop(ec_fsm_slave_config_t *); +void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *); @@ -53,7 +53,7 @@ void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_init(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_enter_preop(ec_fsm_slave_config_t *); +void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *); @@ -289,7 +289,7 @@ void ec_fsm_slave_config_enter_mbox_sync( if (master->debug_level) EC_DBG("Slave %u does not support mailbox communication.\n", slave->ring_position); - ec_fsm_slave_config_enter_preop(fsm); + ec_fsm_slave_config_enter_boot_preop(fsm); return; } @@ -298,7 +298,29 @@ void ec_fsm_slave_config_enter_mbox_sync( slave->ring_position); } - if (slave->sii.sync_count >= 2) { // mailbox configuration provided + if (slave->requested_state == EC_SLAVE_STATE_BOOT) { + ec_sync_t sync; + + ec_datagram_fpwr(datagram, slave->station_address, 0x0800, + EC_SYNC_PAGE_SIZE * 2); + memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * 2); + + ec_sync_init(&sync, slave); + sync.physical_start_address = slave->sii.boot_rx_mailbox_offset; + sync.control_register = 0x26; + sync.enable = 1; + ec_sync_page(&sync, 0, slave->sii.boot_rx_mailbox_size, + EC_DIR_INVALID, // use default direction + datagram->data); + + ec_sync_init(&sync, slave); + sync.physical_start_address = slave->sii.boot_tx_mailbox_offset; + sync.control_register = 0x22; + sync.enable = 1; + ec_sync_page(&sync, 1, slave->sii.boot_tx_mailbox_size, + EC_DIR_INVALID, // use default direction + datagram->data + EC_SYNC_PAGE_SIZE); + } else if (slave->sii.sync_count >= 2) { // mailbox configuration provided ec_datagram_fpwr(datagram, slave->station_address, 0x0800, EC_SYNC_PAGE_SIZE * slave->sii.sync_count); ec_datagram_zero(datagram); @@ -322,18 +344,18 @@ void ec_fsm_slave_config_enter_mbox_sync( ec_datagram_zero(datagram); ec_sync_init(&sync, slave); - sync.physical_start_address = slave->sii.rx_mailbox_offset; + sync.physical_start_address = slave->sii.std_rx_mailbox_offset; sync.control_register = 0x26; sync.enable = 1; - ec_sync_page(&sync, 0, slave->sii.rx_mailbox_size, + ec_sync_page(&sync, 0, slave->sii.std_rx_mailbox_size, EC_DIR_INVALID, // use default direction datagram->data); ec_sync_init(&sync, slave); - sync.physical_start_address = slave->sii.tx_mailbox_offset; + sync.physical_start_address = slave->sii.std_tx_mailbox_offset; sync.control_register = 0x22; sync.enable = 1; - ec_sync_page(&sync, 1, slave->sii.tx_mailbox_size, + ec_sync_page(&sync, 1, slave->sii.std_tx_mailbox_size, EC_DIR_INVALID, // use default direction datagram->data + EC_SYNC_PAGE_SIZE); } @@ -373,27 +395,33 @@ void ec_fsm_slave_config_state_mbox_sync( return; } - ec_fsm_slave_config_enter_preop(fsm); + ec_fsm_slave_config_enter_boot_preop(fsm); } /*****************************************************************************/ /** Request PREOP state. */ -void ec_fsm_slave_config_enter_preop( +void ec_fsm_slave_config_enter_boot_preop( ec_fsm_slave_config_t *fsm /**< slave state machine */ ) { - fsm->state = ec_fsm_slave_config_state_preop; - ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP); + fsm->state = ec_fsm_slave_config_state_boot_preop; + + if (fsm->slave->requested_state != EC_SLAVE_STATE_BOOT) { + ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP); + } else { // BOOT + ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_BOOT); + } + ec_fsm_change_exec(fsm->fsm_change); // execute immediately } /*****************************************************************************/ -/** Slave configuration state: PREOP. +/** Slave configuration state: BOOT/PREOP. */ -void ec_fsm_slave_config_state_preop( +void ec_fsm_slave_config_state_boot_preop( ec_fsm_slave_config_t *fsm /**< slave state machine */ ) { @@ -409,11 +437,13 @@ void ec_fsm_slave_config_state_preop( return; } - // slave is now in PREOP + // slave is now in BOOT/PREOP slave->jiffies_preop = fsm->datagram->jiffies_received; if (master->debug_level) { - EC_DBG("Slave %u is now in PREOP.\n", slave->ring_position); + EC_DBG("Slave %u is now in %s.\n", slave->ring_position, + slave->requested_state != EC_SLAVE_STATE_BOOT + ? "PREOP" : "BOOT"); } if (slave->current_state == slave->requested_state) { diff --git a/master/fsm_slave_scan.c b/master/fsm_slave_scan.c index b2134705..632b6dac 100644 --- a/master/fsm_slave_scan.c +++ b/master/fsm_slave_scan.c @@ -237,7 +237,7 @@ void ec_fsm_slave_scan_state_state( slave->current_state = EC_READ_U8(datagram->data); if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { char state_str[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, state_str); + ec_state_string(slave->current_state, state_str, 0); EC_WARN("Slave %u has state error bit set (%s)!\n", slave->ring_position, state_str); } @@ -469,13 +469,21 @@ void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm /**< slave state EC_READ_U32(slave->sii_words + 0x000C); slave->sii.serial_number = EC_READ_U32(slave->sii_words + 0x000E); - slave->sii.rx_mailbox_offset = + slave->sii.boot_rx_mailbox_offset = + EC_READ_U16(slave->sii_words + 0x0014); + slave->sii.boot_rx_mailbox_size = + EC_READ_U16(slave->sii_words + 0x0015); + slave->sii.boot_tx_mailbox_offset = + EC_READ_U16(slave->sii_words + 0x0016); + slave->sii.boot_tx_mailbox_size = + EC_READ_U16(slave->sii_words + 0x0017); + slave->sii.std_rx_mailbox_offset = EC_READ_U16(slave->sii_words + 0x0018); - slave->sii.rx_mailbox_size = + slave->sii.std_rx_mailbox_size = EC_READ_U16(slave->sii_words + 0x0019); - slave->sii.tx_mailbox_offset = + slave->sii.std_tx_mailbox_offset = EC_READ_U16(slave->sii_words + 0x001A); - slave->sii.tx_mailbox_size = + slave->sii.std_tx_mailbox_size = EC_READ_U16(slave->sii_words + 0x001B); slave->sii.mailbox_protocols = EC_READ_U16(slave->sii_words + 0x001C); diff --git a/master/globals.h b/master/globals.h index a1d16cc4..1cb9dad7 100644 --- a/master/globals.h +++ b/master/globals.h @@ -115,6 +115,8 @@ typedef enum { /**< INIT state (no mailbox communication, no IO) */ EC_SLAVE_STATE_PREOP = 0x02, /**< PREOP state (mailbox communication, no IO) */ + EC_SLAVE_STATE_BOOT = 0x03, + /**< Bootstrap state (mailbox communication, firmware update) */ EC_SLAVE_STATE_SAFEOP = 0x04, /**< SAFEOP (mailbox communication and input update) */ EC_SLAVE_STATE_OP = 0x08, @@ -226,7 +228,7 @@ extern char *ec_master_version_str; void ec_print_data(const uint8_t *, size_t); void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t); -size_t ec_state_string(uint8_t, char *); +size_t ec_state_string(uint8_t, char *, uint8_t); ssize_t ec_mac_print(const uint8_t *, char *); int ec_mac_is_zero(const uint8_t *); diff --git a/master/ioctl.h b/master/ioctl.h index 967560a6..d55728f6 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -135,10 +135,14 @@ typedef struct { uint32_t revision_number; uint32_t serial_number; uint16_t alias; - uint16_t rx_mailbox_offset; - uint16_t rx_mailbox_size; - uint16_t tx_mailbox_offset; - uint16_t tx_mailbox_size; + uint16_t boot_rx_mailbox_offset; + uint16_t boot_rx_mailbox_size; + uint16_t boot_tx_mailbox_offset; + uint16_t boot_tx_mailbox_size; + uint16_t std_rx_mailbox_offset; + uint16_t std_rx_mailbox_size; + uint16_t std_tx_mailbox_offset; + uint16_t std_tx_mailbox_size; uint16_t mailbox_protocols; uint8_t has_general_category; ec_sii_coe_details_t coe_details; diff --git a/master/mailbox.c b/master/mailbox.c index dfefd7d2..77d8fb3a 100644 --- a/master/mailbox.c +++ b/master/mailbox.c @@ -53,6 +53,7 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */ { size_t total_size; int ret; + uint16_t mailbox_offset, mailbox_size; if (unlikely(!slave->sii.mailbox_protocols)) { EC_ERR("Slave %u does not support mailbox communication!\n", @@ -61,14 +62,22 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */ } total_size = EC_MBOX_HEADER_SIZE + size; - if (unlikely(total_size > slave->sii.rx_mailbox_size)) { + + if (slave->current_state != EC_SLAVE_STATE_BOOT) { + mailbox_offset = slave->sii.std_rx_mailbox_offset; + mailbox_size = slave->sii.std_rx_mailbox_size; + } else { + mailbox_offset = slave->sii.boot_rx_mailbox_offset; + mailbox_size = slave->sii.boot_rx_mailbox_size; + } + + if (unlikely(total_size > mailbox_size)) { EC_ERR("Data size does not fit in mailbox!\n"); return ERR_PTR(-EOVERFLOW); } ret = ec_datagram_fpwr(datagram, slave->station_address, - slave->sii.rx_mailbox_offset, - slave->sii.rx_mailbox_size); + mailbox_offset, mailbox_size); if (ret) return ERR_PTR(ret); @@ -123,9 +132,19 @@ int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */ ec_datagram_t *datagram /**< datagram */ ) { - int ret = ec_datagram_fprd(datagram, slave->station_address, - slave->sii.tx_mailbox_offset, - slave->sii.tx_mailbox_size); + int ret; + uint16_t mailbox_offset, mailbox_size; + + if (slave->current_state != EC_SLAVE_STATE_BOOT) { + mailbox_offset = slave->sii.std_tx_mailbox_offset; + mailbox_size = slave->sii.std_tx_mailbox_size; + } else { + mailbox_offset = slave->sii.boot_tx_mailbox_offset; + mailbox_size = slave->sii.boot_tx_mailbox_size; + } + + ret = ec_datagram_fprd(datagram, slave->station_address, + mailbox_offset, mailbox_size); if (ret) return ret; @@ -164,13 +183,22 @@ uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */ ) { size_t data_size; + uint16_t mailbox_offset, mailbox_size; + + if (slave->current_state != EC_SLAVE_STATE_BOOT) { + mailbox_offset = slave->sii.std_tx_mailbox_offset; + mailbox_size = slave->sii.std_tx_mailbox_size; + } else { + mailbox_offset = slave->sii.boot_tx_mailbox_offset; + mailbox_size = slave->sii.boot_tx_mailbox_size; + } data_size = EC_READ_U16(datagram->data); - if (data_size + EC_MBOX_HEADER_SIZE > slave->sii.tx_mailbox_size) { + if (data_size + EC_MBOX_HEADER_SIZE > mailbox_size) { EC_ERR("Corrupt mailbox response received from slave %u!\n", - slave->ring_position); - ec_print_data(datagram->data, slave->sii.tx_mailbox_size); + slave->ring_position); + ec_print_data(datagram->data, mailbox_size); return ERR_PTR(-EPROTO); } @@ -185,9 +213,10 @@ uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */ slave->ring_position); for (mbox_msg = mbox_error_messages; mbox_msg->code; mbox_msg++) { - if (mbox_msg->code != code) continue; + if (mbox_msg->code != code) + continue; printk("Code 0x%04X: \"%s\".\n", - mbox_msg->code, mbox_msg->message); + mbox_msg->code, mbox_msg->message); break; } diff --git a/master/module.c b/master/module.c index 3eff5696..63e95ef1 100644 --- a/master/module.c +++ b/master/module.c @@ -358,8 +358,9 @@ void ec_print_data_diff(const uint8_t *d1, /**< first data */ /** Prints slave states in clear text. */ size_t ec_state_string(uint8_t states, /**< slave states */ - char *buffer /**< target buffer + char *buffer, /**< target buffer (min. EC_STATE_STRING_SIZE bytes) */ + uint8_t multi /**< Show multi-state mask. */ ) { off_t off = 0; @@ -370,24 +371,42 @@ size_t ec_state_string(uint8_t states, /**< slave states */ return off; } - if (states & EC_SLAVE_STATE_INIT) { - off += sprintf(buffer + off, "INIT"); + if (multi) { // multiple slaves + if (states & EC_SLAVE_STATE_INIT) { + off += sprintf(buffer + off, "INIT"); + first = 0; + } + if (states & EC_SLAVE_STATE_PREOP) { + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "PREOP"); + first = 0; + } + if (states & EC_SLAVE_STATE_SAFEOP) { + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "SAFEOP"); + first = 0; + } + if (states & EC_SLAVE_STATE_OP) { + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "OP"); + } + } else { // single slave + if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_INIT) { + off += sprintf(buffer + off, "INIT"); + } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_PREOP) { + off += sprintf(buffer + off, "PREOP"); + } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_BOOT) { + off += sprintf(buffer + off, "BOOT"); + } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_SAFEOP) { + off += sprintf(buffer + off, "SAFEOP"); + } else if ((states & EC_SLAVE_STATE_MASK) == EC_SLAVE_STATE_OP) { + off += sprintf(buffer + off, "OP"); + } else { + off += sprintf(buffer + off, "(invalid)"); + } first = 0; } - if (states & EC_SLAVE_STATE_PREOP) { - if (!first) off += sprintf(buffer + off, ", "); - off += sprintf(buffer + off, "PREOP"); - first = 0; - } - if (states & EC_SLAVE_STATE_SAFEOP) { - if (!first) off += sprintf(buffer + off, ", "); - off += sprintf(buffer + off, "SAFEOP"); - first = 0; - } - if (states & EC_SLAVE_STATE_OP) { - if (!first) off += sprintf(buffer + off, ", "); - off += sprintf(buffer + off, "OP"); - } + if (states & EC_SLAVE_STATE_ACK_ERR) { if (!first) off += sprintf(buffer + off, " + "); off += sprintf(buffer + off, "ERROR"); diff --git a/master/slave.c b/master/slave.c index 0c321f74..cd4fc05a 100644 --- a/master/slave.c +++ b/master/slave.c @@ -90,15 +90,19 @@ void ec_slave_init( slave->sii_words = NULL; slave->sii_nwords = 0; - slave->sii.alias = 0; - slave->sii.vendor_id = 0; - slave->sii.product_code = 0; - slave->sii.revision_number = 0; - slave->sii.serial_number = 0; - slave->sii.rx_mailbox_offset = 0; - slave->sii.rx_mailbox_size = 0; - slave->sii.tx_mailbox_offset = 0; - slave->sii.tx_mailbox_size = 0; + slave->sii.alias = 0x0000; + slave->sii.vendor_id = 0x00000000; + slave->sii.product_code = 0x00000000; + slave->sii.revision_number = 0x00000000; + slave->sii.serial_number = 0x00000000; + slave->sii.boot_rx_mailbox_offset = 0x0000; + slave->sii.boot_rx_mailbox_size = 0x0000; + slave->sii.boot_tx_mailbox_offset = 0x0000; + slave->sii.boot_tx_mailbox_size = 0x0000; + slave->sii.std_rx_mailbox_offset = 0x0000; + slave->sii.std_rx_mailbox_size = 0x0000; + slave->sii.std_tx_mailbox_offset = 0x0000; + slave->sii.std_tx_mailbox_size = 0x0000; slave->sii.mailbox_protocols = 0; slave->sii.strings = NULL; @@ -199,8 +203,8 @@ void ec_slave_set_state(ec_slave_t *slave, /**< EtherCAT slave */ if (slave->master->debug_level) { char old_state[EC_STATE_STRING_SIZE], cur_state[EC_STATE_STRING_SIZE]; - ec_state_string(slave->current_state, old_state); - ec_state_string(new_state, cur_state); + ec_state_string(slave->current_state, old_state, 0); + ec_state_string(new_state, cur_state, 0); EC_DBG("Slave %u: %s -> %s.\n", slave->ring_position, old_state, cur_state); } diff --git a/master/slave.h b/master/slave.h index 75ffc755..266313a8 100644 --- a/master/slave.h +++ b/master/slave.h @@ -54,10 +54,14 @@ typedef struct { uint32_t product_code; /**< Vendor-specific product code. */ uint32_t revision_number; /**< Revision number. */ uint32_t serial_number; /**< Serial number. */ - uint16_t rx_mailbox_offset; /**< Mailbox address (master to slave). */ - uint16_t rx_mailbox_size; /**< Mailbox size (master to slave). */ - uint16_t tx_mailbox_offset; /**< Mailbox address (slave to master). */ - uint16_t tx_mailbox_size; /**< Mailbox size (slave to master). */ + uint16_t boot_rx_mailbox_offset; /**< Bootstrap receive mailbox address. */ + uint16_t boot_rx_mailbox_size; /**< Bootstrap receive mailbox size. */ + uint16_t boot_tx_mailbox_offset; /**< Bootstrap transmit mailbox address. */ + uint16_t boot_tx_mailbox_size; /**< Bootstrap transmit mailbox size. */ + uint16_t std_rx_mailbox_offset; /**< Standard receive mailbox address. */ + uint16_t std_rx_mailbox_size; /**< Standard receive mailbox size. */ + uint16_t std_tx_mailbox_offset; /**< Standard transmit mailbox address. */ + uint16_t std_tx_mailbox_size; /**< Standard transmit mailbox size. */ uint16_t mailbox_protocols; /**< Supported mailbox protocols. */ // Strings diff --git a/tool/Command.cpp b/tool/Command.cpp index b2f81b7b..c54036ec 100644 --- a/tool/Command.cpp +++ b/tool/Command.cpp @@ -284,6 +284,7 @@ string Command::alStateString(uint8_t state) switch (state) { case 1: return "INIT"; case 2: return "PREOP"; + case 3: return "BOOT"; case 4: return "SAFEOP"; case 8: return "OP"; default: return "???"; diff --git a/tool/CommandSlaves.cpp b/tool/CommandSlaves.cpp index f13736f8..cf4c438f 100644 --- a/tool/CommandSlaves.cpp +++ b/tool/CommandSlaves.cpp @@ -216,12 +216,18 @@ void CommandSlaves::showSlaves( list::const_iterator protoIter; cout << "Mailboxes:" << endl - << " RX: 0x" - << hex << setw(4) << si->rx_mailbox_offset << "/" - << dec << si->rx_mailbox_size + << " Bootstrap RX: 0x" + << hex << setw(4) << si->boot_rx_mailbox_offset << "/" + << dec << si->boot_rx_mailbox_size << ", TX: 0x" - << hex << setw(4) << si->tx_mailbox_offset << "/" - << dec << si->tx_mailbox_size << endl + << hex << setw(4) << si->boot_tx_mailbox_offset << "/" + << dec << si->boot_tx_mailbox_size << endl + << " Standard RX: 0x" + << hex << setw(4) << si->std_rx_mailbox_offset << "/" + << dec << si->std_rx_mailbox_size + << ", TX: 0x" + << hex << setw(4) << si->std_tx_mailbox_offset << "/" + << dec << si->std_tx_mailbox_size << endl << " Supported protocols: "; if (si->mailbox_protocols & EC_MBOX_AOE) { diff --git a/tool/CommandStates.cpp b/tool/CommandStates.cpp index cc855429..ed706f2b 100644 --- a/tool/CommandStates.cpp +++ b/tool/CommandStates.cpp @@ -28,7 +28,7 @@ string CommandStates::helpString() const << getBriefDescription() << endl << endl << "Arguments:" << endl - << " STATE can be 'INIT', 'PREOP', 'SAFEOP', or 'OP'." << endl + << " STATE can be 'INIT', 'PREOP', 'BOOT', 'SAFEOP', or 'OP'." << endl << endl << "Command-specific options:" << endl << " --alias -a " << endl @@ -63,6 +63,8 @@ void CommandStates::execute(MasterDevice &m, const StringVector &args) state = 0x01; } else if (stateStr == "PREOP") { state = 0x02; + } else if (stateStr == "BOOT") { + state = 0x03; } else if (stateStr == "SAFEOP") { state = 0x04; } else if (stateStr == "OP") {