Added configure option for redundancy (--with-devices).
This commit is contained in:
parent
19d1b6ee9c
commit
3cb0b12899
13
TODO
13
TODO
|
|
@ -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:
|
||||
|
|
|
|||
32
configure.ac
32
configure.ac
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
111
master/domain.c
111
master/domain.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue