AL state timeout lookup logic.
This commit is contained in:
parent
36d036b081
commit
b182bef611
|
|
@ -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
|
* 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
|
* state transition for the given state transition (for example from PREOP to
|
||||||
* SAFEOP). The default timeout is 10 s. Some transitions of specific slaves
|
* SAFEOP). The default values are defined in ETG.2000.
|
||||||
* may take longer.
|
*
|
||||||
|
* A timeout value of zero ms will restore the default value.
|
||||||
*
|
*
|
||||||
* This method has to be called in non-realtime context before
|
* This method has to be called in non-realtime context before
|
||||||
* ecrt_master_activate().
|
* ecrt_master_activate().
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,11 @@
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
#include "fsm_change.h"
|
#include "fsm_change.h"
|
||||||
|
#include "slave_config.h"
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
/** Timeout while waiting for AL state change [s].
|
unsigned int ec_fsm_change_timeout_ms(const ec_fsm_change_t *);
|
||||||
*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
void ec_fsm_change_state_start(ec_fsm_change_t *);
|
void ec_fsm_change_state_start(ec_fsm_change_t *);
|
||||||
void ec_fsm_change_state_check(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.
|
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_datagram_t *datagram = fsm->datagram;
|
||||||
ec_slave_t *slave = fsm->slave;
|
ec_slave_t *slave = fsm->slave;
|
||||||
|
unsigned int timeout_ms;
|
||||||
|
|
||||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||||
return;
|
return;
|
||||||
|
|
@ -297,13 +336,15 @@ void ec_fsm_change_state_status(ec_fsm_change_t *fsm
|
||||||
|
|
||||||
// still old state
|
// still old state
|
||||||
|
|
||||||
|
timeout_ms = ec_fsm_change_timeout_ms(fsm);
|
||||||
if (datagram->jiffies_received - fsm->jiffies_start >=
|
if (datagram->jiffies_received - fsm->jiffies_start >=
|
||||||
EC_AL_STATE_CHANGE_TIMEOUT * HZ) {
|
timeout_ms * HZ / 1000) {
|
||||||
// timeout while checking
|
// timeout while checking
|
||||||
char state_str[EC_STATE_STRING_SIZE];
|
char state_str[EC_STATE_STRING_SIZE];
|
||||||
ec_state_string(fsm->requested_state, state_str, 0);
|
ec_state_string(fsm->requested_state, state_str, 0);
|
||||||
fsm->state = ec_fsm_change_state_error;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -492,6 +533,7 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm
|
||||||
{
|
{
|
||||||
ec_datagram_t *datagram = fsm->datagram;
|
ec_datagram_t *datagram = fsm->datagram;
|
||||||
ec_slave_t *slave = fsm->slave;
|
ec_slave_t *slave = fsm->slave;
|
||||||
|
unsigned int timeout_ms;
|
||||||
|
|
||||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||||
return;
|
return;
|
||||||
|
|
@ -530,14 +572,15 @@ void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timeout_ms = ec_fsm_change_timeout_ms(fsm);
|
||||||
if (datagram->jiffies_received - fsm->jiffies_start >=
|
if (datagram->jiffies_received - fsm->jiffies_start >=
|
||||||
EC_AL_STATE_CHANGE_TIMEOUT * HZ) {
|
timeout_ms * HZ / 1000) {
|
||||||
// timeout while checking
|
// timeout while checking
|
||||||
char state_str[EC_STATE_STRING_SIZE];
|
char state_str[EC_STATE_STRING_SIZE];
|
||||||
ec_state_string(slave->current_state, state_str, 0);
|
ec_state_string(slave->current_state, state_str, 0);
|
||||||
fsm->state = ec_fsm_change_state_error;
|
fsm->state = ec_fsm_change_state_error;
|
||||||
EC_SLAVE_ERR(slave, "Timeout while acknowledging state %s.\n",
|
EC_SLAVE_ERR(slave, "Timeout after %u ms while acknowledging"
|
||||||
state_str);
|
" state %s.\n", timeout_ms, state_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
/** Slave configuration constructor.
|
||||||
*
|
*
|
||||||
* See ecrt_master_slave_config() for the usage of the \a alias and \a
|
* 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->voe_handlers);
|
||||||
INIT_LIST_HEAD(&sc->soe_configs);
|
INIT_LIST_HEAD(&sc->soe_configs);
|
||||||
INIT_LIST_HEAD(&sc->flags);
|
INIT_LIST_HEAD(&sc->flags);
|
||||||
|
INIT_LIST_HEAD(&sc->al_timeouts);
|
||||||
|
|
||||||
#ifdef EC_EOE
|
#ifdef EC_EOE
|
||||||
ec_eoe_request_init(&sc->eoe_ip_param_request);
|
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_reg_request_t *reg, *next_reg;
|
||||||
ec_soe_request_t *soe, *next_soe;
|
ec_soe_request_t *soe, *next_soe;
|
||||||
ec_flag_t *flag, *next_flag;
|
ec_flag_t *flag, *next_flag;
|
||||||
|
ec_al_timeout_t *timeout, *next_timeout;
|
||||||
|
|
||||||
ec_slave_config_detach(sc);
|
ec_slave_config_detach(sc);
|
||||||
|
|
||||||
|
|
@ -169,6 +190,12 @@ void ec_slave_config_clear(
|
||||||
kfree(flag);
|
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);
|
ec_coe_emerg_ring_clear(&sc->emerg_ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -625,6 +652,26 @@ ec_flag_t *ec_slave_config_find_flag(
|
||||||
return NULL;
|
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
|
* 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 */
|
/** \cond */
|
||||||
|
|
||||||
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
|
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_dns_address);
|
||||||
EXPORT_SYMBOL(ecrt_slave_config_eoe_hostname);
|
EXPORT_SYMBOL(ecrt_slave_config_eoe_hostname);
|
||||||
#endif
|
#endif
|
||||||
|
EXPORT_SYMBOL(ecrt_slave_config_state_timeout);
|
||||||
|
|
||||||
/** \endcond */
|
/** \endcond */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ struct ec_slave_config {
|
||||||
struct list_head reg_requests; /**< List of register requests. */
|
struct list_head reg_requests; /**< List of register requests. */
|
||||||
struct list_head soe_configs; /**< List of SoE configurations. */
|
struct list_head soe_configs; /**< List of SoE configurations. */
|
||||||
struct list_head flags; /**< List of feature flags. */
|
struct list_head flags; /**< List of feature flags. */
|
||||||
|
struct list_head al_timeouts; /**< List of specific AL state timeouts. */
|
||||||
|
|
||||||
#ifdef EC_EOE
|
#ifdef EC_EOE
|
||||||
ec_eoe_request_t eoe_ip_param_request; /**< EoE IP parameters. */
|
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_reg_request_t *ecrt_slave_config_create_reg_request_err(
|
||||||
ec_slave_config_t *, size_t);
|
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
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue