52 #define SCAN_RETRY_TIME 100 69 #ifdef EC_SII_OVERRIDE 96 #ifdef EC_SII_OVERRIDE 179 fsm->
state(fsm, datagram);
242 "Failed to receive station address datagram: ");
282 EC_SLAVE_ERR(slave,
"Failed to receive AL state datagram: ");
299 EC_SLAVE_WARN(slave,
"Slave has state error bit set (%s)!\n",
330 EC_SLAVE_ERR(slave,
"Failed to receive base data datagram: ");
349 EC_SLAVE_WARN(slave,
"Slave has more FMMUs (%u) than the master can" 356 EC_SLAVE_WARN(slave,
"Slave provides more sync managers (%u)" 357 " than the master can handle (%u).\n",
364 slave->
ports[i].
desc = (octet >> (2 * i)) & 0x03;
404 EC_SLAVE_ERR(slave,
"Failed to receive system time datagram: ");
411 EC_SLAVE_DBG(slave, 1,
"Slave has the System Time register.\n");
413 EC_SLAVE_DBG(slave, 1,
"Slave has no System Time register; delay " 414 "measurement only.\n");
418 EC_SLAVE_ERR(slave,
"Failed to determine, if system time register is " 452 EC_SLAVE_ERR(slave,
"Failed to receive system time datagram: ");
460 EC_SLAVE_ERR(slave,
"Failed to get DC receive times: ");
515 fsm->
state(fsm, datagram);
533 unsigned int found = 0;
542 EC_SLAVE_DBG(slave, 1,
"Slave can re-use SII image data stored." 551 EC_SLAVE_DBG(slave, 1,
"Slave can re-use SII image data stored." 552 " Identified by vendor id 0x%08x," 553 " product code 0x%08x, revision 0x%08x and serial 0x%08x.\n",
564 EC_SLAVE_DBG(slave, 1,
"Slave cannot be uniquely identified." 565 " SII image data cannot be re-used!\n");
580 ec_fsm_slave_scan_enter_regalias(fsm, datagram);
599 " for slave SII image.\n");
624 #ifdef EC_SII_OVERRIDE 627 (uint16_t *) kmalloc(32, GFP_KERNEL))) {
628 EC_SLAVE_ERR(slave,
"Failed to allocate 16 words of SII data.\n");
637 fsm->
state = ec_fsm_slave_scan_state_sii_device;
647 fsm->
state(fsm, datagram);
663 EC_SLAVE_DBG(slave, 1,
"Assigning SII access to EtherCAT.\n");
694 EC_SLAVE_ERR(slave,
"Failed to receive DL status datagram: ");
711 #elif defined(EC_SII_CACHE) 739 EC_SLAVE_WARN(slave,
"Failed to receive SII assignment datagram: ");
742 goto continue_with_sii_size;
751 continue_with_sii_size:
780 EC_SLAVE_ERR(slave,
"Failed to determine SII identity\n");
832 EC_SLAVE_ERR(slave,
"Unexpected offset %u in identity scan.\n",
843 #ifdef EC_SII_OVERRIDE 850 void ec_fsm_slave_scan_state_sii_device(
861 EC_SLAVE_ERR(slave,
"Failed to determine product and vendor id." 862 " Reading word offset 0x%04x failed.\n",
894 EC_SLAVE_ERR(slave,
"Failed to determine product and vendor id." 895 " SII returned a zero value.\n");
913 ec_fsm_slave_scan_enter_sii_request(fsm, datagram);
918 struct firmware_request_context
920 struct task_struct *fsm_task;
925 static const struct firmware no_sii_firmware;
927 static void firmware_request_complete(
928 const struct firmware *firmware,
932 struct firmware_request_context *ctx = context;
935 if (fsm->
slave != ctx->slave) {
936 printk(KERN_ERR
"Aborting firmware request; FSM slave changed unexpectedly.\n");
937 ec_release_sii_firmware(firmware);
938 }
else if (fsm->
state != ec_fsm_slave_scan_state_sii_request) {
939 EC_SLAVE_WARN(fsm->
slave,
"Aborting firmware request; FSM state changed unexpectedly.\n");
940 ec_release_sii_firmware(firmware);
942 fsm->sii_firmware = firmware ? firmware : &no_sii_firmware;
954 void ec_fsm_slave_scan_enter_sii_request(
960 struct firmware_request_context *ctx;
962 if (!(ctx = kmalloc(
sizeof(*ctx), GFP_KERNEL))) {
963 EC_SLAVE_ERR(slave,
"Unable to allocate firmware request context.\n");
968 ctx->fsm_task = current;
972 fsm->sii_firmware = NULL;
973 fsm->
state = ec_fsm_slave_scan_state_sii_request;
974 ec_request_sii_firmware(slave, ctx, firmware_request_complete);
975 fsm->
state(fsm, datagram);
984 void ec_fsm_slave_scan_state_sii_request(
990 const struct firmware *firmware = fsm->sii_firmware;
992 if (firmware == &no_sii_firmware) {
993 EC_SLAVE_DBG(slave, 1,
"SII firmware file not found; reading SII data from slave.\n");
994 fsm->sii_firmware = NULL;
1000 fsm->
state(fsm, datagram);
1001 }
else if (firmware) {
1002 EC_SLAVE_DBG(slave, 1,
"Firmware file found, reading %zu bytes.\n", firmware->size);
1012 EC_SLAVE_ERR(slave,
"Failed to allocate %zu words of SII data.\n",
1016 ec_release_sii_firmware(firmware);
1017 fsm->sii_firmware = NULL;
1024 ec_release_sii_firmware(firmware);
1025 fsm->sii_firmware = NULL;
1028 fsm->
state(fsm, datagram);
1048 uint16_t cat_type, cat_size;
1054 EC_SLAVE_ERR(slave,
"Slave has no SII image attached!\n");
1062 EC_SLAVE_ERR(slave,
"Failed to determine SII content size" 1069 EC_SLAVE_ERR(slave,
"Failed to determine SII content size:" 1070 " Reading word offset 0x%04x failed. Assuming %u words.\n",
1080 if (cat_type != 0xFFFF) {
1081 off_t next_offset = 2UL + fsm->
sii_offset + cat_size;
1106 EC_SLAVE_ERR(slave,
"Failed to allocate %zu words of SII data.\n",
1114 #ifdef EC_SII_OVERRIDE 1148 EC_SLAVE_ERR(slave,
"Failed to fetch SII contents.\n");
1159 EC_SLAVE_ERR(slave,
"Slave has no SII image attached!\n");
1183 fsm->
state(fsm, datagram);
1198 uint16_t *cat_word, cat_type, cat_size;
1204 #ifndef EC_SII_OVERRIDE 1236 #if !defined(EC_SII_OVERRIDE) && defined(EC_SII_CACHE) 1257 EC_SLAVE_ERR(slave,
"Unexpected mailbox offset in SII data.\n");
1268 " First category header missing.\n");
1279 " Category header incomplete.\n");
1289 " Category data incomplete.\n");
1322 EC_SLAVE_DBG(slave, 1,
"Unknown category type 0x%04X.\n",
1326 cat_word += cat_size;
1329 " Next category header missing.\n");
1335 ec_fsm_slave_scan_enter_regalias(fsm, datagram);
1346 EC_SLAVE_ERR(slave,
"Failed to analyze category data.\n");
1357 void ec_fsm_slave_scan_enter_regalias(
1365 EC_SLAVE_DBG(slave, 1,
"Reading alias from register.\n");
1369 fsm->
state = ec_fsm_slave_scan_state_regalias;
1376 void ec_fsm_slave_scan_state_regalias(
1390 EC_SLAVE_ERR(slave,
"Failed to receive register alias datagram: ");
1396 EC_SLAVE_DBG(slave, 1,
"Failed to read register alias.\n");
1399 EC_SLAVE_DBG(slave, 1,
"Read alias %u from register.\n",
1404 EC_SLAVE_ERR(slave,
"Slave has no SII image attached!\n");
1417 #endif // defined EC_REGALIAS 1438 " to do mailbox com (%s), setting to PREOP.\n", str);
1447 " sync manager configuration.\n");
1498 " configuration datagram: ");
1525 EC_SLAVE_ERR(slave,
"Slave has no SII image attached!\n");
1571 unsigned int fetch_pdos = 1;
1582 EC_SLAVE_INFO(slave,
"Cleared old data from the mailbox\n");
1587 EC_SLAVE_ERR(slave,
"Slave has no SII image attached!\n");
1624 EC_SLAVE_DBG(slave, 1,
"Scanning PDO assignment and mapping.\n");
1679 unsigned long diff_ms =
#define EC_FSM_RETRIES
Number of state machine retries on datagram timeout.
#define EC_ALIAS_SII_OFFSET
Word offset of SII alias.
ec_slave_t * slave
Slave the FSM runs on.
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 ...
uint16_t ring_position
Ring position.
uint32_t revision_number
Revision number.
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.
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII DATA.
void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SYNC.
#define EC_SLAVE_STATE_MASK
Slave state mask.
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_scan_state_datalink(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DATALINK.
ec_datagram_t * datagram
Datagram used in the state machine.
struct list_head list
List item.
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
uint16_t base_build
Build number.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state PDOS.
OP (mailbox communication and input/output update)
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
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.
ec_slave_state_t current_state
Current application state.
Complete slave information interface data image.
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
ec_slave_port_link_t link
Port link status.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
struct list_head list
List of PDOs.
uint32_t serial_number
Serial number.
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
void ec_fsm_slave_scan_enter_clear_mailbox(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state: Clear Mailbox.
uint16_t working_counter
Working counter.
int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: START.
Acknowledge/Error bit (no actual state)
int ec_fsm_sii_exec(ec_fsm_sii_t *fsm, ec_datagram_t *datagram)
Executes the SII state machine.
uint16_t boot_tx_mailbox_size
Bootstrap transmit mailbox size.
int ec_slave_fetch_sii_strings(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a STRING category.
void ec_slave_set_dl_status(ec_slave_t *slave, uint16_t new_state)
Sets the data-link state of a slave.
void ec_fsm_slave_scan_enter_attach_sii(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state ATTACH_SII.
EtherCAT slave scanning state machine.
uint16_t station_address
Configured station address.
#define EC_MAX_SII_SIZE
Maximum SII size in words, to avoid infinite reading.
#define EC_VENDOR_SII_OFFSET
Word offset of SII vendor ID.
unsigned int sync_count
Number of sync managers.
uint16_t std_rx_mailbox_size
Standard receive mailbox size.
#define EC_MAX_FMMUS
Maximum number of FMMUs per slave.
uint8_t base_type
Slave type.
Global definitions and macros.
uint16_t std_tx_mailbox_offset
Standard transmit mailbox address.
void(* state)(ec_fsm_slave_scan_t *, ec_datagram_t *)
State function.
EtherCAT master structure.
SAFEOP (mailbox communication and input update)
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
uint16_t boot_tx_mailbox_offset
Bootstrap transmit mailbox address.
ec_fsm_slave_config_t * fsm_slave_config
Slave configuration state machine to use.
#define EC_SERIAL_SII_OFFSET
Word offset of SII serial number.
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.
void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan entry function: DATALINK.
ec_sii_image_t * sii_image
Current complete SII image.
ec_datagram_state_t state
State.
void ec_fsm_slave_scan_state_sii_parse(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII PARSE.
ec_fsm_pdo_t * fsm_pdo
PDO configuration state machine to use.
void ec_slave_sii_image_init(ec_sii_image_t *sii_image)
void ec_slave_clear_sync_managers(ec_slave_t *slave)
Clear the sync manager array.
Use configured addresses.
uint16_t mailbox_protocols
Supported mailbox protocols.
void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *, ec_datagram_t *)
State: END.
void ec_fsm_slave_scan_state_sii_identity(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII IDENTITY.
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *fsm, ec_slave_t *slave)
Start reading the PDO configuration.
ec_fsm_sii_t fsm_sii
SII state machine.
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.
uint16_t std_rx_mailbox_offset
Standard receive mailbox address.
uint8_t base_fmmu_bit_operation
FMMU bit operation is supported.
void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: ADDRESS.
int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *fsm)
uint16_t alias
Configured station alias.
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DC CAPABILITIES.
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *, ec_datagram_t *)
State: ERROR.
uint8_t base_fmmu_count
Number of supported FMMUs.
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
void ec_fsm_slave_scan_state_mailbox_cleared(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: Mailbox cleared.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
uint32_t effective_product_code
Effective product code.
ec_slave_t * slave
Slave, the sync manager belongs to.
ec_slave_port_desc_t desc
Port descriptors.
Finite state machine for scanning an EtherCAT slave.
#define SCAN_RETRY_TIME
Time to wait before slave scan retry [ms].
ec_master_t * master
Master owning the slave.
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: PDOS.
void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: ASSIGN_SII.
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_scan_enter_assign_sii(ec_fsm_slave_scan_t *fsm, ec_datagram_t *datagram)
Enter slave scan state ASSIGN_SII.
void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: DC TIMES.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
unsigned int retries
Retries on datagram timeout.
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.
Values read by the master.
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: PREOP.
PDO configuration state machine.
#define EC_FIRST_SII_CATEGORY_OFFSET
Word offset of first SII category.
uint8_t base_revision
Revision.
void ec_fsm_sii_read(ec_fsm_sii_t *fsm, ec_slave_t *slave, uint16_t word_offset, ec_fsm_sii_addressing_t mode)
Initializes the SII read state machine.
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
void ec_fsm_slave_scan_enter_sii_identity(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state SII_IDENTITY.
uint32_t effective_vendor_id
Effective vendor ID.
unsigned long scan_jiffies_start
scan retry start timestamp.
uint16_t * vendor_words
First 16 words of SII image.
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state PREOP.
uint8_t valid_mbox_data
Received mailbox data is valid.
void ec_fsm_sii_clear(ec_fsm_sii_t *fsm)
Destructor.
int ec_fsm_pdo_success(const ec_fsm_pdo_t *fsm)
Get execution result.
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: BASE.
uint16_t effective_alias
Effective alias address.
#define EC_PRODUCT_SII_OFFSET
Word offset of SII product number.
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.
Finite state machine to configure an EtherCAT slave.
void ec_datagram_print_state(const ec_datagram_t *datagram)
Prints the state of a datagram.
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *fsm)
Start slave scan state machine.
int ec_slave_fetch_sii_syncs(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a SYNC MANAGER category.
#define EC_STATE_STRING_SIZE
Minimum size of a buffer used with ec_state_string().
uint16_t boot_rx_mailbox_size
Bootstrap receive mailbox size.
#define EC_MAX_PORTS
Maximum number of slave ports.
uint32_t effective_serial_number
Effective serial number.
void ec_fsm_slave_scan_state_retry_wait(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: scan retry wait.
uint8_t bypassed
Packets are bypassing this port (eg.
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_scan_state_state(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: STATE.
void ec_fsm_sii_init(ec_fsm_sii_t *fsm)
Constructor.
uint32_t receive_time
Port receive times for delay measurement.
void ec_fsm_slave_scan_enter_sii_size(ec_fsm_slave_scan_t *, ec_datagram_t *)
Enter slave scan state SII_SIZE.
uint16_t sii_offset
SII offset in words.
ec_pdo_list_t pdos
Current PDO assignment.
void ec_slave_request_state(ec_slave_t *slave, ec_slave_state_t state)
Request a slave state and resets the error flag.
void ec_fsm_slave_scan_state_retry(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: scan retry.
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_scan_state_sii_size(ec_fsm_slave_scan_t *, ec_datagram_t *)
Slave scan state: SII SIZE.
#define EC_REVISION_SII_OFFSET
Word offset of SII revision number.
uint8_t base_sync_count
Number of supported sync managers.
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
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.
ec_sii_t sii
Extracted SII data.
Unused and should not be queued (dequeued).
unsigned int scan_retries
Retries on scan read error.
uint32_t product_code
Vendor-specific product code.
PREOP state (mailbox communication, no IO)
Values written by the master.
size_t nwords
Size of the SII contents in words.
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.
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, ec_slave_t *slave, ec_fsm_slave_config_t *fsm_slave_config, ec_fsm_pdo_t *fsm_pdo)
Constructor.
uint32_t effective_revision_number
Effective revision number.
int ec_slave_fetch_sii_pdos(ec_slave_t *slave, const uint8_t *data, size_t data_size, ec_direction_t dir)
Fetches data from a [RT]xPDO category.
#define EC_MAX_SYNC_MANAGERS
Maximum number of sync managers per slave.
int ec_datagram_repeat(ec_datagram_t *datagram, const ec_datagram_t *source)
Copies a previously constructed datagram for repeated send.
int ec_slave_fetch_sii_general(ec_slave_t *slave, const uint8_t *data, size_t data_size)
Fetches data from a GENERAL category.
uint32_t vendor_id
Vendor ID.
struct list_head sii_images
List of slave SII images.
int ec_fsm_slave_scan_success(const ec_fsm_slave_scan_t *fsm)
uint8_t value[4]
raw SII value (32bit)