mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 11:51:45 +08:00
Measure port receive times.
This commit is contained in:
1
TODO
1
TODO
@@ -14,6 +14,7 @@ Version 1.5.0:
|
||||
- Delay calculation.
|
||||
- Use common application time offset when setting start times.
|
||||
- Check 32/64 bit operations.
|
||||
- Set system time offset only when application time available.
|
||||
* Fix unloading problem of ec_e100 driver.
|
||||
* Use ec_datagram_zero() where possible.
|
||||
* Fix arguments of reg_read.
|
||||
|
||||
@@ -43,7 +43,10 @@ digraph master {
|
||||
acknowledge -> action_configure [weight=10]
|
||||
|
||||
clear_addresses [fontname="Helvetica"]
|
||||
clear_addresses -> scan_slave [weight=10]
|
||||
clear_addresses -> dc_measure_delays [weight=10]
|
||||
|
||||
dc_measure_delays [fontname="Helvetica"]
|
||||
dc_measure_delays -> scan_slave [weight=10]
|
||||
|
||||
scan_slave [fontname="Helvetica"]
|
||||
scan_slave -> start
|
||||
|
||||
@@ -257,7 +257,11 @@ int ec_cdev_ioctl_slave(
|
||||
data.general_flags = slave->sii.general_flags;
|
||||
data.current_on_ebus = slave->sii.current_on_ebus;
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
data.ports[i] = slave->base_ports[i];
|
||||
data.port_descs[i] = slave->base_ports[i];
|
||||
data.ports[i].dl_link = slave->ports[i].dl_link;
|
||||
data.ports[i].dl_loop = slave->ports[i].dl_loop;
|
||||
data.ports[i].dl_signal = slave->ports[i].dl_signal;
|
||||
data.dc_receive_times[i] = slave->dc_receive_times[i];
|
||||
}
|
||||
data.fmmu_bit = slave->base_fmmu_bit_operation;
|
||||
data.dc_supported = slave->base_dc_supported;
|
||||
|
||||
@@ -52,6 +52,7 @@ void ec_fsm_master_state_read_state(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_write_sii(ec_fsm_master_t *);
|
||||
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *);
|
||||
@@ -771,6 +772,42 @@ void ec_fsm_master_state_clear_addresses(
|
||||
datagram->working_counter, master->slave_count);
|
||||
}
|
||||
|
||||
if (master->debug_level)
|
||||
EC_DBG("Sending broadcast-write to measure transmission delays.\n");
|
||||
|
||||
ec_datagram_bwr(datagram, 0x0900, 1);
|
||||
ec_datagram_zero(datagram);
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_master_state_dc_measure_delays;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Master state: DC MEASURE DELAYS.
|
||||
*/
|
||||
void ec_fsm_master_state_dc_measure_delays(
|
||||
ec_fsm_master_t *fsm /**< Master state machine. */
|
||||
)
|
||||
{
|
||||
ec_master_t *master = fsm->master;
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
EC_ERR("Failed to receive delay measuring datagram (state %u).\n",
|
||||
datagram->state);
|
||||
master->scan_busy = 0;
|
||||
wake_up_interruptible(&master->scan_queue);
|
||||
ec_fsm_master_restart(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (master->debug_level)
|
||||
EC_DBG("%u slaves responded to delay measuring.\n",
|
||||
datagram->working_counter);
|
||||
|
||||
EC_INFO("Scanning bus.\n");
|
||||
|
||||
// begin scanning of slaves
|
||||
|
||||
@@ -48,6 +48,7 @@ void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
|
||||
@@ -257,11 +258,11 @@ void ec_fsm_slave_scan_state_state(
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave scan state: BASE.
|
||||
*/
|
||||
|
||||
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
|
||||
/** Slave scan state: BASE.
|
||||
*/
|
||||
void ec_fsm_slave_scan_state_base(
|
||||
ec_fsm_slave_scan_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
@@ -374,6 +375,51 @@ void ec_fsm_slave_scan_state_dc_cap(
|
||||
return;
|
||||
}
|
||||
|
||||
// read DC port receive times
|
||||
ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
|
||||
ec_datagram_zero(datagram);
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_slave_scan_state_dc_times;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Slave scan state: DC TIMES.
|
||||
*/
|
||||
|
||||
void ec_fsm_slave_scan_state_dc_times(
|
||||
ec_fsm_slave_scan_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
int i;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
fsm->state = ec_fsm_slave_scan_state_error;
|
||||
EC_ERR("Failed to receive system time datagram for slave %u"
|
||||
" (datagram state %u).\n",
|
||||
slave->ring_position, datagram->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->state = ec_fsm_slave_scan_state_error;
|
||||
EC_ERR("Failed to get DC receive times of slave %u: ",
|
||||
slave->ring_position);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
slave->dc_receive_times[i] = EC_READ_U32(datagram->data + 4 * i);
|
||||
}
|
||||
|
||||
ec_fsm_slave_scan_enter_datalink(fsm);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,14 @@ typedef enum {
|
||||
EC_PORT_MII
|
||||
} ec_slave_port_desc_t;
|
||||
|
||||
/** EtherCAT slave port information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t dl_link; /**< Link detected. */
|
||||
uint8_t dl_loop; /**< Loop closed. */
|
||||
uint8_t dl_signal; /**< Detected signal on RX port. */
|
||||
} ec_slave_port_t;
|
||||
|
||||
/** EtherCAT slave distributed clocks range.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
@@ -165,11 +165,13 @@ typedef struct {
|
||||
ec_sii_coe_details_t coe_details;
|
||||
ec_sii_general_flags_t general_flags;
|
||||
int16_t current_on_ebus;
|
||||
ec_slave_port_desc_t ports[EC_MAX_PORTS];
|
||||
ec_slave_port_desc_t port_descs[EC_MAX_PORTS];
|
||||
ec_slave_port_t ports[EC_MAX_PORTS];
|
||||
uint8_t fmmu_bit;
|
||||
uint8_t dc_supported;
|
||||
ec_slave_dc_range_t dc_range;
|
||||
uint8_t has_dc_system_time;
|
||||
uint32_t dc_receive_times[EC_MAX_PORTS];
|
||||
uint8_t al_state;
|
||||
uint8_t error_flag;
|
||||
uint8_t sync_count;
|
||||
|
||||
@@ -95,6 +95,8 @@ void ec_slave_init(
|
||||
slave->ports[i].dl_loop = 0;
|
||||
slave->ports[i].dl_signal = 0;
|
||||
slave->sii.physical_layer[i] = 0xFF;
|
||||
|
||||
slave->dc_receive_times[i] = 0U;
|
||||
}
|
||||
|
||||
slave->base_fmmu_bit_operation = 0;
|
||||
|
||||
@@ -92,16 +92,6 @@ typedef struct {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** EtherCAT slave port information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t dl_link; /**< Link detected. */
|
||||
uint8_t dl_loop; /**< Loop closed. */
|
||||
uint8_t dl_signal; /**< Detected signal on RX port. */
|
||||
} ec_slave_port_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** EtherCAT slave.
|
||||
*/
|
||||
struct ec_slave
|
||||
@@ -136,6 +126,8 @@ struct ec_slave
|
||||
uint8_t has_dc_system_time; /**< The slave supports the DC system time
|
||||
register. Otherwise it can only be used for
|
||||
delay measurement. */
|
||||
uint32_t dc_receive_times[EC_MAX_PORTS]; /**< Port receive times for delay
|
||||
measurement. */
|
||||
|
||||
// data link status
|
||||
ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port link status. */
|
||||
|
||||
@@ -241,28 +241,6 @@ void CommandSlaves::showSlaves(
|
||||
<< " Serial number: 0x"
|
||||
<< setw(8) << si->serial_number << endl;
|
||||
|
||||
cout << "Ports:" << endl;
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
cout << " " << i << ": ";
|
||||
switch (si->ports[i]) {
|
||||
case EC_PORT_NOT_IMPLEMENTED:
|
||||
cout << "Not implemented.";
|
||||
break;
|
||||
case EC_PORT_NOT_CONFIGURED:
|
||||
cout << "Not configured.";
|
||||
break;
|
||||
case EC_PORT_EBUS:
|
||||
cout << "EBUS.";
|
||||
break;
|
||||
case EC_PORT_MII:
|
||||
cout << "MII.";
|
||||
break;
|
||||
default:
|
||||
cout << "???";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
cout << "DL information:" << endl
|
||||
<< " FMMU bit operation: "
|
||||
<< (si->fmmu_bit ? "yes" : "no") << endl
|
||||
@@ -280,13 +258,62 @@ void CommandSlaves::showSlaves(
|
||||
default:
|
||||
cout << "???";
|
||||
}
|
||||
cout << endl;
|
||||
} else {
|
||||
cout << "yes, delay measurement only";
|
||||
cout << "yes, delay measurement only" << endl;
|
||||
}
|
||||
} else {
|
||||
cout << "no";
|
||||
cout << "no" << endl;
|
||||
}
|
||||
|
||||
cout << "Port Type Link Loop Signal";
|
||||
if (si->dc_supported)
|
||||
cout << " RxTime Diff";
|
||||
cout << endl;
|
||||
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
cout << " " << i << " " << setfill(' ') << left << setw(4);
|
||||
switch (si->port_descs[i]) {
|
||||
case EC_PORT_NOT_IMPLEMENTED:
|
||||
cout << "N/A";
|
||||
break;
|
||||
case EC_PORT_NOT_CONFIGURED:
|
||||
cout << "N/C";
|
||||
break;
|
||||
case EC_PORT_EBUS:
|
||||
cout << "EBUS";
|
||||
break;
|
||||
case EC_PORT_MII:
|
||||
cout << "MII";
|
||||
break;
|
||||
default:
|
||||
cout << "???";
|
||||
}
|
||||
|
||||
cout << " " << setw(4)
|
||||
<< (si->ports[i].dl_link ? "up" : "down")
|
||||
<< " " << setw(6)
|
||||
<< (si->ports[i].dl_loop ? "closed" : "open")
|
||||
<< " " << setw(3)
|
||||
<< (si->ports[i].dl_signal ? "yes" : "no");
|
||||
|
||||
if (si->dc_supported) {
|
||||
cout << " " << setw(10) << right;
|
||||
if (si->ports[i].dl_signal) {
|
||||
cout << dec << si->dc_receive_times[i];
|
||||
} else {
|
||||
cout << "-";
|
||||
}
|
||||
cout << " " << setw(10);
|
||||
if (si->ports[i].dl_signal) {
|
||||
cout << si->dc_receive_times[i] - si->dc_receive_times[0];
|
||||
} else {
|
||||
cout << "-";
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
if (si->mailbox_protocols) {
|
||||
list<string> protoList;
|
||||
|
||||
Reference in New Issue
Block a user