43 #define EC_SYSTEM_TIME_TOLERANCE_NS 1000000 235 list_del_init(&request->
list);
236 request->
state = EC_INT_REQUEST_BUSY;
239 EC_MASTER_ERR(master,
"Emergency request data too large!\n");
240 request->
state = EC_INT_REQUEST_FAILURE;
248 " write requests!\n");
249 request->
state = EC_INT_REQUEST_FAILURE;
255 EC_MASTER_DBG(master, 1,
"Writing emergency register request...\n");
260 request->
state = EC_INT_REQUEST_SUCCESS;
283 unsigned int i, size;
305 "link down on %s device. Clearing slave list.\n",
351 unsigned int count = 0, next_dev_slave, ring_position;
386 " of slave memory!\n", size);
397 for (i = 0; i < count; i++, ring_position++) {
398 slave = master->
slaves + i;
399 while (i >= next_dev_slave) {
478 list_del_init(&request->
list);
479 request->
state = EC_INT_REQUEST_BUSY;
486 assign_to_pdi = flag->
value;
493 "Assigning SII back to EtherCAT.\n");
532 for (slave = master->
slaves;
541 if (sdo_req->
state == EC_INT_REQUEST_QUEUED) {
544 sdo_req->
state = EC_INT_REQUEST_FAILURE;
551 sdo_req->
state = EC_INT_REQUEST_FAILURE;
555 sdo_req->
state = EC_INT_REQUEST_BUSY;
557 " SDO request...\n");
569 if (soe_req->
state == EC_INT_REQUEST_QUEUED) {
572 soe_req->
state = EC_INT_REQUEST_FAILURE;
579 soe_req->
state = EC_INT_REQUEST_FAILURE;
583 soe_req->
state = EC_INT_REQUEST_BUSY;
585 " SoE request...\n");
618 for (slave = master->
slaves;
625 for (slave = master->
slaves;
705 " (aborting state check).\n");
726 EC_SLAVE_DBG(slave, 1,
"Changing state from %s to %s%s.\n",
727 old_state, new_state,
761 EC_SLAVE_ERR(slave,
"Failed to receive AL state datagram: ");
771 EC_SLAVE_DBG(slave, 1,
"Slave did not respond to state query.\n");
816 EC_SLAVE_ERR(slave,
"Failed to acknowledge state change.\n");
855 " clearing datagram on %s link: ",
866 EC_MASTER_WARN(master,
"Failed to clear station addresses on %s link:" 873 " to measure transmission delays on %s link.\n",
899 EC_MASTER_ERR(master,
"Failed to receive delay measuring datagram" 909 EC_MASTER_DBG(master, 1,
"%u slaves responded to delay measuring" 959 if (!(eoe = kmalloc(
sizeof(
ec_eoe_t), GFP_KERNEL))) {
960 EC_SLAVE_ERR(slave,
"Failed to allocate EoE handler memory!\n");
1075 " but master already active.\n");
1077 EC_MASTER_DBG(master, 1,
"No app_time received up to now.\n");
1096 unsigned long jiffies_since_read
1100 u32 correction, system_time32, old_offset32, new_offset;
1103 system_time32 = (u32) system_time;
1104 old_offset32 = (u32) old_offset;
1107 correction = jiffies_since_read * 1000 / HZ * 1000000;
1108 system_time32 += correction;
1111 EC_SLAVE_DBG(slave, 1,
"DC 32 bit system time offset calculation:" 1112 " system_time=%u (corrected with %u)," 1113 " app_time=%llu, diff=%i\n",
1114 system_time32, correction,
1118 new_offset = time_diff + old_offset32;
1119 EC_SLAVE_DBG(slave, 1,
"Setting time offset to %u (was %u)\n",
1120 new_offset, old_offset32);
1121 return (u64) new_offset;
1138 unsigned long jiffies_since_read
1142 u64 new_offset, correction;
1146 correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;
1147 system_time += correction;
1150 EC_SLAVE_DBG(slave, 1,
"DC 64 bit system time offset calculation:" 1151 " system_time=%llu (corrected with %llu)," 1152 " app_time=%llu, diff=%lli\n",
1153 system_time, correction,
1157 new_offset = time_diff + old_offset;
1158 EC_SLAVE_DBG(slave, 1,
"Setting time offset to %llu (was %llu)\n",
1159 new_offset, old_offset);
1161 new_offset = old_offset;
1178 u64 system_time, old_offset, new_offset;
1179 unsigned long jiffies_since_read;
1185 EC_SLAVE_ERR(slave,
"Failed to receive DC times datagram: ");
1206 system_time, old_offset, jiffies_since_read);
1209 system_time, old_offset, jiffies_since_read);
1237 "Failed to receive DC system time offset datagram: ");
1245 EC_SLAVE_ERR(slave,
"Failed to set DC system time offset: ");
1272 EC_SLAVE_ERR(slave,
"Failed to receive SII assignment datagram: ");
1278 EC_SLAVE_ERR(slave,
"Failed to assign SII back to EtherCAT: ");
1285 EC_SLAVE_DBG(slave, 1,
"Writing SII data (after assignment)...\n");
1309 request->
state = EC_INT_REQUEST_FAILURE;
1326 EC_SLAVE_DBG(slave, 1,
"Finished writing %zu words of SII data.\n",
1337 request->
state = EC_INT_REQUEST_SUCCESS;
1370 unsigned int sdo_count, entry_count;
1372 EC_SLAVE_DBG(slave, 1,
"Fetched %u SDOs and %u entries.\n",
1373 sdo_count, entry_count);
1404 "Failed to process internal SDO request.\n");
1405 request->
state = EC_INT_REQUEST_FAILURE;
1412 request->
state = EC_INT_REQUEST_SUCCESS;
1447 "Failed to process internal SoE request.\n");
1448 request->
state = EC_INT_REQUEST_FAILURE;
1455 request->
state = EC_INT_REQUEST_SUCCESS;
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *)
Master state: CONFIGURE SLAVE.
uint16_t ring_position
Ring position for emergency requests.
ec_internal_request_state_t state
Request state.
uint16_t offset
SII word offset.
uint16_t ring_position
Ring position.
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
ec_datagram_t * datagram
datagram used in the state machine
ec_sii_write_request_t * sii_request
SII write request.
ec_sii_t sii
Extracted SII data.
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
ec_fsm_soe_t fsm_soe
SoE state machine.
struct semaphore config_sem
Semaphore protecting the config_busy variable and the allow_config flag.
void ec_master_calc_dc(ec_master_t *master)
Distributed-clocks calculations.
size_t transfer_size
Size of the data to transfer.
void ec_slave_attach_pdo_names(ec_slave_t *slave)
Attach PDO names.
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.
ec_fsm_pdo_t fsm_pdo
PDO configuration state machine.
Finite state machine of an EtherCAT master.
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.
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
size_t ec_state_string(uint8_t, char *, uint8_t)
Prints slave states in clear text.
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.
u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 64 bit time offset.
size_t nwords
Number of words.
void(* state)(ec_fsm_master_t *)
master state function
ec_internal_request_state_t state
SDO request state.
uint16_t address
Register address.
struct list_head eoe_handlers
Ethernet over EtherCAT handlers.
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 *)
Restarts the master state machine.
unsigned int rescan_required
A bus rescan is required.
ec_sii_coe_details_t coe_details
CoE detail flags.
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.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
unsigned int scan_index
Index of slave currently scanned.
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.
void ec_slave_set_state(ec_slave_t *slave, ec_slave_state_t new_state)
Sets the application state of a slave.
uint16_t working_counter
Working counter.
void ec_fsm_eoe_init(ec_fsm_eoe_t *fsm)
Constructor.
int ec_sdo_request_timed_out(const ec_sdo_request_t *req)
Checks, if the timeout was exceeded.
int ec_fsm_master_action_process_int_request(ec_fsm_master_t *)
Check for pending internal SDO/SoE requests and process one.
void ec_fsm_master_action_idle(ec_fsm_master_t *)
Master action: IDLE.
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor.
Acknowledge/Error bit (no actual state)
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
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).
wait_queue_head_t request_queue
Wait queue for external requests from user space.
void ec_fsm_sii_init(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Constructor.
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 *)
Master action: Get state of next slave.
#define EC_WAIT_SDO_DICT
Seconds to wait before fetching SDO dictionary after slave entered PREOP state.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm)
Executes the current state of the state machine.
Global definitions and macros.
void ec_fsm_pdo_clear(ec_fsm_pdo_t *fsm)
Destructor.
void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *)
Start clearing slave addresses.
EtherCAT master structure.
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 *)
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.
u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long)
Configure 32 bit time offset.
void ec_slave_sdo_dict_info(const ec_slave_t *slave, unsigned int *sdo_count, unsigned int *entry_count)
Counts the total number of SDOs and entries in the dictionary.
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_fsm_master_state_read_state(ec_fsm_master_t *)
Master state: READ STATE.
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *)
Master state: SDO REQUEST.
void ec_fsm_master_state_scan_slave(ec_fsm_master_t *)
Master state: SCAN SLAVE.
void ec_fsm_soe_transfer(ec_fsm_soe_t *fsm, ec_slave_t *slave, ec_soe_request_t *request)
Starts to transfer an IDN to/from a slave.
int ec_fsm_soe_success(const ec_fsm_soe_t *fsm)
Returns, if the state machine terminated with success.
Ethernet over EtherCAT (EoE)
ec_datagram_state_t state
State.
ec_slave_config_t * config
Current configuration.
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.
uint8_t enable_sdo_info
SDO information service available.
Use configured addresses.
ec_fsm_eoe_t fsm_eoe
EoE state machine.
Slave configutation feature flag.
ec_fsm_slave_scan_t fsm_slave_scan
slave state machine
uint8_t sdo_dictionary_fetched
Dictionary has been fetched.
struct list_head sdo_requests
List of SDO requests.
uint16_t mailbox_protocols
Supported mailbox protocols.
void ec_fsm_master_action_configure(ec_fsm_master_t *)
Master action: Configure.
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
ec_sdo_request_t * sdo_request
SDO request to process.
unsigned int debug_level
Master debug level.
#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.
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
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.
void ec_fsm_pdo_init(ec_fsm_pdo_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
ec_soe_request_t * soe_request
SoE request to process.
void ec_fsm_coe_clear(ec_fsm_coe_t *fsm)
Destructor.
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
#define EC_ABS(X)
Absolute value.
void ec_fsm_master_state_assign_sii(ec_fsm_master_t *)
Master state: ASSIGN SII.
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
unsigned int active
Master has been activated.
ec_master_t * master
Master owning the slave.
struct list_head soe_requests
List of SoE requests.
void ec_fsm_change_clear(ec_fsm_change_t *fsm)
Destructor.
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.
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.
void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, ec_slave_t *slave)
Starts reading a slaves' SDO dictionary.
void ec_fsm_master_state_soe_request(ec_fsm_master_t *)
Master state: SoE REQUEST.
ec_device_index_t device_index
Device via which the datagram shall be / was sent.
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo, ec_fsm_eoe_t *fsm_eoe)
Constructor.
int ec_fsm_master_idle(const ec_fsm_master_t *fsm)
void ec_master_clear_slaves(ec_master_t *master)
Clear all slaves.
void ec_fsm_change_init(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Constructor.
struct list_head list
list item
void ec_fsm_coe_init(ec_fsm_coe_t *fsm)
Constructor.
void ec_fsm_master_state_acknowledge(ec_fsm_master_t *)
Master state: ACKNOWLEDGE.
void ec_fsm_eoe_clear(ec_fsm_eoe_t *fsm)
Destructor.
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
INIT state (no mailbox communication, no IO)
int idle
state machine is in idle phase
struct semaphore scan_sem
Semaphore protecting the scan_busy variable and the allow_scan flag.
void ec_fsm_master_state_start(ec_fsm_master_t *)
Master state: START.
uint16_t effective_alias
Effective alias address.
void ec_master_clear_eoe_handlers(ec_master_t *master)
Clear and free all EoE handlers.
ec_fsm_slave_config_t fsm_slave_config
slave state machine
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm)
Executes the SII state machine.
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
void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *)
Master state: SDO DICTIONARY.
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.
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *)
Master state: CLEAR ADDRESSES.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
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_change_ack(ec_fsm_change_t *fsm, ec_slave_t *slave)
Starts the change state machine to only acknowlegde a slave's state.
wait_queue_head_t config_queue
Queue for processes that wait for slave configuration.
int32_t value
Flag value (meaning depends on key).
unsigned int retries
retries on datagram timeout.
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
u64 app_time
Time of the last ecrt_master_sync() call.
unsigned long jiffies_preop
Time, the slave went to PREOP.
void ec_fsm_soe_init(ec_fsm_soe_t *fsm)
Constructor.
uint8_t base_dc_supported
Distributed clocks are supported.
void ec_fsm_soe_clear(ec_fsm_soe_t *fsm)
Destructor.
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave)
Start slave scan state machine.
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.
EtherCAT slave configuration.
int ec_soe_request_timed_out(const ec_soe_request_t *req)
Checks, if the timeout was exceeded.
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
Executes the current state of the state machine.
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm)
Destructor.
EtherCAT slave configuration structure.
size_t mem_size
Datagram data memory size.
ec_device_index_t device_index
Index of device the slave responds on.
int ec_fsm_soe_exec(ec_fsm_soe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
ec_slave_t * slave
current slave
Values written by the master.
ec_fsm_change_t fsm_change
State change state machine.
Ethernet over EtherCAT (EoE) handler.
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.
unsigned int config_changed
The configuration changed.
struct list_head list
List item.
ec_slave_state_t requested_state
Requested application state.
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.
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
ec_internal_request_state_t state
Request state.
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.
Sercos-over-EtherCAT request.
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.
ec_fsm_coe_t fsm_coe
CoE state machine.
void ec_fsm_master_state_dc_read_offset(ec_fsm_master_t *)
Master state: DC READ OFFSET.
unsigned int force_config
Force (re-)configuration.
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
unsigned int has_general
General category present.
int ec_datagram_bwr(ec_datagram_t *datagram, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT BWR datagram.