Renamed command structure to datagram.
This commit is contained in:
parent
4a72709aa1
commit
6fdf205382
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -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
|
|
@ -107,9 +107,9 @@ int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */
|
|||
fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
|
||||
fsm->master_validation = 0;
|
||||
|
||||
ec_command_init(&fsm->command);
|
||||
if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) {
|
||||
EC_ERR("Failed to allocate FSM command.\n");
|
||||
ec_datagram_init(&fsm->datagram);
|
||||
if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) {
|
||||
EC_ERR("Failed to allocate FSM datagram.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */
|
|||
|
||||
void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_clear(&fsm->command);
|
||||
ec_datagram_clear(&fsm->datagram);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -162,8 +162,8 @@ void ec_fsm_execute(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_master_start(ec_fsm_t *fsm)
|
||||
{
|
||||
ec_command_brd(&fsm->command, 0x0130, 2);
|
||||
ec_master_queue_command(fsm->master, &fsm->command);
|
||||
ec_datagram_brd(&fsm->datagram, 0x0130, 2);
|
||||
ec_master_queue_datagram(fsm->master, &fsm->datagram);
|
||||
fsm->master_state = ec_fsm_master_broadcast;
|
||||
}
|
||||
|
||||
|
|
@ -176,12 +176,12 @@ void ec_fsm_master_start(ec_fsm_t *fsm)
|
|||
|
||||
void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
unsigned int topology_change, states_change, i;
|
||||
ec_slave_t *slave;
|
||||
ec_master_t *master = fsm->master;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED) {
|
||||
if (datagram->state != EC_CMD_RECEIVED) {
|
||||
if (!master->device->link_state) {
|
||||
fsm->master_slaves_responding = 0;
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
|
|
@ -193,12 +193,12 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
topology_change = (command->working_counter !=
|
||||
topology_change = (datagram->working_counter !=
|
||||
fsm->master_slaves_responding);
|
||||
states_change = (EC_READ_U8(command->data) != fsm->master_slave_states);
|
||||
states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states);
|
||||
|
||||
fsm->master_slave_states = EC_READ_U8(command->data);
|
||||
fsm->master_slaves_responding = command->working_counter;
|
||||
fsm->master_slave_states = EC_READ_U8(datagram->data);
|
||||
fsm->master_slaves_responding = datagram->working_counter;
|
||||
|
||||
if (topology_change) {
|
||||
EC_INFO("%i slave%s responding.\n",
|
||||
|
|
@ -272,8 +272,8 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
// fetch state from each slave
|
||||
fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
|
||||
ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(master, &fsm->command);
|
||||
ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_datagram(master, &fsm->datagram);
|
||||
fsm->master_state = ec_fsm_master_states;
|
||||
}
|
||||
|
||||
|
|
@ -293,8 +293,9 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm
|
|||
if (slave->list.next != &master->slaves) {
|
||||
// process next slave
|
||||
fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
|
||||
ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(master, &fsm->command);
|
||||
ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address,
|
||||
0x0130, 2);
|
||||
ec_master_queue_datagram(master, &fsm->datagram);
|
||||
fsm->master_state = ec_fsm_master_states;
|
||||
return;
|
||||
}
|
||||
|
|
@ -331,17 +332,17 @@ void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm
|
|||
void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
uint8_t new_state;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED) {
|
||||
if (datagram->state != EC_CMD_RECEIVED) {
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// did the slave not respond to its station address?
|
||||
if (command->working_counter != 1) {
|
||||
if (datagram->working_counter != 1) {
|
||||
if (slave->online) {
|
||||
slave->online = 0;
|
||||
EC_INFO("Slave %i: offline.\n", slave->ring_position);
|
||||
|
|
@ -351,7 +352,7 @@ void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// slave responded
|
||||
new_state = EC_READ_U8(command->data);
|
||||
new_state = EC_READ_U8(datagram->data);
|
||||
if (!slave->online) { // slave was offline before
|
||||
slave->online = 1;
|
||||
slave->error_flag = 0; // clear error flag
|
||||
|
|
@ -535,7 +536,7 @@ void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
while (fsm->slave->online) {
|
||||
if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
|
||||
|
|
@ -550,9 +551,9 @@ void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */)
|
|||
EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
|
||||
|
||||
// write station address
|
||||
ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
|
||||
EC_WRITE_U16(command->data, fsm->slave->station_address);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
|
||||
EC_WRITE_U16(datagram->data, fsm->slave->station_address);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->master_state = ec_fsm_master_address;
|
||||
}
|
||||
|
||||
|
|
@ -566,9 +567,9 @@ void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */)
|
|||
void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
EC_ERR("Failed to write station address on slave %i.\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
|
@ -752,12 +753,12 @@ void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
// write station address
|
||||
ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
|
||||
EC_WRITE_U16(command->data, fsm->slave->station_address);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
|
||||
EC_WRITE_U16(datagram->data, fsm->slave->station_address);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_read_state;
|
||||
}
|
||||
|
||||
|
|
@ -769,9 +770,9 @@ void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to write station address of slave %i.\n",
|
||||
|
|
@ -780,8 +781,8 @@ void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// Read AL state
|
||||
ec_command_nprd(command, fsm->slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_read_base;
|
||||
}
|
||||
|
||||
|
|
@ -793,10 +794,10 @@ void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to read AL state of slave %i.\n",
|
||||
|
|
@ -804,7 +805,7 @@ void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
slave->current_state = EC_READ_U8(command->data);
|
||||
slave->current_state = EC_READ_U8(datagram->data);
|
||||
if (slave->current_state & EC_ACK) {
|
||||
EC_WARN("Slave %i has state error bit set (0x%02X)!\n",
|
||||
slave->ring_position, slave->current_state);
|
||||
|
|
@ -812,8 +813,8 @@ void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// read base data
|
||||
ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_read_dl;
|
||||
}
|
||||
|
||||
|
|
@ -825,10 +826,10 @@ void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to read base data of slave %i.\n",
|
||||
|
|
@ -836,18 +837,18 @@ void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
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
|
||||
ec_command_nprd(command, slave->station_address, 0x0110, 2);
|
||||
ec_master_queue_command(slave->master, command);
|
||||
ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2);
|
||||
ec_master_queue_datagram(slave->master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_eeprom_size;
|
||||
}
|
||||
|
||||
|
|
@ -860,12 +861,12 @@ void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
uint16_t dl_status;
|
||||
unsigned int i;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to read DL status of slave %i.\n",
|
||||
|
|
@ -873,7 +874,7 @@ void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -1068,7 +1069,7 @@ void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */)
|
|||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = fsm->master;
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
fsm->change_state(fsm); // execute state change state machine
|
||||
|
||||
|
|
@ -1101,10 +1102,10 @@ void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// reset FMMUs
|
||||
ec_command_npwr(command, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
ec_master_queue_command(master, command);
|
||||
ec_datagram_npwr(datagram, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_sync;
|
||||
}
|
||||
|
||||
|
|
@ -1117,13 +1118,13 @@ void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
unsigned int j;
|
||||
const ec_sync_t *sync;
|
||||
ec_eeprom_sync_t *eeprom_sync, mbox_sync;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to reset FMMUs of slave %i.\n",
|
||||
|
|
@ -1138,15 +1139,15 @@ void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// configure sync managers
|
||||
ec_command_npwr(command, slave->station_address, 0x0800,
|
||||
EC_SYNC_SIZE * slave->base_sync_count);
|
||||
memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
ec_datagram_npwr(datagram, slave->station_address, 0x0800,
|
||||
EC_SYNC_SIZE * slave->base_sync_count);
|
||||
memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
|
||||
// known slave type, take type's SM information
|
||||
if (slave->type) {
|
||||
for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
|
||||
sync = slave->type->sync_managers[j];
|
||||
ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j);
|
||||
ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1163,7 +1164,7 @@ void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
return;
|
||||
}
|
||||
ec_eeprom_sync_config(eeprom_sync,
|
||||
command->data + EC_SYNC_SIZE
|
||||
datagram->data + EC_SYNC_SIZE
|
||||
* eeprom_sync->index);
|
||||
}
|
||||
}
|
||||
|
|
@ -1175,7 +1176,7 @@ void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
mbox_sync.length = slave->sii_rx_mailbox_size;
|
||||
mbox_sync.control_register = 0x26;
|
||||
mbox_sync.enable = 1;
|
||||
ec_eeprom_sync_config(&mbox_sync, command->data);
|
||||
ec_eeprom_sync_config(&mbox_sync, datagram->data);
|
||||
|
||||
mbox_sync.physical_start_address =
|
||||
slave->sii_tx_mailbox_offset;
|
||||
|
|
@ -1183,14 +1184,14 @@ void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
mbox_sync.control_register = 0x22;
|
||||
mbox_sync.enable = 1;
|
||||
ec_eeprom_sync_config(&mbox_sync,
|
||||
command->data + EC_SYNC_SIZE);
|
||||
datagram->data + EC_SYNC_SIZE);
|
||||
}
|
||||
|
||||
EC_INFO("Mailbox configured for unknown slave %i\n",
|
||||
slave->ring_position);
|
||||
}
|
||||
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_preop;
|
||||
}
|
||||
|
||||
|
|
@ -1203,10 +1204,10 @@ void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to set sync managers on slave %i.\n",
|
||||
|
|
@ -1231,7 +1232,7 @@ void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
|||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_master_t *master = fsm->master;
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
unsigned int j;
|
||||
|
||||
fsm->change_state(fsm); // execute state change state machine
|
||||
|
|
@ -1263,15 +1264,15 @@ void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// configure FMMUs
|
||||
ec_command_npwr(command, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
ec_fmmu_config(&slave->fmmus[j], slave,
|
||||
command->data + EC_FMMU_SIZE * j);
|
||||
datagram->data + EC_FMMU_SIZE * j);
|
||||
}
|
||||
|
||||
ec_master_queue_command(master, command);
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
fsm->slave_state = ec_fsm_slave_saveop;
|
||||
}
|
||||
|
||||
|
|
@ -1284,10 +1285,10 @@ void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED ||
|
||||
command->working_counter != 1)) {
|
||||
if (fsm->slave->base_fmmu_count && (datagram->state != EC_CMD_RECEIVED ||
|
||||
datagram->working_counter != 1)) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
EC_ERR("Failed to set FMMUs on slave %i.\n",
|
||||
|
|
@ -1379,20 +1380,20 @@ void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
// initiate read operation
|
||||
if (fsm->sii_mode) {
|
||||
ec_command_npwr(command, fsm->slave->station_address, 0x502, 4);
|
||||
ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
|
||||
}
|
||||
else {
|
||||
ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4);
|
||||
ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4);
|
||||
}
|
||||
|
||||
EC_WRITE_U8 (command->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U16(command->data + 2, fsm->sii_offset);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
EC_WRITE_U8 (datagram->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U16(datagram->data + 2, fsm->sii_offset);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->sii_state = ec_fsm_sii_read_check;
|
||||
}
|
||||
|
||||
|
|
@ -1400,30 +1401,30 @@ void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
/**
|
||||
SII state: READ_CHECK.
|
||||
Checks, if the SII-read-command has been sent and issues a fetch command.
|
||||
Checks, if the SII-read-datagram has been sent and issues a fetch datagram.
|
||||
*/
|
||||
|
||||
void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of read command failed.\n");
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of read datagram failed.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->sii_start = get_cycles();
|
||||
|
||||
// issue check/fetch command
|
||||
// issue check/fetch datagram
|
||||
if (fsm->sii_mode) {
|
||||
ec_command_nprd(command, fsm->slave->station_address, 0x502, 10);
|
||||
ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
|
||||
}
|
||||
else {
|
||||
ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10);
|
||||
ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
|
||||
}
|
||||
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->sii_state = ec_fsm_sii_read_fetch;
|
||||
}
|
||||
|
||||
|
|
@ -1431,55 +1432,55 @@ void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
/**
|
||||
SII state: READ_FETCH.
|
||||
Fetches the result of an SII-read command.
|
||||
Fetches the result of an SII-read datagram.
|
||||
*/
|
||||
|
||||
void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of check/fetch command failed.\n");
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of check/fetch datagram failed.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
return;
|
||||
}
|
||||
|
||||
// check "busy bit"
|
||||
if (EC_READ_U8(command->data + 1) & 0x81) {
|
||||
if (EC_READ_U8(datagram->data + 1) & 0x81) {
|
||||
// still busy... timeout?
|
||||
if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
|
||||
EC_ERR("SII: Timeout.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
#if 0
|
||||
EC_DBG("SII busy: %02X %02X %02X %02X\n",
|
||||
EC_READ_U8(command->data + 0),
|
||||
EC_READ_U8(command->data + 1),
|
||||
EC_READ_U8(command->data + 2),
|
||||
EC_READ_U8(command->data + 3));
|
||||
EC_READ_U8(datagram->data + 0),
|
||||
EC_READ_U8(datagram->data + 1),
|
||||
EC_READ_U8(datagram->data + 2),
|
||||
EC_READ_U8(datagram->data + 3));
|
||||
#endif
|
||||
}
|
||||
|
||||
// issue check/fetch command again
|
||||
// issue check/fetch datagram again
|
||||
if (fsm->sii_mode) {
|
||||
ec_command_nprd(command, fsm->slave->station_address, 0x502, 10);
|
||||
ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
|
||||
}
|
||||
else {
|
||||
ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10);
|
||||
ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
|
||||
}
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
|
||||
EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1),
|
||||
EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3),
|
||||
EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7),
|
||||
EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9));
|
||||
EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
|
||||
EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
|
||||
EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
|
||||
EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
|
||||
#endif
|
||||
|
||||
// SII value received.
|
||||
memcpy(fsm->sii_value, command->data + 6, 4);
|
||||
memcpy(fsm->sii_value, datagram->data + 6, 4);
|
||||
fsm->sii_state = ec_fsm_sii_end;
|
||||
}
|
||||
|
||||
|
|
@ -1492,15 +1493,15 @@ void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
// initiate write operation
|
||||
ec_command_npwr(command, fsm->slave->station_address, 0x502, 8);
|
||||
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, fsm->sii_offset);
|
||||
memcpy(command->data + 6, fsm->sii_value, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
|
||||
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, fsm->sii_offset);
|
||||
memcpy(datagram->data + 6, fsm->sii_value, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->sii_state = ec_fsm_sii_write_check;
|
||||
}
|
||||
|
||||
|
|
@ -1512,19 +1513,19 @@ void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of write command failed.\n");
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of write datagram failed.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->sii_start = get_cycles();
|
||||
|
||||
// issue check/fetch command
|
||||
ec_command_nprd(command, fsm->slave->station_address, 0x502, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
// issue check/fetch datagram
|
||||
ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->sii_state = ec_fsm_sii_write_check2;
|
||||
}
|
||||
|
||||
|
|
@ -1536,25 +1537,25 @@ void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of write check command failed.\n");
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
EC_ERR("SII: Reception of write check datagram failed.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (EC_READ_U8(command->data + 1) & 0x82) {
|
||||
if (EC_READ_U8(datagram->data + 1) & 0x82) {
|
||||
// still busy... timeout?
|
||||
if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
|
||||
EC_ERR("SII: Write timeout.\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
}
|
||||
|
||||
// issue check/fetch command again
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
// issue check/fetch datagram again
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
}
|
||||
else if (EC_READ_U8(command->data + 1) & 0x40) {
|
||||
else if (EC_READ_U8(datagram->data + 1) & 0x40) {
|
||||
EC_ERR("SII: Write operation failed!\n");
|
||||
fsm->sii_state = ec_fsm_sii_error;
|
||||
}
|
||||
|
|
@ -1595,13 +1596,13 @@ void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
// write new state to slave
|
||||
ec_command_npwr(command, slave->station_address, 0x0120, 2);
|
||||
EC_WRITE_U16(command->data, fsm->change_new);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
|
||||
EC_WRITE_U16(datagram->data, fsm->change_new);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->change_state = ec_fsm_change_check;
|
||||
}
|
||||
|
||||
|
|
@ -1613,17 +1614,17 @@ void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED) {
|
||||
if (datagram->state != EC_CMD_RECEIVED) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Failed to send state command to slave %i!\n",
|
||||
EC_ERR("Failed to send state datagram to slave %i!\n",
|
||||
fsm->slave->ring_position);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command->working_counter != 1) {
|
||||
if (datagram->working_counter != 1) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not"
|
||||
" respond.\n", fsm->change_new, fsm->slave->ring_position);
|
||||
|
|
@ -1633,8 +1634,8 @@ void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */)
|
|||
fsm->change_start = get_cycles();
|
||||
|
||||
// read AL status from slave
|
||||
ec_command_nprd(command, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->change_state = ec_fsm_change_status;
|
||||
}
|
||||
|
||||
|
|
@ -1646,17 +1647,17 @@ void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Failed to check state 0x%02X on slave %i.\n",
|
||||
fsm->change_new, slave->ring_position);
|
||||
return;
|
||||
}
|
||||
|
||||
slave->current_state = EC_READ_U8(command->data);
|
||||
slave->current_state = EC_READ_U8(datagram->data);
|
||||
|
||||
if (slave->current_state == fsm->change_new) {
|
||||
// state has been set successfully
|
||||
|
|
@ -1671,8 +1672,8 @@ void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */)
|
|||
" (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
|
||||
slave->current_state);
|
||||
// fetch AL status error code
|
||||
ec_command_nprd(command, slave->station_address, 0x0134, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->change_state = ec_fsm_change_code;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1686,8 +1687,8 @@ void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// still old state: check again
|
||||
ec_command_nprd(command, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1724,18 +1725,18 @@ const ec_code_msg_t al_status_messages[] = {
|
|||
|
||||
void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
uint32_t code;
|
||||
const ec_code_msg_t *al_msg;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Reception of AL status code command failed.\n");
|
||||
EC_ERR("Reception of AL status code datagram failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((code = EC_READ_U16(command->data))) {
|
||||
if ((code = EC_READ_U16(datagram->data))) {
|
||||
for (al_msg = al_status_messages; al_msg->code; al_msg++) {
|
||||
if (al_msg->code != code) continue;
|
||||
EC_ERR("AL status message 0x%04X: \"%s\".\n",
|
||||
|
|
@ -1747,9 +1748,9 @@ void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
// acknowledge "old" slave state
|
||||
ec_command_npwr(command, slave->station_address, 0x0120, 2);
|
||||
EC_WRITE_U16(command->data, slave->current_state);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
|
||||
EC_WRITE_U16(datagram->data, slave->current_state);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->change_state = ec_fsm_change_ack;
|
||||
}
|
||||
|
||||
|
|
@ -1761,18 +1762,18 @@ void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Reception of state ack command failed.\n");
|
||||
EC_ERR("Reception of state ack datagram failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// read new AL status
|
||||
ec_command_nprd(command, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_command(fsm->master, command);
|
||||
ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
|
||||
ec_master_queue_datagram(fsm->master, datagram);
|
||||
fsm->change_state = ec_fsm_change_ack2;
|
||||
}
|
||||
|
||||
|
|
@ -1785,16 +1786,16 @@ void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
ec_command_t *command = &fsm->command;
|
||||
ec_datagram_t *datagram = &fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
|
||||
if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
EC_ERR("Reception of state ack check command failed.\n");
|
||||
EC_ERR("Reception of state ack check datagram failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
slave->current_state = EC_READ_U8(command->data);
|
||||
slave->current_state = EC_READ_U8(datagram->data);
|
||||
|
||||
if (slave->current_state == fsm->change_new) {
|
||||
fsm->change_state = ec_fsm_change_error;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -50,7 +50,7 @@
|
|||
#include "slave.h"
|
||||
#include "types.h"
|
||||
#include "device.h"
|
||||
#include "command.h"
|
||||
#include "datagram.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -110,10 +110,10 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
master->device = NULL;
|
||||
master->reserved = 0;
|
||||
INIT_LIST_HEAD(&master->slaves);
|
||||
INIT_LIST_HEAD(&master->command_queue);
|
||||
INIT_LIST_HEAD(&master->datagram_queue);
|
||||
INIT_LIST_HEAD(&master->domains);
|
||||
INIT_LIST_HEAD(&master->eoe_handlers);
|
||||
ec_command_init(&master->simple_command);
|
||||
ec_datagram_init(&master->simple_datagram);
|
||||
INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master);
|
||||
init_timer(&master->eoe_timer);
|
||||
master->eoe_timer.function = ec_master_eoe_run;
|
||||
|
|
@ -171,7 +171,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
/**
|
||||
Master destructor.
|
||||
Removes all pending commands, clears the slave list, clears all domains
|
||||
Removes all pending datagrams, clears the slave list, clears all domains
|
||||
and frees the device.
|
||||
*/
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
|
||||
ec_master_reset(master);
|
||||
ec_fsm_clear(&master->fsm);
|
||||
ec_command_clear(&master->simple_command);
|
||||
ec_datagram_clear(&master->simple_datagram);
|
||||
destroy_workqueue(master->workqueue);
|
||||
|
||||
// clear EoE objects
|
||||
|
|
@ -212,17 +212,18 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
|
||||
void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_command_t *command, *next_c;
|
||||
ec_datagram_t *datagram, *next_c;
|
||||
ec_domain_t *domain, *next_d;
|
||||
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_freerun_stop(master);
|
||||
ec_master_clear_slaves(master);
|
||||
|
||||
// empty command queue
|
||||
list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
|
||||
list_del_init(&command->queue);
|
||||
command->state = EC_CMD_ERROR;
|
||||
// empty datagram queue
|
||||
list_for_each_entry_safe(datagram, next_c,
|
||||
&master->datagram_queue, queue) {
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_CMD_ERROR;
|
||||
}
|
||||
|
||||
// clear domains
|
||||
|
|
@ -232,7 +233,7 @@ void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
|
|||
kobject_put(&domain->kobj);
|
||||
}
|
||||
|
||||
master->command_index = 0;
|
||||
master->datagram_index = 0;
|
||||
master->debug_level = 0;
|
||||
master->timeout = 500; // 500us
|
||||
|
||||
|
|
@ -274,97 +275,97 @@ void ec_master_clear_slaves(ec_master_t *master)
|
|||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Places a command in the command queue.
|
||||
Places a datagram in the datagram queue.
|
||||
*/
|
||||
|
||||
void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */
|
||||
ec_command_t *command /**< command */
|
||||
)
|
||||
void ec_master_queue_datagram(ec_master_t *master, /**< EtherCAT master */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
)
|
||||
{
|
||||
ec_command_t *queued_command;
|
||||
ec_datagram_t *queued_datagram;
|
||||
|
||||
// check, if the command is already queued
|
||||
list_for_each_entry(queued_command, &master->command_queue, queue) {
|
||||
if (queued_command == command) {
|
||||
command->state = EC_CMD_QUEUED;
|
||||
// check, if the datagram is already queued
|
||||
list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
|
||||
if (queued_datagram == datagram) {
|
||||
datagram->state = EC_CMD_QUEUED;
|
||||
if (unlikely(master->debug_level))
|
||||
EC_WARN("command already queued.\n");
|
||||
EC_WARN("datagram already queued.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
list_add_tail(&command->queue, &master->command_queue);
|
||||
command->state = EC_CMD_QUEUED;
|
||||
list_add_tail(&datagram->queue, &master->datagram_queue);
|
||||
datagram->state = EC_CMD_QUEUED;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sends the commands in the queue.
|
||||
Sends the datagrams in the queue.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
|
||||
void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
size_t command_size;
|
||||
ec_datagram_t *datagram;
|
||||
size_t datagram_size;
|
||||
uint8_t *frame_data, *cur_data;
|
||||
void *follows_word;
|
||||
cycles_t t_start, t_end;
|
||||
unsigned int frame_count, more_commands_waiting;
|
||||
unsigned int frame_count, more_datagrams_waiting;
|
||||
|
||||
frame_count = 0;
|
||||
t_start = get_cycles();
|
||||
|
||||
if (unlikely(master->debug_level > 0))
|
||||
EC_DBG("ec_master_send_commands\n");
|
||||
EC_DBG("ec_master_send_datagrams\n");
|
||||
|
||||
do {
|
||||
// fetch pointer to transmit socket buffer
|
||||
frame_data = ec_device_tx_data(master->device);
|
||||
cur_data = frame_data + EC_FRAME_HEADER_SIZE;
|
||||
follows_word = NULL;
|
||||
more_commands_waiting = 0;
|
||||
more_datagrams_waiting = 0;
|
||||
|
||||
// fill current frame with commands
|
||||
list_for_each_entry(command, &master->command_queue, queue) {
|
||||
if (command->state != EC_CMD_QUEUED) continue;
|
||||
// fill current frame with datagrams
|
||||
list_for_each_entry(datagram, &master->datagram_queue, queue) {
|
||||
if (datagram->state != EC_CMD_QUEUED) continue;
|
||||
|
||||
// does the current command fit in the frame?
|
||||
command_size = EC_COMMAND_HEADER_SIZE + command->data_size
|
||||
+ EC_COMMAND_FOOTER_SIZE;
|
||||
if (cur_data - frame_data + command_size > ETH_DATA_LEN) {
|
||||
more_commands_waiting = 1;
|
||||
// does the current datagram fit in the frame?
|
||||
datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size
|
||||
+ EC_DATAGRAM_FOOTER_SIZE;
|
||||
if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) {
|
||||
more_datagrams_waiting = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
command->state = EC_CMD_SENT;
|
||||
command->t_sent = t_start;
|
||||
command->index = master->command_index++;
|
||||
datagram->state = EC_CMD_SENT;
|
||||
datagram->t_sent = t_start;
|
||||
datagram->index = master->datagram_index++;
|
||||
|
||||
if (unlikely(master->debug_level > 0))
|
||||
EC_DBG("adding command 0x%02X\n", command->index);
|
||||
EC_DBG("adding datagram 0x%02X\n", datagram->index);
|
||||
|
||||
// set "command following" flag in previous frame
|
||||
// set "datagram following" flag in previous frame
|
||||
if (follows_word)
|
||||
EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000);
|
||||
|
||||
// EtherCAT command header
|
||||
EC_WRITE_U8 (cur_data, command->type);
|
||||
EC_WRITE_U8 (cur_data + 1, command->index);
|
||||
EC_WRITE_U32(cur_data + 2, command->address.logical);
|
||||
EC_WRITE_U16(cur_data + 6, command->data_size & 0x7FF);
|
||||
// EtherCAT datagram header
|
||||
EC_WRITE_U8 (cur_data, datagram->type);
|
||||
EC_WRITE_U8 (cur_data + 1, datagram->index);
|
||||
EC_WRITE_U32(cur_data + 2, datagram->address.logical);
|
||||
EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF);
|
||||
EC_WRITE_U16(cur_data + 8, 0x0000);
|
||||
follows_word = cur_data + 6;
|
||||
cur_data += EC_COMMAND_HEADER_SIZE;
|
||||
cur_data += EC_DATAGRAM_HEADER_SIZE;
|
||||
|
||||
// EtherCAT command data
|
||||
memcpy(cur_data, command->data, command->data_size);
|
||||
cur_data += command->data_size;
|
||||
// EtherCAT datagram data
|
||||
memcpy(cur_data, datagram->data, datagram->data_size);
|
||||
cur_data += datagram->data_size;
|
||||
|
||||
// EtherCAT command footer
|
||||
// EtherCAT datagram footer
|
||||
EC_WRITE_U16(cur_data, 0x0000); // reset working counter
|
||||
cur_data += EC_COMMAND_FOOTER_SIZE;
|
||||
cur_data += EC_DATAGRAM_FOOTER_SIZE;
|
||||
}
|
||||
|
||||
if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) {
|
||||
|
|
@ -388,11 +389,11 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
|
|||
ec_device_send(master->device, cur_data - frame_data);
|
||||
frame_count++;
|
||||
}
|
||||
while (more_commands_waiting);
|
||||
while (more_datagrams_waiting);
|
||||
|
||||
if (unlikely(master->debug_level > 0)) {
|
||||
t_end = get_cycles();
|
||||
EC_DBG("ec_master_send_commands sent %i frames in %ius.\n",
|
||||
EC_DBG("ec_master_send_datagrams sent %i frames in %ius.\n",
|
||||
frame_count, (u32) (t_end - t_start) * 1000 / cpu_khz);
|
||||
}
|
||||
}
|
||||
|
|
@ -411,10 +412,10 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT master */
|
|||
)
|
||||
{
|
||||
size_t frame_size, data_size;
|
||||
uint8_t command_type, command_index;
|
||||
uint8_t datagram_type, datagram_index;
|
||||
unsigned int cmd_follows, matched;
|
||||
const uint8_t *cur_data;
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
if (unlikely(size < EC_FRAME_HEADER_SIZE)) {
|
||||
master->stats.corrupted++;
|
||||
|
|
@ -436,64 +437,64 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
cmd_follows = 1;
|
||||
while (cmd_follows) {
|
||||
// process command header
|
||||
command_type = EC_READ_U8 (cur_data);
|
||||
command_index = EC_READ_U8 (cur_data + 1);
|
||||
data_size = EC_READ_U16(cur_data + 6) & 0x07FF;
|
||||
cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000;
|
||||
cur_data += EC_COMMAND_HEADER_SIZE;
|
||||
// process datagram header
|
||||
datagram_type = EC_READ_U8 (cur_data);
|
||||
datagram_index = EC_READ_U8 (cur_data + 1);
|
||||
data_size = EC_READ_U16(cur_data + 6) & 0x07FF;
|
||||
cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000;
|
||||
cur_data += EC_DATAGRAM_HEADER_SIZE;
|
||||
|
||||
if (unlikely(cur_data - frame_data
|
||||
+ data_size + EC_COMMAND_FOOTER_SIZE > size)) {
|
||||
+ data_size + EC_DATAGRAM_FOOTER_SIZE > size)) {
|
||||
master->stats.corrupted++;
|
||||
ec_master_output_stats(master);
|
||||
return;
|
||||
}
|
||||
|
||||
// search for matching command in the queue
|
||||
// search for matching datagram in the queue
|
||||
matched = 0;
|
||||
list_for_each_entry(command, &master->command_queue, queue) {
|
||||
if (command->state == EC_CMD_SENT
|
||||
&& command->type == command_type
|
||||
&& command->index == command_index
|
||||
&& command->data_size == data_size) {
|
||||
list_for_each_entry(datagram, &master->datagram_queue, queue) {
|
||||
if (datagram->state == EC_CMD_SENT
|
||||
&& datagram->type == datagram_type
|
||||
&& datagram->index == datagram_index
|
||||
&& datagram->data_size == data_size) {
|
||||
matched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no matching command was found
|
||||
// no matching datagram was found
|
||||
if (!matched) {
|
||||
master->stats.unmatched++;
|
||||
ec_master_output_stats(master);
|
||||
cur_data += data_size + EC_COMMAND_FOOTER_SIZE;
|
||||
cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy received data in the command memory
|
||||
memcpy(command->data, cur_data, data_size);
|
||||
// copy received data in the datagram memory
|
||||
memcpy(datagram->data, cur_data, data_size);
|
||||
cur_data += data_size;
|
||||
|
||||
// set the command's working counter
|
||||
command->working_counter = EC_READ_U16(cur_data);
|
||||
cur_data += EC_COMMAND_FOOTER_SIZE;
|
||||
// set the datagram's working counter
|
||||
datagram->working_counter = EC_READ_U16(cur_data);
|
||||
cur_data += EC_DATAGRAM_FOOTER_SIZE;
|
||||
|
||||
// dequeue the received command
|
||||
command->state = EC_CMD_RECEIVED;
|
||||
list_del_init(&command->queue);
|
||||
// dequeue the received datagram
|
||||
datagram->state = EC_CMD_RECEIVED;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sends a single command and waits for its reception.
|
||||
If the slave doesn't respond, the command is sent again.
|
||||
Sends a single datagram and waits for its reception.
|
||||
If the slave doesn't respond, the datagram is sent again.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */
|
||||
ec_command_t *command /**< command */
|
||||
ec_datagram_t *datagram /**< datagram */
|
||||
)
|
||||
{
|
||||
unsigned int response_tries_left;
|
||||
|
|
@ -502,19 +503,19 @@ int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
while (1)
|
||||
{
|
||||
ec_master_queue_command(master, command);
|
||||
ec_master_queue_datagram(master, datagram);
|
||||
ecrt_master_sync_io(master);
|
||||
|
||||
if (command->state == EC_CMD_RECEIVED) {
|
||||
if (likely(command->working_counter))
|
||||
if (datagram->state == EC_CMD_RECEIVED) {
|
||||
if (likely(datagram->working_counter))
|
||||
return 0;
|
||||
}
|
||||
else if (command->state == EC_CMD_TIMEOUT) {
|
||||
else if (datagram->state == EC_CMD_TIMEOUT) {
|
||||
EC_ERR("Simple-IO TIMEOUT!\n");
|
||||
return -1;
|
||||
}
|
||||
else if (command->state == EC_CMD_ERROR) {
|
||||
EC_ERR("Simple-IO command error!\n");
|
||||
else if (datagram->state == EC_CMD_ERROR) {
|
||||
EC_ERR("Simple-IO datagram error!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +541,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
|
|||
{
|
||||
ec_slave_t *slave;
|
||||
ec_slave_ident_t *ident;
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
unsigned int i;
|
||||
uint16_t coupler_index, coupler_subindex;
|
||||
uint16_t reverse_coupler_index, current_coupler_index;
|
||||
|
|
@ -550,12 +551,12 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
|
|||
return -1;
|
||||
}
|
||||
|
||||
command = &master->simple_command;
|
||||
datagram = &master->simple_datagram;
|
||||
|
||||
// determine number of slaves on bus
|
||||
if (ec_command_brd(command, 0x0000, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(master, command))) return -1;
|
||||
master->slave_count = command->working_counter;
|
||||
if (ec_datagram_brd(datagram, 0x0000, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) return -1;
|
||||
master->slave_count = datagram->working_counter;
|
||||
EC_INFO("Found %i slaves on bus.\n", master->slave_count);
|
||||
|
||||
if (!master->slave_count) return 0;
|
||||
|
|
@ -588,10 +589,10 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
|
|||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
|
||||
// write station address
|
||||
if (ec_command_apwr(command, slave->ring_position, 0x0010,
|
||||
if (ec_datagram_apwr(datagram, slave->ring_position, 0x0010,
|
||||
sizeof(uint16_t))) goto out_free;
|
||||
EC_WRITE_U16(command->data, slave->station_address);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_WRITE_U16(datagram->data, slave->station_address);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Writing station address failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
goto out_free;
|
||||
|
|
@ -650,7 +651,7 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
if (unlikely((u32) (t_now - master->stats.t_last) / cpu_khz > 1000)) {
|
||||
if (master->stats.timeouts) {
|
||||
EC_WARN("%i commands TIMED OUT!\n", master->stats.timeouts);
|
||||
EC_WARN("%i datagrams TIMED OUT!\n", master->stats.timeouts);
|
||||
master->stats.timeouts = 0;
|
||||
}
|
||||
if (master->stats.delayed) {
|
||||
|
|
@ -662,7 +663,7 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
|
|||
master->stats.corrupted = 0;
|
||||
}
|
||||
if (master->stats.unmatched) {
|
||||
EC_WARN("%i command(s) UNMATCHED!\n", master->stats.unmatched);
|
||||
EC_WARN("%i datagram(s) UNMATCHED!\n", master->stats.unmatched);
|
||||
master->stats.unmatched = 0;
|
||||
}
|
||||
master->stats.t_last = t_now;
|
||||
|
|
@ -1075,7 +1076,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
{
|
||||
unsigned int j;
|
||||
ec_slave_t *slave;
|
||||
ec_command_t *command;
|
||||
ec_datagram_t *datagram;
|
||||
const ec_sync_t *sync;
|
||||
const ec_slave_type_t *type;
|
||||
const ec_fmmu_t *fmmu;
|
||||
|
|
@ -1083,7 +1084,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
ec_domain_t *domain;
|
||||
ec_eeprom_sync_t *eeprom_sync, mbox_sync;
|
||||
|
||||
command = &master->simple_command;
|
||||
datagram = &master->simple_datagram;
|
||||
|
||||
// allocate all domains
|
||||
domain_offset = 0;
|
||||
|
|
@ -1112,11 +1113,12 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
// reset FMMUs
|
||||
if (slave->base_fmmu_count) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count))
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count))
|
||||
return -1;
|
||||
memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
memset(datagram->data, 0x00,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Resetting FMMUs failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1125,11 +1127,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
// reset sync managers
|
||||
if (slave->base_sync_count) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0800,
|
||||
if (ec_datagram_npwr(datagram, slave->station_address, 0x0800,
|
||||
EC_SYNC_SIZE * slave->base_sync_count))
|
||||
return -1;
|
||||
memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Resetting sync managers failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1140,11 +1142,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
if (type) { // known slave type, take type's SM information
|
||||
for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
|
||||
sync = type->sync_managers[j];
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
|
||||
return -1;
|
||||
ec_sync_config(sync, slave, command->data);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
ec_sync_config(sync, slave, datagram->data);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1156,12 +1158,12 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
if (!list_empty(&slave->eeprom_syncs)) {
|
||||
list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
|
||||
EC_INFO("Sync manager %i...\n", eeprom_sync->index);
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x800 + eeprom_sync->index *
|
||||
EC_SYNC_SIZE,
|
||||
EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(eeprom_sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x800 + eeprom_sync->index *
|
||||
EC_SYNC_SIZE,
|
||||
EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(eeprom_sync, datagram->data);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
eeprom_sync->index, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1174,10 +1176,10 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
mbox_sync.length = slave->sii_rx_mailbox_size;
|
||||
mbox_sync.control_register = 0x26;
|
||||
mbox_sync.enable = 1;
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x800,EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(&mbox_sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x800,EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(&mbox_sync, datagram->data);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Setting sync manager 0 failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1188,10 +1190,10 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
mbox_sync.length = slave->sii_tx_mailbox_size;
|
||||
mbox_sync.control_register = 0x22;
|
||||
mbox_sync.enable = 1;
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x808, EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(&mbox_sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x808, EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(&mbox_sync, datagram->data);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Setting sync manager 1 failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1218,11 +1220,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
// configure FMMUs
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
fmmu = &slave->fmmus[j];
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
|
||||
if (ec_datagram_npwr(datagram, slave->station_address,
|
||||
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
|
||||
return -1;
|
||||
ec_fmmu_config(fmmu, slave, command->data);
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
ec_fmmu_config(fmmu, slave, datagram->data);
|
||||
if (unlikely(ec_master_simple_io(master, datagram))) {
|
||||
EC_ERR("Setting FMMU %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1288,17 +1290,17 @@ int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT master */)
|
|||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sends queued commands and waits for their reception.
|
||||
Sends queued datagrams and waits for their reception.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_command_t *command, *n;
|
||||
unsigned int commands_sent;
|
||||
ec_datagram_t *datagram, *n;
|
||||
unsigned int datagrams_sent;
|
||||
cycles_t t_start, t_end, t_timeout;
|
||||
|
||||
// send commands
|
||||
// send datagrams
|
||||
ecrt_master_async_send(master);
|
||||
|
||||
t_start = get_cycles(); // measure io time
|
||||
|
|
@ -1310,23 +1312,23 @@ void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
|
|||
t_end = get_cycles(); // take current time
|
||||
if (t_end - t_start >= t_timeout) break; // timeout!
|
||||
|
||||
commands_sent = 0;
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
if (command->state == EC_CMD_RECEIVED)
|
||||
list_del_init(&command->queue);
|
||||
else if (command->state == EC_CMD_SENT)
|
||||
commands_sent++;
|
||||
datagrams_sent = 0;
|
||||
list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
|
||||
if (datagram->state == EC_CMD_RECEIVED)
|
||||
list_del_init(&datagram->queue);
|
||||
else if (datagram->state == EC_CMD_SENT)
|
||||
datagrams_sent++;
|
||||
}
|
||||
|
||||
if (!commands_sent) break;
|
||||
if (!datagrams_sent) break;
|
||||
}
|
||||
|
||||
// timeout; dequeue all commands
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
switch (command->state) {
|
||||
// timeout; dequeue all datagrams
|
||||
list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
|
||||
switch (datagram->state) {
|
||||
case EC_CMD_SENT:
|
||||
case EC_CMD_QUEUED:
|
||||
command->state = EC_CMD_TIMEOUT;
|
||||
datagram->state = EC_CMD_TIMEOUT;
|
||||
master->stats.timeouts++;
|
||||
ec_master_output_stats(master);
|
||||
break;
|
||||
|
|
@ -1337,26 +1339,26 @@ void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
list_del_init(&command->queue);
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Asynchronous sending of commands.
|
||||
Asynchronous sending of datagrams.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_command_t *command, *n;
|
||||
ec_datagram_t *datagram, *n;
|
||||
|
||||
if (unlikely(!master->device->link_state)) {
|
||||
// link is down, no command can be sent
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
command->state = EC_CMD_ERROR;
|
||||
list_del_init(&command->queue);
|
||||
// link is down, no datagram can be sent
|
||||
list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
|
||||
datagram->state = EC_CMD_ERROR;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
|
||||
// query link state
|
||||
|
|
@ -1365,19 +1367,19 @@ void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */)
|
|||
}
|
||||
|
||||
// send frames
|
||||
ec_master_send_commands(master);
|
||||
ec_master_send_datagrams(master);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Asynchronous receiving of commands.
|
||||
Asynchronous receiving of datagrams.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_command_t *command, *next;
|
||||
ec_datagram_t *datagram, *next;
|
||||
cycles_t t_received, t_timeout;
|
||||
|
||||
ec_device_call_isr(master->device);
|
||||
|
|
@ -1385,18 +1387,19 @@ void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
|
|||
t_received = get_cycles();
|
||||
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
|
||||
|
||||
// dequeue all received commands
|
||||
list_for_each_entry_safe(command, next, &master->command_queue, queue)
|
||||
if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue);
|
||||
// dequeue all received datagrams
|
||||
list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue)
|
||||
if (datagram->state == EC_CMD_RECEIVED)
|
||||
list_del_init(&datagram->queue);
|
||||
|
||||
// dequeue all commands that timed out
|
||||
list_for_each_entry_safe(command, next, &master->command_queue, queue) {
|
||||
switch (command->state) {
|
||||
// dequeue all datagrams that timed out
|
||||
list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
|
||||
switch (datagram->state) {
|
||||
case EC_CMD_SENT:
|
||||
case EC_CMD_QUEUED:
|
||||
if (t_received - command->t_sent > t_timeout) {
|
||||
list_del_init(&command->queue);
|
||||
command->state = EC_CMD_TIMEOUT;
|
||||
if (t_received - datagram->t_sent > t_timeout) {
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_CMD_TIMEOUT;
|
||||
master->stats.timeouts++;
|
||||
ec_master_output_stats(master);
|
||||
}
|
||||
|
|
@ -1411,7 +1414,7 @@ void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
/**
|
||||
Prepares synchronous IO.
|
||||
Queues all domain commands and sends them. Then waits a certain time, so
|
||||
Queues all domain datagrams and sends them. Then waits a certain time, so
|
||||
that ecrt_master_sasync_receive() can be called securely.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
|
@ -1421,7 +1424,7 @@ void ecrt_master_prepare_async_io(ec_master_t *master /**< EtherCAT master */)
|
|||
ec_domain_t *domain;
|
||||
cycles_t t_start, t_end, t_timeout;
|
||||
|
||||
// queue commands of all domains
|
||||
// queue datagrams of all domains
|
||||
list_for_each_entry(domain, &master->domains, list)
|
||||
ecrt_domain_queue(domain);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
Loading…
Reference in New Issue