Measure port receive times.

This commit is contained in:
Florian Pose
2009-04-27 15:20:14 +00:00
parent 69da9e5524
commit d427828ecc
10 changed files with 164 additions and 42 deletions

1
TODO
View File

@@ -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.

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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. */

View File

@@ -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;