Added configure option for redundancy (--with-devices).

This commit is contained in:
Florian Pose 2012-11-30 20:15:31 +01:00
parent 19d1b6ee9c
commit 3cb0b12899
21 changed files with 466 additions and 294 deletions

13
TODO
View File

@ -8,6 +8,15 @@ vim700: spelllang=en spell
-------------------------------------------------------------------------------
Version 1.5.2:
• Try redundancy with more then 2 devices.
• Document --with-devices.
• Document RTDM interface.
• Set the "Cyclic Generation Start Time" based on the slave's
"System Time" register instead of using the application time.
• Add ecrt_slave_config_reg_pdo_entry_by_pos().
Future issues:
* Fix link detection in generic driver.
@ -19,7 +28,6 @@ Future issues:
* Only output watchdog config if not default.
* Implement CompleteAccess for SDO uploads.
* Output warning when send_ext() is called in illegal context.
* Change SDO index at runtime for SDO request.
* Implement ecrt_slave_config_request_state().
* Remove default buffer size in SDO upload.
* Override sync manager size?
@ -29,8 +37,6 @@ Future issues:
- Skip setting system time offset when application detached.
- How to use the SYNC1 shift time?
- Do not output graph, if topology calculation failed.
- Set the "Cyclic Generation Start Time" based on the slave's
"System Time" register instead of using the application time.
- Check if register 0x0980 is working, to avoid clearing it when
configuring.
* Mailbox protocol handlers.
@ -43,7 +49,6 @@ Future issues:
* Separate CoE debugging.
* Evaluate EEPROM contents after writing.
* Optimize alignment of process data.
* Redundancy with 2 network adapters.
* Interface/buffers for asynchronous domain IO.
* Make scanning and configuration run parallel (each).
* ethercat tool:

View File

@ -781,6 +781,38 @@ if test "x${wildcards}" = "x1"; then
[Use vendor id / product code wildcards])
fi
#------------------------------------------------------------------------------
# Redundancy (number of devices)
#------------------------------------------------------------------------------
AC_ARG_WITH([devices],
AC_HELP_STRING(
[--with-devices=<NUMBER>],
[Number of Ethernet devices per master. Default: 1]
),
[
devices=[$withval]
],
[
devices=1
]
)
AC_MSG_CHECKING([for number of Ethernet devices])
if test "${devices}" -lt 1; then
AC_MSG_ERROR([Number must be greater zero!])
else
if test "${devices}" -gt 1; then
AC_MSG_RESULT([$devices (Redundancy enabled)])
else
AC_MSG_RESULT([$devices (Redundancy disabled)])
fi
fi
AC_DEFINE_UNQUOTED([EC_MAX_NUM_DEVICES], $devices,
[Max. number of Ethernet devices per master])
#------------------------------------------------------------------------------
AC_CONFIG_FILES([

View File

@ -58,29 +58,34 @@ int ec_datagram_pair_init(
INIT_LIST_HEAD(&pair->list);
pair->domain = domain;
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_init(&pair->datagrams[dev_idx]);
snprintf(pair->datagrams[dev_idx].name,
EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
logical_offset, ec_device_names[dev_idx]);
logical_offset, ec_device_names[dev_idx != 0]);
pair->datagrams[dev_idx].device_index = dev_idx;
}
pair->expected_working_counter = 0U;
/* backup datagram has its own memory */
ret = ec_datagram_prealloc(&pair->datagrams[EC_DEVICE_BACKUP],
data_size);
if (ret) {
goto out_datagrams;
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
/* backup datagrams have their own memory */
ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
if (ret) {
goto out_datagrams;
}
}
#if EC_MAX_NUM_DEVICES > 1
if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
EC_MASTER_ERR(domain->master,
"Failed to allocate domain send buffer!\n");
ret = -ENOMEM;
goto out_datagrams;
}
#endif
/* The ec_datagram_lxx() calls below can not fail, because either the
* datagram has external memory or it is preallocated. */
@ -88,8 +93,12 @@ int ec_datagram_pair_init(
if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) { // inputs and outputs
ec_datagram_lrw_ext(&pair->datagrams[EC_DEVICE_MAIN],
logical_offset, data_size, data);
ec_datagram_lrw(&pair->datagrams[EC_DEVICE_BACKUP],
logical_offset, data_size);
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_lrw(&pair->datagrams[dev_idx],
logical_offset, data_size);
}
// If LRW is used, output FMMUs increment the working counter by 2,
// while input FMMUs increment it by 1.
@ -98,27 +107,35 @@ int ec_datagram_pair_init(
} else if (used[EC_DIR_OUTPUT]) { // outputs only
ec_datagram_lwr_ext(&pair->datagrams[EC_DEVICE_MAIN],
logical_offset, data_size, data);
ec_datagram_lwr(&pair->datagrams[EC_DEVICE_BACKUP],
logical_offset, data_size);
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_lwr(&pair->datagrams[dev_idx],
logical_offset, data_size);
}
pair->expected_working_counter = used[EC_DIR_OUTPUT];
} else { // inputs only (or nothing)
ec_datagram_lrd_ext(&pair->datagrams[EC_DEVICE_MAIN],
logical_offset, data_size, data);
ec_datagram_lrd(&pair->datagrams[EC_DEVICE_BACKUP],
logical_offset, data_size);
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
data_size);
}
pair->expected_working_counter = used[EC_DIR_INPUT];
}
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_zero(&pair->datagrams[dev_idx]);
}
return 0;
out_datagrams:
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
ec_datagram_clear(&pair->datagrams[dev_idx]);
}
@ -135,13 +152,17 @@ void ec_datagram_pair_clear(
{
unsigned int dev_idx;
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(pair->domain->master);
dev_idx++) {
ec_datagram_clear(&pair->datagrams[dev_idx]);
}
#if EC_MAX_NUM_DEVICES > 1
if (pair->send_buffer) {
kfree(pair->send_buffer);
}
#endif
}
/*****************************************************************************/
@ -150,13 +171,14 @@ void ec_datagram_pair_clear(
*/
uint16_t ec_datagram_pair_process(
ec_datagram_pair_t *pair, /**< Datagram pair. */
uint16_t wc_sum[EC_NUM_DEVICES] /**< Working counter sums. */
uint16_t wc_sum[] /**< Working counter sums. */
)
{
unsigned int dev_idx;
uint16_t pair_wc = 0;
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
dev_idx++) {
ec_datagram_t *datagram = &pair->datagrams[dev_idx];
ec_datagram_output_stats(datagram);

View File

@ -49,9 +49,10 @@
typedef struct {
struct list_head list; /**< List header. */
ec_domain_t *domain;
ec_datagram_t datagrams[EC_NUM_DEVICES]; /**< Main and backup datagram.
*/
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]; /**< Datagrams. */
#if EC_MAX_NUM_DEVICES > 1
uint8_t *send_buffer;
#endif
unsigned int expected_working_counter; /**< Expectord working conter. */
} ec_datagram_pair_t;
@ -61,8 +62,7 @@ int ec_datagram_pair_init(ec_datagram_pair_t *, ec_domain_t *, uint32_t,
uint8_t *, size_t, const unsigned int []);
void ec_datagram_pair_clear(ec_datagram_pair_t *);
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *,
uint16_t[EC_NUM_DEVICES]);
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *, uint16_t[]);
/*****************************************************************************/

View File

@ -81,10 +81,12 @@ int ec_device_init(
device->tx_ring_index = 0;
#ifdef EC_DEBUG_IF
if (device == &master->main_device)
if (device == &master->devices[EC_DEVICE_MAIN]) {
mb = 'm';
else if (device == &master->backup_device)
}
else {
mb = 'b';
}
sprintf(ifname, "ecdbg%c%u", mb, master->index);
@ -136,7 +138,9 @@ void ec_device_clear(
{
unsigned int i;
if (device->open) ec_device_close(device);
if (device->open) {
ec_device_close(device);
}
for (i = 0; i < EC_TX_RING_SIZE; i++)
dev_kfree_skb(device->tx_skb[i]);
#ifdef EC_DEBUG_IF
@ -541,6 +545,7 @@ int ecdev_open(ec_device_t *device /**< EtherCAT device */)
{
int ret;
ec_master_t *master = device->master;
unsigned int all_open = 1, dev_idx;
ret = ec_device_open(device);
if (ret) {
@ -548,9 +553,15 @@ int ecdev_open(ec_device_t *device /**< EtherCAT device */)
return ret;
}
if (master->devices[EC_DEVICE_MAIN].open &&
(ec_mac_is_zero(master->macs[EC_DEVICE_BACKUP]) ||
master->devices[EC_DEVICE_BACKUP].open)) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(device->master); dev_idx++) {
if (!master->devices[dev_idx].open) {
all_open = 0;
break;
}
}
if (all_open) {
ret = ec_master_enter_idle_phase(device->master);
if (ret) {
EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");

View File

@ -59,6 +59,8 @@ void ec_domain_init(
unsigned int index /**< Index. */
)
{
unsigned int dev_idx;
domain->master = master;
domain->index = index;
INIT_LIST_HEAD(&domain->fmmu_configs);
@ -67,8 +69,10 @@ void ec_domain_init(
domain->data_origin = EC_ORIG_INTERNAL;
domain->logical_base_address = 0x00000000;
INIT_LIST_HEAD(&domain->datagram_pairs);
domain->working_counter[EC_DEVICE_MAIN] = 0x0000;
domain->working_counter[EC_DEVICE_BACKUP] = 0x0000;
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
domain->working_counter[dev_idx] = 0x0000;
}
domain->expected_working_counter = 0x0000;
domain->working_counter_changes = 0;
domain->redundancy_active = 0;
@ -355,6 +359,8 @@ const ec_fmmu_config_t *ec_domain_find_fmmu(
/*****************************************************************************/
#if EC_MAX_NUM_DEVICES > 1
/** Process received data.
*/
int data_changed(
@ -377,6 +383,8 @@ int data_changed(
return 0;
}
#endif
/******************************************************************************
* Application interface
*****************************************************************************/
@ -443,15 +451,17 @@ uint8_t *ecrt_domain_data(ec_domain_t *domain)
void ecrt_domain_process(ec_domain_t *domain)
{
uint16_t wc_sum[EC_NUM_DEVICES] = {};
uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, redundant_wc, wc_total;
ec_datagram_pair_t *pair;
ec_datagram_t *main_datagram, *backup_datagram;
ec_datagram_t *main_datagram;
uint32_t logical_datagram_address;
size_t datagram_size;
uint16_t datagram_pair_wc;
unsigned int datagram_offset;
unsigned int dev_idx, wc_change;
#if EC_MAX_NUM_DEVICES > 1
ec_fmmu_config_t *fmmu =
list_first_entry(&domain->fmmu_configs, ec_fmmu_config_t, list);
#endif
unsigned int redundancy;
#if DEBUG_REDUNDANCY
@ -461,7 +471,6 @@ void ecrt_domain_process(ec_domain_t *domain)
list_for_each_entry(pair, &domain->datagram_pairs, list) {
main_datagram = &pair->datagrams[EC_DEVICE_MAIN];
backup_datagram = &pair->datagrams[EC_DEVICE_BACKUP];
logical_datagram_address = EC_READ_U32(main_datagram->address);
datagram_size = main_datagram->data_size;
@ -472,8 +481,16 @@ void ecrt_domain_process(ec_domain_t *domain)
datagram_pair_wc = ec_datagram_pair_process(pair, wc_sum);
/* Go through all FMMU configs to detect data changes. */
#if EC_MAX_NUM_DEVICES > 1
if (ec_master_num_devices(domain->master) < 2) {
continue;
}
/* Redundancy: Go through all FMMU configs to detect data changes. */
list_for_each_entry_from(fmmu, &domain->fmmu_configs, list) {
unsigned int datagram_offset;
ec_datagram_t *backup_datagram =
&pair->datagrams[EC_DEVICE_BACKUP];
if (fmmu->dir != EC_DIR_INPUT) {
continue;
@ -533,9 +550,16 @@ void ecrt_domain_process(ec_domain_t *domain)
#endif
}
}
#endif // EC_MAX_NUM_DEVICES > 1
}
redundancy = wc_sum[EC_DEVICE_BACKUP] > 0;
redundant_wc = 0;
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
redundant_wc += wc_sum[dev_idx];
}
redundancy = redundant_wc > 0;
if (redundancy != domain->redundancy_active) {
if (redundancy) {
EC_MASTER_WARN(domain->master,
@ -549,12 +573,19 @@ void ecrt_domain_process(ec_domain_t *domain)
domain->redundancy_active = redundancy;
}
if ((wc_sum[EC_DEVICE_MAIN] != domain->working_counter[EC_DEVICE_MAIN])
|| (wc_sum[EC_DEVICE_BACKUP]
!= domain->working_counter[EC_DEVICE_BACKUP])) {
wc_change = 0;
wc_total = 0;
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
if (wc_sum[dev_idx] != domain->working_counter[dev_idx]) {
wc_change = 1;
domain->working_counter[dev_idx] = wc_sum[dev_idx];
}
wc_total += wc_sum[dev_idx];
}
if (wc_change) {
domain->working_counter_changes++;
domain->working_counter[EC_DEVICE_MAIN] = wc_sum[EC_DEVICE_MAIN];
domain->working_counter[EC_DEVICE_BACKUP] = wc_sum[EC_DEVICE_BACKUP];
}
if (domain->working_counter_changes &&
@ -562,20 +593,28 @@ void ecrt_domain_process(ec_domain_t *domain)
domain->notify_jiffies = jiffies;
if (domain->working_counter_changes == 1) {
EC_MASTER_INFO(domain->master, "Domain %u: Working counter"
" changed to %u/%u (%u+%u).\n", domain->index,
domain->working_counter[EC_DEVICE_MAIN] +
domain->working_counter[EC_DEVICE_BACKUP],
domain->expected_working_counter,
wc_sum[EC_DEVICE_MAIN], wc_sum[EC_DEVICE_BACKUP]);
" changed to %u/%u", domain->index,
wc_total, domain->expected_working_counter);
} else {
EC_MASTER_INFO(domain->master, "Domain %u: %u working counter"
" changes - now %u/%u (%u+%u).\n", domain->index,
" changes - now %u/%u", domain->index,
domain->working_counter_changes,
domain->working_counter[EC_DEVICE_MAIN] +
domain->working_counter[EC_DEVICE_BACKUP],
domain->expected_working_counter,
wc_sum[EC_DEVICE_MAIN], wc_sum[EC_DEVICE_BACKUP]);
wc_total, domain->expected_working_counter);
}
if (ec_master_num_devices(domain->master) > 1) {
printk(" (");
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master);
dev_idx++) {
printk("%u", domain->working_counter[dev_idx]);
if (dev_idx + 1 < ec_master_num_devices(domain->master)) {
printk("+");
}
}
printk(")");
}
printk(".\n");
domain->working_counter_changes = 0;
}
}
@ -589,17 +628,21 @@ void ecrt_domain_queue(ec_domain_t *domain)
list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
#if EC_MAX_NUM_DEVICES > 1
/* copy main data to send buffer */
memcpy(datagram_pair->send_buffer,
datagram_pair->datagrams[EC_DEVICE_MAIN].data,
datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
#endif
ec_master_queue_datagram(domain->master,
&datagram_pair->datagrams[EC_DEVICE_MAIN]);
/* copy main data to backup datagram */
memcpy(datagram_pair->datagrams[EC_DEVICE_BACKUP].data,
datagram_pair->datagrams[EC_DEVICE_MAIN].data,
datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_BACKUP;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
memcpy(datagram_pair->datagrams[dev_idx].data,
datagram_pair->datagrams[EC_DEVICE_MAIN].data,
datagram_pair->datagrams[EC_DEVICE_MAIN].data_size);
ec_master_queue_datagram(domain->master,
&datagram_pair->datagrams[dev_idx]);
}
@ -610,9 +653,15 @@ void ecrt_domain_queue(ec_domain_t *domain)
void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
{
state->working_counter =
domain->working_counter[EC_DEVICE_MAIN]
+ domain->working_counter[EC_DEVICE_BACKUP];
unsigned int dev_idx;
uint16_t wc = 0;
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
wc += domain->working_counter[dev_idx];
}
state->working_counter = wc;
if (state->working_counter) {
if (state->working_counter == domain->expected_working_counter) {

View File

@ -65,8 +65,7 @@ struct ec_domain
process data. */
struct list_head datagram_pairs; /**< Datagrams pairs (main/backup) for
process data exchange. */
uint16_t working_counter[EC_NUM_DEVICES]; /**< Last working counter
uint16_t working_counter[EC_MAX_NUM_DEVICES]; /**< Last working counter
values. */
uint16_t expected_working_counter; /**< Expected working counter. */
unsigned int working_counter_changes; /**< Working counter changes

View File

@ -86,7 +86,8 @@ void ec_fsm_master_init(
fsm->state = ec_fsm_master_state_start;
fsm->idle = 0;
fsm->dev_idx = EC_DEVICE_MAIN;
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
fsm->link_state[dev_idx] = 0;
fsm->slaves_responding[dev_idx] = 0;
fsm->slave_states[dev_idx] = EC_SLAVE_STATE_UNKNOWN;
@ -209,7 +210,7 @@ void ec_fsm_master_state_broadcast(
fsm->slaves_responding[fsm->dev_idx] = datagram->working_counter;
EC_MASTER_INFO(master, "%u slave(s) responding on %s device.\n",
fsm->slaves_responding[fsm->dev_idx],
ec_device_names[fsm->dev_idx]);
ec_device_names[fsm->dev_idx != 0]);
}
if (fsm->link_state[fsm->dev_idx] &&
@ -218,7 +219,7 @@ void ec_fsm_master_state_broadcast(
EC_MASTER_DBG(master, 1, "Master state machine detected "
"link down on %s device. Clearing slave list.\n",
ec_device_names[fsm->dev_idx]);
ec_device_names[fsm->dev_idx != 0]);
#ifdef EC_EOE
ec_master_eoe_stop(master);
@ -226,7 +227,8 @@ void ec_fsm_master_state_broadcast(
#endif
ec_master_clear_slaves(master);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(master); dev_idx++) {
fsm->slave_states[dev_idx] = 0x00;
fsm->slaves_responding[dev_idx] = 0; /* Reset to trigger rescan on
next link up. */
@ -243,14 +245,14 @@ void ec_fsm_master_state_broadcast(
fsm->slave_states[fsm->dev_idx] = states;
ec_state_string(states, state_str, 1);
EC_MASTER_INFO(master, "Slave states on %s device: %s.\n",
ec_device_names[fsm->dev_idx], state_str);
ec_device_names[fsm->dev_idx != 0], state_str);
}
} else {
fsm->slave_states[fsm->dev_idx] = 0x00;
}
fsm->dev_idx++;
if (fsm->dev_idx < EC_NUM_DEVICES) {
if (fsm->dev_idx < ec_master_num_devices(master)) {
// check number of responding slaves on next device
fsm->state = ec_fsm_master_state_start;
fsm->state(fsm); // execute immediately
@ -279,8 +281,8 @@ void ec_fsm_master_state_broadcast(
#endif
ec_master_clear_slaves(master);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES;
dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(master); dev_idx++) {
count += fsm->slaves_responding[dev_idx];
}
@ -708,7 +710,7 @@ void ec_fsm_master_state_clear_addresses(
if (datagram->state != EC_DATAGRAM_RECEIVED) {
EC_MASTER_ERR(master, "Failed to receive address"
" clearing datagram on %s link: ",
ec_device_names[fsm->dev_idx]);
ec_device_names[fsm->dev_idx != 0]);
ec_datagram_print_state(datagram);
master->scan_busy = 0;
wake_up_interruptible(&master->scan_queue);
@ -719,13 +721,13 @@ void ec_fsm_master_state_clear_addresses(
if (datagram->working_counter != fsm->slaves_responding[fsm->dev_idx]) {
EC_MASTER_WARN(master, "Failed to clear station addresses on %s link:"
" Cleared %u of %u",
ec_device_names[fsm->dev_idx], datagram->working_counter,
ec_device_names[fsm->dev_idx != 0], datagram->working_counter,
fsm->slaves_responding[fsm->dev_idx]);
}
EC_MASTER_DBG(master, 1, "Sending broadcast-write"
" to measure transmission delays on %s link.\n",
ec_device_names[fsm->dev_idx]);
ec_device_names[fsm->dev_idx != 0]);
ec_datagram_bwr(datagram, 0x0900, 1);
ec_datagram_zero(datagram);
@ -750,7 +752,7 @@ void ec_fsm_master_state_dc_measure_delays(
if (datagram->state != EC_DATAGRAM_RECEIVED) {
EC_MASTER_ERR(master, "Failed to receive delay measuring datagram"
" on %s link: ", ec_device_names[fsm->dev_idx]);
" on %s link: ", ec_device_names[fsm->dev_idx != 0]);
ec_datagram_print_state(datagram);
master->scan_busy = 0;
wake_up_interruptible(&master->scan_queue);
@ -760,13 +762,13 @@ void ec_fsm_master_state_dc_measure_delays(
EC_MASTER_DBG(master, 1, "%u slaves responded to delay measuring"
" on %s link.\n",
datagram->working_counter, ec_device_names[fsm->dev_idx]);
datagram->working_counter, ec_device_names[fsm->dev_idx != 0]);
do {
fsm->dev_idx++;
} while (fsm->dev_idx < EC_NUM_DEVICES &&
} while (fsm->dev_idx < ec_master_num_devices(master) &&
!fsm->slaves_responding[fsm->dev_idx]);
if (fsm->dev_idx < EC_NUM_DEVICES) {
if (fsm->dev_idx < ec_master_num_devices(master)) {
ec_fsm_master_enter_clear_addresses(fsm);
return;
}
@ -777,7 +779,7 @@ void ec_fsm_master_state_dc_measure_delays(
fsm->slave = master->slaves;
EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
fsm->slave->ring_position,
ec_device_names[fsm->slave->device_index]);
ec_device_names[fsm->slave->device_index != 0]);
fsm->state = ec_fsm_master_state_scan_slave;
ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
@ -823,7 +825,7 @@ void ec_fsm_master_state_scan_slave(
if (fsm->slave < master->slaves + master->slave_count) {
EC_MASTER_DBG(master, 1, "Scanning slave %u on %s link.\n",
fsm->slave->ring_position,
ec_device_names[fsm->slave->device_index]);
ec_device_names[fsm->slave->device_index != 0]);
ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
fsm->datagram->device_index = fsm->slave->device_index;

View File

@ -105,15 +105,15 @@ struct ec_fsm_master {
*/
int idle; /**< state machine is in idle phase */
unsigned long scan_jiffies; /**< beginning of slave scanning */
uint8_t link_state[EC_NUM_DEVICES]; /**< Last link state for every device.
*/
unsigned int slaves_responding[EC_NUM_DEVICES]; /**< Number of responding
slaves for every device.
*/
uint8_t link_state[EC_MAX_NUM_DEVICES]; /**< Last link state for every
device. */
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]; /**< Number of
responding slaves
for every device. */
unsigned int rescan_required; /**< A bus rescan is required. */
ec_slave_state_t slave_states[EC_NUM_DEVICES]; /**< AL states of
responding slaves for
every device. */
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]; /**< AL states of
responding slaves for
every device. */
ec_slave_t *slave; /**< current slave */
ec_sii_write_request_t *sii_request; /**< SII write request */
off_t sii_index; /**< index to SII write request data */

View File

@ -200,11 +200,10 @@ enum {
*/
typedef enum {
EC_DEVICE_MAIN, /**< Main device. */
EC_DEVICE_BACKUP, /**< Backup device */
EC_NUM_DEVICES /**< Number of devices. */
EC_DEVICE_BACKUP /**< Backup device */
} ec_device_index_t;
extern const char *ec_device_names[EC_NUM_DEVICES];
extern const char *ec_device_names[2]; // only main and backup!
/*****************************************************************************/

View File

@ -93,80 +93,86 @@ static int ec_ioctl_master(
void *arg /**< Userspace address to store the results. */
)
{
ec_ioctl_master_t data;
unsigned int i, j;
ec_ioctl_master_t io;
unsigned int dev_idx, j;
if (down_interruptible(&master->master_sem))
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
data.slave_count = master->slave_count;
data.config_count = ec_master_config_count(master);
data.domain_count = ec_master_domain_count(master);
io.slave_count = master->slave_count;
io.config_count = ec_master_config_count(master);
io.domain_count = ec_master_domain_count(master);
#ifdef EC_EOE
data.eoe_handler_count = ec_master_eoe_handler_count(master);
io.eoe_handler_count = ec_master_eoe_handler_count(master);
#endif
data.phase = (uint8_t) master->phase;
data.active = (uint8_t) master->active;
data.scan_busy = master->scan_busy;
io.phase = (uint8_t) master->phase;
io.active = (uint8_t) master->active;
io.scan_busy = master->scan_busy;
up(&master->master_sem);
if (down_interruptible(&master->device_sem))
if (down_interruptible(&master->device_sem)) {
return -EINTR;
}
for (i = 0; i < EC_NUM_DEVICES; i++) {
ec_device_t *device = &master->devices[i];
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(master); dev_idx++) {
ec_device_t *device = &master->devices[dev_idx];
if (device->dev) {
memcpy(data.devices[i].address,
device->dev->dev_addr, ETH_ALEN);
memcpy(io.devices[dev_idx].address, device->dev->dev_addr,
ETH_ALEN);
} else {
memcpy(data.devices[i].address, master->macs[i], ETH_ALEN);
memcpy(io.devices[dev_idx].address, master->macs[dev_idx],
ETH_ALEN);
}
data.devices[i].attached = device->dev ? 1 : 0;
data.devices[i].link_state = device->link_state ? 1 : 0;
data.devices[i].tx_count = device->tx_count;
data.devices[i].rx_count = device->rx_count;
data.devices[i].tx_bytes = device->tx_bytes;
data.devices[i].rx_bytes = device->rx_bytes;
data.devices[i].tx_errors = device->tx_errors;
io.devices[dev_idx].attached = device->dev ? 1 : 0;
io.devices[dev_idx].link_state = device->link_state ? 1 : 0;
io.devices[dev_idx].tx_count = device->tx_count;
io.devices[dev_idx].rx_count = device->rx_count;
io.devices[dev_idx].tx_bytes = device->tx_bytes;
io.devices[dev_idx].rx_bytes = device->rx_bytes;
io.devices[dev_idx].tx_errors = device->tx_errors;
for (j = 0; j < EC_RATE_COUNT; j++) {
data.devices[i].tx_frame_rates[j] =
io.devices[dev_idx].tx_frame_rates[j] =
device->tx_frame_rates[j];
data.devices[i].rx_frame_rates[j] =
io.devices[dev_idx].rx_frame_rates[j] =
device->rx_frame_rates[j];
data.devices[i].tx_byte_rates[j] =
io.devices[dev_idx].tx_byte_rates[j] =
device->tx_byte_rates[j];
data.devices[i].rx_byte_rates[j] =
io.devices[dev_idx].rx_byte_rates[j] =
device->rx_byte_rates[j];
}
}
io.num_devices = ec_master_num_devices(master);
data.tx_count = master->device_stats.tx_count;
data.rx_count = master->device_stats.rx_count;
data.tx_bytes = master->device_stats.tx_bytes;
data.rx_bytes = master->device_stats.rx_bytes;
for (i = 0; i < EC_RATE_COUNT; i++) {
data.tx_frame_rates[i] =
master->device_stats.tx_frame_rates[i];
data.rx_frame_rates[i] =
master->device_stats.rx_frame_rates[i];
data.tx_byte_rates[i] =
master->device_stats.tx_byte_rates[i];
data.rx_byte_rates[i] =
master->device_stats.rx_byte_rates[i];
data.loss_rates[i] =
master->device_stats.loss_rates[i];
io.tx_count = master->device_stats.tx_count;
io.rx_count = master->device_stats.rx_count;
io.tx_bytes = master->device_stats.tx_bytes;
io.rx_bytes = master->device_stats.rx_bytes;
for (j = 0; j < EC_RATE_COUNT; j++) {
io.tx_frame_rates[j] =
master->device_stats.tx_frame_rates[j];
io.rx_frame_rates[j] =
master->device_stats.rx_frame_rates[j];
io.tx_byte_rates[j] =
master->device_stats.tx_byte_rates[j];
io.rx_byte_rates[j] =
master->device_stats.rx_byte_rates[j];
io.loss_rates[j] =
master->device_stats.loss_rates[j];
}
up(&master->device_sem);
data.app_time = master->app_time;
data.ref_clock =
io.app_time = master->app_time;
io.ref_clock =
master->dc_ref_clock ? master->dc_ref_clock->ring_position : 0xffff;
if (copy_to_user((void __user *) arg, &data, sizeof(data)))
if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
return -EFAULT;
}
return 0;
}
@ -459,7 +465,8 @@ static int ec_ioctl_domain(
data.data_size = domain->data_size;
data.logical_base_address = domain->logical_base_address;
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
data.working_counter[dev_idx] = domain->working_counter[dev_idx];
}
data.expected_working_counter = domain->expected_working_counter;

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 23
#define EC_IOCTL_VERSION_MAGIC 24
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -187,7 +187,8 @@ typedef struct {
int32_t rx_frame_rates[EC_RATE_COUNT];
int32_t tx_byte_rates[EC_RATE_COUNT];
int32_t rx_byte_rates[EC_RATE_COUNT];
} devices[EC_NUM_DEVICES];
} devices[EC_MAX_NUM_DEVICES];
uint32_t num_devices;
uint64_t tx_count;
uint64_t rx_count;
uint64_t tx_bytes;
@ -304,7 +305,7 @@ typedef struct {
// outputs
uint32_t data_size;
uint32_t logical_base_address;
uint16_t working_counter[EC_NUM_DEVICES];
uint16_t working_counter[EC_MAX_NUM_DEVICES];
uint16_t expected_working_counter;
uint32_t fmmu_count;
} ec_ioctl_domain_t;

View File

@ -136,14 +136,28 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
)
{
int ret;
unsigned int dev_idx;
master->index = index;
master->reserved = 0;
sema_init(&master->master_sem, 1);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_MAX_NUM_DEVICES; dev_idx++) {
master->macs[dev_idx] = NULL;
}
master->macs[EC_DEVICE_MAIN] = main_mac;
#if EC_MAX_NUM_DEVICES > 1
master->macs[EC_DEVICE_BACKUP] = backup_mac;
master->num_devices = 1 + !ec_mac_is_zero(backup_mac);
#else
if (!ec_mac_is_zero(backup_mac)) {
EC_MASTER_WARN(master, "Ignoring backup MAC address!");
}
#endif
ec_master_clear_device_stats(master);
sema_init(&master->device_sem, 1);
@ -209,13 +223,13 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
init_waitqueue_head(&master->sii_queue);
// init devices
ret = ec_device_init(&master->devices[EC_DEVICE_MAIN], master);
if (ret < 0)
goto out_return;
ret = ec_device_init(&master->devices[EC_DEVICE_BACKUP], master);
if (ret < 0)
goto out_clear_main;
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
ret = ec_device_init(&master->devices[dev_idx], master);
if (ret < 0) {
goto out_clear_devices;
}
}
// init state machine datagram
ec_datagram_init(&master->fsm_datagram);
@ -224,7 +238,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
if (ret < 0) {
ec_datagram_clear(&master->fsm_datagram);
EC_MASTER_ERR(master, "Failed to allocate FSM datagram.\n");
goto out_clear_backup;
goto out_clear_devices;
}
// create state machine object
@ -325,11 +339,10 @@ out_clear_ref_sync:
out_clear_fsm:
ec_fsm_master_clear(&master->fsm);
ec_datagram_clear(&master->fsm_datagram);
out_clear_backup:
ec_device_clear(&master->devices[EC_DEVICE_BACKUP]);
out_clear_main:
ec_device_clear(&master->devices[EC_DEVICE_MAIN]);
out_return:
out_clear_devices:
for (; dev_idx > 0; dev_idx--) {
ec_device_clear(&master->devices[dev_idx - 1]);
}
return ret;
}
@ -341,6 +354,8 @@ void ec_master_clear(
ec_master_t *master /**< EtherCAT master */
)
{
unsigned int dev_idx;
#ifdef EC_RTDM
ec_rtdm_dev_clear(&master->rtdm_dev);
#endif
@ -365,8 +380,11 @@ void ec_master_clear(
ec_datagram_clear(&master->ref_sync_datagram);
ec_fsm_master_clear(&master->fsm);
ec_datagram_clear(&master->fsm_datagram);
ec_device_clear(&master->devices[EC_DEVICE_BACKUP]);
ec_device_clear(&master->devices[EC_DEVICE_MAIN]);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
ec_device_clear(&master->devices[dev_idx]);
}
}
/*****************************************************************************/
@ -575,7 +593,8 @@ int ec_master_enter_idle_phase(
master->phase = EC_IDLE;
// reset number of responding slaves to trigger scanning
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
master->fsm.slaves_responding[dev_idx] = 0;
}
@ -1222,7 +1241,7 @@ void ec_master_update_device_stats(
ec_device_stats_t *s = &master->device_stats;
s32 tx_frame_rate, rx_frame_rate, tx_byte_rate, rx_byte_rate, loss_rate;
u64 loss;
unsigned int i;
unsigned int i, dev_idx;
// frame statistics
if (likely(jiffies - s->jiffies < HZ)) {
@ -1255,8 +1274,10 @@ void ec_master_update_device_stats(
s->last_rx_bytes = s->rx_bytes;
s->last_loss = loss;
ec_device_update_stats(&master->devices[EC_DEVICE_MAIN]);
ec_device_update_stats(&master->devices[EC_DEVICE_BACKUP]);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
ec_device_update_stats(&master->devices[dev_idx]);
}
s->jiffies = jiffies;
}
@ -2265,7 +2286,8 @@ void ecrt_master_send(ec_master_t *master)
ec_master_inject_external_datagrams(master);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
if (unlikely(!master->devices[dev_idx].link_state)) {
// link is down, no datagram can be sent
list_for_each_entry_safe(datagram, n,
@ -2297,12 +2319,13 @@ void ecrt_master_send(ec_master_t *master)
void ecrt_master_receive(ec_master_t *master)
{
unsigned int dev_idx;
ec_datagram_t *datagram, *next;
// receive datagrams
ec_device_poll(&master->devices[EC_DEVICE_MAIN]);
if (master->devices[EC_DEVICE_BACKUP].dev) {
ec_device_poll(&master->devices[EC_DEVICE_BACKUP]);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
ec_device_poll(&master->devices[dev_idx]);
}
ec_master_update_device_stats(master);
@ -2540,7 +2563,8 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
state->al_states = 0;
state->link_up = 0U;
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
/* Announce sum of responding slaves on all links. */
state->slaves_responding += master->fsm.slaves_responding[dev_idx];
@ -2557,7 +2581,7 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx,
ec_master_link_state_t *state)
{
if (dev_idx >= EC_NUM_DEVICES) {
if (dev_idx >= ec_master_num_devices(master)) {
return -EINVAL;
}

View File

@ -172,6 +172,12 @@ typedef struct {
/*****************************************************************************/
#if EC_MAX_NUM_DEVICES < 1
#error Invalid number of devices
#endif
/*****************************************************************************/
/** EtherCAT master.
*
* Manages slaves, domains and IO.
@ -193,8 +199,13 @@ struct ec_master {
struct semaphore master_sem; /**< Master semaphore. */
ec_device_t devices[EC_NUM_DEVICES]; /**< EtherCAT devices. */
const uint8_t *macs[EC_NUM_DEVICES]; /**< Device MAC addresses. */
ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. */
const uint8_t *macs[EC_MAX_NUM_DEVICES]; /**< Device MAC addresses. */
#if EC_MAX_NUM_DEVICES > 1
unsigned int num_devices; /**< Number of devices. Access this always via
ec_master_num_devices(), because it may be
optimized! */
#endif
struct semaphore device_sem; /**< Device semaphore. */
ec_device_stats_t device_stats; /**< Device statistics. */
@ -290,6 +301,12 @@ int ec_master_init(ec_master_t *, unsigned int, const uint8_t *,
const uint8_t *, dev_t, struct class *, unsigned int);
void ec_master_clear(ec_master_t *);
#if EC_MAX_NUM_DEVICES > 1
#define ec_master_num_devices(MASTER) ((MASTER)->num_devices)
#else
#define ec_master_num_devices(MASTER) 1
#endif
// phase transitions
int ec_master_enter_idle_phase(ec_master_t *);
void ec_master_leave_idle_phase(ec_master_t *);

View File

@ -453,7 +453,7 @@ size_t ec_state_string(uint8_t states, /**< slave states */
/** Device names.
*/
const char *ec_device_names[EC_NUM_DEVICES] = {
const char *ec_device_names[2] = {
"main",
"backup"
};
@ -476,29 +476,34 @@ ec_device_t *ecdev_offer(
{
ec_master_t *master;
char str[EC_MAX_MAC_STRING_SIZE];
unsigned int i, j;
unsigned int i, dev_idx;
for (i = 0; i < master_count; i++) {
master = &masters[i];
ec_mac_print(net_dev->dev_addr, str);
down(&master->device_sem);
if (down_interruptible(&master->device_sem)) {
EC_MASTER_WARN(master, "%s() interrupted!\n", __func__);
return NULL;
}
for (j = 0; j < EC_NUM_DEVICES; j++) {
if (!master->devices[j].dev
&& (ec_mac_equal(master->macs[j], net_dev->dev_addr)
|| ec_mac_is_broadcast(master->macs[j]))) {
for (dev_idx = EC_DEVICE_MAIN;
dev_idx < ec_master_num_devices(master); dev_idx++) {
if (!master->devices[dev_idx].dev
&& (ec_mac_equal(master->macs[dev_idx], net_dev->dev_addr)
|| ec_mac_is_broadcast(master->macs[dev_idx]))) {
EC_INFO("Accepting %s as %s device for master %u.\n",
str, ec_device_names[j], master->index);
str, ec_device_names[dev_idx != 0], master->index);
ec_device_attach(&master->devices[j], net_dev, poll, module);
ec_device_attach(&master->devices[dev_idx],
net_dev, poll, module);
up(&master->device_sem);
snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
ec_device_names[j][0], master->index);
ec_device_names[dev_idx != 0][0], master->index);
return &master->devices[j]; // offer accepted
return &master->devices[dev_idx]; // offer accepted
}
}
@ -523,7 +528,7 @@ ec_master_t *ecrt_request_master_err(
)
{
ec_master_t *master, *errptr = NULL;
unsigned int i, got_modules = 0;
unsigned int dev_idx = EC_DEVICE_MAIN;
EC_INFO("Requesting master %u...\n", master_index);
@ -560,17 +565,14 @@ ec_master_t *ecrt_request_master_err(
goto out_release;
}
for (i = 0; i < EC_NUM_DEVICES; i++) {
ec_device_t *device = &master->devices[i];
if (device->dev) {
if (!try_module_get(device->module)) {
up(&master->device_sem);
EC_MASTER_ERR(master, "Device module is unloading!\n");
errptr = ERR_PTR(-ENODEV);
goto out_module_put;
}
for (; dev_idx < ec_master_num_devices(master); dev_idx++) {
ec_device_t *device = &master->devices[dev_idx];
if (!try_module_get(device->module)) {
up(&master->device_sem);
EC_MASTER_ERR(master, "Device module is unloading!\n");
errptr = ERR_PTR(-ENODEV);
goto out_module_put;
}
got_modules++;
}
up(&master->device_sem);
@ -585,11 +587,9 @@ ec_master_t *ecrt_request_master_err(
return master;
out_module_put:
for (; got_modules > 0; got_modules--) {
ec_device_t *device = &master->devices[i - 1];
if (device->dev) {
module_put(device->module);
}
for (; dev_idx > 0; dev_idx--) {
ec_device_t *device = &master->devices[dev_idx - 1];
module_put(device->module);
}
out_release:
master->reserved = 0;
@ -609,7 +609,7 @@ ec_master_t *ecrt_request_master(unsigned int master_index)
void ecrt_release_master(ec_master_t *master)
{
unsigned int i;
unsigned int dev_idx;
EC_MASTER_INFO(master, "Releasing master...\n");
@ -621,10 +621,9 @@ void ecrt_release_master(ec_master_t *master)
ec_master_leave_operation_phase(master);
for (i = 0; i < EC_NUM_DEVICES; i++) {
if (master->devices[i].dev) {
module_put(master->devices[i].module);
}
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
module_put(master->devices[dev_idx].module);
}
master->reserved = 0;

View File

@ -467,19 +467,17 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m)
/****************************************************************************/
Command::DomainList Command::selectedDomains(MasterDevice &m)
Command::DomainList Command::selectedDomains(MasterDevice &m,
const ec_ioctl_master_t &io)
{
ec_ioctl_master_t master;
DomainList list;
m.getMaster(&master);
PositionParser pp(master.domain_count);
PositionParser pp(io.domain_count);
NumberListParser::List domList = pp.parse(domains.c_str());
NumberListParser::List::const_iterator di;
for (di = domList.begin(); di != domList.end(); di++) {
if (*di < master.domain_count) {
if (*di < io.domain_count) {
ec_ioctl_domain_t d;
m.getDomain(&d, *di);
list.push_back(d);

View File

@ -139,7 +139,7 @@ class Command
typedef list<ec_ioctl_config_t> ConfigList;
ConfigList selectedConfigs(MasterDevice &);
typedef list<ec_ioctl_domain_t> DomainList;
DomainList selectedDomains(MasterDevice &);
DomainList selectedDomains(MasterDevice &, const ec_ioctl_master_t &);
static string alStateString(uint8_t);

View File

@ -82,9 +82,12 @@ void CommandData::execute(const StringVector &args)
MasterIndexList::const_iterator mi;
for (mi = masterIndices.begin();
mi != masterIndices.end(); mi++) {
ec_ioctl_master_t io;
MasterDevice m(*mi);
m.open(MasterDevice::Read);
domains = selectedDomains(m);
m.getMaster(&io);
domains = selectedDomains(m, io);
for (di = domains.begin(); di != domains.end(); di++) {
outputDomainData(m, *di);

View File

@ -108,16 +108,18 @@ void CommandDomains::execute(const StringVector &args)
MasterIndexList::const_iterator mi;
for (mi = masterIndices.begin();
mi != masterIndices.end(); mi++) {
ec_ioctl_master_t io;
MasterDevice m(*mi);
m.open(MasterDevice::Read);
domains = selectedDomains(m);
m.getMaster(&io);
domains = selectedDomains(m, io);
if (domains.size() && doIndent) {
cout << "Master" << dec << *mi << endl;
}
for (di = domains.begin(); di != domains.end(); di++) {
showDomain(m, *di, doIndent);
showDomain(m, io, *di, doIndent);
}
}
}
@ -126,6 +128,7 @@ void CommandDomains::execute(const StringVector &args)
void CommandDomains::showDomain(
MasterDevice &m,
const ec_ioctl_master_t &master,
const ec_ioctl_domain_t &domain,
bool doIndent
)
@ -138,7 +141,7 @@ void CommandDomains::showDomain(
string indent(doIndent ? " " : "");
unsigned int wc_sum = 0, dev_idx;
for (dev_idx = 0; dev_idx < EC_NUM_DEVICES; dev_idx++) {
for (dev_idx = EC_DEVICE_MAIN; dev_idx < master.num_devices; dev_idx++) {
wc_sum += domain.working_counter[dev_idx];
}
@ -151,10 +154,16 @@ void CommandDomains::showDomain(
<< ", WorkingCounter "
<< wc_sum << "/"
<< domain.expected_working_counter;
if (EC_NUM_DEVICES == 2) {
cout << " (" << domain.working_counter[EC_DEVICE_MAIN]
<< "+" << domain.working_counter[EC_DEVICE_BACKUP]
<< ")";
if (master.num_devices > 1) {
cout << " (";
for (dev_idx = EC_DEVICE_MAIN; dev_idx < master.num_devices;
dev_idx++) {
cout << domain.working_counter[dev_idx];
if (dev_idx + 1 < master.num_devices) {
cout << "+";
}
}
cout << ")";
}
cout << endl;

View File

@ -44,7 +44,8 @@ class CommandDomains:
void execute(const StringVector &);
protected:
void showDomain(MasterDevice &, const ec_ioctl_domain_t &, bool);
void showDomain(MasterDevice &, const ec_ioctl_master_t &,
const ec_ioctl_domain_t &, bool);
};
/****************************************************************************/

View File

@ -70,7 +70,7 @@ void CommandMaster::execute(const StringVector &args)
MasterIndexList masterIndices;
ec_ioctl_master_t data;
stringstream err;
unsigned int i, j;
unsigned int dev_idx, j;
time_t epoch;
char time_str[MAX_TIME_STR_SIZE + 1];
size_t time_str_size;
@ -104,84 +104,78 @@ void CommandMaster::execute(const StringVector &args)
<< " Slaves: " << data.slave_count << endl
<< " Ethernet devices:" << endl;
for (i = 0; i < 2; i++) {
cout << " " << (i == 0 ? "Main" : "Backup") << ": ";
if (data.devices[i].address[0] == 0x00
&& data.devices[i].address[1] == 0x00
&& data.devices[i].address[2] == 0x00
&& data.devices[i].address[3] == 0x00
&& data.devices[i].address[4] == 0x00
&& data.devices[i].address[5] == 0x00) {
cout << "None." << endl;
} else {
cout << hex << setfill('0')
<< setw(2) << (unsigned int) data.devices[i].address[0]
<< ":"
<< setw(2) << (unsigned int) data.devices[i].address[1]
<< ":"
<< setw(2) << (unsigned int) data.devices[i].address[2]
<< ":"
<< setw(2) << (unsigned int) data.devices[i].address[3]
<< ":"
<< setw(2) << (unsigned int) data.devices[i].address[4]
<< ":"
<< setw(2) << (unsigned int) data.devices[i].address[5]
<< " ("
<< (data.devices[i].attached ? "attached" : "waiting...")
<< ")" << endl << dec
<< " Link: "
<< (data.devices[i].link_state ? "UP" : "DOWN") << endl
<< " Tx frames: "
<< data.devices[i].tx_count << endl
<< " Tx bytes: "
<< data.devices[i].tx_bytes << endl
<< " Rx frames: "
<< data.devices[i].rx_count << endl
<< " Rx bytes: "
<< data.devices[i].rx_bytes << endl
<< " Tx errors: "
<< data.devices[i].tx_errors << endl
<< " Tx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[i].tx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
for (dev_idx = EC_DEVICE_MAIN; dev_idx < data.num_devices;
dev_idx++) {
cout << " " << (dev_idx == EC_DEVICE_MAIN ? "Main" : "Backup")
<< ": ";
cout << hex << setfill('0')
<< setw(2) << (unsigned int) data.devices[dev_idx].address[0]
<< ":"
<< setw(2) << (unsigned int) data.devices[dev_idx].address[1]
<< ":"
<< setw(2) << (unsigned int) data.devices[dev_idx].address[2]
<< ":"
<< setw(2) << (unsigned int) data.devices[dev_idx].address[3]
<< ":"
<< setw(2) << (unsigned int) data.devices[dev_idx].address[4]
<< ":"
<< setw(2) << (unsigned int) data.devices[dev_idx].address[5]
<< " ("
<< (data.devices[dev_idx].attached ?
"attached" : "waiting...")
<< ")" << endl << dec
<< " Link: "
<< (data.devices[dev_idx].link_state ? "UP" : "DOWN") << endl
<< " Tx frames: "
<< data.devices[dev_idx].tx_count << endl
<< " Tx bytes: "
<< data.devices[dev_idx].tx_bytes << endl
<< " Rx frames: "
<< data.devices[dev_idx].rx_count << endl
<< " Rx bytes: "
<< data.devices[dev_idx].rx_bytes << endl
<< " Tx errors: "
<< data.devices[dev_idx].tx_errors << endl
<< " Tx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[dev_idx].tx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
cout << endl
<< " Tx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[i].tx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[i].rx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[i].rx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << setprecision(0) << endl;
}
cout << endl
<< " Tx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[dev_idx].tx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[dev_idx].rx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[dev_idx].rx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << setprecision(0) << endl;
}
unsigned int lost = data.tx_count - data.rx_count;
if (lost == 1) {