mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-05 19:39:50 +08:00
Renamed command structure to datagram.
This commit is contained in:
@@ -42,7 +42,7 @@ ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := ec_master.o
|
||||
|
||||
ec_master-objs := module.o master.o device.o slave.o command.o types.o \
|
||||
ec_master-objs := module.o master.o device.o slave.o datagram.o types.o \
|
||||
domain.o mailbox.o canopen.o ethernet.o debug.o fsm.o
|
||||
|
||||
REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_canopen_abort_msg(uint32_t);
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *, ec_command_t *);
|
||||
int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_command_t *,
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *, ec_datagram_t *);
|
||||
int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_datagram_t *,
|
||||
ec_sdo_t *, uint8_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -65,13 +65,13 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint8_t *target /**< 4-byte memory */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
ec_datagram_t datagram;
|
||||
size_t rec_size;
|
||||
uint8_t *data;
|
||||
|
||||
ec_command_init(&command);
|
||||
ec_datagram_init(&datagram);
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6)))
|
||||
goto err;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
@@ -80,7 +80,7 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
|
||||
goto err;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
@@ -104,10 +104,10 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
memcpy(target, data + 6, 4);
|
||||
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return 0;
|
||||
err:
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -127,16 +127,16 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t rec_size;
|
||||
ec_command_t command;
|
||||
ec_datagram_t datagram;
|
||||
|
||||
ec_command_init(&command);
|
||||
ec_datagram_init(&datagram);
|
||||
|
||||
if (size == 0 || size > 4) {
|
||||
EC_ERR("Invalid data size!\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 0x0A)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 0x0A)))
|
||||
goto err;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
@@ -149,7 +149,7 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
memcpy(data + 6, sdo_data, size);
|
||||
if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
|
||||
goto err;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
@@ -172,10 +172,10 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return 0;
|
||||
err:
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -198,11 +198,11 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint8_t *data;
|
||||
size_t rec_size, data_size;
|
||||
uint32_t complete_size;
|
||||
ec_command_t command;
|
||||
ec_datagram_t datagram;
|
||||
|
||||
ec_command_init(&command);
|
||||
ec_datagram_init(&datagram);
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6)))
|
||||
goto err;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
@@ -210,7 +210,7 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
|
||||
goto err;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
@@ -253,10 +253,10 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
memcpy(target, data + 10, data_size);
|
||||
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return 0;
|
||||
err:
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -274,11 +274,11 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
unsigned int i, sdo_count;
|
||||
ec_sdo_t *sdo;
|
||||
uint16_t sdo_index;
|
||||
ec_command_t command;
|
||||
ec_datagram_t datagram;
|
||||
|
||||
ec_command_init(&command);
|
||||
ec_datagram_init(&datagram);
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 8)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 8)))
|
||||
goto err;
|
||||
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
@@ -287,13 +287,13 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
|
||||
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, &datagram))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position);
|
||||
goto err;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!(data = ec_slave_mbox_simple_receive(slave, &command,
|
||||
if (!(data = ec_slave_mbox_simple_receive(slave, &datagram,
|
||||
0x03, &rec_size)))
|
||||
goto err;
|
||||
|
||||
@@ -342,12 +342,12 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
while (EC_READ_U8(data + 2) & 0x80);
|
||||
|
||||
// Fetch all SDO descriptions
|
||||
if (ec_slave_fetch_sdo_descriptions(slave, &command)) goto err;
|
||||
if (ec_slave_fetch_sdo_descriptions(slave, &datagram)) goto err;
|
||||
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return 0;
|
||||
err:
|
||||
ec_command_clear(&command);
|
||||
ec_datagram_clear(&datagram);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
*/
|
||||
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
ec_command_t *command /**< command */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
@@ -367,7 +367,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
ec_sdo_t *sdo;
|
||||
|
||||
list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 8)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8)))
|
||||
return -1;
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x03); // Get object description request
|
||||
@@ -375,7 +375,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, sdo->index); // SDO index
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
@@ -428,7 +428,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
}
|
||||
|
||||
// Fetch all entries (subindices)
|
||||
if (ec_slave_fetch_sdo_entries(slave, command, sdo,
|
||||
if (ec_slave_fetch_sdo_entries(slave, datagram, sdo,
|
||||
EC_READ_U8(data + 10)))
|
||||
return -1;
|
||||
}
|
||||
@@ -444,7 +444,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
*/
|
||||
|
||||
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
ec_command_t *command, /**< command */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
ec_sdo_t *sdo, /**< SDO */
|
||||
uint8_t subindices /**< number of subindices */
|
||||
)
|
||||
@@ -455,7 +455,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
ec_sdo_entry_t *entry;
|
||||
|
||||
for (i = 1; i <= subindices; i++) {
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 10)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10)))
|
||||
return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
@@ -466,7 +466,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
EC_WRITE_U8 (data + 8, i); // SDO subindex
|
||||
EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
|
||||
297
master/command.c
297
master/command.c
@@ -1,297 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 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
|
||||
* as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 right to use EtherCAT Technology is granted and comes free of
|
||||
* charge under condition of compatibility of product made by
|
||||
* Licensee. People intending to distribute/sell products based on the
|
||||
* code, have to sign an agreement to guarantee that products using
|
||||
* software based on IgH EtherCAT master stay compatible with the actual
|
||||
* EtherCAT specification (which are released themselves as an open
|
||||
* standard) as the (only) precondition to have the right to use EtherCAT
|
||||
* Technology, IP and trade marks.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
\file
|
||||
Methods of an EtherCAT command.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "master.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
#define EC_FUNC_HEADER \
|
||||
if (unlikely(ec_command_prealloc(command, data_size))) \
|
||||
return -1; \
|
||||
command->index = 0; \
|
||||
command->working_counter = 0; \
|
||||
command->state = EC_CMD_INIT;
|
||||
|
||||
#define EC_FUNC_FOOTER \
|
||||
command->data_size = data_size; \
|
||||
memset(command->data, 0x00, data_size); \
|
||||
return 0;
|
||||
|
||||
/** \endcond */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Command constructor.
|
||||
*/
|
||||
|
||||
void ec_command_init(ec_command_t *command /**< EtherCAT command */)
|
||||
{
|
||||
command->type = EC_CMD_NONE;
|
||||
command->address.logical = 0x00000000;
|
||||
command->data = NULL;
|
||||
command->mem_size = 0;
|
||||
command->data_size = 0;
|
||||
command->index = 0x00;
|
||||
command->working_counter = 0x00;
|
||||
command->state = EC_CMD_INIT;
|
||||
command->t_sent = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Command destructor.
|
||||
*/
|
||||
|
||||
void ec_command_clear(ec_command_t *command /**< EtherCAT command */)
|
||||
{
|
||||
if (command->data) kfree(command->data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Allocates command data memory.
|
||||
If the allocated memory is already larger than requested, nothing ist done.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_prealloc(ec_command_t *command, /**< EtherCAT command */
|
||||
size_t size /**< New size in bytes */
|
||||
)
|
||||
{
|
||||
if (size <= command->mem_size) return 0;
|
||||
|
||||
if (command->data) {
|
||||
kfree(command->data);
|
||||
command->data = NULL;
|
||||
command->mem_size = 0;
|
||||
}
|
||||
|
||||
if (!(command->data = kmalloc(size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %i bytes of command memory!\n", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
command->mem_size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT NPRD command.
|
||||
Node-adressed physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_nprd(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t node_address,
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_NPRD;
|
||||
command->address.physical.slave = node_address;
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT NPWR command.
|
||||
Node-adressed physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_npwr(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t node_address,
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_NPWR;
|
||||
command->address.physical.slave = node_address;
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT APRD command.
|
||||
Autoincrement physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_aprd(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t ring_position,
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_APRD;
|
||||
command->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT APWR command.
|
||||
Autoincrement physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_apwr(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t ring_position,
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_APWR;
|
||||
command->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT BRD command.
|
||||
Broadcast read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_brd(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_BRD;
|
||||
command->address.physical.slave = 0x0000;
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT BWR command.
|
||||
Broadcast write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_bwr(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_BWR;
|
||||
command->address.physical.slave = 0x0000;
|
||||
command->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT LRW command.
|
||||
Logical read write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_lrw(ec_command_t *command,
|
||||
/**< EtherCAT command */
|
||||
uint32_t offset,
|
||||
/**< logical address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read/write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
command->type = EC_CMD_LRW;
|
||||
command->address.logical = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
297
master/datagram.c
Normal file
297
master/datagram.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 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
|
||||
* as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 right to use EtherCAT Technology is granted and comes free of
|
||||
* charge under condition of compatibility of product made by
|
||||
* Licensee. People intending to distribute/sell products based on the
|
||||
* code, have to sign an agreement to guarantee that products using
|
||||
* software based on IgH EtherCAT master stay compatible with the actual
|
||||
* EtherCAT specification (which are released themselves as an open
|
||||
* standard) as the (only) precondition to have the right to use EtherCAT
|
||||
* Technology, IP and trade marks.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
\file
|
||||
Methods of an EtherCAT datagram.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "datagram.h"
|
||||
#include "master.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
#define EC_FUNC_HEADER \
|
||||
if (unlikely(ec_datagram_prealloc(datagram, data_size))) \
|
||||
return -1; \
|
||||
datagram->index = 0; \
|
||||
datagram->working_counter = 0; \
|
||||
datagram->state = EC_CMD_INIT;
|
||||
|
||||
#define EC_FUNC_FOOTER \
|
||||
datagram->data_size = data_size; \
|
||||
memset(datagram->data, 0x00, data_size); \
|
||||
return 0;
|
||||
|
||||
/** \endcond */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Datagram constructor.
|
||||
*/
|
||||
|
||||
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
|
||||
{
|
||||
datagram->type = EC_CMD_NONE;
|
||||
datagram->address.logical = 0x00000000;
|
||||
datagram->data = NULL;
|
||||
datagram->mem_size = 0;
|
||||
datagram->data_size = 0;
|
||||
datagram->index = 0x00;
|
||||
datagram->working_counter = 0x00;
|
||||
datagram->state = EC_CMD_INIT;
|
||||
datagram->t_sent = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Datagram destructor.
|
||||
*/
|
||||
|
||||
void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram */)
|
||||
{
|
||||
if (datagram->data) kfree(datagram->data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Allocates datagram data memory.
|
||||
If the allocated memory is already larger than requested, nothing ist done.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_prealloc(ec_datagram_t *datagram, /**< EtherCAT datagram */
|
||||
size_t size /**< New size in bytes */
|
||||
)
|
||||
{
|
||||
if (size <= datagram->mem_size) return 0;
|
||||
|
||||
if (datagram->data) {
|
||||
kfree(datagram->data);
|
||||
datagram->data = NULL;
|
||||
datagram->mem_size = 0;
|
||||
}
|
||||
|
||||
if (!(datagram->data = kmalloc(size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %i bytes of datagram memory!\n", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
datagram->mem_size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT NPRD datagram.
|
||||
Node-adressed physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_nprd(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t node_address,
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_NPRD;
|
||||
datagram->address.physical.slave = node_address;
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT NPWR datagram.
|
||||
Node-adressed physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_npwr(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t node_address,
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_NPWR;
|
||||
datagram->address.physical.slave = node_address;
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT APRD datagram.
|
||||
Autoincrement physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_aprd(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t ring_position,
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_APRD;
|
||||
datagram->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT APWR datagram.
|
||||
Autoincrement physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_apwr(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t ring_position,
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_APWR;
|
||||
datagram->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT BRD datagram.
|
||||
Broadcast read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_brd(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_BRD;
|
||||
datagram->address.physical.slave = 0x0000;
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT BWR datagram.
|
||||
Broadcast write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_bwr(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint16_t offset,
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_BWR;
|
||||
datagram->address.physical.slave = 0x0000;
|
||||
datagram->address.physical.mem = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes an EtherCAT LRW datagram.
|
||||
Logical read write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_datagram_lrw(ec_datagram_t *datagram,
|
||||
/**< EtherCAT datagram */
|
||||
uint32_t offset,
|
||||
/**< logical address */
|
||||
size_t data_size
|
||||
/**< number of bytes to read/write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
datagram->type = EC_CMD_LRW;
|
||||
datagram->address.logical = offset;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -33,13 +33,13 @@
|
||||
|
||||
/**
|
||||
\file
|
||||
EtherCAT command structure.
|
||||
EtherCAT datagram structure.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _EC_COMMAND_H_
|
||||
#define _EC_COMMAND_H_
|
||||
#ifndef _EC_DATAGRAM_H_
|
||||
#define _EC_DATAGRAM_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/timex.h>
|
||||
@@ -49,7 +49,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT command type.
|
||||
EtherCAT datagram type.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
@@ -63,22 +63,22 @@ typedef enum
|
||||
EC_CMD_BWR = 0x08, /**< Broadcast write */
|
||||
EC_CMD_LRW = 0x0C /**< Logical read/write */
|
||||
}
|
||||
ec_command_type_t;
|
||||
ec_datagram_type_t;
|
||||
|
||||
/**
|
||||
EtherCAT command state.
|
||||
EtherCAT datagram state.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_CMD_INIT, /**< new command */
|
||||
EC_CMD_QUEUED, /**< command queued by master */
|
||||
EC_CMD_SENT, /**< command has been sent */
|
||||
EC_CMD_RECEIVED, /**< command has been received */
|
||||
EC_CMD_TIMEOUT, /**< command timed out */
|
||||
EC_CMD_INIT, /**< new datagram */
|
||||
EC_CMD_QUEUED, /**< datagram queued by master */
|
||||
EC_CMD_SENT, /**< datagram has been sent */
|
||||
EC_CMD_RECEIVED, /**< datagram has been received */
|
||||
EC_CMD_TIMEOUT, /**< datagram timed out */
|
||||
EC_CMD_ERROR /**< error while sending/receiving */
|
||||
}
|
||||
ec_command_state_t;
|
||||
ec_datagram_state_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -102,38 +102,38 @@ ec_address_t;
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT command.
|
||||
EtherCAT datagram.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list; /**< needed by domain command lists */
|
||||
struct list_head queue; /**< master command queue item */
|
||||
ec_command_type_t type; /**< command type (APRD, BWR, etc) */
|
||||
struct list_head list; /**< needed by domain datagram lists */
|
||||
struct list_head queue; /**< master datagram queue item */
|
||||
ec_datagram_type_t type; /**< datagram type (APRD, BWR, etc) */
|
||||
ec_address_t address; /**< receipient address */
|
||||
uint8_t *data; /**< command data */
|
||||
size_t mem_size; /**< command \a data memory size */
|
||||
uint8_t *data; /**< datagram data */
|
||||
size_t mem_size; /**< datagram \a data memory size */
|
||||
size_t data_size; /**< size of the data in \a data */
|
||||
uint8_t index; /**< command index (set by master) */
|
||||
uint8_t index; /**< datagram index (set by master) */
|
||||
uint16_t working_counter; /**< working counter */
|
||||
ec_command_state_t state; /**< command state */
|
||||
cycles_t t_sent; /**< time, the commands was sent */
|
||||
ec_datagram_state_t state; /**< datagram state */
|
||||
cycles_t t_sent; /**< time, the datagrams was sent */
|
||||
}
|
||||
ec_command_t;
|
||||
ec_datagram_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_command_init(ec_command_t *);
|
||||
void ec_command_clear(ec_command_t *);
|
||||
int ec_command_prealloc(ec_command_t *, size_t);
|
||||
void ec_datagram_init(ec_datagram_t *);
|
||||
void ec_datagram_clear(ec_datagram_t *);
|
||||
int ec_datagram_prealloc(ec_datagram_t *, size_t);
|
||||
|
||||
int ec_command_nprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_npwr(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_aprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_apwr(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_brd(ec_command_t *, uint16_t, size_t);
|
||||
int ec_command_bwr(ec_command_t *, uint16_t, size_t);
|
||||
int ec_command_lrw(ec_command_t *, uint32_t, size_t);
|
||||
int ec_datagram_nprd(ec_datagram_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_datagram_npwr(ec_datagram_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_datagram_aprd(ec_datagram_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_datagram_apwr(ec_datagram_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_datagram_brd(ec_datagram_t *, uint16_t, size_t);
|
||||
int ec_datagram_bwr(ec_datagram_t *, uint16_t, size_t);
|
||||
int ec_datagram_lrw(ec_datagram_t *, uint32_t, size_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -90,7 +90,7 @@ int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
domain->response_count = 0xFFFFFFFF;
|
||||
|
||||
INIT_LIST_HEAD(&domain->field_regs);
|
||||
INIT_LIST_HEAD(&domain->commands);
|
||||
INIT_LIST_HEAD(&domain->datagrams);
|
||||
|
||||
// init kobject and add it to the hierarchy
|
||||
memset(&domain->kobj, 0x00, sizeof(struct kobject));
|
||||
@@ -113,16 +113,16 @@ int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
|
||||
void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
|
||||
{
|
||||
ec_command_t *command, *next;
|
||||
ec_datagram_t *datagram, *next;
|
||||
ec_domain_t *domain;
|
||||
|
||||
domain = container_of(kobj, ec_domain_t, kobj);
|
||||
|
||||
EC_INFO("Clearing domain %i.\n", domain->index);
|
||||
|
||||
list_for_each_entry_safe(command, next, &domain->commands, list) {
|
||||
ec_command_clear(command);
|
||||
kfree(command);
|
||||
list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
|
||||
ec_datagram_clear(datagram);
|
||||
kfree(datagram);
|
||||
}
|
||||
|
||||
ec_domain_clear_field_regs(domain);
|
||||
@@ -187,30 +187,30 @@ void ec_domain_clear_field_regs(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Allocates a process data command and appends it to the list.
|
||||
Allocates a process data datagram and appends it to the list.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_domain_add_command(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
uint32_t offset, /**< logical offset */
|
||||
size_t data_size /**< size of the command data */
|
||||
)
|
||||
int ec_domain_add_datagram(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
uint32_t offset, /**< logical offset */
|
||||
size_t data_size /**< size of the datagram data */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
if (!(command = kmalloc(sizeof(ec_command_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate domain command!\n");
|
||||
if (!(datagram = kmalloc(sizeof(ec_datagram_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate domain datagram!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_command_init(command);
|
||||
ec_datagram_init(datagram);
|
||||
|
||||
if (ec_command_lrw(command, offset, data_size)) {
|
||||
kfree(command);
|
||||
if (ec_datagram_lrw(datagram, offset, data_size)) {
|
||||
kfree(datagram);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add_tail(&command->list, &domain->commands);
|
||||
list_add_tail(&datagram->list, &domain->datagrams);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
uint32_t field_off, field_off_cmd;
|
||||
uint32_t cmd_offset;
|
||||
size_t cmd_data_size, sync_size;
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
domain->base_address = base_address;
|
||||
|
||||
@@ -252,8 +252,8 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
sync_size = ec_slave_calc_sync_size(slave, fmmu->sync);
|
||||
domain->data_size += sync_size;
|
||||
if (cmd_data_size + sync_size > EC_MAX_DATA_SIZE) {
|
||||
if (ec_domain_add_command(domain, cmd_offset,
|
||||
cmd_data_size)) return -1;
|
||||
if (ec_domain_add_datagram(domain, cmd_offset,
|
||||
cmd_data_size)) return -1;
|
||||
cmd_offset += cmd_data_size;
|
||||
cmd_data_size = 0;
|
||||
cmd_count++;
|
||||
@@ -263,9 +263,9 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
}
|
||||
}
|
||||
|
||||
// allocate last command
|
||||
// allocate last datagram
|
||||
if (cmd_data_size) {
|
||||
if (ec_domain_add_command(domain, cmd_offset, cmd_data_size))
|
||||
if (ec_domain_add_datagram(domain, cmd_offset, cmd_data_size))
|
||||
return -1;
|
||||
cmd_count++;
|
||||
}
|
||||
@@ -283,12 +283,12 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
if (fmmu->domain == domain && fmmu->sync == field_reg->sync) {
|
||||
field_off = fmmu->logical_start_address +
|
||||
field_reg->field_offset;
|
||||
// search command
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
field_off_cmd = field_off - command->address.logical;
|
||||
if (field_off >= command->address.logical &&
|
||||
field_off_cmd < command->mem_size) {
|
||||
*field_reg->data_ptr = command->data + field_off_cmd;
|
||||
// search datagram
|
||||
list_for_each_entry(datagram, &domain->datagrams, list) {
|
||||
field_off_cmd = field_off - datagram->address.logical;
|
||||
if (field_off >= datagram->address.logical &&
|
||||
field_off_cmd < datagram->mem_size) {
|
||||
*field_reg->data_ptr = datagram->data + field_off_cmd;
|
||||
}
|
||||
}
|
||||
if (!field_reg->data_ptr) {
|
||||
@@ -300,7 +300,7 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
}
|
||||
}
|
||||
|
||||
EC_INFO("Domain %i - Allocated %i bytes in %i command%s\n",
|
||||
EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s\n",
|
||||
domain->index, domain->data_size, cmd_count,
|
||||
cmd_count == 1 ? "" : "s");
|
||||
|
||||
@@ -314,7 +314,7 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
/**
|
||||
Sets the number of responding slaves and outputs it on demand.
|
||||
This number isn't really the number of responding slaves, but the sum of
|
||||
the working counters of all domain commands. Some slaves increase the
|
||||
the working counters of all domain datagrams. Some slaves increase the
|
||||
working counter by 2, some by 1.
|
||||
*/
|
||||
|
||||
@@ -479,16 +479,16 @@ int ecrt_domain_register_field_list(ec_domain_t *domain,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Places all process data commands in the masters command queue.
|
||||
Places all process data datagrams in the masters datagram queue.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
ec_master_queue_command(domain->master, command);
|
||||
list_for_each_entry(datagram, &domain->datagrams, list) {
|
||||
ec_master_queue_datagram(domain->master, datagram);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,13 +502,13 @@ void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
unsigned int working_counter_sum;
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
working_counter_sum = 0;
|
||||
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
if (command->state == EC_CMD_RECEIVED) {
|
||||
working_counter_sum += command->working_counter;
|
||||
list_for_each_entry(datagram, &domain->datagrams, list) {
|
||||
if (datagram->state == EC_CMD_RECEIVED) {
|
||||
working_counter_sum += datagram->working_counter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,16 +519,16 @@ void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
|
||||
/**
|
||||
Returns the state of a domain.
|
||||
\return 0 if all commands were received, else -1.
|
||||
\return 0 if all datagrams were received, else -1.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
int ecrt_domain_state(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
if (command->state != EC_CMD_RECEIVED) return -1;
|
||||
list_for_each_entry(datagram, &domain->datagrams, list) {
|
||||
if (datagram->state != EC_CMD_RECEIVED) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "slave.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -68,7 +68,7 @@ ec_field_reg_t;
|
||||
|
||||
/**
|
||||
EtherCAT domain.
|
||||
Handles the process data and the therefore needed commands of a certain
|
||||
Handles the process data and the therefore needed datagrams of a certain
|
||||
group of slaves.
|
||||
*/
|
||||
|
||||
@@ -79,7 +79,7 @@ struct ec_domain
|
||||
unsigned int index; /**< domain index (just a number) */
|
||||
ec_master_t *master; /**< EtherCAT master owning the domain */
|
||||
size_t data_size; /**< size of the process data */
|
||||
struct list_head commands; /**< process data commands */
|
||||
struct list_head datagrams; /**< process data datagrams */
|
||||
uint32_t base_address; /**< logical offset address of the process data */
|
||||
unsigned int response_count; /**< number of responding slaves */
|
||||
struct list_head field_regs; /**< data field registrations */
|
||||
|
||||
@@ -87,7 +87,7 @@ int ec_eoe_init(ec_eoe_t *eoe /**< EoE handler */)
|
||||
int result, i;
|
||||
|
||||
eoe->slave = NULL;
|
||||
ec_command_init(&eoe->command);
|
||||
ec_datagram_init(&eoe->datagram);
|
||||
eoe->state = ec_eoe_state_rx_start;
|
||||
eoe->opened = 0;
|
||||
eoe->rx_skb = NULL;
|
||||
@@ -169,7 +169,7 @@ void ec_eoe_clear(ec_eoe_t *eoe /**< EoE handler */)
|
||||
|
||||
if (eoe->rx_skb) dev_kfree_skb(eoe->rx_skb);
|
||||
|
||||
ec_command_clear(&eoe->command);
|
||||
ec_datagram_clear(&eoe->datagram);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -246,7 +246,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */)
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->command,
|
||||
if (!(data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->datagram,
|
||||
0x02, current_size + 4)))
|
||||
return -1;
|
||||
|
||||
@@ -257,7 +257,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */)
|
||||
(eoe->tx_frame_number & 0x0F) << 12));
|
||||
|
||||
memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size);
|
||||
ec_master_queue_command(eoe->slave->master, &eoe->command);
|
||||
ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
|
||||
|
||||
eoe->tx_offset += current_size;
|
||||
eoe->tx_fragment_number++;
|
||||
@@ -312,8 +312,8 @@ void ec_eoe_print(const ec_eoe_t *eoe /**< EoE handler */)
|
||||
|
||||
/**
|
||||
State: RX_START.
|
||||
Starts a new receiving sequence by queueing a command that checks the
|
||||
slave's mailbox for a new EoE command.
|
||||
Starts a new receiving sequence by queueing a datagram that checks the
|
||||
slave's mailbox for a new EoE datagram.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
@@ -321,8 +321,8 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
if (!eoe->slave->online || !eoe->slave->master->device->link_state)
|
||||
return;
|
||||
|
||||
ec_slave_mbox_prepare_check(eoe->slave, &eoe->command);
|
||||
ec_master_queue_command(eoe->slave->master, &eoe->command);
|
||||
ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram);
|
||||
ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
|
||||
eoe->state = ec_eoe_state_rx_check;
|
||||
}
|
||||
|
||||
@@ -330,25 +330,25 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
|
||||
/**
|
||||
State: RX_CHECK.
|
||||
Processes the checking command sent in RX_START and issues a receive
|
||||
command, if new data is available.
|
||||
Processes the checking datagram sent in RX_START and issues a receive
|
||||
datagram, if new data is available.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->command.state != EC_CMD_RECEIVED) {
|
||||
if (eoe->datagram.state != EC_CMD_RECEIVED) {
|
||||
eoe->stats.rx_errors++;
|
||||
eoe->state = ec_eoe_state_tx_start;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec_slave_mbox_check(&eoe->command)) {
|
||||
if (!ec_slave_mbox_check(&eoe->datagram)) {
|
||||
eoe->state = ec_eoe_state_tx_start;
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->command);
|
||||
ec_master_queue_command(eoe->slave->master, &eoe->command);
|
||||
ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram);
|
||||
ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
|
||||
eoe->state = ec_eoe_state_rx_fetch;
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
|
||||
/**
|
||||
State: RX_FETCH.
|
||||
Checks if the requested data of RX_CHECK was received and processes the
|
||||
EoE command.
|
||||
EoE datagram.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
||||
@@ -367,13 +367,13 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
||||
uint8_t frame_number, fragment_offset, fragment_number;
|
||||
off_t offset;
|
||||
|
||||
if (eoe->command.state != EC_CMD_RECEIVED) {
|
||||
if (eoe->datagram.state != EC_CMD_RECEIVED) {
|
||||
eoe->stats.rx_errors++;
|
||||
eoe->state = ec_eoe_state_tx_start;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mbox_fetch(eoe->slave, &eoe->command,
|
||||
if (!(data = ec_slave_mbox_fetch(eoe->slave, &eoe->datagram,
|
||||
0x02, &rec_size))) {
|
||||
eoe->stats.rx_errors++;
|
||||
eoe->state = ec_eoe_state_tx_start;
|
||||
@@ -560,19 +560,19 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
|
||||
/**
|
||||
State: TX SENT.
|
||||
Checks is the previous transmit command succeded and sends the next
|
||||
Checks is the previous transmit datagram succeded and sends the next
|
||||
fragment, if necessary.
|
||||
*/
|
||||
|
||||
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->command.state != EC_CMD_RECEIVED) {
|
||||
if (eoe->datagram.state != EC_CMD_RECEIVED) {
|
||||
eoe->stats.tx_errors++;
|
||||
eoe->state = ec_eoe_state_rx_start;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eoe->command.working_counter != 1) {
|
||||
if (eoe->datagram.working_counter != 1) {
|
||||
eoe->stats.tx_errors++;
|
||||
eoe->state = ec_eoe_state_rx_start;
|
||||
return;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "../include/ecrt.h"
|
||||
#include "globals.h"
|
||||
#include "slave.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -73,7 +73,7 @@ struct ec_eoe
|
||||
{
|
||||
struct list_head list; /**< list item */
|
||||
ec_slave_t *slave; /**< pointer to the corresponding slave */
|
||||
ec_command_t command; /**< command */
|
||||
ec_datagram_t datagram; /**< datagram */
|
||||
void (*state)(ec_eoe_t *); /**< state function for the state machine */
|
||||
struct net_device *dev; /**< net_device for virtual ethernet device */
|
||||
struct net_device_stats stats; /**< device statistics */
|
||||
|
||||
327
master/fsm.c
327
master/fsm.c
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
||||
#define __EC_STATES__
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
#include "slave.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -57,7 +57,7 @@ struct ec_fsm
|
||||
{
|
||||
ec_master_t *master; /**< master the FSM runs on */
|
||||
ec_slave_t *slave; /**< slave the FSM runs on */
|
||||
ec_command_t command; /**< command used in the state machine */
|
||||
ec_datagram_t datagram; /**< datagram used in the state machine */
|
||||
|
||||
void (*master_state)(ec_fsm_t *); /**< master state function */
|
||||
unsigned int master_slaves_responding; /**< number of responding slaves */
|
||||
|
||||
@@ -72,11 +72,11 @@
|
||||
/** size of an EtherCAT frame header */
|
||||
#define EC_FRAME_HEADER_SIZE 2
|
||||
|
||||
/** size of an EtherCAT command header */
|
||||
#define EC_COMMAND_HEADER_SIZE 10
|
||||
/** size of an EtherCAT datagram header */
|
||||
#define EC_DATAGRAM_HEADER_SIZE 10
|
||||
|
||||
/** size of an EtherCAT command footer */
|
||||
#define EC_COMMAND_FOOTER_SIZE 2
|
||||
/** size of an EtherCAT datagram footer */
|
||||
#define EC_DATAGRAM_FOOTER_SIZE 2
|
||||
|
||||
/** size of a sync manager configuration page */
|
||||
#define EC_SYNC_SIZE 8
|
||||
@@ -84,9 +84,9 @@
|
||||
/** size of an FMMU configuration page */
|
||||
#define EC_FMMU_SIZE 16
|
||||
|
||||
/** resulting maximum data size of a single command in a frame */
|
||||
/** resulting maximum data size of a single datagram in a frame */
|
||||
#define EC_MAX_DATA_SIZE (ETH_DATA_LEN - EC_FRAME_HEADER_SIZE \
|
||||
- EC_COMMAND_HEADER_SIZE - EC_COMMAND_FOOTER_SIZE)
|
||||
- EC_DATAGRAM_HEADER_SIZE - EC_DATAGRAM_FOOTER_SIZE)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -178,7 +178,7 @@ extern void ec_print_states(uint8_t);
|
||||
|
||||
/**
|
||||
Code - Message pair.
|
||||
Some EtherCAT commands support reading a status code to display a certain
|
||||
Some EtherCAT datagrams support reading a status code to display a certain
|
||||
message. This type allows to map a code to a message string.
|
||||
*/
|
||||
|
||||
|
||||
@@ -42,18 +42,18 @@
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "mailbox.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
#include "master.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prepares a mailbox-send command.
|
||||
\return pointer to mailbox command data
|
||||
Prepares a mailbox-send datagram.
|
||||
\return pointer to mailbox datagram data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command, /**< command */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
uint8_t type, /**< mailbox protocol */
|
||||
size_t size /**< size of the data */
|
||||
)
|
||||
@@ -72,32 +72,32 @@ uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
slave->sii_rx_mailbox_offset,
|
||||
slave->sii_rx_mailbox_size))
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
slave->sii_rx_mailbox_offset,
|
||||
slave->sii_rx_mailbox_size))
|
||||
return NULL;
|
||||
|
||||
EC_WRITE_U16(command->data, size); // mailbox service data length
|
||||
EC_WRITE_U16(command->data + 2, slave->station_address); // station address
|
||||
EC_WRITE_U8 (command->data + 4, 0x00); // channel & priority
|
||||
EC_WRITE_U8 (command->data + 5, type); // underlying protocol type
|
||||
EC_WRITE_U16(datagram->data, size); // mailbox service data length
|
||||
EC_WRITE_U16(datagram->data + 2, slave->station_address); // station addr.
|
||||
EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
|
||||
EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
|
||||
|
||||
return command->data + 6;
|
||||
return datagram->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prepares a command for checking the mailbox state.
|
||||
Prepares a datagram for checking the mailbox state.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command /**< command */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
)
|
||||
{
|
||||
// FIXME: second sync manager?
|
||||
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x808, 8))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -106,29 +106,29 @@ int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Processes a mailbox state checking command.
|
||||
Processes a mailbox state checking datagram.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_check(const ec_command_t *command /**< command */)
|
||||
int ec_slave_mbox_check(const ec_datagram_t *datagram /**< datagram */)
|
||||
{
|
||||
return EC_READ_U8(command->data + 5) & 8 ? 1 : 0;
|
||||
return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prepares a command to fetch mailbox data.
|
||||
Prepares a datagram to fetch mailbox data.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command /**< command */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
)
|
||||
{
|
||||
if (ec_command_nprd(command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size)) return -1;
|
||||
if (ec_datagram_nprd(datagram, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -140,64 +140,64 @@ int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command, /**< command */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
uint8_t type, /**< expected mailbox protocol */
|
||||
size_t *size /**< size of the received data */
|
||||
)
|
||||
{
|
||||
size_t data_size;
|
||||
|
||||
if ((EC_READ_U8(command->data + 5) & 0x0F) != type) {
|
||||
if ((EC_READ_U8(datagram->data + 5) & 0x0F) != type) {
|
||||
EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at"
|
||||
" slave %i!\n", EC_READ_U8(command->data + 5), type,
|
||||
" slave %i!\n", EC_READ_U8(datagram->data + 5), type,
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((data_size = EC_READ_U16(command->data)) >
|
||||
if ((data_size = EC_READ_U16(datagram->data)) >
|
||||
slave->sii_tx_mailbox_size - 6) {
|
||||
EC_ERR("Currupt mailbox response detected!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*size = data_size;
|
||||
return command->data + 6;
|
||||
return datagram->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sends a mailbox command and waits for its reception.
|
||||
Sends a mailbox datagram and waits for its reception.
|
||||
\return pointer to the received data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command, /**< command */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
size_t *size /**< size of the received data */
|
||||
)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
type = EC_READ_U8(command->data + 5);
|
||||
type = EC_READ_U8(datagram->data + 5);
|
||||
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ec_slave_mbox_simple_receive(slave, command, type, size);
|
||||
return ec_slave_mbox_simple_receive(slave, datagram, type, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Waits for the reception of a mailbox command.
|
||||
Waits for the reception of a mailbox datagram.
|
||||
\return pointer to the received data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
|
||||
ec_command_t *command, /**< command */
|
||||
ec_datagram_t *datagram, /**< datagram */
|
||||
uint8_t type, /**< expected protocol */
|
||||
size_t *size /**< received data size */
|
||||
)
|
||||
@@ -209,8 +209,8 @@ uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (ec_slave_mbox_prepare_check(slave, command)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_slave_mbox_prepare_check(slave, datagram)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
@@ -218,7 +218,7 @@ uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (ec_slave_mbox_check(command))
|
||||
if (ec_slave_mbox_check(datagram))
|
||||
break; // proceed with receiving data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
@@ -230,8 +230,8 @@ uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (ec_slave_mbox_prepare_fetch(slave, command)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_slave_mbox_prepare_fetch(slave, datagram)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Mailbox receiving failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
@@ -241,7 +241,7 @@ uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
|
||||
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
|
||||
/ cpu_khz));
|
||||
|
||||
return ec_slave_mbox_fetch(slave, command, type, size);
|
||||
return ec_slave_mbox_fetch(slave, datagram, type, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -45,16 +45,17 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *, ec_command_t *,
|
||||
uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *, ec_datagram_t *,
|
||||
uint8_t, size_t);
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t *, ec_command_t *);
|
||||
int ec_slave_mbox_check(const ec_command_t *);
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t *, ec_command_t *);
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t *, ec_command_t *,
|
||||
int ec_slave_mbox_prepare_check(const ec_slave_t *, ec_datagram_t *);
|
||||
int ec_slave_mbox_check(const ec_datagram_t *);
|
||||
int ec_slave_mbox_prepare_fetch(const ec_slave_t *, ec_datagram_t *);
|
||||
uint8_t *ec_slave_mbox_fetch(const ec_slave_t *, ec_datagram_t *,
|
||||
uint8_t, size_t *);
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *, ec_command_t *, size_t *);
|
||||
uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *, ec_command_t *,
|
||||
uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *, ec_datagram_t *,
|
||||
size_t *);
|
||||
uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *, ec_datagram_t *,
|
||||
uint8_t, size_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
335
master/master.c
335
master/master.c
File diff suppressed because it is too large
Load Diff
@@ -71,10 +71,10 @@ ec_master_mode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int timeouts; /**< command timeouts */
|
||||
unsigned int delayed; /**< delayed commands */
|
||||
unsigned int timeouts; /**< datagram timeouts */
|
||||
unsigned int delayed; /**< delayed datagrams */
|
||||
unsigned int corrupted; /**< corrupted frames */
|
||||
unsigned int unmatched; /**< unmatched commands */
|
||||
unsigned int unmatched; /**< unmatched datagrams */
|
||||
cycles_t t_last; /**< time of last output */
|
||||
}
|
||||
ec_stats_t;
|
||||
@@ -99,12 +99,12 @@ struct ec_master
|
||||
|
||||
ec_device_t *device; /**< EtherCAT device */
|
||||
|
||||
struct list_head command_queue; /**< command queue */
|
||||
uint8_t command_index; /**< current command index */
|
||||
struct list_head datagram_queue; /**< datagram queue */
|
||||
uint8_t datagram_index; /**< current datagram index */
|
||||
|
||||
struct list_head domains; /**< list of domains */
|
||||
|
||||
ec_command_t simple_command; /**< command structure for initialization */
|
||||
ec_datagram_t simple_datagram; /**< datagram structure for initialization */
|
||||
unsigned int timeout; /**< timeout in synchronous IO */
|
||||
|
||||
int debug_level; /**< master debug level */
|
||||
@@ -143,8 +143,8 @@ void ec_master_eoe_stop(ec_master_t *);
|
||||
|
||||
// IO
|
||||
void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
|
||||
void ec_master_queue_command(ec_master_t *, ec_command_t *);
|
||||
int ec_master_simple_io(ec_master_t *, ec_command_t *);
|
||||
void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *);
|
||||
int ec_master_simple_io(ec_master_t *, ec_datagram_t *);
|
||||
|
||||
// slave management
|
||||
int ec_master_bus_scan(ec_master_t *);
|
||||
|
||||
191
master/slave.c
191
master/slave.c
@@ -43,7 +43,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "slave.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
#include "master.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -259,38 +259,40 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
|
||||
|
||||
int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
unsigned int i;
|
||||
uint16_t dl_status;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
// read base data
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0000, 6))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Reading base data from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
slave->base_type = EC_READ_U8 (command->data);
|
||||
slave->base_revision = EC_READ_U8 (command->data + 1);
|
||||
slave->base_build = EC_READ_U16(command->data + 2);
|
||||
slave->base_fmmu_count = EC_READ_U8 (command->data + 4);
|
||||
slave->base_sync_count = EC_READ_U8 (command->data + 5);
|
||||
slave->base_type = EC_READ_U8 (datagram->data);
|
||||
slave->base_revision = EC_READ_U8 (datagram->data + 1);
|
||||
slave->base_build = EC_READ_U16(datagram->data + 2);
|
||||
slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
|
||||
slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
|
||||
|
||||
if (slave->base_fmmu_count > EC_MAX_FMMUS)
|
||||
slave->base_fmmu_count = EC_MAX_FMMUS;
|
||||
|
||||
// read data link status
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Reading DL status from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dl_status = EC_READ_U16(command->data);
|
||||
dl_status = EC_READ_U16(datagram->data);
|
||||
for (i = 0; i < 4; i++) {
|
||||
slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
|
||||
slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
|
||||
@@ -342,17 +344,18 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
||||
/**< target memory */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
// initiate read operation
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6))
|
||||
return -1;
|
||||
EC_WRITE_U8 (datagram->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(datagram->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
@@ -364,9 +367,9 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
||||
{
|
||||
udelay(10);
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
@@ -375,8 +378,8 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
||||
end = get_cycles();
|
||||
|
||||
// check for "busy bit"
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U16(command->data + 6);
|
||||
if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U16(datagram->data + 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -402,17 +405,18 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
||||
/**< target memory */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
// initiate read operation
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6))
|
||||
return -1;
|
||||
EC_WRITE_U8 (datagram->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(datagram->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
@@ -424,9 +428,9 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
||||
{
|
||||
udelay(10);
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
@@ -435,8 +439,8 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
||||
end = get_cycles();
|
||||
|
||||
// check "busy bit"
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U32(command->data + 6);
|
||||
if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U32(datagram->data + 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -462,21 +466,22 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
||||
/**< new value */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n",
|
||||
slave->ring_position, offset, value);
|
||||
|
||||
// initiate write operation
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x01); // enable write access
|
||||
EC_WRITE_U8 (command->data + 1, 0x02); // request write operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
EC_WRITE_U16(command->data + 6, value);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 8))
|
||||
return -1;
|
||||
EC_WRITE_U8 (datagram->data, 0x01); // enable write access
|
||||
EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
|
||||
EC_WRITE_U32(datagram->data + 2, offset);
|
||||
EC_WRITE_U16(datagram->data + 6, value);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("SII-write failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
@@ -488,9 +493,9 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
||||
{
|
||||
udelay(10);
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 2))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Getting SII-write status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
@@ -499,8 +504,8 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
||||
end = get_cycles();
|
||||
|
||||
// check "busy bit"
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x82) == 0)) {
|
||||
if (EC_READ_U8(command->data + 1) & 0x40) {
|
||||
if (likely((EC_READ_U8(datagram->data + 1) & 0x82) == 0)) {
|
||||
if (EC_READ_U8(datagram->data + 1) & 0x40) {
|
||||
EC_ERR("SII-write failed!\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -834,14 +839,14 @@ void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint8_t state /**< previous state */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return;
|
||||
EC_WRITE_U16(command->data, state | EC_ACK);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) return;
|
||||
EC_WRITE_U16(datagram->data, state | EC_ACK);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_WARN("Acknowledge sending failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
@@ -854,9 +859,9 @@ void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
{
|
||||
udelay(100); // wait a little bit...
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2))
|
||||
return;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
EC_WARN("Acknowledge checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
@@ -865,7 +870,7 @@ void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (likely(EC_READ_U8(command->data) == state)) {
|
||||
if (likely(EC_READ_U8(datagram->data) == state)) {
|
||||
slave->current_state = state;
|
||||
EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state,
|
||||
slave->ring_position);
|
||||
@@ -891,20 +896,20 @@ void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
uint16_t code;
|
||||
const ec_code_msg_t *al_msg;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0134, 2)) return;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2)) return;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_WARN("Failed to read AL status code on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(code = EC_READ_U16(command->data))) return;
|
||||
if (!(code = EC_READ_U16(datagram->data))) return;
|
||||
|
||||
for (al_msg = al_status_messages; al_msg->code; al_msg++) {
|
||||
if (al_msg->code == code) {
|
||||
@@ -928,16 +933,17 @@ int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint8_t state /**< new state */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
slave->requested_state = state;
|
||||
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1;
|
||||
EC_WRITE_U16(command->data, state);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2))
|
||||
return -1;
|
||||
EC_WRITE_U16(datagram->data, state);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_ERR("Failed to set state 0x%02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return -1;
|
||||
@@ -950,9 +956,9 @@ int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
{
|
||||
udelay(100); // wait a little bit
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
|
||||
EC_ERR("Failed to check state 0x%02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
@@ -961,18 +967,19 @@ int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error
|
||||
if (unlikely(EC_READ_U8(datagram->data) & 0x10)) {
|
||||
// state change error
|
||||
EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
|
||||
" (code 0x%02X)!\n", state, slave->ring_position,
|
||||
EC_READ_U8(command->data));
|
||||
slave->current_state = EC_READ_U8(command->data);
|
||||
EC_READ_U8(datagram->data));
|
||||
slave->current_state = EC_READ_U8(datagram->data);
|
||||
state = slave->current_state & 0x0F;
|
||||
ec_slave_read_al_status_code(slave);
|
||||
ec_slave_state_ack(slave, state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (likely(EC_READ_U8(command->data) == (state & 0x0F))) {
|
||||
if (likely(EC_READ_U8(datagram->data) == (state & 0x0F))) {
|
||||
slave->current_state = state;
|
||||
return 0; // state change successful
|
||||
}
|
||||
@@ -1205,44 +1212,46 @@ void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT slave */
|
||||
|
||||
int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
datagram = &slave->master->simple_datagram;
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0300, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_nprd(datagram, slave->station_address, 0x0300, 4))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_WARN("Reading CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!EC_READ_U32(command->data)) return 0; // no CRC faults
|
||||
if (!EC_READ_U32(datagram->data)) return 0; // no CRC faults
|
||||
|
||||
if (EC_READ_U8(command->data))
|
||||
if (EC_READ_U8(datagram->data))
|
||||
EC_WARN("%3i RX-error%s on slave %i, channel A.\n",
|
||||
EC_READ_U8(command->data),
|
||||
EC_READ_U8(command->data) == 1 ? "" : "s",
|
||||
EC_READ_U8(datagram->data),
|
||||
EC_READ_U8(datagram->data) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command->data + 1))
|
||||
if (EC_READ_U8(datagram->data + 1))
|
||||
EC_WARN("%3i invalid frame%s on slave %i, channel A.\n",
|
||||
EC_READ_U8(command->data + 1),
|
||||
EC_READ_U8(command->data + 1) == 1 ? "" : "s",
|
||||
EC_READ_U8(datagram->data + 1),
|
||||
EC_READ_U8(datagram->data + 1) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command->data + 2))
|
||||
if (EC_READ_U8(datagram->data + 2))
|
||||
EC_WARN("%3i RX-error%s on slave %i, channel B.\n",
|
||||
EC_READ_U8(command->data + 2),
|
||||
EC_READ_U8(command->data + 2) == 1 ? "" : "s",
|
||||
EC_READ_U8(datagram->data + 2),
|
||||
EC_READ_U8(datagram->data + 2) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command->data + 3))
|
||||
if (EC_READ_U8(datagram->data + 3))
|
||||
EC_WARN("%3i invalid frame%s on slave %i, channel B.\n",
|
||||
EC_READ_U8(command->data + 3),
|
||||
EC_READ_U8(command->data + 3) == 1 ? "" : "s",
|
||||
EC_READ_U8(datagram->data + 3),
|
||||
EC_READ_U8(datagram->data + 3) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
|
||||
// reset CRC counters
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1;
|
||||
EC_WRITE_U32(command->data, 0x00000000);
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x0300, 4))
|
||||
return -1;
|
||||
EC_WRITE_U32(datagram->data, 0x00000000);
|
||||
if (unlikely(ec_master_simple_io(slave->master, datagram))) {
|
||||
EC_WARN("Resetting CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <linux/kobject.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
#include "types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user