Merge branch 'next-patches-from-gavins-patchset' into 'master'
More patches from Gavin Lamberts patchset See merge request etherlab.org/ethercat!80
This commit is contained in:
commit
775b93de5b
29
configure.ac
29
configure.ac
|
|
@ -1185,6 +1185,35 @@ esac
|
|||
AM_CONDITIONAL(HAVE_SYSTEMD, test "x$with_systemdsystemunitdir" != "x")
|
||||
AC_SUBST(systemdsystemunitdir,[$with_systemdsystemunitdir])
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Skip SDO dictionary during slave scan
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_MSG_CHECKING([whether to skip SDO dictionary during slave scan])
|
||||
|
||||
AC_ARG_ENABLE([skip-sdo-dict],
|
||||
AS_HELP_STRING([--enable-skip-sdo-dict],
|
||||
[Enable skip SDO dictionary (default: no)]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) skipsdodict=1
|
||||
;;
|
||||
no) skipsdodict=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-skip-sdo-dict])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[skipsdodict=0]
|
||||
)
|
||||
|
||||
if test "x${skipsdodict}" = "x1"; then
|
||||
AC_DEFINE([EC_SKIP_SDO_DICT], [1], [Skip SDO dictionary during slave scan])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ ec_master-objs := \
|
|||
soe_request.o \
|
||||
sync.o \
|
||||
sync_config.o \
|
||||
voe_handler.o
|
||||
voe_handler.o \
|
||||
dict_request.o
|
||||
|
||||
ifeq (@ENABLE_EOE@,1)
|
||||
ec_master-objs += eoe_request.o
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ noinst_HEADERS = \
|
|||
soe_request.c soe_request.h \
|
||||
sync.c sync.h \
|
||||
sync_config.c sync_config.h \
|
||||
voe_handler.c voe_handler.h
|
||||
voe_handler.c voe_handler.h \
|
||||
dict_request.c dict_request.h
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* The license mentioned above concerns the source code only. Using the
|
||||
* EtherCAT technology and brand is only permitted in compliance with the
|
||||
* industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Canopen over EtherCAT dictionary request functions.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dict_request.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Dictionary request constructor.
|
||||
*/
|
||||
void ec_dict_request_init(ec_dict_request_t *req)
|
||||
{
|
||||
req->state = EC_INT_REQUEST_INIT;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_dict_request_read(ec_dict_request_t *req)
|
||||
{
|
||||
req->state = EC_INT_REQUEST_QUEUED;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
|
||||
/** \endcond */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* The license mentioned above concerns the source code only. Using the
|
||||
* EtherCAT technology and brand is only permitted in compliance with the
|
||||
* industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
\file
|
||||
EtherCAT CANopen dictionary request structure.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __EC_DICT_REQUEST_H__
|
||||
#define __EC_DICT_REQUEST_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** CANopen dictionary request.
|
||||
*/
|
||||
typedef struct {
|
||||
struct list_head list; /**< List item. */
|
||||
ec_internal_request_state_t state; /**< SDO request state. */
|
||||
} ec_dict_request_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_dict_request_init(ec_dict_request_t *);
|
||||
void ec_dict_request_read(ec_dict_request_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
@ -230,35 +230,34 @@ void ec_fsm_coe_transfer(
|
|||
|
||||
/** Executes the current state of the state machine.
|
||||
*
|
||||
* \return 1 if the datagram was used, else 0.
|
||||
* \return 1 if the state machine is still in progress, else 0.
|
||||
*/
|
||||
int ec_fsm_coe_exec(
|
||||
ec_fsm_coe_t *fsm, /**< Finite state machine. */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
int datagram_used = 0;
|
||||
|
||||
if (fsm->state == ec_fsm_coe_end || fsm->state == ec_fsm_coe_error)
|
||||
return 0;
|
||||
if (fsm->datagram &&
|
||||
(fsm->datagram->state == EC_DATAGRAM_INIT ||
|
||||
fsm->datagram->state == EC_DATAGRAM_QUEUED ||
|
||||
fsm->datagram->state == EC_DATAGRAM_SENT)) {
|
||||
// datagram not received yet
|
||||
return datagram_used;
|
||||
if (datagram != fsm->datagram)
|
||||
datagram->state = EC_DATAGRAM_INVALID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fsm->state(fsm, datagram);
|
||||
|
||||
datagram_used =
|
||||
fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error;
|
||||
|
||||
if (datagram_used) {
|
||||
fsm->datagram = datagram;
|
||||
} else {
|
||||
if (fsm->state == ec_fsm_coe_end || fsm->state == ec_fsm_coe_error) {
|
||||
fsm->datagram = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datagram_used;
|
||||
fsm->datagram = datagram;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -101,35 +101,35 @@ void ec_fsm_eoe_set_ip_param(
|
|||
|
||||
/** Executes the current state of the state machine.
|
||||
*
|
||||
* \return 1 if the datagram was used, else 0.
|
||||
* \return 1 if the state machine is still in progress, else 0.
|
||||
*/
|
||||
int ec_fsm_eoe_exec(
|
||||
ec_fsm_eoe_t *fsm, /**< finite state machine */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
int datagram_used = 0;
|
||||
if (fsm->state == ec_fsm_eoe_end || fsm->state == ec_fsm_eoe_error)
|
||||
return 0;
|
||||
|
||||
if (fsm->datagram &&
|
||||
(fsm->datagram->state == EC_DATAGRAM_INIT ||
|
||||
fsm->datagram->state == EC_DATAGRAM_QUEUED ||
|
||||
fsm->datagram->state == EC_DATAGRAM_SENT)) {
|
||||
// datagram not received yet
|
||||
return datagram_used;
|
||||
if (datagram != fsm->datagram)
|
||||
datagram->state = EC_DATAGRAM_INVALID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fsm->state(fsm, datagram);
|
||||
|
||||
datagram_used =
|
||||
fsm->state != ec_fsm_eoe_end && fsm->state != ec_fsm_eoe_error;
|
||||
|
||||
if (datagram_used) {
|
||||
fsm->datagram = datagram;
|
||||
} else {
|
||||
if (fsm->state == ec_fsm_eoe_end || fsm->state == ec_fsm_eoe_error) {
|
||||
fsm->datagram = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datagram_used;
|
||||
fsm->datagram = datagram;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -123,35 +123,35 @@ void ec_fsm_foe_clear(ec_fsm_foe_t *fsm /**< finite state machine */)
|
|||
|
||||
/** Executes the current state of the state machine.
|
||||
*
|
||||
* \return 1, if the datagram was used, else 0.
|
||||
* \return 1 if the state machine is still in progress, else 0.
|
||||
*/
|
||||
int ec_fsm_foe_exec(
|
||||
ec_fsm_foe_t *fsm, /**< finite state machine */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
int datagram_used = 0;
|
||||
if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error)
|
||||
return 0;
|
||||
|
||||
if (fsm->datagram &&
|
||||
(fsm->datagram->state == EC_DATAGRAM_INIT ||
|
||||
fsm->datagram->state == EC_DATAGRAM_QUEUED ||
|
||||
fsm->datagram->state == EC_DATAGRAM_SENT)) {
|
||||
// datagram not received yet
|
||||
return datagram_used;
|
||||
if (datagram != fsm->datagram)
|
||||
datagram->state = EC_DATAGRAM_INVALID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fsm->state(fsm, datagram);
|
||||
|
||||
datagram_used =
|
||||
fsm->state != ec_fsm_foe_end && fsm->state != ec_fsm_foe_error;
|
||||
|
||||
if (datagram_used) {
|
||||
fsm->datagram = datagram;
|
||||
} else {
|
||||
if (fsm->state == ec_fsm_foe_end || fsm->state == ec_fsm_foe_error) {
|
||||
fsm->datagram = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datagram_used;
|
||||
fsm->datagram = datagram;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@ void ec_fsm_master_action_idle(
|
|||
for (slave = master->slaves;
|
||||
slave < master->slaves + master->slave_count;
|
||||
slave++) {
|
||||
#ifndef EC_SKIP_SDO_DICT
|
||||
if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
|
||||
|| (slave->sii.has_general
|
||||
&& !slave->sii.coe_details.enable_sdo_info)
|
||||
|
|
@ -596,8 +597,10 @@ void ec_fsm_master_action_idle(
|
|||
|| (slave->sii.has_general
|
||||
&& !slave->sii.coe_details.enable_sdo_info)
|
||||
){
|
||||
#endif
|
||||
// SDO info not supported. Enable processing of requests
|
||||
ec_fsm_slave_set_ready(&slave->fsm);
|
||||
#ifndef EC_SKIP_SDO_DICT
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -614,6 +617,7 @@ void ec_fsm_master_action_idle(
|
|||
ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); // execute immediately
|
||||
fsm->datagram->device_index = fsm->slave->device_index;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
// check for pending SII write operations.
|
||||
|
|
@ -1135,6 +1139,9 @@ void ec_fsm_master_state_scan_slave(
|
|||
if (ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan)) {
|
||||
return;
|
||||
}
|
||||
// Assume that the slaves mailbox data is valid even if the slave scanning skipped
|
||||
// the clear mailbox state, e.g. if the slave refused to enter state INIT.
|
||||
fsm->slave->valid_mbox_data = 1;
|
||||
|
||||
#ifdef EC_EOE
|
||||
if (slave->sii.mailbox_protocols & EC_MBOX_EOE) {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *, ec_datagram_t *);
|
|||
int ec_fsm_slave_action_process_eoe(ec_fsm_slave_t *, ec_datagram_t *);
|
||||
void ec_fsm_slave_state_eoe_request(ec_fsm_slave_t *, ec_datagram_t *);
|
||||
#endif
|
||||
int ec_fsm_slave_action_process_dict(ec_fsm_slave_t *, ec_datagram_t *);
|
||||
void ec_fsm_slave_state_dict_request(ec_fsm_slave_t *, ec_datagram_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -249,6 +251,11 @@ void ec_fsm_slave_state_ready(
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for pending dictionary requests
|
||||
if (ec_fsm_slave_action_process_dict(fsm, datagram)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -618,6 +625,121 @@ void ec_fsm_slave_state_soe_request(
|
|||
fsm->state = ec_fsm_slave_state_ready;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Check for pending dictionary requests and process one.
|
||||
*
|
||||
* \return non-zero, if a request is processed.
|
||||
*/
|
||||
int ec_fsm_slave_action_process_dict(
|
||||
ec_fsm_slave_t *fsm, /**< Slave state machine. */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_dict_request_t *request;
|
||||
|
||||
if (list_empty(&slave->dict_requests)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// take the first request to be processed
|
||||
request = list_entry(slave->dict_requests.next, ec_dict_request_t, list);
|
||||
list_del_init(&request->list); // dequeue
|
||||
|
||||
if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
|
||||
|| (slave->sii.has_general
|
||||
&& !slave->sii.coe_details.enable_sdo_info))
|
||||
{
|
||||
EC_SLAVE_INFO(slave, "Aborting dictionary request,"
|
||||
" slave does not support SDO Info.\n");
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->dict_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_ready;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (slave->sdo_dictionary_fetched)
|
||||
{
|
||||
EC_SLAVE_DBG(slave, 1, "Aborting dictionary request,"
|
||||
" dictionary already uploaded.\n");
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->dict_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_ready;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
|
||||
EC_SLAVE_WARN(slave, "Aborting dictionary request,"
|
||||
" slave has error flag set.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (slave->current_state == EC_SLAVE_STATE_INIT) {
|
||||
EC_SLAVE_WARN(slave, "Aborting dictioanry request, slave is in INIT.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->state = ec_fsm_slave_state_idle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fsm->dict_request = request;
|
||||
request->state = EC_INT_REQUEST_BUSY;
|
||||
|
||||
// Found pending dictionary request. Execute it!
|
||||
EC_SLAVE_DBG(slave, 1, "Processing dictionary request...\n");
|
||||
|
||||
// Start dictionary transfer
|
||||
fsm->state = ec_fsm_slave_state_dict_request;
|
||||
ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
|
||||
ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave state: DICT_REQUEST.
|
||||
*/
|
||||
void ec_fsm_slave_state_dict_request(
|
||||
ec_fsm_slave_t *fsm, /**< Slave state machine. */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_dict_request_t *request = fsm->dict_request;
|
||||
|
||||
if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||
EC_SLAVE_ERR(slave, "Failed to process dictionary request.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->dict_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_ready;
|
||||
return;
|
||||
}
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "Finished dictionary request.\n");
|
||||
|
||||
// Dictionary request finished
|
||||
slave->sdo_dictionary_fetched = 1;
|
||||
|
||||
// attach pdo names from dictionary
|
||||
ec_slave_attach_pdo_names(slave);
|
||||
|
||||
request->state = EC_INT_REQUEST_SUCCESS;
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
fsm->dict_request = NULL;
|
||||
fsm->state = ec_fsm_slave_state_ready;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
#ifdef EC_EOE
|
||||
/** Check for pending EoE IP parameter requests and process one.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "sdo_request.h"
|
||||
#include "reg_request.h"
|
||||
#include "eoe_request.h"
|
||||
#include "dict_request.h"
|
||||
#include "fsm_coe.h"
|
||||
#include "fsm_foe.h"
|
||||
#include "fsm_soe.h"
|
||||
|
|
@ -69,6 +70,7 @@ struct ec_fsm_slave {
|
|||
#ifdef EC_EOE
|
||||
ec_eoe_request_t *eoe_request; /**< EoE request to process. */
|
||||
#endif
|
||||
ec_dict_request_t *dict_request; /**< Dictionary request to process. */
|
||||
|
||||
ec_fsm_coe_t fsm_coe; /**< CoE state machine. */
|
||||
ec_fsm_foe_t fsm_foe; /**< FoE state machine. */
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *);
|
|||
#endif
|
||||
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_state_mailbox_cleared(ec_fsm_slave_scan_t *);
|
||||
#ifdef EC_REGALIAS
|
||||
void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
|
||||
#endif
|
||||
|
|
@ -70,6 +71,7 @@ void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *);
|
|||
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_clear_mailbox(ec_fsm_slave_scan_t *);
|
||||
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -774,6 +776,23 @@ void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm
|
|||
" Disabling mailbox communication.");
|
||||
}
|
||||
|
||||
// clear mailbox settings if invalid values due to invalid sii file
|
||||
if ((slave->sii.boot_rx_mailbox_offset == 0xFFFF) ||
|
||||
(slave->sii.boot_tx_mailbox_offset == 0xFFFF) ||
|
||||
(slave->sii.std_rx_mailbox_offset == 0xFFFF) ||
|
||||
(slave->sii.std_tx_mailbox_offset == 0xFFFF)) {
|
||||
slave->sii.boot_rx_mailbox_offset = 0;
|
||||
slave->sii.boot_tx_mailbox_offset = 0;
|
||||
slave->sii.boot_rx_mailbox_size = 0;
|
||||
slave->sii.boot_tx_mailbox_size = 0;
|
||||
slave->sii.std_rx_mailbox_offset = 0;
|
||||
slave->sii.std_tx_mailbox_offset = 0;
|
||||
slave->sii.std_rx_mailbox_size = 0;
|
||||
slave->sii.std_tx_mailbox_size = 0;
|
||||
slave->sii.mailbox_protocols = 0;
|
||||
EC_SLAVE_ERR(slave, "Unexpected mailbox offset in SII data.\n");
|
||||
}
|
||||
|
||||
if (slave->sii_nwords == EC_FIRST_SII_CATEGORY_OFFSET) {
|
||||
// sii does not contain category data
|
||||
fsm->state = ec_fsm_slave_scan_state_end;
|
||||
|
|
@ -979,7 +998,7 @@ void ec_fsm_slave_scan_state_preop(
|
|||
return;
|
||||
}
|
||||
|
||||
ec_fsm_slave_scan_enter_pdos(fsm);
|
||||
ec_fsm_slave_scan_enter_clear_mailbox(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1050,6 +1069,51 @@ void ec_fsm_slave_scan_state_sync(
|
|||
// allocate memory for mailbox response data for supported mailbox protocols
|
||||
ec_mbox_prot_data_prealloc(slave, slave->sii.mailbox_protocols, slave->configured_tx_mailbox_size);
|
||||
|
||||
ec_fsm_slave_scan_enter_clear_mailbox(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Enter slave scan state: Clear Mailbox.
|
||||
*/
|
||||
void ec_fsm_slave_scan_enter_clear_mailbox(
|
||||
ec_fsm_slave_scan_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
// If there is some old data in the slave's mailbox, read it out and
|
||||
// discard it. We don't need to check the mailbox first, we just ignore
|
||||
// an error or empty mailbox response.
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_slave_scan_state_mailbox_cleared;
|
||||
|
||||
slave->valid_mbox_data = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave scan state: Mailbox cleared.
|
||||
*/
|
||||
void ec_fsm_slave_scan_state_mailbox_cleared(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
|
||||
if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
|
||||
ec_slave_mbox_prepare_fetch(fsm->slave, datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(slave->master->debug_level > 0)
|
||||
&& datagram->state == EC_DATAGRAM_RECEIVED
|
||||
&& datagram->working_counter == 1)
|
||||
EC_SLAVE_INFO(slave, "Cleared old data from the mailbox\n");
|
||||
|
||||
slave->valid_mbox_data = 1;
|
||||
|
||||
ec_fsm_slave_scan_enter_pdos(fsm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,35 +147,35 @@ void ec_fsm_soe_transfer(
|
|||
|
||||
/** Executes the current state of the state machine.
|
||||
*
|
||||
* \return 1 if the datagram was used, else 0.
|
||||
* \return 1 if the state machine is still in progress, else 0.
|
||||
*/
|
||||
int ec_fsm_soe_exec(
|
||||
ec_fsm_soe_t *fsm, /**< finite state machine */
|
||||
ec_datagram_t *datagram /**< Datagram to use. */
|
||||
)
|
||||
{
|
||||
int datagram_used = 0;
|
||||
if (fsm->state == ec_fsm_soe_end || fsm->state == ec_fsm_soe_error)
|
||||
return 0;
|
||||
|
||||
if (fsm->datagram &&
|
||||
(fsm->datagram->state == EC_DATAGRAM_INIT ||
|
||||
fsm->datagram->state == EC_DATAGRAM_QUEUED ||
|
||||
fsm->datagram->state == EC_DATAGRAM_SENT)) {
|
||||
// datagram not received yet
|
||||
return datagram_used;
|
||||
if (datagram != fsm->datagram)
|
||||
datagram->state = EC_DATAGRAM_INVALID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fsm->state(fsm, datagram);
|
||||
|
||||
datagram_used =
|
||||
fsm->state != ec_fsm_soe_end && fsm->state != ec_fsm_soe_error;
|
||||
|
||||
if (datagram_used) {
|
||||
fsm->datagram = datagram;
|
||||
} else {
|
||||
if (fsm->state == ec_fsm_soe_end || fsm->state == ec_fsm_soe_error) {
|
||||
fsm->datagram = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datagram_used;
|
||||
fsm->datagram = datagram;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -4622,6 +4622,28 @@ static ATTRIBUTES int ec_ioctl_slave_soe_write(
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Upload Dictionary.
|
||||
*
|
||||
* \return Zero on success, otherwise a negative error code.
|
||||
*/
|
||||
static ATTRIBUTES int ec_ioctl_slave_dict_upload(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
void *arg /**< ioctl() argument. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_slave_dict_upload_t data;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = ec_master_dict_upload(master, data.slave_position);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** ioctl() function to use.
|
||||
|
|
@ -5196,6 +5218,9 @@ long EC_IOCTL(
|
|||
}
|
||||
ret = ec_ioctl_set_send_interval(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_SLAVE_DICT_UPLOAD:
|
||||
ret = ec_ioctl_slave_dict_upload(master, arg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
*
|
||||
* Increment this when changing the ioctl interface!
|
||||
*/
|
||||
#define EC_IOCTL_VERSION_MAGIC 38
|
||||
#define EC_IOCTL_VERSION_MAGIC 39
|
||||
|
||||
// Command-line tool
|
||||
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
|
||||
|
|
@ -86,6 +86,7 @@
|
|||
#ifdef EC_EOE
|
||||
#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x1f, ec_ioctl_eoe_handler_t)
|
||||
#endif
|
||||
#define EC_IOCTL_SLAVE_DICT_UPLOAD EC_IOW(0x7f, ec_ioctl_slave_dict_upload_t)
|
||||
|
||||
// Application interface
|
||||
#define EC_IOCTL_REQUEST EC_IO(0x20)
|
||||
|
|
@ -812,6 +813,13 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint16_t slave_position;
|
||||
} ec_ioctl_slave_dict_upload_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/** Context data structure for file handles.
|
||||
|
|
|
|||
240
master/master.c
240
master/master.c
|
|
@ -1286,67 +1286,72 @@ void ec_master_receive_datagrams(
|
|||
if (slave->station_address == datagram_slave_addr) {
|
||||
if (slave->configured_tx_mailbox_offset != 0) {
|
||||
if (datagram_offset_addr == slave->configured_tx_mailbox_offset) {
|
||||
datagram_mbox_prot = EC_READ_U8(cur_data + 5) & 0x0F;
|
||||
switch (datagram_mbox_prot) {
|
||||
if (slave->valid_mbox_data) {
|
||||
datagram_mbox_prot = EC_READ_U8(cur_data + 5) & 0x0F;
|
||||
switch (datagram_mbox_prot) {
|
||||
#ifdef EC_EOE
|
||||
case EC_MBOX_TYPE_EOE:
|
||||
// check EOE type and store in correct handlers mbox data cache
|
||||
eoe_type = EC_READ_U8(cur_data + 6) & 0x0F;
|
||||
case EC_MBOX_TYPE_EOE:
|
||||
// check EOE type and store in correct handlers mbox data cache
|
||||
eoe_type = EC_READ_U8(cur_data + 6) & 0x0F;
|
||||
|
||||
switch (eoe_type) {
|
||||
switch (eoe_type) {
|
||||
|
||||
case EC_EOE_TYPE_FRAME_FRAG:
|
||||
// EoE Frame Fragment handler
|
||||
if ((slave->mbox_eoe_frag_data.data) && (data_size <= slave->mbox_eoe_frag_data.data_size)) {
|
||||
memcpy(slave->mbox_eoe_frag_data.data, cur_data, data_size);
|
||||
slave->mbox_eoe_frag_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_EOE_TYPE_INIT_RES:
|
||||
// EoE Init / Set IP response handler
|
||||
if ((slave->mbox_eoe_init_data.data) && (data_size <= slave->mbox_eoe_init_data.data_size)) {
|
||||
memcpy(slave->mbox_eoe_init_data.data, cur_data, data_size);
|
||||
slave->mbox_eoe_init_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_MASTER_DBG(master, 1, "Unhandled EoE protocol type from slave: %u Protocol: %u, Type: %x\n",
|
||||
datagram_slave_addr, datagram_mbox_prot, eoe_type);
|
||||
// copy instead received data into the datagram memory.
|
||||
memcpy(datagram->data, cur_data, data_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EC_EOE_TYPE_FRAME_FRAG:
|
||||
// EoE Frame Fragment handler
|
||||
if ((slave->mbox_eoe_frag_data.data) && (data_size <= slave->mbox_eoe_frag_data.data_size)) {
|
||||
memcpy(slave->mbox_eoe_frag_data.data, cur_data, data_size);
|
||||
slave->mbox_eoe_frag_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_EOE_TYPE_INIT_RES:
|
||||
// EoE Init / Set IP response handler
|
||||
if ((slave->mbox_eoe_init_data.data) && (data_size <= slave->mbox_eoe_init_data.data_size)) {
|
||||
memcpy(slave->mbox_eoe_init_data.data, cur_data, data_size);
|
||||
slave->mbox_eoe_init_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_MASTER_DBG(master, 1, "Unhandled EoE protocol type from slave: %u Protocol: %u, Type: %x\n",
|
||||
datagram_slave_addr, datagram_mbox_prot, eoe_type);
|
||||
// copy instead received data into the datagram memory.
|
||||
memcpy(datagram->data, cur_data, data_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case EC_MBOX_TYPE_COE:
|
||||
if ((slave->mbox_coe_data.data) && (data_size <= slave->mbox_coe_data.data_size)) {
|
||||
memcpy(slave->mbox_coe_data.data, cur_data, data_size);
|
||||
slave->mbox_coe_data.payload_size = data_size;
|
||||
case EC_MBOX_TYPE_COE:
|
||||
if ((slave->mbox_coe_data.data) && (data_size <= slave->mbox_coe_data.data_size)) {
|
||||
memcpy(slave->mbox_coe_data.data, cur_data, data_size);
|
||||
slave->mbox_coe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_FOE:
|
||||
if ((slave->mbox_foe_data.data) && (data_size <= slave->mbox_foe_data.data_size)) {
|
||||
memcpy(slave->mbox_foe_data.data, cur_data, data_size);
|
||||
slave->mbox_foe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_SOE:
|
||||
if ((slave->mbox_soe_data.data) && (data_size <= slave->mbox_soe_data.data_size)) {
|
||||
memcpy(slave->mbox_soe_data.data, cur_data, data_size);
|
||||
slave->mbox_soe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_VOE:
|
||||
if ((slave->mbox_voe_data.data) && (data_size <= slave->mbox_voe_data.data_size)) {
|
||||
memcpy(slave->mbox_voe_data.data, cur_data, data_size);
|
||||
slave->mbox_voe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_MASTER_DBG(master, 1, "Unknown mailbox protocol from slave: %u Protocol: %u\n", datagram_slave_addr, datagram_mbox_prot);
|
||||
// copy instead received data into the datagram memory.
|
||||
memcpy(datagram->data, cur_data, data_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_FOE:
|
||||
if ((slave->mbox_foe_data.data) && (data_size <= slave->mbox_foe_data.data_size)) {
|
||||
memcpy(slave->mbox_foe_data.data, cur_data, data_size);
|
||||
slave->mbox_foe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_SOE:
|
||||
if ((slave->mbox_soe_data.data) && (data_size <= slave->mbox_soe_data.data_size)) {
|
||||
memcpy(slave->mbox_soe_data.data, cur_data, data_size);
|
||||
slave->mbox_soe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
case EC_MBOX_TYPE_VOE:
|
||||
if ((slave->mbox_voe_data.data) && (data_size <= slave->mbox_voe_data.data_size)) {
|
||||
memcpy(slave->mbox_voe_data.data, cur_data, data_size);
|
||||
slave->mbox_voe_data.payload_size = data_size;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_MASTER_DBG(master, 1, "Unknown mailbox protocol from slave: %u Protocol: %u\n", datagram_slave_addr, datagram_mbox_prot);
|
||||
} else {
|
||||
// copy instead received data into the datagram memory.
|
||||
memcpy(datagram->data, cur_data, data_size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// copy instead received data into the datagram memory.
|
||||
|
|
@ -1404,25 +1409,26 @@ void ec_master_receive_datagrams(
|
|||
void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
if (unlikely(jiffies - master->stats.output_jiffies >= HZ)) {
|
||||
master->stats.output_jiffies = jiffies;
|
||||
|
||||
if (master->stats.timeouts) {
|
||||
EC_MASTER_WARN(master, "%u datagram%s TIMED OUT!\n",
|
||||
master->stats.timeouts,
|
||||
master->stats.timeouts == 1 ? "" : "s");
|
||||
master->stats.timeouts = 0;
|
||||
}
|
||||
if (master->stats.corrupted) {
|
||||
EC_MASTER_WARN(master, "%u frame%s CORRUPTED!\n",
|
||||
master->stats.corrupted,
|
||||
master->stats.corrupted == 1 ? "" : "s");
|
||||
master->stats.corrupted = 0;
|
||||
}
|
||||
if (master->stats.unmatched) {
|
||||
EC_MASTER_WARN(master, "%u datagram%s UNMATCHED!\n",
|
||||
master->stats.unmatched,
|
||||
master->stats.unmatched == 1 ? "" : "s");
|
||||
master->stats.unmatched = 0;
|
||||
if (!master->scan_busy || (master->debug_level > 0)) {
|
||||
master->stats.output_jiffies = jiffies;
|
||||
if (master->stats.timeouts) {
|
||||
EC_MASTER_WARN(master, "%u datagram%s TIMED OUT!\n",
|
||||
master->stats.timeouts,
|
||||
master->stats.timeouts == 1 ? "" : "s");
|
||||
master->stats.timeouts = 0;
|
||||
}
|
||||
if (master->stats.corrupted) {
|
||||
EC_MASTER_WARN(master, "%u frame%s CORRUPTED!\n",
|
||||
master->stats.corrupted,
|
||||
master->stats.corrupted == 1 ? "" : "s");
|
||||
master->stats.corrupted = 0;
|
||||
}
|
||||
if (master->stats.unmatched) {
|
||||
EC_MASTER_WARN(master, "%u datagram%s UNMATCHED!\n",
|
||||
master->stats.unmatched,
|
||||
master->stats.unmatched == 1 ? "" : "s");
|
||||
master->stats.unmatched = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1628,13 +1634,15 @@ void ec_master_exec_slave_fsms(
|
|||
fsm->slave->ring_position);
|
||||
#endif
|
||||
if (ec_fsm_slave_exec(fsm, datagram)) {
|
||||
// FSM consumed datagram
|
||||
if (datagram->state != EC_DATAGRAM_INVALID) {
|
||||
// FSM consumed datagram
|
||||
#if DEBUG_INJECT
|
||||
EC_MASTER_DBG(master, 1, "FSM consumed datagram %s\n",
|
||||
datagram->name);
|
||||
EC_MASTER_DBG(master, 1, "FSM consumed datagram %s\n",
|
||||
datagram->name);
|
||||
#endif
|
||||
master->ext_ring_idx_fsm =
|
||||
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
|
||||
master->ext_ring_idx_fsm =
|
||||
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// FSM finished
|
||||
|
|
@ -1654,8 +1662,10 @@ void ec_master_exec_slave_fsms(
|
|||
datagram = ec_master_get_external_datagram(master);
|
||||
|
||||
if (ec_fsm_slave_exec(&master->fsm_slave->fsm, datagram)) {
|
||||
master->ext_ring_idx_fsm =
|
||||
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
|
||||
if (datagram->state != EC_DATAGRAM_INVALID) {
|
||||
master->ext_ring_idx_fsm =
|
||||
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
|
||||
}
|
||||
list_add_tail(&master->fsm_slave->fsm.list,
|
||||
&master->fsm_exec_list);
|
||||
master->fsm_exec_count++;
|
||||
|
|
@ -1895,12 +1905,16 @@ static int ec_master_eoe_thread(void *priv_data)
|
|||
// actual EoE processing
|
||||
sth_to_send = 0;
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
ec_eoe_run(eoe);
|
||||
if (eoe->queue_datagram) {
|
||||
sth_to_send = 1;
|
||||
}
|
||||
if (!ec_eoe_is_idle(eoe)) {
|
||||
all_idle = 0;
|
||||
if ((eoe->slave->current_state == EC_SLAVE_STATE_PREOP) ||
|
||||
(eoe->slave->current_state == EC_SLAVE_STATE_SAFEOP) ||
|
||||
(eoe->slave->current_state == EC_SLAVE_STATE_OP)) {
|
||||
ec_eoe_run(eoe);
|
||||
if (eoe->queue_datagram) {
|
||||
sth_to_send = 1;
|
||||
}
|
||||
if (!ec_eoe_is_idle(eoe)) {
|
||||
all_idle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2418,6 +2432,60 @@ void ec_master_request_op(
|
|||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ec_master_dict_upload(ec_master_t *master, uint16_t slave_position)
|
||||
{
|
||||
ec_dict_request_t request;
|
||||
ec_slave_t *slave;
|
||||
int ret = 0;
|
||||
|
||||
EC_MASTER_DBG(master, 1, "%s(master = 0x%p, slave_position = %u\n",
|
||||
__func__, master, slave_position);
|
||||
|
||||
ec_dict_request_init(&request);
|
||||
ec_dict_request_read(&request);
|
||||
|
||||
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||
ec_lock_up(&master->master_sem);
|
||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
EC_SLAVE_DBG(slave, 1, "Scheduling dictionary upload request.\n");
|
||||
|
||||
// schedule request.
|
||||
list_add_tail(&request.list, &slave->dict_requests);
|
||||
|
||||
ec_lock_up(&master->master_sem);
|
||||
|
||||
// wait for processing through FSM
|
||||
if (wait_event_interruptible(master->request_queue,
|
||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||
// interrupted by signal
|
||||
ec_lock_down(&master->master_sem);
|
||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||
list_del(&request.list);
|
||||
ec_lock_up(&master->master_sem);
|
||||
return -EINTR;
|
||||
}
|
||||
// request already processing: interrupt not possible.
|
||||
ec_lock_up(&master->master_sem);
|
||||
}
|
||||
|
||||
// wait until master FSM has finished processing
|
||||
wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
|
||||
|
||||
if (request.state != EC_INT_REQUEST_SUCCESS) {
|
||||
ret = -EIO;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Application interface
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -384,6 +384,8 @@ void ec_master_request_op(ec_master_t *);
|
|||
void ec_master_internal_send_cb(void *);
|
||||
void ec_master_internal_receive_cb(void *);
|
||||
|
||||
int ec_master_dict_upload(ec_master_t *, uint16_t);
|
||||
|
||||
extern const unsigned int rate_intervals[EC_RATE_COUNT]; // see master.c
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ void ec_slave_init(
|
|||
INIT_LIST_HEAD(&slave->foe_requests);
|
||||
INIT_LIST_HEAD(&slave->soe_requests);
|
||||
INIT_LIST_HEAD(&slave->eoe_requests);
|
||||
INIT_LIST_HEAD(&slave->dict_requests);
|
||||
|
||||
// create state machine object
|
||||
ec_fsm_slave_init(&slave->fsm, slave);
|
||||
|
|
@ -176,6 +177,8 @@ void ec_slave_init(
|
|||
ec_mbox_data_init(&slave->mbox_foe_data);
|
||||
ec_mbox_data_init(&slave->mbox_soe_data);
|
||||
ec_mbox_data_init(&slave->mbox_voe_data);
|
||||
|
||||
slave->valid_mbox_data = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -271,6 +274,15 @@ void ec_slave_clear(ec_slave_t *slave /**< EtherCAT slave */)
|
|||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
}
|
||||
|
||||
while (!list_empty(&slave->dict_requests)) {
|
||||
ec_dict_request_t *request =
|
||||
list_entry(slave->dict_requests.next, ec_dict_request_t, list);
|
||||
list_del_init(&request->list); // dequeue
|
||||
EC_SLAVE_WARN(slave, "Discarding dictionary request,"
|
||||
" slave about to be deleted.\n");
|
||||
request->state = EC_INT_REQUEST_FAILURE;
|
||||
}
|
||||
|
||||
wake_up_all(&slave->master->request_queue);
|
||||
|
||||
if (slave->config) {
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ struct ec_slave
|
|||
struct list_head foe_requests; /**< FoE requests. */
|
||||
struct list_head soe_requests; /**< SoE requests. */
|
||||
struct list_head eoe_requests; /**< EoE set IP parameter requests. */
|
||||
struct list_head dict_requests; /**< Dictionary read requests. */
|
||||
|
||||
ec_fsm_slave_t fsm; /**< Slave state machine. */
|
||||
|
||||
|
|
@ -268,6 +269,8 @@ struct ec_slave
|
|||
ec_mbox_data_t mbox_foe_data; /**< Received mailbox data for FoE. */
|
||||
ec_mbox_data_t mbox_soe_data; /**< Received mailbox data for SoE. */
|
||||
ec_mbox_data_t mbox_voe_data; /**< Received mailbox data for VoE. */
|
||||
|
||||
uint8_t valid_mbox_data; /**< Received mailbox data is valid. */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ void CommandSdos::execute(const StringVector &args)
|
|||
SlaveList::const_iterator si;
|
||||
bool showHeader, multiMaster;
|
||||
|
||||
ec_ioctl_slave_dict_upload_t data;
|
||||
|
||||
if (args.size()) {
|
||||
stringstream err;
|
||||
err << "'" << getName() << "' takes no arguments!";
|
||||
|
|
@ -108,6 +110,19 @@ void CommandSdos::execute(const StringVector &args)
|
|||
MasterDevice m(*mi);
|
||||
m.open(MasterDevice::Read);
|
||||
slaves = selectedSlaves(m);
|
||||
for (si = slaves.begin(); si != slaves.end(); si++) {
|
||||
if (si->coe_details.enable_sdo_info) {
|
||||
data.slave_position = si->position;
|
||||
try {
|
||||
m.dictUpload(&data);
|
||||
} catch (MasterDeviceException &e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
m.close();
|
||||
m.open(MasterDevice::Read);
|
||||
slaves = selectedSlaves(m);
|
||||
showHeader = multiMaster || slaves.size() > 1;
|
||||
|
||||
for (si = slaves.begin(); si != slaves.end(); si++) {
|
||||
|
|
|
|||
|
|
@ -134,13 +134,15 @@ void CommandUpload::execute(const StringVector &args)
|
|||
data.sdo_index, data.sdo_entry_subindex);
|
||||
} catch (MasterDeviceException &e) {
|
||||
err << "Failed to determine SDO entry data type. "
|
||||
<< "Please specify --type.";
|
||||
<< "Please specify --type or fetch directory "
|
||||
<< "with ethercat sdos command.";
|
||||
throwCommandException(err);
|
||||
}
|
||||
if (!(dataType = findDataType(entry.data_type))) {
|
||||
err << "PDO entry has unknown data type 0x"
|
||||
<< hex << setfill('0') << setw(4) << entry.data_type << "!"
|
||||
<< " Please specify --type.";
|
||||
<< " Please specify --type or fetch directory "
|
||||
<< "with ethercat sdos command.";;
|
||||
throwCommandException(err);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -536,6 +536,17 @@ void MasterDevice::sdoUpload(ec_ioctl_slave_sdo_upload_t *data)
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::dictUpload(ec_ioctl_slave_dict_upload_t *data)
|
||||
{
|
||||
if (ioctl(fd, EC_IOCTL_SLAVE_DICT_UPLOAD, data) < 0) {
|
||||
stringstream err;
|
||||
err << "Failed to upload dictionary: " << strerror(errno);
|
||||
throw MasterDeviceException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::requestState(
|
||||
uint16_t slavePosition,
|
||||
uint8_t state
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ class MasterDevice
|
|||
#endif
|
||||
void readSoe(ec_ioctl_slave_soe_read_t *);
|
||||
void writeSoe(ec_ioctl_slave_soe_write_t *);
|
||||
void dictUpload(ec_ioctl_slave_dict_upload_t *);
|
||||
|
||||
unsigned int getMasterCount() const {return masterCount;}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue