Added API for querying CoE emergency requests.

This commit is contained in:
Florian Pose 2012-11-06 14:23:44 +01:00
parent 15516c1f55
commit cd415846d5
11 changed files with 670 additions and 23 deletions

View File

@ -48,6 +48,10 @@
* redundancy features.
* - Added ecrt_sdo_request_index() to change SDO index and subindex after
* handler creation.
* - Added interface for retrieving CoE emergency messages, i. e.
* ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(),
* ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and
* the defines EC_HAVE_EMERGENCY and EC_COE_EMERGENCY_MSG_SIZE.
*
* Changes in version 1.5:
*
@ -140,6 +144,12 @@
*/
#define EC_HAVE_REDUNDANCY
/** Defined, if the CoE emergency ring feature is available.
*
* I. e. if the ecrt_slave_config_emerg_*() methods are available.
*/
#define EC_HAVE_EMERGENCY
/*****************************************************************************/
/** End of list marker.
@ -172,6 +182,12 @@
#define EC_TIMEVAL2NANO(TV) \
(((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_usec * 1000ULL)
/** Size of a CoE emergency message in byte.
*
* \see ecrt_slave_config_emerg_pop().
*/
#define EC_COE_EMERGENCY_MSG_SIZE 8
/******************************************************************************
* Data types
*****************************************************************************/
@ -1283,6 +1299,55 @@ int ecrt_slave_config_complete_sdo(
size_t size /**< Size of the \a data. */
);
/** Set the size of the CoE emergency ring buffer.
*
* The initial size is zero, so all messages will be dropped. This method can
* be called even after master activation, but it will clear the ring buffer!
*
* \return 0 on success, or negative error code.
*/
int ecrt_slave_config_emerg_size(
ec_slave_config_t *sc, /**< Slave configuration. */
size_t elements /**< Number of records of the CoE emergency ring. */
);
/** Read and remove one record from the CoE emergency ring buffer.
*
* A record consists of 8 bytes:
*
* Byte 0-1: Error code (little endian)
* Byte 2: Error register
* Byte 3-7: Data
*
* \return 0 on success (record popped), or negative error code (i. e.
* -ENOENT, if ring is empty).
*/
int ecrt_slave_config_emerg_pop(
ec_slave_config_t *sc, /**< Slave configuration. */
uint8_t *target /**< Pointer to target memory (at least
EC_COE_EMERGENCY_MSG_SIZE bytes). */
);
/** Clears CoE emergency ring buffer and the overrun counter.
*
* \return 0 on success, or negative error code.
*/
int ecrt_slave_config_emerg_clear(
ec_slave_config_t *sc /**< Slave configuration. */
);
/** Read the number of CoE emergency overruns.
*
* The overrun counter will be incremented when a CoE emergency message could
* not be stored in the ring buffer and had to be dropped. Call
* ecrt_slave_config_emerg_clear() to reset the counter.
*
* \return Number of overruns since last clear, or negative error code.
*/
int ecrt_slave_config_emerg_overruns(
ec_slave_config_t *sc /**< Slave configuration. */
);
/** Create an SDO request to exchange SDOs during realtime operation.
*
* The created SDO request object is freed automatically when the master is

View File

@ -403,6 +403,84 @@ int ecrt_slave_config_sdo32(ec_slave_config_t *sc, uint16_t index,
/*****************************************************************************/
int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements)
{
ec_ioctl_sc_emerg_t io;
int ret;
io.config_index = sc->index;
io.size = elements;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_SIZE, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to set emergency ring size: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/*****************************************************************************/
int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target)
{
ec_ioctl_sc_emerg_t io;
int ret;
io.config_index = sc->index;
io.target = target;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_POP, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to get emergency message: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/*****************************************************************************/
int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc)
{
ec_ioctl_sc_emerg_t io;
int ret;
io.config_index = sc->index;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_CLEAR, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to clear emergency ring: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/*****************************************************************************/
int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc)
{
ec_ioctl_sc_emerg_t io;
int ret;
io.config_index = sc->index;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_OVERRUNS, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to get emergency overruns: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return io.overruns;
}
/*****************************************************************************/
void ec_slave_config_add_sdo_request(ec_slave_config_t *sc,
ec_sdo_request_t *req)
{

View File

@ -35,6 +35,7 @@ obj-m := ec_master.o
ec_master-objs := \
cdev.o \
coe_emerg_ring.o \
datagram.o \
datagram_pair.o \
device.o \

View File

@ -30,6 +30,7 @@
# using HEADERS to enable tags target
noinst_HEADERS = \
cdev.c cdev.h \
coe_emerg_ring.c coe_emerg_ring.h \
datagram.c datagram.h \
datagram_pair.c datagram_pair.h \
debug.c debug.h \

170
master/coe_emerg_ring.c Normal file
View File

@ -0,0 +1,170 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2012 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.
*
* vim: expandtab
*
*****************************************************************************/
/**
\file
EtherCAT CoE emergency ring buffer methods.
*/
/*****************************************************************************/
#include <linux/slab.h>
#include "coe_emerg_ring.h"
/*****************************************************************************/
/** Emergency ring buffer constructor.
*/
void ec_coe_emerg_ring_init(
ec_coe_emerg_ring_t *ring, /**< Emergency ring. */
ec_slave_config_t *sc /**< Slave configuration. */
)
{
ring->sc = sc;
ring->msgs = NULL;
ring->size = 0;
ring->read_index = 0;
ring->write_index = 0;
ring->overruns = 0;
}
/*****************************************************************************/
/** Emergency ring buffer destructor.
*/
void ec_coe_emerg_ring_clear(
ec_coe_emerg_ring_t *ring /**< Emergency ring. */
)
{
if (ring->msgs) {
kfree(ring->msgs);
}
}
/*****************************************************************************/
/** Set the ring size.
*/
int ec_coe_emerg_ring_size(
ec_coe_emerg_ring_t *ring, /**< Emergency ring. */
size_t size /**< Maximum number of messages in the ring. */
)
{
ring->size = 0;
if (size < 0) {
size = 0;
}
ring->read_index = ring->write_index = 0;
if (ring->msgs) {
kfree(ring->msgs);
}
ring->msgs = NULL;
if (size == 0) {
return 0;
}
ring->msgs = kmalloc(sizeof(ec_coe_emerg_msg_t) * (size + 1), GFP_KERNEL);
if (!ring->msgs) {
return -ENOMEM;
}
ring->size = size;
return 0;
}
/*****************************************************************************/
/** Add a new emergency message.
*/
void ec_coe_emerg_ring_push(
ec_coe_emerg_ring_t *ring, /**< Emergency ring. */
const u8 *msg /**< Emergency message. */
)
{
if (!ring->size ||
(ring->write_index + 1) % (ring->size + 1) == ring->read_index) {
ring->overruns++;
return;
}
memcpy(ring->msgs[ring->write_index].data, msg,
EC_COE_EMERGENCY_MSG_SIZE);
ring->write_index = (ring->write_index + 1) % (ring->size + 1);
}
/*****************************************************************************/
/** Remove an emergency message from the ring.
*/
int ec_coe_emerg_ring_pop(
ec_coe_emerg_ring_t *ring, /**< Emergency ring. */
u8 *msg /**< Memory to store the emergency message. */
)
{
if (ring->read_index == ring->write_index) {
return -ENOENT;
}
memcpy(msg, ring->msgs[ring->read_index].data, EC_COE_EMERGENCY_MSG_SIZE);
ring->read_index = (ring->read_index + 1) % (ring->size + 1);
return 0;
}
/*****************************************************************************/
/** Clear the ring.
*/
int ec_coe_emerg_ring_clear_ring(
ec_coe_emerg_ring_t *ring /**< Emergency ring. */
)
{
ring->read_index = ring->write_index;
ring->overruns = 0;
return 0;
}
/*****************************************************************************/
/** Read the number of overruns.
*/
int ec_coe_emerg_ring_overruns(
ec_coe_emerg_ring_t *ring /**< Emergency ring. */
)
{
return ring->overruns;
}
/*****************************************************************************/

78
master/coe_emerg_ring.h Normal file
View File

@ -0,0 +1,78 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2012 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 CoE emergency ring buffer structure.
*/
/*****************************************************************************/
#ifndef __EC_COE_EMERG_RING_H__
#define __EC_COE_EMERG_RING_H__
#include "globals.h"
/*****************************************************************************/
/** EtherCAT CoE emergency message record.
*/
typedef struct {
u8 data[EC_COE_EMERGENCY_MSG_SIZE];
} ec_coe_emerg_msg_t;
/*****************************************************************************/
/** EtherCAT CoE emergency ring buffer.
*/
typedef struct {
ec_slave_config_t *sc; /**< Slave configuration owning the ring. */
ec_coe_emerg_msg_t *msgs;
size_t size;
unsigned int read_index;
unsigned int write_index;
unsigned int overruns;
} ec_coe_emerg_ring_t;
/*****************************************************************************/
void ec_coe_emerg_ring_init(ec_coe_emerg_ring_t *, ec_slave_config_t *);
void ec_coe_emerg_ring_clear(ec_coe_emerg_ring_t *);
int ec_coe_emerg_ring_size(ec_coe_emerg_ring_t *, size_t);
void ec_coe_emerg_ring_push(ec_coe_emerg_ring_t *, const u8 *);
int ec_coe_emerg_ring_pop(ec_coe_emerg_ring_t *, u8 *);
int ec_coe_emerg_ring_clear_ring(ec_coe_emerg_ring_t *);
int ec_coe_emerg_ring_overruns(ec_coe_emerg_ring_t *);
/*****************************************************************************/
#endif

View File

@ -38,6 +38,7 @@
#include "master.h"
#include "mailbox.h"
#include "fsm_coe.h"
#include "slave_config.h"
/*****************************************************************************/
@ -269,6 +270,13 @@ int ec_fsm_coe_check_emergency(
return 1;
}
{
ec_slave_config_t *sc = fsm->slave->config;
if (sc) {
ec_coe_emerg_ring_push(&sc->emerg_ring, data + 2);
}
}
EC_SLAVE_WARN(fsm->slave, "CoE Emergency Request received:\n"
"Error code 0x%04X, Error register 0x%02X, data:\n",
EC_READ_U16(data + 2), EC_READ_U8(data + 4));

View File

@ -2276,6 +2276,169 @@ static int ec_ioctl_sc_sdo(
/*****************************************************************************/
/** Set the emergency ring buffer size.
*/
static int ec_ioctl_sc_emerg_size(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_sc_emerg_t io;
ec_slave_config_t *sc;
int ret;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
return -EFAULT;
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
ret = ecrt_slave_config_emerg_size(sc, io.size);
up(&master->master_sem);
return ret;
}
/*****************************************************************************/
/** Get an emergency message from the ring.
*/
static int ec_ioctl_sc_emerg_pop(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_sc_emerg_t io;
ec_slave_config_t *sc;
u8 msg[EC_COE_EMERGENCY_MSG_SIZE];
int ret;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
return -EFAULT;
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
ret = ecrt_slave_config_emerg_pop(sc, msg);
up(&master->master_sem);
if (ret < 0) {
return ret;
}
if (copy_to_user((void __user *) io.target, msg, sizeof(msg))) {
return -EFAULT;
}
return ret;
}
/*****************************************************************************/
/** Clear the emergency ring.
*/
static int ec_ioctl_sc_emerg_clear(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_sc_emerg_t io;
ec_slave_config_t *sc;
int ret;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
return -EFAULT;
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
ret = ecrt_slave_config_emerg_clear(sc);
up(&master->master_sem);
return ret;
}
/*****************************************************************************/
/** Get the number of emergency overruns.
*/
static int ec_ioctl_sc_emerg_overruns(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_sc_emerg_t io;
ec_slave_config_t *sc;
int ret;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&io, (void __user *) arg, sizeof(io)))
return -EFAULT;
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
ret = ecrt_slave_config_emerg_overruns(sc);
up(&master->master_sem);
if (ret < 0) {
return ret;
}
io.overruns = ret;
if (copy_to_user((void __user *) arg, &io, sizeof(io))) {
return -EFAULT;
}
return 0;
}
/*****************************************************************************/
/** Create an SDO request.
*/
static int ec_ioctl_sc_create_sdo_request(
@ -3678,6 +3841,34 @@ long EC_IOCTL(ec_master_t *master, ec_ioctl_context_t *ctx,
}
ret = ec_ioctl_sc_sdo(master, arg, ctx);
break;
case EC_IOCTL_SC_EMERG_SIZE:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_emerg_size(master, arg, ctx);
break;
case EC_IOCTL_SC_EMERG_POP:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_emerg_pop(master, arg, ctx);
break;
case EC_IOCTL_SC_EMERG_CLEAR:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_emerg_clear(master, arg, ctx);
break;
case EC_IOCTL_SC_EMERG_OVERRUNS:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx);
break;
case EC_IOCTL_SC_SDO_REQUEST:
if (!ctx->writable) {
ret = -EPERM;

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 20
#define EC_IOCTL_VERSION_MAGIC 21
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -117,28 +117,32 @@
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x33, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_DC EC_IOW(0x34, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x35, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x36, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x37, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x38, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x39, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3a)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3b)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3c)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3d, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3f, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x40, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x41, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x42, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x43, ec_ioctl_sdo_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x44, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x45, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x46, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x47, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x48, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x49, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x4a, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4b, size_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x36, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x37, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x38, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x39, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x3b, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x3c, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x3d, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3e)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3f)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x40)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x41, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x42, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x43, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x44, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x45, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x46, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x47, ec_ioctl_sdo_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x48, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x49, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x4a, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x4b, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x4c, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x4d, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x4e, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4f, size_t)
/*****************************************************************************/
@ -619,6 +623,18 @@ typedef struct {
/*****************************************************************************/
typedef struct {
// inputs
uint32_t config_index;
size_t size;
uint8_t *target;
// outputs
int32_t overruns;
} ec_ioctl_sc_emerg_t;
/*****************************************************************************/
typedef struct {
// inputs
uint32_t config_index;

View File

@ -88,6 +88,8 @@ void ec_slave_config_init(
INIT_LIST_HEAD(&sc->sdo_requests);
INIT_LIST_HEAD(&sc->voe_handlers);
INIT_LIST_HEAD(&sc->soe_configs);
ec_coe_emerg_ring_init(&sc->emerg_ring, sc);
}
/*****************************************************************************/
@ -138,6 +140,8 @@ void ec_slave_config_clear(
ec_soe_request_clear(soe);
kfree(soe);
}
ec_coe_emerg_ring_clear(&sc->emerg_ring);
}
/*****************************************************************************/
@ -881,6 +885,34 @@ int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
/*****************************************************************************/
int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements)
{
return ec_coe_emerg_ring_size(&sc->emerg_ring, elements);
}
/*****************************************************************************/
int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target)
{
return ec_coe_emerg_ring_pop(&sc->emerg_ring, target);
}
/*****************************************************************************/
int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc)
{
return ec_coe_emerg_ring_clear_ring(&sc->emerg_ring);
}
/*****************************************************************************/
int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc)
{
return ec_coe_emerg_ring_overruns(&sc->emerg_ring);
}
/*****************************************************************************/
/** Same as ecrt_slave_config_create_sdo_request(), but with ERR_PTR() return
* value.
*/
@ -1063,6 +1095,10 @@ EXPORT_SYMBOL(ecrt_slave_config_sdo8);
EXPORT_SYMBOL(ecrt_slave_config_sdo16);
EXPORT_SYMBOL(ecrt_slave_config_sdo32);
EXPORT_SYMBOL(ecrt_slave_config_complete_sdo);
EXPORT_SYMBOL(ecrt_slave_config_emerg_size);
EXPORT_SYMBOL(ecrt_slave_config_emerg_pop);
EXPORT_SYMBOL(ecrt_slave_config_emerg_clear);
EXPORT_SYMBOL(ecrt_slave_config_emerg_overruns);
EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request);
EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler);
EXPORT_SYMBOL(ecrt_slave_config_state);

View File

@ -43,6 +43,7 @@
#include "slave.h"
#include "sync_config.h"
#include "fmmu_config.h"
#include "coe_emerg_ring.h"
/*****************************************************************************/
@ -141,6 +142,8 @@ struct ec_slave_config {
struct list_head sdo_requests; /**< List of SDO requests. */
struct list_head voe_handlers; /**< List of VoE handlers. */
struct list_head soe_configs; /**< List of SoE configurations. */
ec_coe_emerg_ring_t emerg_ring; /**< CoE emergency ring buffer. */
};
/*****************************************************************************/