37 #include <asm/div64.h> 52 #define EC_DC_MAX_SYNC_DIFF_NS 10000 56 #define EC_DC_SYNC_WAIT_MS 5000 60 #define EC_DC_START_OFFSET 100000000ULL 206 fsm->
state(fsm, datagram);
298 EC_SLAVE_DBG(slave, 1,
"Clearing FMMU configurations...\n");
307 EC_SLAVE_DBG(slave, 1,
"Clearing mailbox check flag...\n");
361 EC_SLAVE_DBG(slave, 1,
"Clearing sync manager configurations...\n");
389 " clearing datagram.\n");
397 "Failed to clear sync manager configurations: ");
446 " clearing datagram.\n");
480 EC_SLAVE_ERR(slave,
"Slave cannot configure SyncManager." 481 " SII data not available.\n");
488 " mailbox communication.\n");
497 EC_SLAVE_DBG(slave, 1,
"Configuring mailbox sync managers...\n");
538 for (i = 0; i < 2; i++) {
562 " mailbox sync manager configurations.\n");
625 " configuration datagram: ");
647 " mailbox sync managers.\n");
651 (
unsigned int) diff * 1000 / HZ);
688 EC_SLAVE_DBG(slave, 1,
"Assigning SII access to PDI.\n");
717 EC_SLAVE_WARN(slave,
"Failed receive SII assignment datagram: ");
784 EC_SLAVE_DBG(slave, 1,
"Assigning SII access back to EtherCAT.\n");
820 EC_SLAVE_WARN(slave,
"Failed receive SII assignment datagram: ");
826 EC_SLAVE_WARN(slave,
"Failed to assign SII back to EtherCAT: ");
1006 fsm->
state(fsm, datagram);
1049 EC_SLAVE_DBG(slave, 1,
"Setting watchdog divider to %u.\n",
1079 EC_SLAVE_ERR(slave,
"Failed to receive watchdog divider" 1080 " configuration datagram: ");
1141 " watchdog configuration datagram: ");
1148 " watchdog intervals: ");
1165 unsigned int i, j, offset, num_pdo_syncs;
1172 EC_SLAVE_ERR(slave,
"Slave cannot configure PDO SyncManager." 1173 " SII data not available.\n");
1197 for (i = 0; i < num_pdo_syncs; i++) {
1199 uint8_t pdo_xfer = 0;
1200 sync_index = i + offset;
1222 ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer,
1248 EC_SLAVE_ERR(slave,
"Failed to receive process data sync" 1249 " manager configuration datagram: ");
1257 EC_SLAVE_ERR(slave,
"Failed to set process data sync managers: ");
1307 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",
1416 EC_SLAVE_ERR(slave,
"Failed to receive DC cycle times datagram: ");
1452 uint32_t abs_sync_diff;
1453 unsigned long diff_ms;
1470 EC_SLAVE_ERR(slave,
"Failed to receive DC sync check datagram: ");
1493 if ((diff_ms < fsm->last_diff_ms)
1496 EC_SLAVE_DBG(slave, 1,
"Sync after %4lu ms: %10d ns\n",
1497 diff_ms, negative ? -abs_sync_diff: abs_sync_diff);
1507 EC_SLAVE_DBG(slave, 1,
"%d ns difference after %lu ms.\n",
1508 negative ? -abs_sync_diff: abs_sync_diff, diff_ms);
1518 u32 remainder, cycle;
1522 remainder = do_div(diff, cycle);
1524 start = start_time + cycle - remainder + sync0->
shift_time;
1528 EC_SLAVE_DBG(slave, 1,
" start_time=%llu\n", start_time);
1536 " Cyclic start time will not be in phase.\n");
1541 " start time to %llu.\n", start_time);
1573 EC_SLAVE_ERR(slave,
"Failed to receive DC start time datagram: ");
1586 EC_SLAVE_DBG(slave, 1,
"Setting DC AssignActivate to 0x%04x.\n",
1614 EC_SLAVE_ERR(slave,
"Failed to receive DC activation datagram: ");
1794 EC_SLAVE_DBG(slave, 1,
"Now in OP. Finished configuration.\n");
1809 "configuration. Reconfiguring.");
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
Finite state machines for the Sercos over EtherCAT protocol.
void ec_mbox_prot_data_prealloc(ec_slave_t *slave, uint16_t protocols, size_t size)
Allocates internal memory for mailbox response data for all slave supported mailbox protocols ...
unsigned long jiffies_sent
Jiffies, when the datagram was sent.
struct list_head sdo_configs
List of SDO configurations.
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *fsm)
Start slave configuration state machine.
uint16_t boot_rx_mailbox_offset
Bootstrap receive mailbox address.
#define EC_SYNC_PAGE_SIZE
Size of a sync manager configuration page.
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_state_op(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: OP.
uint8_t spontaneous_change
spontaneous state change detected
void ec_fsm_slave_config_state_soe_conf_safeop(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: SOE_CONF.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
ec_sdo_request_t * request
SDO request for SDO configuration.
struct list_head list
List item.
#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].
OP (mailbox communication and input/output update)
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
ec_fsm_change_t * fsm_change
State change state machine.
ec_slave_state_t current_state
Current application state.
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_state_start(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: START.
void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: WATCHDOG.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
void ec_fsm_slave_config_quick_start(ec_fsm_slave_config_t *fsm)
Start slave configuration state machine for "quick" SAFEOP->OP.
u64 dc_ref_time
Common reference timestamp for DC start times.
Bootstrap state (mailbox communication, firmware update)
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.
void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: WATCHDOG_DIVIDER.
uint16_t working_counter
Working counter.
void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *, ec_datagram_t *)
Assign SII to PDI.
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
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_assign_pdi(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: ASSIGN_PDI.
uint16_t station_address
Configured station address.
unsigned int sync_count
Number of sync managers.
ec_sdo_request_t request_copy
Copied SDO request.
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
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.
void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Configure PDO sync managers.
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_clear_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Clear the sync manager configurations.
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_enter_soe_conf_preop(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for SoE configurations to be applied.
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
EtherCAT slave configuration state machine.
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.
void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for FMMUs to be configured.
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine.
ec_sii_image_t * sii_image
Current complete SII image.
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.
void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: INIT.
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.
void ec_fsm_slave_config_enter_dc_cycle(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for DC to be configured.
uint16_t mailbox_protocols
Supported mailbox protocols.
void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: BOOT/PREOP.
void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: SOE_CONF.
int ec_fsm_slave_config_running(const ec_fsm_slave_config_t *fsm)
void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: PDO_CONF.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
void ec_fsm_slave_config_state_dc_cycle(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: DC CYCLE.
void ec_fsm_slave_config_enter_soe_conf_safeop(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for SoE configurations to be applied in SAFEOP.
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.
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for SDO configurations to be applied.
void ec_soe_request_clear(ec_soe_request_t *req)
SoE request destructor.
ec_pdo_list_t pdos
Current PDO assignment.
uint16_t dc_assign_activate
Vendor-specific AssignActivate word.
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.
void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: CLEAR SYNC.
uint8_t base_fmmu_count
Number of supported FMMUs.
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for mailbox sync managers to be configured.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
uint16_t watchdog_intervals
Process data watchdog intervals (see spec.
ec_master_t * master
Master owning the slave.
void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Check for PDO sync managers to be configured.
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_init(ec_fsm_slave_config_t *, ec_datagram_t *)
Start state change to INIT.
void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: ASSIGN_ETHERCAT.
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_state_mbox_sync(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: SYNC.
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.
void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: FMMU.
void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: SAFEOP.
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.
ec_al_state_t al_state
AL state (only valid for IDN config).
void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *, ec_datagram_t *)
Reconfigure the slave starting at INIT.
#define EC_DC_MAX_SYNC_DIFF_NS
Maximum clock difference (in ns) before going to SAFEOP.
void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: CLEAR DC ASSIGN.
ec_fsm_soe_t * fsm_soe
SoE state machine.
struct list_head soe_configs
List of SoE configurations.
unsigned int take_time
Store jiffies after datagram reception.
void ec_read_mbox_lock_clear(ec_slave_t *slave)
Clears the mailbox lock.
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_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: SDO_CONF.
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
#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.
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.
int ec_fsm_slave_config_exec(ec_fsm_slave_config_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_config_enter_safeop(ec_fsm_slave_config_t *, ec_datagram_t *)
Request SAFEOP state.
int ec_fsm_change_exec(ec_fsm_change_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
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.
void ec_fsm_slave_config_state_dc_sync_check(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: DC SYNC CHECK.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
uint8_t base_dc_supported
Distributed clocks are supported.
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *fsm, ec_slave_t *slave, ec_fsm_change_t *fsm_change, ec_fsm_coe_t *fsm_coe, ec_fsm_soe_t *fsm_soe, ec_fsm_pdo_t *fsm_pdo)
Constructor.
uint8_t * data
Datagram payload.
void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *, ec_datagram_t *)
WATCHDOG_DIVIDER entry function.
void ec_fsm_slave_config_state_quick_start(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: QUICK START.
uint8_t base_sync_count
Number of supported sync managers.
void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *, ec_datagram_t *)
Request PREOP state.
EtherCAT slave configuration.
ec_soe_request_t * soe_request
SDO request for SDO configuration.
void ec_soe_request_write(ec_soe_request_t *req)
Request a write operation.
void ec_fsm_slave_config_enter_op(ec_fsm_slave_config_t *, ec_datagram_t *)
Bring slave to OP.
int ec_fsm_slave_config_success(const ec_fsm_slave_config_t *fsm)
void ec_soe_request_init(ec_soe_request_t *req)
SoE request constructor.
EtherCAT slave configuration structure.
ec_sii_t sii
Extracted SII data.
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.
PREOP state (mailbox communication, no IO)
void ec_fsm_slave_config_state_dc_assign(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: DC ASSIGN.
unsigned long last_diff_ms
For sync reporting.
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *, ec_datagram_t *)
PDO_CONF entry function.
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_fsm_slave_config_enter_dc_clear_assign(ec_fsm_slave_config_t *, ec_datagram_t *)
Clear the DC assignment.
int ec_datagram_repeat(ec_datagram_t *datagram, const ec_datagram_t *source)
Copies a previously constructed datagram for repeated send.
void ec_sync_init(ec_sync_t *sync, ec_slave_t *slave)
Constructor.
void ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: CLEAR FMMU.
#define EC_DC_SYNC_WAIT_MS
Maximum time (in ms) to wait for clock discipline.
unsigned long jiffies_received
Jiffies, when the datagram was received.
void(* state)(ec_fsm_slave_config_t *, ec_datagram_t *)
State function.
void ec_fsm_slave_config_state_dc_start(ec_fsm_slave_config_t *, ec_datagram_t *)
Slave configuration state: DC START.
EtherCAT state change FSM.
void ec_fsm_slave_config_state_error(ec_fsm_slave_config_t *, ec_datagram_t *)
State: ERROR.
int ec_soe_request_copy(ec_soe_request_t *req, const ec_soe_request_t *other)
Copy another SoE request.
void ec_fsm_slave_config_state_end(ec_fsm_slave_config_t *, ec_datagram_t *)
State: END.
int ec_fsm_change_success(ec_fsm_change_t *fsm)
Returns, if the state machine terminated with success.
unsigned long jiffies_start
For timeout calculations.
Sercos-over-EtherCAT request.
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.
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *, ec_datagram_t *)
WATCHDOG entry function.