From 299a039c49873b6c4bc4bb0f0281c0d0415838b9 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 10:10:05 +0200 Subject: [PATCH 1/8] Defined interface. --- include/ecrt.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/ecrt.h b/include/ecrt.h index 4db3448d..3a6addcf 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -49,6 +49,9 @@ * ecrt_slave_config_eoe_dns_address(), * ecrt_slave_config_eoe_hostname() and the EC_HAVE_SET_IP * definition to check for its existence. + * - Added ecrt_slave_config_state_timeout() to set the application-layer + * state change timeout and EC_HAVE_STATE_TIMEOUT to check for its + * existence. * * Changes since version 1.5.2: * @@ -252,6 +255,10 @@ */ #define EC_HAVE_SET_IP +/** Defined, if the method ecrt_slave_config_state_timeout() is available. + */ +#define EC_HAVE_STATE_TIMEOUT + /****************************************************************************/ /** Symbol visibility control macro. @@ -2003,6 +2010,26 @@ EC_PUBLIC_API int ecrt_slave_config_eoe_hostname( const char *name /**< Zero-terminated host name. */ ); +/** Sets the application-layer state transition timeout in ms. + * + * Change the maximum allowed time for a slave to make an application-layer + * state transition for the given state transition (for example from PREOP to + * SAFEOP). The default timeout is 10 s. Some transitions of specific slaves + * may take longer. + * + * This method has to be called in non-realtime context before + * ecrt_master_activate(). + * + * \retval 0 Success. + * \retval <0 Error code. + */ +EC_PUBLIC_API int ecrt_slave_config_state_timeout( + ec_slave_config_t *sc, /**< Slave configuration. */ + ec_al_state_t from_state, /**< Initial state. */ + ec_al_state_t to_state, /**< Target state. */ + unsigned int timeout_ms /**< Timeout in [ms]. */ + ); + /***************************************************************************** * Domain methods ****************************************************************************/ From 4fe6b87f89c27c846b399c20e7b8b3603e521519 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 11:00:25 +0200 Subject: [PATCH 2/8] Added missing prototypes. --- devices/generic.c | 8 ++++++++ examples/mini/mini.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/devices/generic.c b/devices/generic.c index 53307bda..f078057b 100644 --- a/devices/generic.c +++ b/devices/generic.c @@ -56,6 +56,7 @@ int __init ec_gen_init_module(void); void __exit ec_gen_cleanup_module(void); +void ec_gen_poll(struct net_device *); /****************************************************************************/ @@ -87,11 +88,18 @@ typedef struct { uint8_t dev_addr[ETH_ALEN]; } ec_gen_interface_desc_t; +int ec_gen_device_init(ec_gen_device_t *); +void ec_gen_device_clear(ec_gen_device_t *); +int ec_gen_device_create_socket(ec_gen_device_t *, ec_gen_interface_desc_t *); +int ec_gen_device_offer(ec_gen_device_t *, ec_gen_interface_desc_t *); int ec_gen_device_open(ec_gen_device_t *); int ec_gen_device_stop(ec_gen_device_t *); int ec_gen_device_start_xmit(ec_gen_device_t *, struct sk_buff *); void ec_gen_device_poll(ec_gen_device_t *); +int offer_device(ec_gen_interface_desc_t *); +void clear_devices(void); + /****************************************************************************/ static int ec_gen_netdev_open(struct net_device *dev) diff --git a/examples/mini/mini.c b/examples/mini/mini.c index 4c3af9c4..1ebadd87 100644 --- a/examples/mini/mini.c +++ b/examples/mini/mini.c @@ -182,6 +182,21 @@ static ec_voe_handler_t *voe; /****************************************************************************/ +void check_domain1_state(void); +void check_master_state(void); +void check_slave_config_states(void); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) +void cyclic_task(struct timer_list *); +#else +void cyclic_task(unsigned long); +#endif +void send_callback(void *); +void receive_callback(void *); +int init_mini_module(void); +void cleanup_mini_module(void); + +/****************************************************************************/ + void check_domain1_state(void) { ec_domain_state_t ds; From 6503e0a32a6e090afca2b9464548ea98490f5298 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 11:01:37 +0200 Subject: [PATCH 3/8] Added missing prototypes. --- master/domain.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/master/domain.c b/master/domain.c index 34eecb4b..d74fd715 100644 --- a/master/domain.c +++ b/master/domain.c @@ -41,7 +41,14 @@ /****************************************************************************/ +// prototypes for private methods void ec_domain_clear_data(ec_domain_t *); +int ec_domain_add_datagram_pair(ec_domain_t *, uint32_t, size_t, uint8_t *, + const unsigned int []); +int shall_count(const ec_fmmu_config_t *, const ec_fmmu_config_t *); +#if EC_MAX_NUM_DEVICES > 1 +int data_changed(uint8_t *, const ec_datagram_t *, size_t, size_t); +#endif /****************************************************************************/ From 737c3cf3d77454ad9d4322e55563d44e0e36229d Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 11:03:10 +0200 Subject: [PATCH 4/8] Removed unused methods. --- master/foe_request.c | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/master/foe_request.c b/master/foe_request.c index a7e7d55b..3b68f734 100644 --- a/master/foe_request.c +++ b/master/foe_request.c @@ -42,6 +42,7 @@ /****************************************************************************/ +// prototypes for private methods void ec_foe_request_clear_data(ec_foe_request_t *); /****************************************************************************/ @@ -165,44 +166,6 @@ int ec_foe_request_timed_out( /****************************************************************************/ -/** Set the request timeout. - */ -void ec_foe_request_timeout( - ec_foe_request_t *req, /**< FoE request. */ - uint32_t timeout /**< Timeout in ms. */ - ) -{ - req->issue_timeout = timeout; -} - -/****************************************************************************/ - -/** Returns a pointer to the request's data. - * - * \return Data pointer. - */ -uint8_t *ec_foe_request_data( - ec_foe_request_t *req /**< FoE request. */ - ) -{ - return req->buffer; -} - -/****************************************************************************/ - -/** Returns the data size. - * - * \return Data size. - */ -size_t ec_foe_request_data_size( - const ec_foe_request_t *req /**< FoE request. */ - ) -{ - return req->data_size; -} - -/****************************************************************************/ - /** Prepares a read request (slave to master). */ void ec_foe_request_read( From 36d036b0815ccaf3883a7e06c2ddcf0f3c916ec5 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 11:05:18 +0200 Subject: [PATCH 5/8] Added missing prototypes. --- master/module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/master/module.c b/master/module.c index 407b7d92..3e81f25e 100644 --- a/master/module.c +++ b/master/module.c @@ -44,6 +44,10 @@ void __exit ec_cleanup_module(void); static int ec_mac_parse(uint8_t *, const char *, int); +// prototypes for private functions +int ec_mac_equal(const uint8_t *, const uint8_t *); +int ec_mac_is_broadcast(const uint8_t *); + /****************************************************************************/ static char *main_devices[MAX_MASTERS]; /**< Main devices parameter. */ From b182bef61119960e2b0fd7cfca27522a13857097 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 11:54:36 +0200 Subject: [PATCH 6/8] AL state timeout lookup logic. --- include/ecrt.h | 5 +- master/fsm_change.c | 69 +++++++++++++++++++++------ master/slave_config.c | 106 ++++++++++++++++++++++++++++++++++++++++++ master/slave_config.h | 4 ++ 4 files changed, 169 insertions(+), 15 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index 3a6addcf..00e2eb8c 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -2014,8 +2014,9 @@ EC_PUBLIC_API int ecrt_slave_config_eoe_hostname( * * Change the maximum allowed time for a slave to make an application-layer * state transition for the given state transition (for example from PREOP to - * SAFEOP). The default timeout is 10 s. Some transitions of specific slaves - * may take longer. + * SAFEOP). The default values are defined in ETG.2000. + * + * A timeout value of zero ms will restore the default value. * * This method has to be called in non-realtime context before * ecrt_master_activate(). diff --git a/master/fsm_change.c b/master/fsm_change.c index 0dc10d6b..98fae184 100644 --- a/master/fsm_change.c +++ b/master/fsm_change.c @@ -29,17 +29,11 @@ #include "globals.h" #include "master.h" #include "fsm_change.h" +#include "slave_config.h" /****************************************************************************/ -/** Timeout while waiting for AL state change [s]. - * - * ETG2000_S_R_V1i0i15 section 5.3.7.2 mentions 10 s as maximum AL state - * change timeout. - */ -#define EC_AL_STATE_CHANGE_TIMEOUT 10 - -/****************************************************************************/ +unsigned int ec_fsm_change_timeout_ms(const ec_fsm_change_t *); void ec_fsm_change_state_start(ec_fsm_change_t *); void ec_fsm_change_state_check(ec_fsm_change_t *); @@ -78,6 +72,50 @@ void ec_fsm_change_clear(ec_fsm_change_t *fsm /**< finite state machine */) /****************************************************************************/ +/** Get timeout in ms. + * + * For defaults see ETG2000_S_R_V1i0i15 section 5.3.6.2. + */ +unsigned int ec_fsm_change_timeout_ms( + const ec_fsm_change_t *fsm /**< finite state machine */ + ) +{ + ec_slave_state_t from = fsm->old_state; + ec_slave_state_t to = fsm->requested_state; + + /* Search for specified timeout in slave configuration */ + if (fsm->slave->config) { + unsigned int timeout_ms = + ec_slave_config_al_timeout(fsm->slave->config, from, to); + if (timeout_ms) { + return timeout_ms; + } + } + + /* No specific timeout found. Use defaults from spec. */ + + if (from == EC_SLAVE_STATE_INIT && + (to == EC_SLAVE_STATE_PREOP || to == EC_SLAVE_STATE_BOOT)) { + return 3000; // PreopTimeout + } + if ((from == EC_SLAVE_STATE_PREOP && to == EC_SLAVE_STATE_SAFEOP) || + (from == EC_SLAVE_STATE_SAFEOP && to == EC_SLAVE_STATE_OP)) { + return 10000; // SafeopOpTimeout + } + if (to == EC_SLAVE_STATE_INIT || + ((from == EC_SLAVE_STATE_OP || from == EC_SLAVE_STATE_SAFEOP) + && to == EC_SLAVE_STATE_PREOP)) { + return 5000; // BackToInitTimeout + } + if (from == EC_SLAVE_STATE_OP && to == EC_SLAVE_STATE_SAFEOP) { + return 200; // BackToSafeopTimeout + } + + return 10000; // default [ms] +} + +/****************************************************************************/ + /** Starts the change state machine. */ @@ -234,6 +272,7 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm { ec_datagram_t *datagram = fsm->datagram; ec_slave_t *slave = fsm->slave; + unsigned int timeout_ms; if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) return; @@ -297,13 +336,15 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm // still old state + timeout_ms = ec_fsm_change_timeout_ms(fsm); if (datagram->jiffies_received - fsm->jiffies_start >= - EC_AL_STATE_CHANGE_TIMEOUT * HZ) { + timeout_ms * HZ / 1000) { // timeout while checking char state_str[EC_STATE_STRING_SIZE]; ec_state_string(fsm->requested_state, state_str, 0); fsm->state = ec_fsm_change_state_error; - EC_SLAVE_ERR(slave, "Timeout while setting state %s.\n", state_str); + EC_SLAVE_ERR(slave, "Timeout after %u ms while setting state %s.\n", + timeout_ms, state_str); return; } @@ -492,6 +533,7 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm { ec_datagram_t *datagram = fsm->datagram; ec_slave_t *slave = fsm->slave; + unsigned int timeout_ms; if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) return; @@ -530,14 +572,15 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm return; } + timeout_ms = ec_fsm_change_timeout_ms(fsm); if (datagram->jiffies_received - fsm->jiffies_start >= - EC_AL_STATE_CHANGE_TIMEOUT * HZ) { + timeout_ms * HZ / 1000) { // timeout while checking char state_str[EC_STATE_STRING_SIZE]; ec_state_string(slave->current_state, state_str, 0); fsm->state = ec_fsm_change_state_error; - EC_SLAVE_ERR(slave, "Timeout while acknowledging state %s.\n", - state_str); + EC_SLAVE_ERR(slave, "Timeout after %u ms while acknowledging" + " state %s.\n", timeout_ms, state_str); return; } diff --git a/master/slave_config.c b/master/slave_config.c index e331aa81..87e81a6c 100644 --- a/master/slave_config.c +++ b/master/slave_config.c @@ -45,6 +45,25 @@ /****************************************************************************/ +// prototypes for private methods +int ec_slave_config_prepare_fmmu(ec_slave_config_t *, ec_domain_t *, uint8_t, + ec_direction_t); +void ec_slave_config_load_default_mapping(const ec_slave_config_t *, + ec_pdo_t *); + +/****************************************************************************/ + +/** EtherCAT application-layer transition timeout. + */ +typedef struct { + struct list_head list; + ec_slave_state_t from; + ec_slave_state_t to; + unsigned int timeout_ms; +} ec_al_timeout_t; + +/****************************************************************************/ + /** Slave configuration constructor. * * See ecrt_master_slave_config() for the usage of the \a alias and \a @@ -89,6 +108,7 @@ void ec_slave_config_init( INIT_LIST_HEAD(&sc->voe_handlers); INIT_LIST_HEAD(&sc->soe_configs); INIT_LIST_HEAD(&sc->flags); + INIT_LIST_HEAD(&sc->al_timeouts); #ifdef EC_EOE ec_eoe_request_init(&sc->eoe_ip_param_request); @@ -113,6 +133,7 @@ void ec_slave_config_clear( ec_reg_request_t *reg, *next_reg; ec_soe_request_t *soe, *next_soe; ec_flag_t *flag, *next_flag; + ec_al_timeout_t *timeout, *next_timeout; ec_slave_config_detach(sc); @@ -169,6 +190,12 @@ void ec_slave_config_clear( kfree(flag); } + // free all AL timeouts + list_for_each_entry_safe(timeout, next_timeout, &sc->al_timeouts, list) { + list_del(&timeout->list); + kfree(timeout); + } + ec_coe_emerg_ring_clear(&sc->emerg_ring); } @@ -625,6 +652,26 @@ ec_flag_t *ec_slave_config_find_flag( return NULL; } +/****************************************************************************/ + +/** Return an AL state timeout. + * + * \return Search result, or 0. + */ +unsigned int ec_slave_config_al_timeout(const ec_slave_config_t *sc, + ec_slave_state_t from, ec_slave_state_t to) +{ + ec_al_timeout_t *timeout; + + list_for_each_entry(timeout, &sc->al_timeouts, list) { + if (timeout->from == from && timeout->to == to) { + return timeout->timeout_ms; + } + } + + return 0; +} + /***************************************************************************** * Application interface ****************************************************************************/ @@ -1504,6 +1551,64 @@ int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc, /****************************************************************************/ +int ecrt_slave_config_state_timeout(ec_slave_config_t *sc, + ec_al_state_t from, ec_al_state_t to, unsigned int timeout_ms) +{ + ec_al_timeout_t *timeout; + ec_slave_state_t from_state, to_state; + + if (from != EC_AL_STATE_INIT && from != EC_AL_STATE_PREOP && + from != EC_AL_STATE_SAFEOP && from != EC_AL_STATE_OP) { + EC_CONFIG_ERR(sc, "Invalid from state %i.\n", from); + return -EINVAL; + } + if (to != EC_AL_STATE_INIT && to != EC_AL_STATE_PREOP && + to != EC_AL_STATE_SAFEOP && to != EC_AL_STATE_OP) { + EC_CONFIG_ERR(sc, "Invalid to state %i.\n", to); + return -EINVAL; + } + + from_state = (ec_slave_state_t) from; + to_state = (ec_slave_state_t) to; + + /* try to find an already configured timeout. */ + list_for_each_entry(timeout, &sc->al_timeouts, list) { + if (timeout->from == from_state && timeout->to == to_state) { + if (timeout_ms == 0) { + // delete configured value + list_del(&timeout->list); + kfree(timeout); + return 0; + } + timeout->timeout_ms = timeout_ms; + return 0; + } + } + + if (timeout_ms == 0) { + return 0; + } + + /* no timeout found. create one. */ + if (!(timeout = (ec_al_timeout_t *) + kmalloc(sizeof(ec_al_timeout_t), GFP_KERNEL))) { + EC_CONFIG_ERR(sc, "Failed to allocate memory for" + " AL timeout configuration!\n"); + return -ENOMEM; + } + + timeout->from = from_state; + timeout->to = to_state; + timeout->timeout_ms = timeout_ms; + + down(&sc->master->master_sem); + list_add_tail(&timeout->list, &sc->al_timeouts); + up(&sc->master->master_sem); + return 0; +} + +/****************************************************************************/ + /** \cond */ EXPORT_SYMBOL(ecrt_slave_config_sync_manager); @@ -1540,6 +1645,7 @@ EXPORT_SYMBOL(ecrt_slave_config_eoe_default_gateway); EXPORT_SYMBOL(ecrt_slave_config_eoe_dns_address); EXPORT_SYMBOL(ecrt_slave_config_eoe_hostname); #endif +EXPORT_SYMBOL(ecrt_slave_config_state_timeout); /** \endcond */ diff --git a/master/slave_config.h b/master/slave_config.h index 688156fc..124995c2 100644 --- a/master/slave_config.h +++ b/master/slave_config.h @@ -140,6 +140,7 @@ struct ec_slave_config { struct list_head reg_requests; /**< List of register requests. */ struct list_head soe_configs; /**< List of SoE configurations. */ struct list_head flags; /**< List of feature flags. */ + struct list_head al_timeouts; /**< List of specific AL state timeouts. */ #ifdef EC_EOE ec_eoe_request_t eoe_ip_param_request; /**< EoE IP parameters. */ @@ -187,6 +188,9 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err( ec_reg_request_t *ecrt_slave_config_create_reg_request_err( ec_slave_config_t *, size_t); +unsigned int ec_slave_config_al_timeout(const ec_slave_config_t *, + ec_slave_state_t, ec_slave_state_t); + /****************************************************************************/ #endif From 95a25495afb725b3f95b52bd6f10b359f1928ad2 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 12:06:48 +0200 Subject: [PATCH 7/8] Added ecrt_slave_config_state_timeout() in user-space library. --- lib/libethercat.map | 1 + lib/slave_config.c | 24 +++++++++++++++ master/ioctl.c | 47 ++++++++++++++++++++++++++++++ master/ioctl.h | 71 ++++++++++++++++++++++++++------------------- 4 files changed, 113 insertions(+), 30 deletions(-) diff --git a/lib/libethercat.map b/lib/libethercat.map index 7a83f83b..759e6b58 100644 --- a/lib/libethercat.map +++ b/lib/libethercat.map @@ -110,4 +110,5 @@ LIBETHERCAT_1.6 { ecrt_slave_config_eoe_default_gateway; ecrt_slave_config_eoe_dns_address; ecrt_slave_config_eoe_hostname; + ecrt_slave_config_state_timeout; } LIBETHERCAT_1.5.3; diff --git a/lib/slave_config.c b/lib/slave_config.c index 7c3b8867..7bef3a99 100644 --- a/lib/slave_config.c +++ b/lib/slave_config.c @@ -1038,3 +1038,27 @@ int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc, #endif // EC_EOE /****************************************************************************/ + +int ecrt_slave_config_state_timeout(ec_slave_config_t *sc, + ec_al_state_t from_state, ec_al_state_t to_state, + unsigned int timeout_ms) +{ + ec_ioctl_sc_state_timeout_t io = {}; + int ret; + + io.config_index = sc->index; + io.from_state = from_state; + io.to_state = to_state; + io.timeout_ms = timeout_ms; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_STATE_TIMEOUT, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to configure AL state timeout: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return 0; +} + +/****************************************************************************/ diff --git a/master/ioctl.c b/master/ioctl.c index a3a7bcf1..ceceb83d 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -3332,6 +3332,46 @@ static ATTRIBUTES int ec_ioctl_sc_flag( /****************************************************************************/ +/** Sets an AL state transition timeout. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_sc_state_timeout( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_state_timeout_t ioctl; + ec_slave_config_t *sc; + int ret; + + if (unlikely(!ctx->requested)) { + return -EPERM; + } + + if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) { + return -EFAULT; + } + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, ioctl.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); /** \todo sc could be invalidated */ + + ret = ecrt_slave_config_state_timeout(sc, ioctl.from_state, + ioctl.to_state, ioctl.timeout_ms); + return ret; +} + +/****************************************************************************/ + #ifdef EC_EOE /** Configures EoE IP parameters. @@ -5493,6 +5533,13 @@ static long ec_ioctl_nrt } ret = ec_ioctl_sc_flag(master, arg, ctx); break; + case EC_IOCTL_SC_STATE_TIMEOUT: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_state_timeout(master, arg, ctx); + break; #ifdef EC_EOE case EC_IOCTL_SC_EOE_IP_PARAM: if (!ctx->writable) { diff --git a/master/ioctl.h b/master/ioctl.h index 2cb90103..0c51e638 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -47,7 +47,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 36 +#define EC_IOCTL_VERSION_MAGIC 37 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -131,35 +131,36 @@ #ifdef EC_EOE #define EC_IOCTL_SC_EOE_IP_PARAM EC_IOW(0x48, ec_ioctl_eoe_ip_t) #endif -#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x49) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x4a) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x4b) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x4c) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4d, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4e, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x50, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x51, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x52, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x53, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x54, ec_ioctl_soe_request_t) -#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x55, ec_ioctl_soe_request_t) -#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x56, ec_ioctl_soe_request_t) -#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x57, ec_ioctl_soe_request_t) -#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x58, ec_ioctl_soe_request_t) -#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x59, ec_ioctl_soe_request_t) -#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x5a, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x5b, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x5c, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5d, ec_ioctl_reg_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5e, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x5f, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x60, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x61, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x62, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x63, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x64, ec_ioctl_voe_t) -#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x65, size_t) +#define EC_IOCTL_SC_STATE_TIMEOUT EC_IOW(0x49, ec_ioctl_sc_state_timeout_t) +#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x4a) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x4b) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x4c) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x4d) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4e, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x50, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x51, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x52, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x53, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x54, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x55, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x56, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x57, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x58, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x59, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x5a, ec_ioctl_soe_request_t) +#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x5b, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x5c, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x5d, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5e, ec_ioctl_reg_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5f, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x60, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x61, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x62, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x63, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x64, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x65, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x66, size_t) /****************************************************************************/ @@ -749,6 +750,16 @@ typedef struct { /****************************************************************************/ +typedef struct { + // inputs + uint32_t config_index; + ec_al_state_t from_state; + ec_al_state_t to_state; + uint32_t timeout_ms; +} ec_ioctl_sc_state_timeout_t; + +/****************************************************************************/ + typedef struct { // inputs uint32_t domain_index; From 7b40d5fc4008d25558002acb30663ddaf25cb97e Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 12:36:16 +0200 Subject: [PATCH 8/8] Added missing prototypes. --- master/ethernet.c | 4 ++++ master/fsm_coe.c | 15 ++++++++++++++- master/fsm_eoe.c | 37 +++++++++++++++++++++---------------- master/fsm_master.c | 12 ++++++++++++ master/fsm_pdo.c | 10 +++++++++- master/fsm_pdo_entry.c | 10 +++++++++- master/fsm_slave_config.c | 5 +++++ master/fsm_slave_scan.c | 24 ++++++++++++++++-------- master/fsm_soe.c | 8 ++++++++ master/master.c | 10 ++++++++++ master/slave.c | 16 +++++++++++----- 11 files changed, 119 insertions(+), 32 deletions(-) diff --git a/master/ethernet.c b/master/ethernet.c index bd755eb5..b11ed09a 100644 --- a/master/ethernet.c +++ b/master/ethernet.c @@ -70,7 +70,11 @@ /****************************************************************************/ +// prototypes for private methods void ec_eoe_flush(ec_eoe_t *); +int ec_eoe_send(ec_eoe_t *); + +/****************************************************************************/ // state functions void ec_eoe_state_rx_start(ec_eoe_t *); diff --git a/master/fsm_coe.c b/master/fsm_coe.c index 9b015de1..69765cd0 100644 --- a/master/fsm_coe.c +++ b/master/fsm_coe.c @@ -59,6 +59,19 @@ /****************************************************************************/ +// prototypes for private methods +void ec_canopen_abort_msg(const ec_slave_t *, uint32_t); +int ec_fsm_coe_check_emergency(const ec_fsm_coe_t *, const uint8_t *, size_t); +int ec_fsm_coe_prepare_dict(ec_fsm_coe_t *, ec_datagram_t *); +int ec_fsm_coe_dict_prepare_desc(ec_fsm_coe_t *, ec_datagram_t *); +int ec_fsm_coe_dict_prepare_entry(ec_fsm_coe_t *, ec_datagram_t *); +int ec_fsm_coe_prepare_down_start(ec_fsm_coe_t *, ec_datagram_t *); +void ec_fsm_coe_down_prepare_segment_request(ec_fsm_coe_t *, ec_datagram_t *); +int ec_fsm_coe_prepare_up(ec_fsm_coe_t *, ec_datagram_t *); +void ec_fsm_coe_up_prepare_segment_request(ec_fsm_coe_t *, ec_datagram_t *); + +/****************************************************************************/ + void ec_fsm_coe_dict_start(ec_fsm_coe_t *, ec_datagram_t *); void ec_fsm_coe_dict_request(ec_fsm_coe_t *, ec_datagram_t *); void ec_fsm_coe_dict_check(ec_fsm_coe_t *, ec_datagram_t *); @@ -267,7 +280,7 @@ int ec_fsm_coe_success( * \return The data were an emergency request. */ int ec_fsm_coe_check_emergency( - ec_fsm_coe_t *fsm, /**< Finite state machine */ + const ec_fsm_coe_t *fsm, /**< Finite state machine */ const uint8_t *data, /**< CoE mailbox data. */ size_t size /**< CoE mailbox data size. */ ) diff --git a/master/fsm_eoe.c b/master/fsm_eoe.c index c061728d..b3ef6898 100644 --- a/master/fsm_eoe.c +++ b/master/fsm_eoe.c @@ -33,6 +33,27 @@ /****************************************************************************/ +/** Maximum time to wait for a set IP parameter response. + */ +#define EC_EOE_RESPONSE_TIMEOUT 3000 // [ms] + +/****************************************************************************/ + +// prototypes for private functions +void memcpy_swap32(void *, const void *); + +int ec_fsm_eoe_prepare_set(ec_fsm_eoe_t *, ec_datagram_t *); + +void ec_fsm_eoe_set_ip_start(ec_fsm_eoe_t *, ec_datagram_t *); +void ec_fsm_eoe_set_ip_request(ec_fsm_eoe_t *, ec_datagram_t *); +void ec_fsm_eoe_set_ip_check(ec_fsm_eoe_t *, ec_datagram_t *); +void ec_fsm_eoe_set_ip_response(ec_fsm_eoe_t *, ec_datagram_t *); + +void ec_fsm_eoe_end(ec_fsm_eoe_t *, ec_datagram_t *); +void ec_fsm_eoe_error(ec_fsm_eoe_t *, ec_datagram_t *); + +/****************************************************************************/ + /** Host-architecture-independent 32-bit swap function. * * The internal storage of struct in_addr is always big-endian. @@ -51,22 +72,6 @@ void memcpy_swap32(void *dst, const void *src) /****************************************************************************/ -/** Maximum time to wait for a set IP parameter response. - */ -#define EC_EOE_RESPONSE_TIMEOUT 3000 // [ms] - -/****************************************************************************/ - -void ec_fsm_eoe_set_ip_start(ec_fsm_eoe_t *, ec_datagram_t *); -void ec_fsm_eoe_set_ip_request(ec_fsm_eoe_t *, ec_datagram_t *); -void ec_fsm_eoe_set_ip_check(ec_fsm_eoe_t *, ec_datagram_t *); -void ec_fsm_eoe_set_ip_response(ec_fsm_eoe_t *, ec_datagram_t *); - -void ec_fsm_eoe_end(ec_fsm_eoe_t *, ec_datagram_t *); -void ec_fsm_eoe_error(ec_fsm_eoe_t *, ec_datagram_t *); - -/****************************************************************************/ - /** Constructor. */ void ec_fsm_eoe_init( diff --git a/master/fsm_master.c b/master/fsm_master.c index 3cbe802a..2290608b 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -44,6 +44,18 @@ /****************************************************************************/ +// prototypes for private methods +void ec_fsm_master_restart(ec_fsm_master_t *); +int ec_fsm_master_action_process_sii(ec_fsm_master_t *); +int ec_fsm_master_action_process_int_request(ec_fsm_master_t *); +void ec_fsm_master_action_idle(ec_fsm_master_t *); +void ec_fsm_master_action_next_slave_state(ec_fsm_master_t *); +void ec_fsm_master_action_configure(ec_fsm_master_t *); +u64 ec_fsm_master_dc_offset32(ec_fsm_master_t *, u64, u64, unsigned long); +u64 ec_fsm_master_dc_offset64(ec_fsm_master_t *, u64, u64, unsigned long); + +/****************************************************************************/ + void ec_fsm_master_state_start(ec_fsm_master_t *); void ec_fsm_master_state_broadcast(ec_fsm_master_t *); void ec_fsm_master_state_read_state(ec_fsm_master_t *); diff --git a/master/fsm_pdo.c b/master/fsm_pdo.c index a5a4b7ad..0d5f87e1 100644 --- a/master/fsm_pdo.c +++ b/master/fsm_pdo.c @@ -34,6 +34,14 @@ /****************************************************************************/ +// prototypes for private methods +void ec_fsm_pdo_print(const ec_fsm_pdo_t *); +int ec_fsm_pdo_running(const ec_fsm_pdo_t *); +ec_pdo_t *ec_fsm_pdo_conf_action_next_pdo(const ec_fsm_pdo_t *, + const struct list_head *); + +/****************************************************************************/ + void ec_fsm_pdo_read_state_start(ec_fsm_pdo_t *, ec_datagram_t *); void ec_fsm_pdo_read_state_pdo_count(ec_fsm_pdo_t *, ec_datagram_t *); void ec_fsm_pdo_read_state_pdo(ec_fsm_pdo_t *, ec_datagram_t *); @@ -94,7 +102,7 @@ void ec_fsm_pdo_clear( /** Print the current and desired PDO assignment. */ void ec_fsm_pdo_print( - ec_fsm_pdo_t *fsm /**< PDO configuration state machine. */ + const ec_fsm_pdo_t *fsm /**< PDO configuration state machine. */ ) { printk(KERN_CONT "Currently assigned PDOs: "); diff --git a/master/fsm_pdo_entry.c b/master/fsm_pdo_entry.c index 3de74ce4..3c7be428 100644 --- a/master/fsm_pdo_entry.c +++ b/master/fsm_pdo_entry.c @@ -34,6 +34,14 @@ /****************************************************************************/ +// prototypes for private methods +void ec_fsm_pdo_entry_print(const ec_fsm_pdo_entry_t *); +int ec_fsm_pdo_entry_running(const ec_fsm_pdo_entry_t *); +ec_pdo_entry_t *ec_fsm_pdo_entry_conf_next_entry(const ec_fsm_pdo_entry_t *, + const struct list_head *); + +/****************************************************************************/ + void ec_fsm_pdo_entry_read_state_start(ec_fsm_pdo_entry_t *, ec_datagram_t *); void ec_fsm_pdo_entry_read_state_count(ec_fsm_pdo_entry_t *, ec_datagram_t *); void ec_fsm_pdo_entry_read_state_entry(ec_fsm_pdo_entry_t *, ec_datagram_t *); @@ -82,7 +90,7 @@ void ec_fsm_pdo_entry_clear( /** Print the current and desired PDO mapping. */ void ec_fsm_pdo_entry_print( - ec_fsm_pdo_entry_t *fsm /**< PDO mapping state machine. */ + const ec_fsm_pdo_entry_t *fsm /**< PDO mapping state machine. */ ) { printk(KERN_CONT "Currently mapped PDO entries: "); diff --git a/master/fsm_slave_config.c b/master/fsm_slave_config.c index f0f0d250..25887ad6 100644 --- a/master/fsm_slave_config.c +++ b/master/fsm_slave_config.c @@ -52,6 +52,11 @@ /****************************************************************************/ +// prototypes for private methods +int ec_fsm_slave_config_running(const ec_fsm_slave_config_t *); + +/****************************************************************************/ + void ec_fsm_slave_config_state_start(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *); diff --git a/master/fsm_slave_scan.c b/master/fsm_slave_scan.c index a4bc3db1..e4b56358 100644 --- a/master/fsm_slave_scan.c +++ b/master/fsm_slave_scan.c @@ -35,6 +35,19 @@ /****************************************************************************/ +// prototypes for private methods +int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *); +void ec_fsm_slave_scan_enter_sii_size(ec_fsm_slave_scan_t *); +void ec_fsm_slave_scan_enter_assign_sii(ec_fsm_slave_scan_t *); +void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *); +#ifdef EC_REGALIAS +void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *); +#endif +void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *); +void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *); + +/****************************************************************************/ + void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *); @@ -57,13 +70,6 @@ void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *); -void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *); -#ifdef EC_REGALIAS -void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *); -#endif -void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *); -void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *); - /****************************************************************************/ /** Constructor. @@ -115,7 +121,9 @@ void ec_fsm_slave_scan_start( \return false, if state machine has terminated */ -int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *fsm /**< slave state machine */) +int ec_fsm_slave_scan_running( + const ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) { return fsm->state != ec_fsm_slave_scan_state_end && fsm->state != ec_fsm_slave_scan_state_error; diff --git a/master/fsm_soe.c b/master/fsm_soe.c index 161e3e3d..b24f03a9 100644 --- a/master/fsm_soe.c +++ b/master/fsm_soe.c @@ -56,6 +56,14 @@ enum { /****************************************************************************/ +// prototypes for private methods +void ec_print_soe_error(const ec_slave_t *, uint16_t); +void ec_fsm_soe_print_error(ec_fsm_soe_t *); +int ec_fsm_soe_prepare_read(ec_fsm_soe_t *, ec_datagram_t *); +void ec_fsm_soe_write_next_fragment(ec_fsm_soe_t *, ec_datagram_t *); + +/****************************************************************************/ + void ec_fsm_soe_read_start(ec_fsm_soe_t *, ec_datagram_t *); void ec_fsm_soe_read_request(ec_fsm_soe_t *, ec_datagram_t *); void ec_fsm_soe_read_check(ec_fsm_soe_t *, ec_datagram_t *); diff --git a/master/master.c b/master/master.c index 0a5f316a..c66bd12a 100644 --- a/master/master.c +++ b/master/master.c @@ -97,8 +97,18 @@ const unsigned int rate_intervals[] = { /****************************************************************************/ +void ec_master_clear_config(ec_master_t *); void ec_master_clear_slave_configs(ec_master_t *); void ec_master_clear_domains(ec_master_t *); +int ec_master_thread_start(ec_master_t *, int (*)(void *), const char *); +void ec_master_thread_stop(ec_master_t *); +void ec_master_inject_external_datagrams(ec_master_t *); +ec_datagram_t *ec_master_get_external_datagram(ec_master_t *); +void ec_master_exec_slave_fsms(ec_master_t *); +void ec_master_send_datagrams(ec_master_t *, ec_device_index_t); +int ec_master_calc_topology_rec(ec_master_t *, ec_slave_t *, unsigned int *); +void ec_master_calc_topology(ec_master_t *); +void ec_master_calc_transmission_delays(ec_master_t *); static int ec_master_idle_thread(void *); static int ec_master_operation_thread(void *); #ifdef EC_EOE diff --git a/master/slave.c b/master/slave.c index 83ebf084..04cf2151 100644 --- a/master/slave.c +++ b/master/slave.c @@ -42,7 +42,13 @@ extern const ec_code_msg_t al_status_messages[]; /****************************************************************************/ -char *ec_slave_sii_string(ec_slave_t *, unsigned int); +// prototypes for private methods +char *ec_slave_sii_string(const ec_slave_t *, unsigned int); +void ec_slave_find_names_for_pdo(ec_slave_t *, ec_pdo_t *); +unsigned int ec_slave_get_previous_port(const ec_slave_t *, unsigned int); +unsigned int ec_slave_get_next_port(const ec_slave_t *, unsigned int); +uint32_t ec_slave_calc_rtt_sum(const ec_slave_t *); +ec_slave_t *ec_slave_find_next_dc_slave(ec_slave_t *); /****************************************************************************/ @@ -570,7 +576,7 @@ int ec_slave_fetch_sii_pdos( */ char *ec_slave_sii_string( - ec_slave_t *slave, /**< EtherCAT slave */ + const ec_slave_t *slave, /**< EtherCAT slave */ unsigned int index /**< string index */ ) { @@ -805,7 +811,7 @@ void ec_slave_attach_pdo_names( * \return Port index. */ unsigned int ec_slave_get_previous_port( - ec_slave_t *slave, /**< EtherCAT slave. */ + const ec_slave_t *slave, /**< EtherCAT slave. */ unsigned int port_index /**< Port index. */ ) { @@ -835,7 +841,7 @@ unsigned int ec_slave_get_previous_port( * \return Port index. */ unsigned int ec_slave_get_next_port( - ec_slave_t *slave, /**< EtherCAT slave. */ + const ec_slave_t *slave, /**< EtherCAT slave. */ unsigned int port_index /**< Port index. */ ) { @@ -865,7 +871,7 @@ unsigned int ec_slave_get_next_port( * \return Round-trip-time in ns. */ uint32_t ec_slave_calc_rtt_sum( - ec_slave_t *slave /**< EtherCAT slave. */ + const ec_slave_t *slave /**< EtherCAT slave. */ ) { uint32_t rtt_sum = 0, rtt;