Merge branch 'al-timeout-api' into 'devel-1.6'
Add interface to set AL state change timeouts See merge request etherlab.org/ethercat!127
This commit is contained in:
commit
eb6e7bf41b
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,27 @@ 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 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().
|
||||
*
|
||||
* \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
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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: ");
|
||||
|
|
|
|||
|
|
@ -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: ");
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue