Mailbox-Interface ausgelagert, erster EOE-Ansatz.
This commit is contained in:
parent
8306f3e3c1
commit
4b4092fd7e
|
|
@ -16,7 +16,7 @@ ifneq ($(KERNELRELEASE),)
|
|||
obj-m := ec_master.o
|
||||
|
||||
ec_master-objs := module.o master.o device.o slave.o command.o types.o \
|
||||
domain.o canopen.o
|
||||
domain.o mailbox.o canopen.o ethernet.o
|
||||
|
||||
EXTRA_CFLAGS := -DSVNREV=$(shell svnversion $(src)) -DUSER=$(USER)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/module.h>
|
||||
|
||||
#include "master.h"
|
||||
#include "mailbox.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -51,18 +52,15 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
size_t rec_size;
|
||||
uint8_t *data;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1;
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer
|
||||
| 0x2 << 5)); // initiate upload request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -107,7 +105,8 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 0x0A))) return -1;
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 0x0A))) return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 // size specified
|
||||
| 0x1 << 1 // expedited transfer
|
||||
|
|
@ -117,12 +116,8 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
memcpy(data + 6, sdo_data, size);
|
||||
if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -164,17 +159,14 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
size_t rec_size, data_size;
|
||||
uint32_t complete_size;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1;
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -232,19 +224,22 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
ec_sdo_t *sdo;
|
||||
uint16_t sdo_index;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 8))) return -1;
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs!
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
|
||||
if (unlikely(ec_master_simple_io(slave->master, &slave->mbox_command))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
if (!(data = ec_slave_mbox_simple_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
|
|
@ -302,20 +297,14 @@ 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_prepare_mailbox_send(slave, 0x03, 8))) return -1;
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1;
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x03); // Get object description request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, sdo->index); // SDO index
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
|
||||
|
|
@ -386,8 +375,9 @@ 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_prepare_mailbox_send(slave, 0x03, 10)))
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 10)))
|
||||
return -1;
|
||||
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x05); // Get entry description request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
|
|
@ -395,14 +385,8 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
EC_WRITE_U16(data + 6, sdo->index); // SDO index
|
||||
EC_WRITE_U8 (data + 8, i); // SDO subindex
|
||||
EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* e t h e r n e t . c
|
||||
*
|
||||
* Ethernet-over-EtherCAT (EoE)
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
#include "globals.h"
|
||||
#include "master.h"
|
||||
#include "slave.h"
|
||||
#include "mailbox.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
|
||||
{
|
||||
eoe->slave = slave;
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_eoe_clear(ec_eoe_t *eoe)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_eoe_run(ec_eoe_t *eoe)
|
||||
{
|
||||
uint8_t *data;
|
||||
ec_master_t *master;
|
||||
size_t rec_size;
|
||||
|
||||
master = eoe->slave->master;
|
||||
|
||||
if (eoe->rx_state == EC_EOE_IDLE) {
|
||||
ec_slave_mbox_prepare_check(eoe->slave);
|
||||
ec_master_queue_command(master, &eoe->slave->mbox_command);
|
||||
eoe->rx_state = EC_EOE_CHECKING;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eoe->rx_state == EC_EOE_CHECKING) {
|
||||
if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
|
||||
master->stats.eoe_errors++;
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
return;
|
||||
}
|
||||
if (!ec_slave_mbox_check(eoe->slave)) {
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
return;
|
||||
}
|
||||
ec_slave_mbox_prepare_fetch(eoe->slave);
|
||||
ec_master_queue_command(master, &eoe->slave->mbox_command);
|
||||
eoe->rx_state = EC_EOE_FETCHING;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eoe->rx_state == EC_EOE_FETCHING) {
|
||||
EC_DBG("EOE fetching\n");
|
||||
if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
|
||||
master->stats.eoe_errors++;
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
return;
|
||||
}
|
||||
if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) {
|
||||
master->stats.eoe_errors++;
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
return;
|
||||
}
|
||||
EC_DBG("EOE received: %i\n", rec_size);
|
||||
eoe->rx_state = EC_EOE_IDLE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_eoe_print(const ec_eoe_t *eoe)
|
||||
{
|
||||
EC_INFO(" EoE slave %i\n", eoe->slave->ring_position);
|
||||
EC_INFO(" RX State %i\n", eoe->rx_state);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* e t h e r n e t . h
|
||||
*
|
||||
* Ethernet-over-EtherCAT (EoE)
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
#include "globals.h"
|
||||
#include "slave.h"
|
||||
#include "command.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_EOE_IDLE,
|
||||
EC_EOE_CHECKING,
|
||||
EC_EOE_FETCHING
|
||||
}
|
||||
ec_eoe_state_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
ec_slave_t *slave;
|
||||
ec_eoe_state_t rx_state;
|
||||
}
|
||||
ec_eoe_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_eoe_init(ec_eoe_t *, ec_slave_t *);
|
||||
void ec_eoe_clear(ec_eoe_t *);
|
||||
void ec_eoe_run(ec_eoe_t *);
|
||||
void ec_eoe_print(const ec_eoe_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* m a i l b o x . c
|
||||
*
|
||||
* Mailbox-Funktionen
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "mailbox.h"
|
||||
#include "command.h"
|
||||
#include "master.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Mailbox-Send-Kommando vor.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Mailbox-Protokoll */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
size_t total_size;
|
||||
|
||||
if (unlikely(!slave->sii_mailbox_protocols)) {
|
||||
EC_ERR("Slave %i does not support mailbox communication!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_size = size + 6;
|
||||
if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
|
||||
EC_ERR("Data size does not fit in mailbox!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ec_command_npwr(command, 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
|
||||
|
||||
return command->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Kommando zum Abfragen des Mailbox-Zustandes vor.
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< Slave */)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
|
||||
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
|
||||
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest den Mailbox-Zustand aus einem empfangenen Kommando.
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_check(const ec_slave_t *slave /**< Slave */)
|
||||
{
|
||||
return EC_READ_U8(slave->mbox_command.data + 5) & 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Kommando zum Laden von Daten von der Mailbox vor.
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< Slave */)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Verarbeitet empfangene Mailbox-Daten.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der empfangenen
|
||||
Daten */
|
||||
)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
size_t data_size;
|
||||
|
||||
if ((EC_READ_U8(command->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->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((data_size = EC_READ_U16(command->data)) >
|
||||
slave->sii_tx_mailbox_size - 6) {
|
||||
EC_ERR("Currupt mailbox response detected!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*size = data_size;
|
||||
return command->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet und wartet auf den Empfang eines Mailbox-Kommandos.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< Slave */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
)
|
||||
{
|
||||
uint8_t type;
|
||||
ec_command_t *command;
|
||||
|
||||
command = &slave->mbox_command;
|
||||
type = EC_READ_U8(command->data + 5);
|
||||
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ec_slave_mbox_simple_receive(slave, type, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Wartet auf den Empfang eines Mailbox-Kommandos.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
)
|
||||
{
|
||||
cycles_t start, end, timeout;
|
||||
ec_command_t *command;
|
||||
|
||||
command = &slave->mbox_command;
|
||||
start = get_cycles();
|
||||
timeout = (cycles_t) 100 * cpu_khz; // 100ms
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (ec_slave_mbox_prepare_check(slave)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (ec_slave_mbox_check(slave))
|
||||
break; // Proceed with receiving data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
EC_ERR("Mailbox check - Slave %i timed out.\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (ec_slave_mbox_prepare_fetch(slave)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Mailbox receiving failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unlikely(slave->master->debug_level) > 1)
|
||||
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
|
||||
/ cpu_khz));
|
||||
|
||||
return ec_slave_mbox_fetch(slave, type, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if 0
|
||||
/**
|
||||
Sendet ein Mailbox-Kommando.
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_send(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint8_t type, /**< Unterliegendes Protokoll */
|
||||
const uint8_t *prot_data, /**< Protokoll-Daten */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
ec_command_t command;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(slave->sii_rx_mailbox_size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %i bytes of memory for mailbox data!\n",
|
||||
slave->sii_rx_mailbox_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(data, 0x00, slave->sii_rx_mailbox_size);
|
||||
EC_WRITE_U16(data, size); // Length of the Mailbox service data
|
||||
EC_WRITE_U16(data + 2, slave->station_address); // Station address
|
||||
EC_WRITE_U8 (data + 4, 0x00); // Channel & priority
|
||||
EC_WRITE_U8 (data + 5, type); // Underlying protocol type
|
||||
memcpy(data + 6, prot_data, size);
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address,
|
||||
slave->sii_rx_mailbox_offset,
|
||||
slave->sii_rx_mailbox_size, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
kfree(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet ein Mailbox-Kommando.
|
||||
*/
|
||||
|
||||
int ec_slave_mailbox_receive(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint8_t type, /**< Unterliegendes Protokoll */
|
||||
uint8_t *prot_data, /**< Protokoll-Daten */
|
||||
size_t *size /**< Datengröße des Puffers, später
|
||||
Größe der gelesenen Daten */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
size_t data_size;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
// Read "written bit" of Sync-Manager
|
||||
start = get_cycles();
|
||||
timeout = (cycles_t) 100 * cpu_khz; // 100ms
|
||||
|
||||
while (1)
|
||||
{
|
||||
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x808, 8);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (EC_READ_U8(command.data + 5) & 8)
|
||||
break; // Proceed with received data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
EC_ERR("Mailbox check - Slave %i timed out.\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
EC_ERR("Mailbox receiving failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((EC_READ_U8(command.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->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlikely(slave->master->debug_level) > 1)
|
||||
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
|
||||
/ cpu_khz));
|
||||
|
||||
if ((data_size = EC_READ_U16(command.data)) > *size) {
|
||||
EC_ERR("Mailbox service data does not fit into buffer (%i > %i).\n",
|
||||
data_size, *size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data_size > slave->sii_tx_mailbox_size - 6) {
|
||||
EC_ERR("Currupt mailbox response detected!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(prot_data, command.data + 6, data_size);
|
||||
*size = data_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint8_t *ec_slave_init_mbox_send_cmd(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
ec_command_t *command, /**< Kommando */
|
||||
uint8_t type, /**< Protokolltyp */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
{
|
||||
size_t total_size;
|
||||
uint8_t *data;
|
||||
|
||||
if (unlikely(!slave->sii_mailbox_protocols)) {
|
||||
EC_ERR("Slave %i does not support mailbox communication!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_size = size + 6;
|
||||
if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
|
||||
EC_ERR("Data size does not fit into mailbox of slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = command->data;
|
||||
|
||||
memset(data, 0x00, slave->sii_rx_mailbox_size);
|
||||
EC_WRITE_U16(data, size); // Length of the Mailbox service data
|
||||
EC_WRITE_U16(data + 2, slave->station_address); // Station address
|
||||
EC_WRITE_U8 (data + 4, 0x00); // Channel & priority
|
||||
EC_WRITE_U8 (data + 5, type); // Underlying protocol type
|
||||
|
||||
return data + 6;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* m a i l b o x . h
|
||||
*
|
||||
* Mailbox-Funktionen.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _EC_MAILBOX_H_
|
||||
#define _EC_MAILBOX_H_
|
||||
|
||||
#include "slave.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *, uint8_t, size_t);
|
||||
int ec_slave_mbox_prepare_check(ec_slave_t *);
|
||||
int ec_slave_mbox_check(const ec_slave_t *);
|
||||
int ec_slave_mbox_prepare_fetch(ec_slave_t *);
|
||||
uint8_t *ec_slave_mbox_fetch(ec_slave_t *, uint8_t, size_t *);
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *, size_t *);
|
||||
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *, uint8_t, size_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "types.h"
|
||||
#include "device.h"
|
||||
#include "command.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ void ec_master_init(ec_master_t *master /**< EtherCAT-Master */)
|
|||
|
||||
INIT_LIST_HEAD(&master->command_queue);
|
||||
INIT_LIST_HEAD(&master->domains);
|
||||
INIT_LIST_HEAD(&master->eoe_slaves);
|
||||
|
||||
ec_command_init(&master->simple_command);
|
||||
ec_command_init(&master->watch_command);
|
||||
|
|
@ -80,6 +82,7 @@ void ec_master_reset(ec_master_t *master
|
|||
unsigned int i;
|
||||
ec_command_t *command, *next_c;
|
||||
ec_domain_t *domain, *next_d;
|
||||
ec_eoe_t *eoe, *next_eoe;
|
||||
|
||||
// Alle Slaves entfernen
|
||||
if (master->slaves) {
|
||||
|
|
@ -104,6 +107,13 @@ void ec_master_reset(ec_master_t *master
|
|||
kfree(domain);
|
||||
}
|
||||
|
||||
// EOE-Liste leeren
|
||||
list_for_each_entry_safe(eoe, next_eoe, &master->domains, list) {
|
||||
list_del(&eoe->list);
|
||||
ec_eoe_clear(eoe);
|
||||
kfree(eoe);
|
||||
}
|
||||
|
||||
master->command_index = 0;
|
||||
master->debug_level = 0;
|
||||
master->timeout = 100; // us
|
||||
|
|
@ -372,13 +382,13 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
|
|||
\return 0 bei Erfolg, sonst < 0
|
||||
*/
|
||||
|
||||
int ec_master_simple_io(ec_master_t *master /**< EtherCAT-Master */)
|
||||
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
|
||||
ec_command_t *command /**< Kommando */
|
||||
)
|
||||
{
|
||||
unsigned int response_tries_left;
|
||||
ec_command_t *command;
|
||||
|
||||
response_tries_left = 10;
|
||||
command = &master->simple_command;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
@ -425,6 +435,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
|||
ec_slave_ident_t *ident;
|
||||
unsigned int i;
|
||||
ec_command_t *command;
|
||||
ec_eoe_t *eoe;
|
||||
|
||||
if (master->slaves || master->slave_count) {
|
||||
EC_ERR("Slave scan already done!\n");
|
||||
|
|
@ -435,7 +446,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
|||
|
||||
// Determine number of slaves on bus
|
||||
if (ec_command_brd(command, 0x0000, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(master))) return -1;
|
||||
if (unlikely(ec_master_simple_io(master, command))) return -1;
|
||||
master->slave_count = command->working_counter;
|
||||
EC_INFO("Found %i slaves on bus.\n", master->slave_count);
|
||||
|
||||
|
|
@ -465,7 +476,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
|||
if (ec_command_apwr(command, slave->ring_position,
|
||||
0x0010, sizeof(uint16_t))) return -1;
|
||||
EC_WRITE_U16(command->data, slave->station_address);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Writing station address failed on slave %i!\n", i);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -488,6 +499,17 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
|||
EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at"
|
||||
" position %i.\n", slave->sii_vendor_id,
|
||||
slave->sii_product_code, i);
|
||||
|
||||
// Does the slave support EoE?
|
||||
if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
|
||||
if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate memory for EoE-Object.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_eoe_init(eoe, slave);
|
||||
list_add_tail(&eoe->list, &master->eoe_slaves);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -525,6 +547,10 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */)
|
|||
EC_WARN("%i command(s) UNMATCHED!\n", master->stats.unmatched);
|
||||
master->stats.unmatched = 0;
|
||||
}
|
||||
if (master->stats.eoe_errors) {
|
||||
EC_WARN("%i EOE ERROR(S)!\n", master->stats.eoe_errors);
|
||||
master->stats.eoe_errors = 0;
|
||||
}
|
||||
master->stats.t_last = t_now;
|
||||
}
|
||||
}
|
||||
|
|
@ -615,7 +641,8 @@ ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
|
|||
if (alias_requested) {
|
||||
for (i = alias_slave_index + 1; i < master->slave_count; i++) {
|
||||
slave = master->slaves + i;
|
||||
if (!slave->type || slave->type->bus_coupler) break;
|
||||
if (!slave->type ||
|
||||
slave->type->special == EC_TYPE_BUS_COUPLER) break;
|
||||
if (i - alias_slave_index == second) return slave;
|
||||
}
|
||||
EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave"
|
||||
|
|
@ -630,7 +657,7 @@ ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
|
|||
for (i = 0; i < master->slave_count; i++, slave_idx++) {
|
||||
slave = master->slaves + i;
|
||||
if (!slave->type) continue;
|
||||
if (slave->type->bus_coupler) {
|
||||
if (slave->type->special == EC_TYPE_BUS_COUPLER) {
|
||||
coupler_idx++;
|
||||
slave_idx = 0;
|
||||
}
|
||||
|
|
@ -845,7 +872,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Resetting FMMUs failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -858,7 +885,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Resetting sync managers failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -874,7 +901,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
|
||||
return -1;
|
||||
ec_sync_config(sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -887,7 +914,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
eeprom_sync->index, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -903,8 +930,8 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
if (!type) continue;
|
||||
|
||||
// Slaves that are not registered are only brought into PREOP
|
||||
// state -> nice blinking and mailbox comm. possible
|
||||
if (!slave->registered && !slave->type->bus_coupler) {
|
||||
// state -> nice blinking and mailbox communication possible
|
||||
if (!slave->registered && !slave->type->special) {
|
||||
EC_WARN("Slave %i was not registered!\n", slave->ring_position);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -917,7 +944,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
|
||||
return -1;
|
||||
ec_fmmu_config(fmmu, command->data);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
if (unlikely(ec_master_simple_io(master, command))) {
|
||||
EC_ERR("Setting FMMU %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1147,6 +1174,9 @@ void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */)
|
|||
// Watchdog-Kommando
|
||||
ec_master_process_watch_command(master);
|
||||
ec_master_queue_command(master, &master->watch_command);
|
||||
|
||||
// Ethernet-over-EtherCAT
|
||||
ec_master_run_eoe(master);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1186,15 +1216,36 @@ void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */
|
|||
)
|
||||
{
|
||||
unsigned int i;
|
||||
ec_eoe_t *eoe;
|
||||
|
||||
EC_INFO("*** Begin master information ***\n");
|
||||
for (i = 0; i < master->slave_count; i++)
|
||||
ec_slave_print(&master->slaves[i], verbosity);
|
||||
if (master->slave_count) {
|
||||
EC_INFO("Slave list:\n");
|
||||
for (i = 0; i < master->slave_count; i++)
|
||||
ec_slave_print(&master->slaves[i], verbosity);
|
||||
}
|
||||
if (!list_empty(&master->eoe_slaves)) {
|
||||
EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n");
|
||||
list_for_each_entry(eoe, &master->eoe_slaves, list) {
|
||||
ec_eoe_print(eoe);
|
||||
}
|
||||
}
|
||||
EC_INFO("*** End master information ***\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_master_run_eoe(ec_master_t *master /**< EtherCAT-Master */)
|
||||
{
|
||||
ec_eoe_t *eoe;
|
||||
|
||||
list_for_each_entry(eoe, &master->eoe_slaves, list) {
|
||||
ec_eoe_run(eoe);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXPORT_SYMBOL(ecrt_master_create_domain);
|
||||
EXPORT_SYMBOL(ecrt_master_activate);
|
||||
EXPORT_SYMBOL(ecrt_master_deactivate);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ typedef struct
|
|||
unsigned int delayed; /**< Verzögerte Kommandos */
|
||||
unsigned int corrupted; /**< Verfälschte Rahmen */
|
||||
unsigned int unmatched; /**< Unpassende Kommandos */
|
||||
unsigned int eoe_errors; /**< Ethernet-over-EtherCAT Fehler */
|
||||
cycles_t t_last; /**< Timestamp-Counter bei der letzten Ausgabe */
|
||||
}
|
||||
ec_stats_t;
|
||||
|
|
@ -57,6 +58,7 @@ struct ec_master
|
|||
int debug_level; /**< Debug-Level im Master-Code */
|
||||
ec_stats_t stats; /**< Rahmen-Statistiken */
|
||||
unsigned int timeout; /**< Timeout für synchronen Datenaustausch */
|
||||
struct list_head eoe_slaves; /**< Ethernet over EtherCAT Slaves */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -69,7 +71,7 @@ void ec_master_reset(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 *);
|
||||
int ec_master_simple_io(ec_master_t *, ec_command_t *);
|
||||
|
||||
// Registration of devices
|
||||
int ec_master_open(ec_master_t *);
|
||||
|
|
@ -82,6 +84,8 @@ int ec_master_bus_scan(ec_master_t *);
|
|||
void ec_master_debug(const ec_master_t *);
|
||||
void ec_master_output_stats(ec_master_t *);
|
||||
|
||||
void ec_master_run_eoe(ec_master_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
160
master/slave.c
160
master/slave.c
|
|
@ -43,11 +43,6 @@ void ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
slave->base_build = 0;
|
||||
slave->base_fmmu_count = 0;
|
||||
slave->base_sync_count = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
slave->dl_status_link[i] = 0;
|
||||
slave->dl_status_loop[i] = 0;
|
||||
slave->dl_status_comm[i] = 0;
|
||||
}
|
||||
slave->ring_position = 0;
|
||||
slave->station_address = 0;
|
||||
slave->sii_alias = 0;
|
||||
|
|
@ -66,10 +61,19 @@ void ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
slave->eeprom_name = NULL;
|
||||
slave->eeprom_group = NULL;
|
||||
slave->eeprom_desc = NULL;
|
||||
|
||||
ec_command_init(&slave->mbox_command);
|
||||
|
||||
INIT_LIST_HEAD(&slave->eeprom_strings);
|
||||
INIT_LIST_HEAD(&slave->eeprom_syncs);
|
||||
INIT_LIST_HEAD(&slave->eeprom_pdos);
|
||||
INIT_LIST_HEAD(&slave->sdo_dictionary);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
slave->dl_status_link[i] = 0;
|
||||
slave->dl_status_loop[i] = 0;
|
||||
slave->dl_status_comm[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -129,6 +133,8 @@ void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
}
|
||||
kfree(sdo);
|
||||
}
|
||||
|
||||
ec_command_clear(&slave->mbox_command);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -149,7 +155,7 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
|
||||
// Read base data
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Reading base data from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -166,7 +172,7 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
|
||||
// Read DL status
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Reading DL status from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -236,7 +242,7 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -254,7 +260,7 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
|||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -301,7 +307,7 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -319,7 +325,7 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
|||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -370,7 +376,7 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
|||
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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("SII-write failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -388,7 +394,7 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
|||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Getting SII-write status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -726,7 +732,7 @@ void ec_slave_state_ack(ec_slave_t *slave,
|
|||
|
||||
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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_WARN("State %02X acknowledge failed on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return;
|
||||
|
|
@ -741,7 +747,7 @@ void ec_slave_state_ack(ec_slave_t *slave,
|
|||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
return;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_WARN("State %02X acknowledge checking failed on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return;
|
||||
|
|
@ -791,7 +797,7 @@ int ec_slave_state_change(ec_slave_t *slave,
|
|||
|
||||
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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Failed to set state %02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -806,7 +812,7 @@ int ec_slave_state_change(ec_slave_t *slave,
|
|||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_ERR("Failed to check state %02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1049,7 +1055,7 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
command = &slave->master->simple_command;
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0300, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_WARN("Reading CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1082,7 +1088,7 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
// 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))) {
|
||||
if (unlikely(ec_master_simple_io(slave->master, command))) {
|
||||
EC_WARN("Resetting CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1093,122 +1099,6 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Mailbox-Send-Kommando vor.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Mailbox-Protokoll */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
{
|
||||
size_t total_size;
|
||||
ec_command_t *command;
|
||||
|
||||
if (unlikely(!slave->sii_mailbox_protocols)) {
|
||||
EC_ERR("Slave %i does not support mailbox communication!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_size = size + 6;
|
||||
if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
|
||||
EC_ERR("Data size does not fit in mailbox!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
if (ec_command_npwr(command, 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
|
||||
|
||||
return command->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Empfängt ein Mailbox-Kommando.
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mailbox_receive(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
size_t data_size;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
// Read "written bit" of Sync-Manager
|
||||
start = get_cycles();
|
||||
timeout = (cycles_t) 100 * cpu_khz; // 100ms
|
||||
|
||||
while (1)
|
||||
{
|
||||
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
|
||||
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
|
||||
return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (EC_READ_U8(command->data + 5) & 8)
|
||||
break; // Proceed with received data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
EC_ERR("Mailbox check - Slave %i timed out.\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox receiving failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((EC_READ_U8(command->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->ring_position);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unlikely(slave->master->debug_level) > 1)
|
||||
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
|
||||
/ cpu_khz));
|
||||
|
||||
if ((data_size = EC_READ_U16(command->data)) >
|
||||
slave->sii_tx_mailbox_size - 6) {
|
||||
EC_ERR("Currupt mailbox response detected!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*size = data_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Schreibt den "Configured station alias".
|
||||
\return 0, wenn alles ok, sonst < 0
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
#ifndef _EC_SLAVE_H_
|
||||
#define _EC_SLAVE_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "command.h"
|
||||
#include "types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -44,11 +48,11 @@ ec_slave_state_t;
|
|||
|
||||
enum
|
||||
{
|
||||
EC_MBOX_AOE = 0x01, /**< ADS over EtherCAT */
|
||||
EC_MBOX_EOE = 0x02, /**< Ethernet over EtherCAT */
|
||||
EC_MBOX_COE = 0x04, /**< CANopen over EtherCAT */
|
||||
EC_MBOX_FOE = 0x08, /**< File Service over EtherCAT */
|
||||
EC_MBOX_SOE = 0x10, /**< Servo Profile over EtherCAT */
|
||||
EC_MBOX_AOE = 0x01, /**< ADS-over-EtherCAT */
|
||||
EC_MBOX_EOE = 0x02, /**< Ethernet-over-EtherCAT */
|
||||
EC_MBOX_COE = 0x04, /**< CANopen-over-EtherCAT */
|
||||
EC_MBOX_FOE = 0x08, /**< File-Access-over-EtherCAT */
|
||||
EC_MBOX_SOE = 0x10, /**< Servo-Profile-over-EtherCAT */
|
||||
EC_MBOX_VOE = 0x20 /**< Vendor specific */
|
||||
};
|
||||
|
||||
|
|
@ -231,6 +235,8 @@ struct ec_slave
|
|||
char *eeprom_desc; /**< Slave-Beschreibung laut Hersteller */
|
||||
|
||||
struct list_head sdo_dictionary; /**< SDO-Verzeichnis des Slaves */
|
||||
|
||||
ec_command_t mbox_command; /**< Kommando für Mailbox-Kommunikation */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -247,10 +253,6 @@ int ec_slave_sii_write16(ec_slave_t *, uint16_t, uint16_t);
|
|||
int ec_slave_state_change(ec_slave_t *, uint8_t);
|
||||
int ec_slave_set_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sync_t *);
|
||||
|
||||
// Mailbox
|
||||
uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *, uint8_t, size_t);
|
||||
uint8_t *ec_slave_mailbox_receive(ec_slave_t *, uint8_t, size_t *);
|
||||
|
||||
// CANopen over EtherCAT
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ const ec_sync_t mailbox_sm1 = {0x18F6, 246, 0x22, {NULL}};
|
|||
/*****************************************************************************/
|
||||
|
||||
const ec_slave_type_t Beckhoff_EK1100 = {
|
||||
"Beckhoff", "EK1100", "Bus Coupler", 1,
|
||||
"Beckhoff", "EK1100", "Bus Coupler", EC_TYPE_BUS_COUPLER,
|
||||
{NULL} // Keine Sync-Manager
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_slave_type_t Beckhoff_EK1110 = {
|
||||
"Beckhoff", "EK1110", "Extension terminal", 0,
|
||||
"Beckhoff", "EK1110", "Extension terminal", EC_TYPE_NORMAL,
|
||||
{NULL} // Keine Sync-Manager
|
||||
};
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ const ec_sync_t el1014_sm0 = { // Inputs
|
|||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL1014 = {
|
||||
"Beckhoff", "EL1014", "4x Digital Input", 0,
|
||||
"Beckhoff", "EL1014", "4x Digital Input", EC_TYPE_NORMAL,
|
||||
{&el1014_sm0, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -60,12 +60,12 @@ const ec_sync_t el20XX_sm0 = {
|
|||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL2004 = {
|
||||
"Beckhoff", "EL2004", "4x Digital Output", 0,
|
||||
"Beckhoff", "EL2004", "4x Digital Output", EC_TYPE_NORMAL,
|
||||
{&el20XX_sm0, NULL}
|
||||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL2032 = {
|
||||
"Beckhoff", "EL2032", "2x Digital Output (2A)", 0,
|
||||
"Beckhoff", "EL2032", "2x Digital Output (2A)", EC_TYPE_NORMAL,
|
||||
{&el20XX_sm0, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -87,12 +87,12 @@ const ec_sync_t el31X2_sm3 = {
|
|||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL3102 = {
|
||||
"Beckhoff", "EL3102", "2x Analog Input diff.", 0,
|
||||
"Beckhoff", "EL3102", "2x Analog Input diff.", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el31X2_sm2, &el31X2_sm3, NULL}
|
||||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL3162 = {
|
||||
"Beckhoff", "EL3162", "2x Analog Input", 0,
|
||||
"Beckhoff", "EL3162", "2x Analog Input", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el31X2_sm2, &el31X2_sm3, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -106,12 +106,12 @@ const ec_sync_t el41X2_sm2 = {
|
|||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL4102 = {
|
||||
"Beckhoff", "EL4102", "2x Analog Output", 0,
|
||||
"Beckhoff", "EL4102", "2x Analog Output", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el41X2_sm2, NULL}
|
||||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL4132 = {
|
||||
"Beckhoff", "EL4132", "2x Analog Output diff.", 0,
|
||||
"Beckhoff", "EL4132", "2x Analog Output diff.", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el41X2_sm2, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ const ec_sync_t el5001_sm3 = {
|
|||
};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL5001 = {
|
||||
"Beckhoff", "EL5001", "SSI-Interface", 0,
|
||||
"Beckhoff", "EL5001", "SSI-Interface", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el5001_sm2, &el5001_sm3, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -155,12 +155,23 @@ const ec_sync_t el5101_sm3 = {
|
|||
|
||||
const ec_slave_type_t Beckhoff_EL5101 =
|
||||
{
|
||||
"Beckhoff", "EL5101", "Incremental Encoder Interface", 0,
|
||||
"Beckhoff", "EL5101", "Incremental Encoder Interface", EC_TYPE_NORMAL,
|
||||
{&mailbox_sm0, &mailbox_sm1, &el5101_sm2, &el5101_sm3, NULL}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_sync_t el6601_sm0 = {0x1800, 522, 0x26, {NULL}};
|
||||
const ec_sync_t el6601_sm1 = {0x1C00, 522, 0x22, {NULL}};
|
||||
|
||||
const ec_slave_type_t Beckhoff_EL6601 =
|
||||
{
|
||||
"Beckhoff", "EL6601", "1-Port Ethernet Switch Terminal", EC_TYPE_EOE,
|
||||
{&el6601_sm0, &el6601_sm1, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beziehung zwischen Identifikationsnummern und Klemmen-Objekt.
|
||||
|
||||
|
|
@ -182,6 +193,7 @@ ec_slave_ident_t slave_idents[] =
|
|||
{0x00000002, 0x10243052, &Beckhoff_EL4132},
|
||||
{0x00000002, 0x13893052, &Beckhoff_EL5001},
|
||||
{0x00000002, 0x13ED3052, &Beckhoff_EL5101},
|
||||
{0x00000002, 0x19C93052, &Beckhoff_EL6601},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,20 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Besondere Slaves.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_TYPE_NORMAL,
|
||||
EC_TYPE_BUS_COUPLER,
|
||||
EC_TYPE_EOE
|
||||
}
|
||||
ec_special_type_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prozessdatenfeld.
|
||||
*/
|
||||
|
|
@ -63,9 +77,7 @@ typedef struct ec_slave_type
|
|||
const char *vendor_name; /**< Name des Herstellers */
|
||||
const char *product_name; /**< Name des Slaves-Typs */
|
||||
const char *description; /**< Genauere Beschreibung des Slave-Typs */
|
||||
uint8_t bus_coupler; /**< Dieser Typ ist ein Buskoppler. Diese dienen als
|
||||
Anker für die Adressierung und müssen nicht
|
||||
registriert werden. */
|
||||
ec_special_type_t special; /**< Spezieller Slave-Typ */
|
||||
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< Sync-Manager
|
||||
Konfigurationen */
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue