28 #include <asm/div64.h> 43 #define EC_DC_MAX_SYNC_DIFF_NS 10000 47 #define EC_DC_SYNC_WAIT_MS 5000 51 #define EC_DC_START_OFFSET 100000000ULL 271 EC_SLAVE_DBG(slave, 1,
"Clearing FMMU configurations...\n");
329 EC_SLAVE_DBG(slave, 1,
"Clearing sync manager configurations...\n");
356 " clearing datagram.\n");
364 "Failed to clear sync manager configurations: ");
412 " clearing datagram.\n");
447 " mailbox communication.\n");
456 EC_SLAVE_DBG(slave, 1,
"Configuring mailbox sync managers...\n");
496 for (i = 0; i < 2; i++) {
516 " mailbox sync manager configurations.\n");
574 " configuration datagram: ");
596 " mailbox sync managers.\n");
600 (
unsigned int) diff * 1000 / HZ);
636 EC_SLAVE_DBG(slave, 1,
"Assigning SII access to PDI.\n");
664 EC_SLAVE_WARN(slave,
"Failed receive SII assignment datagram: ");
739 assign_to_pdi = flag->
value;
744 EC_SLAVE_DBG(slave, 1,
"Skipping SII assignment back to EtherCAT.\n");
754 EC_SLAVE_DBG(slave, 1,
"Assigning SII access back to EtherCAT.\n");
790 EC_SLAVE_WARN(slave,
"Failed receive SII assignment datagram: ");
796 EC_SLAVE_WARN(slave,
"Failed to assign SII back to EtherCAT: ");
973 EC_SLAVE_DBG(slave, 1,
"Setting EoE IP parameters...\n");
1002 EC_SLAVE_DBG(slave, 1,
"Finished setting EoE IP parameters.\n");
1005 EC_SLAVE_ERR(slave,
"Failed to set EoE IP parameters.\n");
1064 EC_SLAVE_DBG(slave, 1,
"Setting watchdog divider to %u.\n",
1092 EC_SLAVE_ERR(slave,
"Failed to receive watchdog divider" 1093 " configuration datagram: ");
1152 " watchdog configuration datagram: ");
1159 " watchdog intervals: ");
1176 unsigned int i, j, offset, num_pdo_syncs;
1201 for (i = 0; i < num_pdo_syncs; i++) {
1203 uint8_t pdo_xfer = 0;
1204 sync_index = i + offset;
1205 sync = &slave->
sii.
syncs[sync_index];
1226 ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer,
1250 EC_SLAVE_ERR(slave,
"Failed to receive process data sync" 1251 " manager configuration datagram: ");
1259 EC_SLAVE_ERR(slave,
"Failed to set process data sync managers: ");
1309 EC_SLAVE_ERR(slave,
"Failed to determine PDO sync manager" 1337 EC_SLAVE_ERR(slave,
"Failed to receive FMMUs datagram: ");
1373 " distributed clocks!\n");
1376 EC_SLAVE_DBG(slave, 1,
"Setting DC cycle times to %u / %u.\n",
1413 EC_SLAVE_ERR(slave,
"Failed to receive DC cycle times datagram: ");
1446 uint32_t abs_sync_diff;
1447 unsigned long diff_ms;
1462 EC_SLAVE_ERR(slave,
"Failed to receive DC sync check datagram: ");
1484 EC_SLAVE_DBG(slave, 1,
"Sync after %4lu ms: %10u ns\n",
1485 diff_ms, abs_sync_diff);
1493 EC_SLAVE_DBG(slave, 1,
"%u ns difference after %lu ms.\n",
1494 abs_sync_diff, diff_ms);
1504 u32 remainder, cycle;
1508 remainder = do_div(diff, cycle);
1510 start = start_time + cycle - remainder + sync0->
shift_time;
1514 EC_SLAVE_DBG(slave, 1,
" start_time=%llu\n", start_time);
1522 " Cyclic start time will not be in phase.\n");
1527 " start time to %llu.\n", start_time);
1557 EC_SLAVE_ERR(slave,
"Failed to receive DC start time datagram: ");
1570 EC_SLAVE_DBG(slave, 1,
"Setting DC AssignActivate to 0x%04x.\n",
1596 EC_SLAVE_ERR(slave,
"Failed to receive DC activation datagram: ");
1628 "WaitBeforeSAFEOPms");
1629 if (flag && flag->
value > 0) {
1658 if (diff * 1000 / HZ < fsm->wait_ms) {
1823 EC_SLAVE_DBG(slave, 1,
"Now in OP. Finished configuration.\n");
1837 "configuration. Reconfiguring.");
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Finite state machines for the Sercos over EtherCAT protocol.
int ec_fsm_eoe_exec(ec_fsm_eoe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *)
Slave configuration state: BOOT/PREOP.
struct list_head sdo_configs
List of SDO configurations.
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
ec_sii_t sii
Extracted SII data.
int ec_fsm_pdo_exec(ec_fsm_pdo_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm, ec_slave_t *slave)
Start slave configuration state machine.
uint8_t spontaneous_change
spontaneous state change detected
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *)
WATCHDOG entry function.
int ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *)
Slave configuration state: INIT.
void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *)
Slave configuration state: SAFEOP.
void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *)
Assign SII to PDI.
ec_sdo_request_t * request
SDO request for SDO configuration.
void ec_fsm_slave_config_state_wait_safeop(ec_fsm_slave_config_t *)
Slave configuration state: WAIT SAFEOP.
void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *)
Reconfigure the slave starting at INIT.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
void ec_fsm_pdo_start_configuration(ec_fsm_pdo_t *fsm, ec_slave_t *slave)
Start writing the PDO configuration.
int32_t shift_time
Shift time [ns].
void ec_fsm_slave_config_enter_eoe_ip_param(ec_fsm_slave_config_t *)
EOE_IP_PARAM entry function.
OP (mailbox communication and input/output update)
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
void ec_fsm_slave_config_state_dc_cycle(ec_fsm_slave_config_t *)
Slave configuration state: DC CYCLE.
ec_fsm_change_t * fsm_change
State change state machine.
ec_slave_state_t current_state
Current application state.
void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR DC ASSIGN.
void ec_fsm_slave_config_state_dc_start(ec_fsm_slave_config_t *)
Slave configuration state: DC START.
uint8_t used_fmmus
Number of FMMUs used.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
void ec_fsm_slave_config_enter_soe_conf_safeop(ec_fsm_slave_config_t *)
Check for SoE configurations to be applied in SAFEOP.
void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *)
Slave configuration state: FMMU.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
u64 dc_ref_time
Common reference timestamp for DC start times.
Bootstrap state (mailbox communication, firmware update)
void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *)
Slave configuration state: SOE_CONF.
ec_eoe_request_t eoe_ip_param_request
EoE IP parameters.
uint32_t cycle_time
Cycle time [ns].
void ec_fsm_change_start(ec_fsm_change_t *fsm, ec_slave_t *slave, ec_slave_state_t state)
Starts the change state machine.
uint16_t working_counter
Working counter.
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
void ec_fsm_slave_config_state_start(ec_fsm_slave_config_t *)
Slave configuration state: START.
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
Sent (still in the queue).
void ec_fmmu_config_page(const ec_fmmu_config_t *fmmu, const ec_sync_t *sync, uint8_t *data)
Initializes an FMMU configuration page.
void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *)
Slave configuration state: SYNC.
void ec_fsm_slave_config_enter_dc_clear_assign(ec_fsm_slave_config_t *)
Clear the DC assignment.
uint16_t station_address
Configured station address.
int ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
unsigned int sync_count
Number of sync managers.
ec_fsm_eoe_t * fsm_eoe
EoE state machine.
ec_sdo_request_t request_copy
Copied SDO request.
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
void ec_fsm_eoe_set_ip_param(ec_fsm_eoe_t *fsm, ec_slave_t *slave, ec_eoe_request_t *request)
Starts to set the EoE IP partameters of a slave.
void ec_sync_page(const ec_sync_t *sync, uint8_t sync_index, uint16_t data_size, const ec_sync_config_t *sync_config, uint8_t pdo_xfer, uint8_t *data)
Initializes a sync manager configuration page.
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
ec_al_state_t al_state
AL state (only valid for IDN config).
EtherCAT master structure.
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]
FMMU configurations.
SAFEOP (mailbox communication and input update)
void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *)
WATCHDOG_DIVIDER entry function.
ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT]
DC sync signals.
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
void ec_fsm_slave_config_state_assign_pdi(ec_fsm_slave_config_t *)
Slave configuration state: ASSIGN_PDI.
int ec_eoe_request_valid(const ec_eoe_request_t *req)
Checks if EoE request has something to set.
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
EtherCAT slave configuration state machine.
void ec_fsm_slave_config_state_soe_conf_safeop(ec_fsm_slave_config_t *)
Slave configuration state: SOE_CONF.
uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *pl)
Calculates the total size of the mapped PDO entries.
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine.
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.
ec_sync_config_t sync_configs[EC_MAX_SYNC_MANAGERS]
Sync manager configurations.
ec_datagram_state_t state
State.
ec_slave_config_t * config
Current configuration.
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
uint8_t sync_index
Index of sync manager to use.
Slave configutation feature flag.
void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *)
Slave configuration state: WATCHDOG_DIVIDER.
uint16_t mailbox_protocols
Supported mailbox protocols.
ec_flag_t * ec_slave_config_find_flag(ec_slave_config_t *sc, const char *key)
Finds a flag.
void ec_fsm_slave_config_state_end(ec_fsm_slave_config_t *)
State: END.
void ec_fsm_slave_config_enter_clear_sync(ec_fsm_slave_config_t *)
Clear the sync manager configurations.
int ec_fsm_slave_config_running(const ec_fsm_slave_config_t *)
#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.
#define EC_DC_START_OFFSET
Time offset (in ns), that is added to cyclic start time.
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
int ec_fsm_change_exec(ec_fsm_change_t *fsm)
Executes the current state of the state machine.
struct list_head list
List item.
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR FMMU.
ec_pdo_list_t pdos
Current PDO assignment.
uint16_t dc_assign_activate
Vendor-specific AssignActivate word.
void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *)
Check for mailbox sync managers to be configured.
ec_datagram_t * datagram
Datagram used in the state machine.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
uint8_t base_fmmu_count
Number of supported FMMUs.
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
int ec_fsm_eoe_success(const ec_fsm_eoe_t *fsm)
Returns, if the state machine terminated with success.
void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *)
Check for FMMUs to be configured.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
unsigned long wait_ms
Wait time (used to wait before SAFEOP).
uint16_t watchdog_intervals
Process data watchdog intervals (see spec.
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *)
Check for SDO configurations to be applied.
ec_master_t * master
Master owning the slave.
int ec_sdo_request_copy(ec_sdo_request_t *req, const ec_sdo_request_t *other)
Copy another SDO request.
void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *)
Check for SoE configurations to be applied.
void(* state)(ec_fsm_slave_config_t *)
State function.
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_slave_config_enter_init(ec_fsm_slave_config_t *)
Start state change to INIT.
void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *)
Slave configuration state: PDO_CONF.
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.
uint8_t control_register
Control register value.
ec_fsm_coe_t * fsm_coe
CoE state machine.
uint16_t watchdog_divider
Watchdog divider as a number of 40ns intervals (see spec.
PDO configuration state machine.
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.
void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *)
Configure PDO sync managers.
#define EC_DC_MAX_SYNC_DIFF_NS
Maximum clock difference (in ns) before going to SAFEOP.
void ec_fsm_slave_config_enter_safeop(ec_fsm_slave_config_t *)
Request SAFEOP state.
ec_fsm_soe_t * fsm_soe
SoE state machine.
struct list_head soe_configs
List of SoE configurations.
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *)
PDO_CONF entry function.
Ethernet-over-EtherCAT set IP parameter request.
unsigned int take_time
Store jiffies after datagram reception.
void ec_fsm_slave_config_state_eoe_ip_param(ec_fsm_slave_config_t *)
Slave configuration state: EOE_IP_PARAM.
INIT state (no mailbox communication, no IO)
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
Finite state machine to configure an EtherCAT slave.
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
uint8_t enable
Enable bit.
ec_slave_t * slave
Slave the FSM runs on.
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *)
Slave configuration state: OP.
#define EC_WRITE_U64(DATA, VAL)
Write a 64-bit unsigned value to EtherCAT data.
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
ec_soe_request_t soe_request_copy
Copied SDO request.
Sync manager configuration.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm)
Executes the current state of the state machine.
struct list_head list
List item.
EtherCAT slave sync signal configuration.
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *)
Slave configuration state: CLEAR SYNC.
void ec_fsm_slave_config_enter_wait_safeop(ec_fsm_slave_config_t *)
Wait before SAFEOP transition.
void ec_fsm_slave_config_state_error(ec_fsm_slave_config_t *)
State: ERROR.
int32_t value
Flag value (meaning depends on key).
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *fsm)
Destructor.
u64 app_time
Time of the last ecrt_master_sync() call.
uint16_t physical_start_address
Physical start address.
unsigned long jiffies_preop
Time, the slave went to PREOP.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
uint8_t base_dc_supported
Distributed clocks are supported.
uint8_t * data
Datagram payload.
void ec_fsm_slave_config_state_dc_assign(ec_fsm_slave_config_t *)
Slave configuration state: DC ASSIGN.
uint8_t base_sync_count
Number of supported sync managers.
void ec_fsm_slave_config_enter_op(ec_fsm_slave_config_t *)
Bring slave to OP.
EtherCAT slave configuration.
ec_soe_request_t * soe_request
SDO request for SDO configuration.
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *)
Check for PDO sync managers to be configured.
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
EtherCAT slave configuration structure.
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.
uint16_t default_length
Data length in bytes.
void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *)
Slave configuration state: ASSIGN_ETHERCAT.
PREOP state (mailbox communication, no IO)
void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *)
Slave configuration state: SDO_CONF.
void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *)
Slave configuration state: WATCHDOG.
void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *)
Request PREOP state.
unsigned int error_flag
Stop processing after an error.
ec_sync_t * syncs
SYNC MANAGER categories.
uint16_t std_tx_mailbox_size
Standard transmit mailbox size.
ec_slave_state_t requested_state
Requested application state.
#define EC_FMMU_PAGE_SIZE
Size of an FMMU configuration page.
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
void ec_fsm_slave_config_state_dc_sync_check(ec_fsm_slave_config_t *)
Slave configuration state: DC SYNC CHECK.
#define EC_DC_SYNC_WAIT_MS
Maximum time (in ms) to wait for clock discipline.
Sercos-over-EtherCAT request.
unsigned long jiffies_received
Jiffies, when the datagram was received.
EtherCAT state change FSM.
void ec_fsm_slave_config_enter_dc_cycle(ec_fsm_slave_config_t *)
Check for DC to be configured.
int ec_soe_request_copy(ec_soe_request_t *req, const ec_soe_request_t *other)
Copy another SoE request.
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
Finite state machines for the Ethernet over EtherCAT protocol.
unsigned long jiffies_start
For timeout calculations.
Finite state machines for the CANopen over EtherCAT protocol.
ec_sync_t * ec_slave_get_sync(ec_slave_t *slave, uint8_t sync_index)
Get the sync manager given an index.
unsigned int retries
Retries on datagram timeout.