Renamed command structure to datagram.

This commit is contained in:
Florian Pose 2006-07-06 08:23:24 +00:00
parent 4a72709aa1
commit 6fdf205382
18 changed files with 932 additions and 918 deletions

View File

@ -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")

View File

@ -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

View File

@ -1,297 +0,0 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
Methods of an EtherCAT command.
*/
/*****************************************************************************/
#include <linux/slab.h>
#include "command.h"
#include "master.h"
/*****************************************************************************/
/** \cond */
#define EC_FUNC_HEADER \
if (unlikely(ec_command_prealloc(command, data_size))) \
return -1; \
command->index = 0; \
command->working_counter = 0; \
command->state = EC_CMD_INIT;
#define EC_FUNC_FOOTER \
command->data_size = data_size; \
memset(command->data, 0x00, data_size); \
return 0;
/** \endcond */
/*****************************************************************************/
/**
Command constructor.
*/
void ec_command_init(ec_command_t *command /**< EtherCAT command */)
{
command->type = EC_CMD_NONE;
command->address.logical = 0x00000000;
command->data = NULL;
command->mem_size = 0;
command->data_size = 0;
command->index = 0x00;
command->working_counter = 0x00;
command->state = EC_CMD_INIT;
command->t_sent = 0;
}
/*****************************************************************************/
/**
Command destructor.
*/
void ec_command_clear(ec_command_t *command /**< EtherCAT command */)
{
if (command->data) kfree(command->data);
}
/*****************************************************************************/
/**
Allocates command data memory.
If the allocated memory is already larger than requested, nothing ist done.
\return 0 in case of success, else < 0
*/
int ec_command_prealloc(ec_command_t *command, /**< EtherCAT command */
size_t size /**< New size in bytes */
)
{
if (size <= command->mem_size) return 0;
if (command->data) {
kfree(command->data);
command->data = NULL;
command->mem_size = 0;
}
if (!(command->data = kmalloc(size, GFP_KERNEL))) {
EC_ERR("Failed to allocate %i bytes of command memory!\n", size);
return -1;
}
command->mem_size = size;
return 0;
}
/*****************************************************************************/
/**
Initializes an EtherCAT NPRD command.
Node-adressed physical read.
\return 0 in case of success, else < 0
*/
int ec_command_nprd(ec_command_t *command,
/**< EtherCAT command */
uint16_t node_address,
/**< configured station address */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
if (unlikely(node_address == 0x0000))
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
command->type = EC_CMD_NPRD;
command->address.physical.slave = node_address;
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT NPWR command.
Node-adressed physical write.
\return 0 in case of success, else < 0
*/
int ec_command_npwr(ec_command_t *command,
/**< EtherCAT command */
uint16_t node_address,
/**< configured station address */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
if (unlikely(node_address == 0x0000))
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
command->type = EC_CMD_NPWR;
command->address.physical.slave = node_address;
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT APRD command.
Autoincrement physical read.
\return 0 in case of success, else < 0
*/
int ec_command_aprd(ec_command_t *command,
/**< EtherCAT command */
uint16_t ring_position,
/**< auto-increment position */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
command->type = EC_CMD_APRD;
command->address.physical.slave = (int16_t) ring_position * (-1);
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT APWR command.
Autoincrement physical write.
\return 0 in case of success, else < 0
*/
int ec_command_apwr(ec_command_t *command,
/**< EtherCAT command */
uint16_t ring_position,
/**< auto-increment position */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
command->type = EC_CMD_APWR;
command->address.physical.slave = (int16_t) ring_position * (-1);
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT BRD command.
Broadcast read.
\return 0 in case of success, else < 0
*/
int ec_command_brd(ec_command_t *command,
/**< EtherCAT command */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
command->type = EC_CMD_BRD;
command->address.physical.slave = 0x0000;
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT BWR command.
Broadcast write.
\return 0 in case of success, else < 0
*/
int ec_command_bwr(ec_command_t *command,
/**< EtherCAT command */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
command->type = EC_CMD_BWR;
command->address.physical.slave = 0x0000;
command->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT LRW command.
Logical read write.
\return 0 in case of success, else < 0
*/
int ec_command_lrw(ec_command_t *command,
/**< EtherCAT command */
uint32_t offset,
/**< logical address */
size_t data_size
/**< number of bytes to read/write */
)
{
EC_FUNC_HEADER;
command->type = EC_CMD_LRW;
command->address.logical = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/

297
master/datagram.c Normal file
View File

@ -0,0 +1,297 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
Methods of an EtherCAT datagram.
*/
/*****************************************************************************/
#include <linux/slab.h>
#include "datagram.h"
#include "master.h"
/*****************************************************************************/
/** \cond */
#define EC_FUNC_HEADER \
if (unlikely(ec_datagram_prealloc(datagram, data_size))) \
return -1; \
datagram->index = 0; \
datagram->working_counter = 0; \
datagram->state = EC_CMD_INIT;
#define EC_FUNC_FOOTER \
datagram->data_size = data_size; \
memset(datagram->data, 0x00, data_size); \
return 0;
/** \endcond */
/*****************************************************************************/
/**
Datagram constructor.
*/
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
datagram->type = EC_CMD_NONE;
datagram->address.logical = 0x00000000;
datagram->data = NULL;
datagram->mem_size = 0;
datagram->data_size = 0;
datagram->index = 0x00;
datagram->working_counter = 0x00;
datagram->state = EC_CMD_INIT;
datagram->t_sent = 0;
}
/*****************************************************************************/
/**
Datagram destructor.
*/
void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
if (datagram->data) kfree(datagram->data);
}
/*****************************************************************************/
/**
Allocates datagram data memory.
If the allocated memory is already larger than requested, nothing ist done.
\return 0 in case of success, else < 0
*/
int ec_datagram_prealloc(ec_datagram_t *datagram, /**< EtherCAT datagram */
size_t size /**< New size in bytes */
)
{
if (size <= datagram->mem_size) return 0;
if (datagram->data) {
kfree(datagram->data);
datagram->data = NULL;
datagram->mem_size = 0;
}
if (!(datagram->data = kmalloc(size, GFP_KERNEL))) {
EC_ERR("Failed to allocate %i bytes of datagram memory!\n", size);
return -1;
}
datagram->mem_size = size;
return 0;
}
/*****************************************************************************/
/**
Initializes an EtherCAT NPRD datagram.
Node-adressed physical read.
\return 0 in case of success, else < 0
*/
int ec_datagram_nprd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t node_address,
/**< configured station address */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
if (unlikely(node_address == 0x0000))
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
datagram->type = EC_CMD_NPRD;
datagram->address.physical.slave = node_address;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT NPWR datagram.
Node-adressed physical write.
\return 0 in case of success, else < 0
*/
int ec_datagram_npwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t node_address,
/**< configured station address */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
if (unlikely(node_address == 0x0000))
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
datagram->type = EC_CMD_NPWR;
datagram->address.physical.slave = node_address;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT APRD datagram.
Autoincrement physical read.
\return 0 in case of success, else < 0
*/
int ec_datagram_aprd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t ring_position,
/**< auto-increment position */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_APRD;
datagram->address.physical.slave = (int16_t) ring_position * (-1);
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT APWR datagram.
Autoincrement physical write.
\return 0 in case of success, else < 0
*/
int ec_datagram_apwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t ring_position,
/**< auto-increment position */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_APWR;
datagram->address.physical.slave = (int16_t) ring_position * (-1);
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT BRD datagram.
Broadcast read.
\return 0 in case of success, else < 0
*/
int ec_datagram_brd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_BRD;
datagram->address.physical.slave = 0x0000;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT BWR datagram.
Broadcast write.
\return 0 in case of success, else < 0
*/
int ec_datagram_bwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t offset,
/**< physical memory address */
size_t data_size
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_BWR;
datagram->address.physical.slave = 0x0000;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/
/**
Initializes an EtherCAT LRW datagram.
Logical read write.
\return 0 in case of success, else < 0
*/
int ec_datagram_lrw(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint32_t offset,
/**< logical address */
size_t data_size
/**< number of bytes to read/write */
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_LRW;
datagram->address.logical = offset;
EC_FUNC_FOOTER;
}
/*****************************************************************************/

View File

@ -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);
/*****************************************************************************/

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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.
*/

View File

@ -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);
}
/*****************************************************************************/

View File

@ -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 *);
/*****************************************************************************/

View File

@ -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);

View File

@ -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 *);

View File

@ -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;

View File

@ -45,7 +45,7 @@
#include <linux/kobject.h>
#include "globals.h"
#include "command.h"
#include "datagram.h"
#include "types.h"
/*****************************************************************************/