51 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000 58 #ifdef EC_LOOP_CONTROL 64 #ifdef EC_LOOP_CONTROL 207 list_del_init(&request->
list);
208 request->
state = EC_INT_REQUEST_BUSY;
211 EC_MASTER_ERR(master,
"Emergency request data too large!\n");
212 request->
state = EC_INT_REQUEST_FAILURE;
220 " write requests!\n");
221 request->
state = EC_INT_REQUEST_FAILURE;
227 EC_MASTER_DBG(master, 1,
"Writing emergency register request...\n");
232 request->
state = EC_INT_REQUEST_SUCCESS;
268 unsigned int i, size;
286 "link down on %s device. Clearing slave list.\n",
338 unsigned int count = 0, next_dev_slave, ring_position;
378 " of slave memory!\n", size);
389 for (i = 0; i < count; i++, ring_position++) {
390 slave = master->
slaves + i;
391 while (i >= next_dev_slave) {
462 list_del_init(&request->
list);
463 request->
state = EC_INT_REQUEST_BUSY;
527 #ifdef EC_LOOP_CONTROL 531 void ec_fsm_master_action_read_dl_status(
539 fsm->
state = ec_fsm_master_state_read_dl_status;
546 void ec_fsm_master_action_open_port(
556 fsm->
state = ec_fsm_master_state_open_port;
565 void ec_fsm_master_state_read_dl_status(
578 EC_SLAVE_ERR(slave,
"Failed to receive AL state datagram: ");
597 switch (port->state) {
598 case EC_SLAVE_PORT_DOWN:
601 port->link_detection_jiffies = jiffies;
602 port->state = EC_SLAVE_PORT_WAIT;
606 port->state = EC_SLAVE_PORT_UP;
609 case EC_SLAVE_PORT_WAIT:
611 if (jiffies - port->link_detection_jiffies >
612 HZ * EC_PORT_WAIT_MS / 1000) {
613 port->state = EC_SLAVE_PORT_UP;
614 ec_fsm_master_action_open_port(fsm);
619 port->state = EC_SLAVE_PORT_DOWN;
624 port->state = EC_SLAVE_PORT_DOWN;
640 void ec_fsm_master_state_open_port(
652 EC_SLAVE_ERR(slave,
"Failed to receive port open datagram: ");
660 EC_SLAVE_ERR(slave,
"Did not respond to port open command!\n");
688 " (aborting state check).\n");
698 #ifdef EC_LOOP_CONTROL 700 ec_fsm_master_action_read_dl_status(fsm);
725 EC_SLAVE_ERR(slave,
"Failed to receive AL state datagram: ");
735 EC_SLAVE_DBG(slave, 1,
"Slave did not respond to state query.\n");
761 #ifdef EC_LOOP_CONTROL 763 ec_fsm_master_action_read_dl_status(fsm);
832 EC_SLAVE_ERR(slave,
"Failed to receive DC receive times datagram: ");
891 " to measure transmission delays on %s link.\n",
903 #ifdef EC_LOOP_CONTROL 907 void ec_fsm_master_enter_loop_control(
912 " loop control registers on %s link.\n",
919 fsm->
state = ec_fsm_master_state_loop_control;
926 void ec_fsm_master_state_loop_control(
939 " datagram on %s link: ",
966 " clearing datagram on %s link: ",
976 EC_MASTER_WARN(master,
"Failed to clear station addresses on %s link:" 982 #ifdef EC_LOOP_CONTROL 983 ec_fsm_master_enter_loop_control(fsm);
1006 EC_MASTER_ERR(master,
"Failed to receive delay measuring datagram" 1015 EC_MASTER_DBG(master, 1,
"%u slaves responded to delay measuring" 1031 for (slave = master->
slaves;
1055 for (slave = master->
slaves;
1130 EC_MASTER_DBG(master, 1,
"No app_time received up to now.\n");
1152 u32 system_time32, old_offset32, new_offset;
1155 system_time32 = (u32) system_time;
1156 old_offset32 = (u32) old_offset;
1158 time_diff = (u32) app_time_sent - system_time32;
1160 EC_SLAVE_DBG(slave, 1,
"DC 32 bit system time offset calculation:" 1161 " system_time=%u, app_time=%llu, diff=%i\n",
1162 system_time32, app_time_sent, time_diff);
1165 new_offset = time_diff + old_offset32;
1166 EC_SLAVE_DBG(slave, 1,
"Setting time offset to %u (was %u)\n",
1167 new_offset, old_offset32);
1168 return (u64) new_offset;
1192 time_diff = app_time_sent - system_time;
1194 EC_SLAVE_DBG(slave, 1,
"DC 64 bit system time offset calculation:" 1195 " system_time=%llu, app_time=%llu, diff=%lli\n",
1196 system_time, app_time_sent, time_diff);
1199 new_offset = time_diff + old_offset;
1200 EC_SLAVE_DBG(slave, 1,
"Setting time offset to %llu (was %llu)\n",
1201 new_offset, old_offset);
1203 new_offset = old_offset;
1221 u64 system_time, old_offset, new_offset;
1228 EC_SLAVE_ERR(slave,
"Failed to receive DC times datagram: ");
1245 " abort DC time offset calculation.\n");
1264 if (new_offset != old_offset
1270 EC_SLAVE_DBG(slave, 1,
"Slave is running; ignoring DC offset change.\n");
1271 new_offset = old_offset;
1306 "Failed to receive DC system time offset datagram: ");
1314 EC_SLAVE_ERR(slave,
"Failed to set DC system time offset: ");
1323 EC_SLAVE_DBG(slave, 1,
"Slave is running; not resetting DC filter.\n");
1351 "Failed to receive DC reset filter datagram: ");
1386 request->
state = EC_INT_REQUEST_FAILURE;
1403 EC_SLAVE_DBG(slave, 1,
"Finished writing %zu words of SII data.\n",
1414 EC_SLAVE_WARN(slave,
"Slave could not update effective alias." 1415 " SII data not available.\n");
1420 request->
state = EC_INT_REQUEST_SUCCESS;
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
uint16_t ring_position
Ring position for emergency requests.
void ec_master_clear_eoe_handlers(ec_master_t *master, unsigned int free_all)
Clear and free auto created EoE handlers.
void ec_fsm_reboot_all(ec_fsm_reboot_t *fsm, ec_master_t *master)
Starts the reboot state machine for all slaves on a master.
ec_internal_request_state_t state
Request state.
uint16_t offset
SII word offset.
uint16_t ring_position
Ring position.
ec_datagram_t * datagram
datagram used in the state machine
ec_sii_write_request_t * sii_request
SII write request.
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
size_t transfer_size
Size of the data to transfer.
struct list_head sii_requests
SII write requests.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
unsigned int reboot
Request reboot.
Finite state machine of an EtherCAT master.
unsigned int reboot
Reboot requested.
uint64_t app_time_sent
App time, when the datagram was sent.
ec_internal_request_state_t state
State of the request.
unsigned int slaves_responding[EC_MAX_NUM_DEVICES]
Number of responding slaves for every device.
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
ec_slave_port_t ports[EC_MAX_PORTS]
Ports.
void ec_fsm_master_enter_dc_read_old_times(ec_fsm_master_t *)
Start reading old timestamps from slaves.
void ec_fsm_master_reset(ec_fsm_master_t *fsm)
Reset state machine.
struct ec_slave ec_slave_t
void ec_master_request_op(ec_master_t *master)
Request OP state for configured slaves.
ec_slave_state_t current_state
Current application state.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
size_t nwords
Number of words.
void(* state)(ec_fsm_master_t *)
master state function
uint16_t address
Register address.
ec_slave_port_link_t link
Port link status.
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, u64 app_time_sent)
Configure 32 bit time offset.
unsigned int allow_scan
True, if slave scanning is allowed.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
void ec_fsm_master_restart(ec_fsm_master_t *fsm)
Restarts the master state machine.
unsigned int rescan_required
A bus rescan is required.
int ec_fsm_reboot_success(ec_fsm_reboot_t *fsm)
Returns, if the state machine terminated with success.
void ec_fsm_master_state_read_al_status(ec_fsm_master_t *)
Master state: READ AL STATUS.
void ec_fsm_sii_write(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, const uint16_t *value, ec_fsm_sii_addressing_t mode)
Initializes the SII write state machine.
void ec_master_expire_slave_config_requests(ec_master_t *master)
Abort active requests for slave configs without attached slaves.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *fsm, u64 system_time, u64 old_offset, u64 app_time_sent)
Configure 64 bit time offset.
u64 dc_ref_time
Common reference timestamp for DC start times.
ec_slave_state_t slave_states[EC_MAX_NUM_DEVICES]
AL states of responding slaves for every device.
struct list_head emerg_reg_requests
Emergency register access requests.
#define EC_SYSTEM_TIME_TOLERANCE_NS
Time difference [ns] to tolerate without setting a new system time offset.
ec_fsm_slave_t fsm
Slave state machine.
uint16_t working_counter
Working counter.
void ec_fsm_master_action_idle(ec_fsm_master_t *fsm)
Master action: IDLE.
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Executes the SII state machine.
uint8_t link_state
device link state
void ec_fsm_master_state_dc_write_offset(ec_fsm_master_t *)
Master state: DC WRITE OFFSET.
Sent (still in the queue).
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
wait_queue_head_t request_queue
Wait queue for external requests from user space.
EtherCAT master state machine.
uint16_t station_address
Configured station address.
const char * ec_device_names[2]
Device names.
struct list_head list
List head.
void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *fsm)
Master action: Get state of next slave.
int ec_datagram_aprd(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APRD datagram.
Global definitions and macros.
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
ec_lock_t config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
void ec_fsm_master_init(ec_fsm_master_t *fsm, ec_master_t *master, ec_datagram_t *datagram)
Constructor.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
int ec_fsm_master_action_process_sii(ec_fsm_master_t *fsm)
Check for pending SII write requests and process one.
ec_slave_t * fsm_slave
Slave that is queried next for FSM exec.
ec_slave_t * slave
EtherCAT slave.
uint8_t loop_closed
Loop closed.
void ec_master_clear_sii_images(ec_master_t *master)
Clear the SII data applied during bus scanning.
void ec_master_attach_slave_configs(ec_master_t *master)
Attaches the slave configurations to the slaves.
int ec_datagram_apwr(ec_datagram_t *datagram, uint16_t ring_position, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT APWR datagram.
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
u8 dc_offset_valid
DC slaves have valid system time offsets.
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
ec_sii_image_t * sii_image
Current complete SII image.
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
ec_master_phase_t phase
Master phase.
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
ec_fsm_sii_t fsm_sii
SII state machine.
ec_slave_t * slaves
Array of slaves on the bus.
Use configured addresses.
void ec_fsm_master_action_configure(ec_fsm_master_t *fsm)
Master action: Configure.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
void ec_datagram_print_wc_error(const ec_datagram_t *datagram)
Evaluates the working counter of a single-cast datagram.
ec_slave_dc_range_t base_dc_range
DC range.
void ec_fsm_slave_set_ready(ec_fsm_slave_t *fsm)
Sets the current state of the state machine to READY.
void ec_fsm_master_state_dc_reset_filter(ec_fsm_master_t *)
Master state: DC RESET FILTER.
uint32_t transmission_delay
DC system time transmission delay (offset from reference clock).
unsigned int slave_count
Number of slaves on the bus.
unsigned int scan_busy
Current scan state.
ec_device_index_t
Master devices.
void ec_fsm_master_state_dc_measure_delays(ec_fsm_master_t *)
Master state: DC MEASURE DELAYS.
void ec_fsm_master_state_broadcast(ec_fsm_master_t *)
Master state: BROADCAST.
uint16_t alias
Configured station alias.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
unsigned long scan_jiffies
beginning of slave scanning
ec_fsm_reboot_t fsm_reboot
Slave reboot state machine.
#define EC_ABS(X)
Absolute value.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
int ec_fsm_reboot_exec(ec_fsm_reboot_t *fsm)
Executes the current state of the state machine.
unsigned int active
Master has been activated.
int ec_datagram_brd(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BRD datagram.
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
uint8_t has_dc_system_time
The slave supports the DC system time register.
void ec_fsm_reboot_init(ec_fsm_reboot_t *fsm, ec_datagram_t *datagram)
Constructor.
void ec_fsm_reboot_single(ec_fsm_reboot_t *fsm, ec_slave_t *slave)
Starts the reboot state machine for a single slave.
wait_queue_head_t scan_queue
Queue for processes that wait for slave scanning.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
int idle
state machine is in idle phase
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
uint16_t effective_alias
Effective alias address.
int ec_fsm_sii_success(ec_fsm_sii_t *fsm)
Returns, if the master startup state machine terminated with success.
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
void ec_master_eoe_start(ec_master_t *master)
Starts Ethernet over EtherCAT processing on demand.
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
ec_master_t * master
master the FSM runs on
uint8_t * data
Pointer to data memory.
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
#define EC_MAX_PORTS
Maximum number of slave ports.
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
void ec_slave_init(ec_slave_t *slave, ec_master_t *master, ec_device_index_t dev_idx, uint16_t ring_position, uint16_t station_address)
Slave constructor.
ec_direction_t dir
Direction.
void ec_fsm_sii_init(ec_fsm_sii_t *fsm)
Constructor.
uint32_t receive_time
Port receive times for delay measurement.
void ec_fsm_master_state_reboot_slave(ec_fsm_master_t *)
Master state: REBOOT SLAVE.
unsigned int retries
retries on datagram timeout.
uint8_t base_dc_supported
Distributed clocks are supported.
void ec_fsm_master_state_write_sii(ec_fsm_master_t *)
Master state: WRITE SII.
uint8_t * data
Datagram payload.
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
void ec_master_slaves_not_available(ec_master_t *master)
Set flag to say that the slaves are not available for slave request processing.
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
size_t mem_size
Datagram data memory size.
void ec_fsm_master_enter_dc_measure_delays(ec_fsm_master_t *fsm)
Start measuring DC delays.
ec_device_index_t device_index
Index of device the slave responds on.
Unused and should not be queued (dequeued).
ec_slave_t * slave
current slave
Values written by the master.
uint8_t scan_required
Scan required.
off_t sii_index
index to SII write request data
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
unsigned int error_flag
Stop processing after an error.
void ec_fsm_master_state_dc_read_old_times(ec_fsm_master_t *)
Master state: DC READ OLD TIMES.
unsigned int config_changed
The configuration changed.
struct list_head list
List item.
ec_device_index_t dev_idx
Current device index (for scanning etc.).
#define EC_READ_U64(DATA)
Read a 64-bit unsigned value from EtherCAT data.
uint8_t link_up
Link detected.
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
ec_lock_t scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
unsigned int config_busy
State of slave configuration.
const uint16_t * words
Pointer to the data words.
void ec_fsm_master_clear(ec_fsm_master_t *fsm)
Destructor.
EtherCAT FoE state machines.
void ec_slave_set_al_status(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *)
Start writing DC system times.
void ec_master_eoe_stop(ec_master_t *master)
Stops the Ethernet over EtherCAT processing.
uint8_t link_state[EC_MAX_NUM_DEVICES]
Last link state for every device.
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
void ec_fsm_reboot_clear(ec_fsm_reboot_t *fsm)
Destructor.
unsigned int force_config
Force (re-)configuration.
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.
void ec_master_slaves_available(ec_master_t *master)
Set flag to say that the slaves are now available for slave request processing.