VERSION 1.1: New realtime interface, only state machines.

This commit is contained in:
Florian Pose
2006-08-03 12:51:17 +00:00
parent fe60abcfc7
commit 258b4d998d
27 changed files with 1216 additions and 3524 deletions
-6
View File
@@ -8,12 +8,6 @@ $Id$
Important things to do:
* New SDO-Configuration interface
* Remove slave type information from master / New RT Interface
* Always use state machines / remove simple IO code
* SysFS interface
- Add secondary slave address
- Add SDO dictionary
+14 -83
View File
@@ -42,8 +42,8 @@
#include <linux/interrupt.h>
#include "../../include/ecrt.h" // EtherCAT realtime interface
#include "../../include/ecdb.h" // EtherCAT slave database
#define ASYNC
#define FREQUENCY 100
/*****************************************************************************/
@@ -56,16 +56,14 @@ ec_domain_t *domain1 = NULL;
spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
// data fields
//void *r_ssi_input, *r_ssi_status, *r_4102[3];
void *r_kbus_in, *r_kbus_out;
void *r_ana_out;
// channels
uint32_t k_pos;
uint8_t k_stat;
ec_field_init_t domain1_fields[] = {
//{&r_kbus_out, "0", "Beckhoff", "BK1120", "Outputs", 0},
//{&r_kbus_in, "0", "Beckhoff", "BK1120", "Inputs", 0},
ec_pdo_reg_t domain1_pdos[] = {
{"1", Beckhoff_EL4132_Output1, &r_ana_out},
{}
};
@@ -74,31 +72,19 @@ ec_field_init_t domain1_fields[] = {
void run(unsigned long data)
{
static unsigned int counter = 0;
unsigned int i;
spin_lock(&master_lock);
#ifdef ASYNC
// receive
ecrt_master_async_receive(master);
ecrt_master_receive(master);
ecrt_domain_process(domain1);
#else
// send and receive
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_sync_io(master);
ecrt_domain_process(domain1);
#endif
// process data
//k_pos = EC_READ_U32(r_ssi);
#ifdef ASYNC
// send
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_async_send(master);
#endif
ecrt_master_send(master);
spin_unlock(&master_lock);
@@ -107,9 +93,10 @@ void run(unsigned long data)
}
else {
counter = FREQUENCY;
printk(KERN_INFO "input = ");
for (i = 0; i < 22; i++) printk("%02X ", *((uint8_t *) r_kbus_in + i));
printk("\n");
//printk(KERN_INFO "input = ");
//for (i = 0; i < 22; i++)
// printk("%02X ", *((uint8_t *) r_kbus_in + i));
//printk("\n");
}
// restart timer
@@ -136,8 +123,6 @@ void release_lock(void *data)
int __init init_mini_module(void)
{
ec_slave_t *slave;
printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n");
if ((master = ecrt_request_master(0)) == NULL) {
@@ -154,69 +139,19 @@ int __init init_mini_module(void)
goto out_release_master;
}
printk(KERN_INFO "Registering domain fields...\n");
if (ecrt_domain_register_field_list(domain1, domain1_fields)) {
printk(KERN_ERR "Field registration failed!\n");
printk(KERN_INFO "Registering PDOs...\n");
if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) {
printk(KERN_ERR "PDO registration failed!\n");
goto out_release_master;
}
#if 1
printk(KERN_INFO "Setting variable data field sizes...\n");
if (!(slave = ecrt_master_get_slave(master, "0"))) {
printk(KERN_ERR "Failed to get slave!\n");
goto out_deactivate;
}
ecrt_slave_field_size(slave, "Outputs", 0, 0x16);
ecrt_slave_field_size(slave, "Inputs", 0, 0x16);
#endif
printk(KERN_INFO "Activating master...\n");
if (ecrt_master_activate(master)) {
printk(KERN_ERR "Failed to activate master!\n");
goto out_release_master;
}
#if 1
if (ecrt_master_fetch_sdo_lists(master)) {
printk(KERN_ERR "Failed to fetch SDO lists!\n");
goto out_deactivate;
}
ecrt_master_print(master, 2);
#else
ecrt_master_print(master, 0);
#endif
#if 0
if (!(slave = ecrt_master_get_slave(master, "5"))) {
printk(KERN_ERR "Failed to get slave 5!\n");
goto out_deactivate;
}
if (ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 1) ||
ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) ||
ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 4) ||
ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) ||
ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) ||
ecrt_slave_sdo_write_exp8(slave, 0x406B, 0, 50)) {
printk(KERN_ERR "Failed to configure SSI slave!\n");
goto out_deactivate;
}
#endif
#ifdef ASYNC
// send once and wait...
ecrt_master_prepare_async_io(master);
#endif
#if 1
if (ecrt_master_start_eoe(master)) {
printk(KERN_ERR "Failed to start EoE processing!\n");
goto out_deactivate;
}
#endif
ecrt_master_prepare(master);
printk("Starting cyclic sample thread.\n");
init_timer(&timer);
@@ -227,10 +162,6 @@ int __init init_mini_module(void)
printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n");
return 0;
#if 1
out_deactivate:
ecrt_master_deactivate(master);
#endif
out_release_master:
ecrt_release_master(master);
out_return:
+17 -90
View File
@@ -48,8 +48,7 @@
// EtherCAT
#include "../../include/ecrt.h"
#define ASYNC
#include "../../include/ecdb.h"
#define HZREDUCTION (MSR_ABTASTFREQUENZ / HZ)
#define TIMERTICKS (1000000000 / MSR_ABTASTFREQUENZ)
@@ -66,16 +65,13 @@ ec_master_t *master = NULL;
ec_domain_t *domain1 = NULL;
// raw process data
void *r_ssi;
void *r_ssi_st;
void *r_ana_out;
// Channels
uint32_t k_ssi;
uint32_t k_ssi_st;
double k_ana_out;
ec_field_init_t domain1_fields[] = {
{&r_ssi, "0:3", "Beckhoff", "EL5001", "InputValue", 0},
{&r_ssi_st, "0:3", "Beckhoff", "EL5001", "Status", 0},
ec_pdo_reg_t domain1_pdos[] = {
{"3", Beckhoff_EL4132_Output1, &r_ana_out},
{}
};
@@ -85,28 +81,16 @@ void msr_controller_run(void)
{
rt_sem_wait(&master_sem);
#ifdef ASYNC
// Empfangen
ecrt_master_async_receive(master);
// receive
ecrt_master_receive(master);
ecrt_domain_process(domain1);
#else
// Senden und empfangen
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_sync_io(master);
ecrt_domain_process(domain1);
#endif
// Prozessdaten verarbeiten
k_ssi = EC_READ_U32(r_ssi);
k_ssi_st = EC_READ_U8 (r_ssi_st);
// Process data
EC_WRITE_S16(r_ana_out, k_ana_out / 10.0 * 0x7FFF);
#ifdef ASYNC
// Senden
ecrt_domain_queue(domain1);
// Send
ecrt_master_run(master);
ecrt_master_async_send(master);
#endif
ecrt_master_send(master);
rt_sem_signal(&master_sem);
@@ -128,8 +112,7 @@ void msr_run(long data)
int msr_reg(void)
{
msr_reg_kanal("/ssi_position", "", &k_ssi, TUINT);
msr_reg_kanal("/ssi_status", "", &k_ssi_st, TUINT);
msr_reg_kanal("/ana_out", "", &k_ana_out, TDBL);
return 0;
}
@@ -157,9 +140,6 @@ void release_lock(void *data)
int __init init_mod(void)
{
RTIME ticks;
#if 0
ec_slave_t *slave;
#endif
printk(KERN_INFO "=== Starting EtherCAT RTAI MSR sample module... ===\n");
@@ -171,7 +151,7 @@ int __init init_mod(void)
goto out_return;
}
if ((master = ecrt_request_master(0)) == NULL) {
if (!(master = ecrt_request_master(0))) {
printk(KERN_ERR "Failed to request master 0!\n");
goto out_msr_cleanup;
}
@@ -184,9 +164,9 @@ int __init init_mod(void)
goto out_release_master;
}
printk(KERN_INFO "Registering domain fields...\n");
if (ecrt_domain_register_field_list(domain1, domain1_fields)) {
printk(KERN_ERR "Failed to register domain fields.\n");
printk(KERN_INFO "Registering PDOs...\n");
if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) {
printk(KERN_ERR "Failed to register PDOs.\n");
goto out_release_master;
}
@@ -196,59 +176,7 @@ int __init init_mod(void)
goto out_release_master;
}
#if 0
if (ecrt_master_fetch_sdo_lists(master)) {
printk(KERN_ERR "Failed to fetch SDO lists!\n");
goto out_deactivate;
}
ecrt_master_print(master, 2);
#else
ecrt_master_print(master, 0);
#endif
#if 0
if (!(slave = ecrt_master_get_slave(master, "0:3"))) {
printk(KERN_ERR "Failed to get slave!\n");
goto out_deactivate;
}
if (
ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 1) || // disable frame error bit
ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 0) || // power failure bit
ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) || // inhibit time
ecrt_slave_sdo_write_exp8(slave, 0x4061, 4, 0) || // test mode
ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 0) || // graycode
ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 5) || // 125kbaud
ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) || // single-turn
ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) || // frame size
ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) || // data length
ecrt_slave_sdo_write_exp16(slave, 0x406B, 0, 50) // inhibit time in us
) {
printk(KERN_ERR "Failed to configure SSI slave!\n");
goto out_deactivate;
}
#endif
#if 0
if (!(slave = ecrt_master_get_slave(master, "1:0"))) {
printk(KERN_ERR "Failed to get slave!\n");
goto out_deactivate;
}
if (ecrt_slave_write_alias(slave, 0x5678)) {
printk(KERN_ERR "Failed to write alias!\n");
goto out_deactivate;
}
#endif
#ifdef ASYNC
// Einmal senden und warten...
ecrt_master_prepare_async_io(master);
#endif
if (ecrt_master_start_eoe(master)) {
printk(KERN_ERR "Failed to start EoE processing!\n");
goto out_deactivate;
}
ecrt_master_prepare(master);
printk("Starting cyclic sample thread...\n");
ticks = start_rt_timer(nano2count(TIMERTICKS));
@@ -268,7 +196,6 @@ int __init init_mod(void)
rt_task_delete(&task);
out_stop_timer:
stop_rt_timer();
out_deactivate:
ecrt_master_deactivate(master);
out_release_master:
ecrt_release_master(master);
+13 -79
View File
@@ -42,6 +42,7 @@
// EtherCAT
#include "../../include/ecrt.h"
#include "../../include/ecdb.h"
/*****************************************************************************/
@@ -51,12 +52,8 @@ MODULE_DESCRIPTION("EtherCAT RTAI sample module");
/*****************************************************************************/
// comment this for synchronous IO
#define ASYNC
// RTAI task frequency in Hz
#define FREQUENCY 10000
#define TIMERTICKS (1000000000 / FREQUENCY)
/*****************************************************************************/
@@ -64,22 +61,20 @@ MODULE_DESCRIPTION("EtherCAT RTAI sample module");
// RTAI
RT_TASK task;
SEM master_sem;
cycles_t t_last_start = 0;
cycles_t t_critical;
cycles_t t_last_start = 0, t_critical;
// EtherCAT
ec_master_t *master = NULL;
ec_domain_t *domain1 = NULL;
// data fields
void *r_ssi_input;
void *r_ana_out;
// channels
uint32_t k_pos;
ec_field_init_t domain1_fields[] = {
{&r_ssi_input, "3", "Beckhoff", "EL5001", "InputValue", 0},
{NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0},
ec_pdo_reg_t domain1_pdos[] = {
{"2", Beckhoff_EL4132_Output1, &r_ana_out},
{}
};
@@ -92,27 +87,14 @@ void run(long data)
t_last_start = get_cycles();
rt_sem_wait(&master_sem);
#ifdef ASYNC
// receive
ecrt_master_async_receive(master);
ecrt_master_receive(master);
ecrt_domain_process(domain1);
#else
// send and receive
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_sync_io(master);
ecrt_domain_process(domain1);
#endif
// process data
k_pos = EC_READ_U32(r_ssi_input);
//k_pos = EC_READ_U32(r_ssi_input);
#ifdef ASYNC
// send
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_async_send(master);
#endif
ecrt_master_send(master);
rt_sem_signal(&master_sem);
rt_task_wait_period();
@@ -158,15 +140,14 @@ int __init init_mod(void)
ecrt_master_callbacks(master, request_lock, release_lock, NULL);
printk(KERN_INFO "Registering domain...\n");
if (!(domain1 = ecrt_master_create_domain(master)))
{
if (!(domain1 = ecrt_master_create_domain(master))) {
printk(KERN_ERR "Domain creation failed!\n");
goto out_release_master;
}
printk(KERN_INFO "Registering domain fields...\n");
if (ecrt_domain_register_field_list(domain1, domain1_fields)) {
printk(KERN_ERR "Field registration failed!\n");
printk(KERN_INFO "Registering PDOs...\n");
if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) {
printk(KERN_ERR "PDO registration failed!\n");
goto out_release_master;
}
@@ -176,53 +157,7 @@ int __init init_mod(void)
goto out_release_master;
}
#if 0
if (ecrt_master_fetch_sdo_lists(master)) {
printk(KERN_ERR "Failed to fetch SDO lists!\n");
goto out_deactivate;
}
ecrt_master_print(master, 2);
#else
ecrt_master_print(master, 0);
#endif
#if 0
if (!(slave = ecrt_master_get_slave(master, "5"))) {
printk(KERN_ERR "Failed to get slave 5!\n");
goto out_deactivate;
}
if (ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 1) ||
ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) ||
ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 4) ||
ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) ||
ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) ||
ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) ||
ecrt_slave_sdo_write_exp8(slave, 0x406B, 0, 50)) {
printk(KERN_ERR "Failed to configure SSI slave!\n");
goto out_deactivate;
}
#endif
#if 0
printk(KERN_INFO "Writing alias...\n");
if (ecrt_slave_sdo_write_exp16(slave, 0xBEEF)) {
printk(KERN_ERR "Failed to write alias!\n");
goto out_deactivate;
}
#endif
#ifdef ASYNC
// send once and wait...
ecrt_master_prepare_async_io(master);
#endif
if (ecrt_master_start_eoe(master)) {
printk(KERN_ERR "Failed to start EoE processing!\n");
goto out_deactivate;
}
ecrt_master_prepare(master);
printk("Starting cyclic sample thread...\n");
requested_ticks = nano2count(TIMERTICKS);
@@ -248,7 +183,6 @@ int __init init_mod(void)
rt_task_delete(&task);
out_stop_timer:
stop_rt_timer();
out_deactivate:
ecrt_master_deactivate(master);
out_release_master:
ecrt_release_master(master);
+51
View File
@@ -0,0 +1,51 @@
/******************************************************************************
*
* $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
EtherCAT Slave Database.
*/
/*****************************************************************************/
#ifndef __ECDB_H__
#define __ECDB_H__
/*****************************************************************************/
#define Beckhoff_EL4132_Output1 0x00000002, 0x10243052, 0x6411, 1
#define Beckhoff_EL4132_Output2 0x00000002, 0x10243052, 0x6411, 2
/*****************************************************************************/
#endif
+31 -51
View File
@@ -69,23 +69,22 @@ struct ec_slave;
typedef struct ec_slave ec_slave_t; /**< \see ec_slave */
/**
Initialization type for field registrations.
This type is used as a parameter for the ec_domain_register_field_list()
Initialization type for PDO registrations.
This type is used as a parameter for the ec_domain_register_pdo_list()
function.
*/
typedef struct
{
void **data_ptr; /**< address of the process data pointer */
const char *slave_address; /**< slave address string (see
ecrt_master_get_slave()) */
const char *vendor_name; /**< vendor name */
const char *product_name; /**< product name */
const char *field_name; /**< data field name */
unsigned int field_index; /**< index in data fields with same name */
unsigned int field_count; /**< number of data fields with same name */
uint32_t vendor_id; /**< vendor ID */
uint32_t product_code; /**< product code */
uint16_t pdo_index; /**< PDO index */
uint8_t pdo_subindex; /**< PDO subindex */
void **data_ptr; /**< address of the process data pointer */
}
ec_field_init_t;
ec_pdo_reg_t;
/******************************************************************************
* Master request functions
@@ -106,66 +105,47 @@ ec_domain_t *ecrt_master_create_domain(ec_master_t *master);
int ecrt_master_activate(ec_master_t *master);
void ecrt_master_deactivate(ec_master_t *master);
int ecrt_master_fetch_sdo_lists(ec_master_t *master);
void ecrt_master_prepare(ec_master_t *master);
void ecrt_master_sync_io(ec_master_t *master);
void ecrt_master_async_send(ec_master_t *master);
void ecrt_master_async_receive(ec_master_t *master);
void ecrt_master_prepare_async_io(ec_master_t *master);
void ecrt_master_send(ec_master_t *master);
void ecrt_master_receive(ec_master_t *master);
void ecrt_master_run(ec_master_t *master);
int ecrt_master_start_eoe(ec_master_t *master);
void ecrt_master_debug(ec_master_t *master, int level);
void ecrt_master_print(const ec_master_t *master, unsigned int verbosity);
ec_slave_t *ecrt_master_get_slave(const ec_master_t *, const char *);
int ecrt_master_state(const ec_master_t *master);
/******************************************************************************
* Domain Methods
*****************************************************************************/
ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
const char *address,
const char *vendor_name,
const char *product_name,
void **data_ptr, const char *field_name,
unsigned int field_index,
unsigned int field_count);
int ecrt_domain_register_field_list(ec_domain_t *domain,
const ec_field_init_t *fields);
ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
const char *address,
uint32_t vendor_id,
uint32_t product_code,
uint16_t pdo_index,
uint8_t pdo_subindex,
void **data_ptr);
int ecrt_domain_register_pdo_list(ec_domain_t *domain,
const ec_pdo_reg_t *pdos);
void ecrt_domain_queue(ec_domain_t *domain);
void ecrt_domain_process(ec_domain_t *domain);
int ecrt_domain_state(ec_domain_t *domain);
int ecrt_domain_state(const ec_domain_t *domain);
/******************************************************************************
* Slave Methods
*****************************************************************************/
/* there SDO functions are deprecated! */
int ecrt_slave_conf_sdo8(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t value);
int ecrt_slave_conf_sdo16(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint16_t value);
int ecrt_slave_conf_sdo32(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint32_t value);
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t *value);
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint16_t *value);
int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint32_t *value);
int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t value);
int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint16_t value);
int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint32_t value);
int ecrt_slave_sdo_read(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t *data, size_t *size);
int ecrt_slave_write_alias(ec_slave_t *slave, uint16_t alias); // deprecated!
int ecrt_slave_field_size(ec_slave_t *slave, const char *field_name,
unsigned int field_index, size_t size);
int ecrt_slave_pdo_size(ec_slave_t *slave, uint16_t pdo_index,
uint8_t pdo_subindex, size_t size);
/******************************************************************************
* Bitwise read/write macros
+2 -2
View File
@@ -42,8 +42,8 @@ ifneq ($(KERNELRELEASE),)
obj-m := ec_master.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
ec_master-objs := module.o master.o device.o slave.o datagram.o \
domain.o mailbox.o ethernet.o debug.o fsm.o
REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
-726
View File
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -52,7 +52,7 @@
return -1; \
datagram->index = 0; \
datagram->working_counter = 0; \
datagram->state = EC_CMD_INIT;
datagram->state = EC_DATAGRAM_INIT;
#define EC_FUNC_FOOTER \
datagram->data_size = data_size; \
@@ -69,14 +69,14 @@
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
datagram->type = EC_CMD_NONE;
datagram->type = EC_DATAGRAM_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->state = EC_DATAGRAM_INIT;
datagram->t_sent = 0;
}
@@ -142,7 +142,7 @@ int ec_datagram_nprd(ec_datagram_t *datagram,
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
datagram->type = EC_CMD_NPRD;
datagram->type = EC_DATAGRAM_NPRD;
datagram->address.physical.slave = node_address;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -170,7 +170,7 @@ int ec_datagram_npwr(ec_datagram_t *datagram,
EC_WARN("Using node address 0x0000!\n");
EC_FUNC_HEADER;
datagram->type = EC_CMD_NPWR;
datagram->type = EC_DATAGRAM_NPWR;
datagram->address.physical.slave = node_address;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -195,7 +195,7 @@ int ec_datagram_aprd(ec_datagram_t *datagram,
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_APRD;
datagram->type = EC_DATAGRAM_APRD;
datagram->address.physical.slave = (int16_t) ring_position * (-1);
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -220,7 +220,7 @@ int ec_datagram_apwr(ec_datagram_t *datagram,
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_APWR;
datagram->type = EC_DATAGRAM_APWR;
datagram->address.physical.slave = (int16_t) ring_position * (-1);
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -243,7 +243,7 @@ int ec_datagram_brd(ec_datagram_t *datagram,
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_BRD;
datagram->type = EC_DATAGRAM_BRD;
datagram->address.physical.slave = 0x0000;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -266,7 +266,7 @@ int ec_datagram_bwr(ec_datagram_t *datagram,
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_BWR;
datagram->type = EC_DATAGRAM_BWR;
datagram->address.physical.slave = 0x0000;
datagram->address.physical.mem = offset;
EC_FUNC_FOOTER;
@@ -289,7 +289,7 @@ int ec_datagram_lrw(ec_datagram_t *datagram,
)
{
EC_FUNC_HEADER;
datagram->type = EC_CMD_LRW;
datagram->type = EC_DATAGRAM_LRW;
datagram->address.logical = offset;
EC_FUNC_FOOTER;
}
+14 -14
View File
@@ -55,14 +55,14 @@
typedef enum
{
EC_CMD_NONE = 0x00, /**< Dummy */
EC_CMD_APRD = 0x01, /**< Auto-increment physical read */
EC_CMD_APWR = 0x02, /**< Auto-increment physical write */
EC_CMD_NPRD = 0x04, /**< Node-addressed physical read */
EC_CMD_NPWR = 0x05, /**< Node-addressed physical write */
EC_CMD_BRD = 0x07, /**< Broadcast read */
EC_CMD_BWR = 0x08, /**< Broadcast write */
EC_CMD_LRW = 0x0C /**< Logical read/write */
EC_DATAGRAM_NONE = 0x00, /**< Dummy */
EC_DATAGRAM_APRD = 0x01, /**< Auto-increment physical read */
EC_DATAGRAM_APWR = 0x02, /**< Auto-increment physical write */
EC_DATAGRAM_NPRD = 0x04, /**< Node-addressed physical read */
EC_DATAGRAM_NPWR = 0x05, /**< Node-addressed physical write */
EC_DATAGRAM_BRD = 0x07, /**< Broadcast read */
EC_DATAGRAM_BWR = 0x08, /**< Broadcast write */
EC_DATAGRAM_LRW = 0x0C /**< Logical read/write */
}
ec_datagram_type_t;
@@ -72,12 +72,12 @@ ec_datagram_type_t;
typedef enum
{
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_DATAGRAM_INIT, /**< new datagram */
EC_DATAGRAM_QUEUED, /**< datagram queued by master */
EC_DATAGRAM_SENT, /**< datagram has been sent */
EC_DATAGRAM_RECEIVED, /**< datagram has been received */
EC_DATAGRAM_TIMED_OUT, /**< datagram timed out */
EC_DATAGRAM_ERROR /**< error while sending/receiving */
}
ec_datagram_state_t;
+182 -172
View File
File diff suppressed because it is too large Load Diff
+3 -18
View File
@@ -45,24 +45,8 @@
#include <linux/kobject.h>
#include "globals.h"
#include "slave.h"
#include "datagram.h"
/*****************************************************************************/
/**
Data field registration type.
*/
typedef struct
{
struct list_head list; /**< list item */
ec_slave_t *slave; /**< slave */
const ec_sync_t *sync; /**< sync manager */
uint32_t field_offset; /**< data field offset */
void **data_ptr; /**< pointer to process data pointer(s) */
}
ec_field_reg_t;
#include "master.h"
/*****************************************************************************/
@@ -82,7 +66,7 @@ struct ec_domain
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 */
struct list_head data_regs; /**< PDO data registrations */
};
/*****************************************************************************/
@@ -90,6 +74,7 @@ struct ec_domain
int ec_domain_init(ec_domain_t *, ec_master_t *, unsigned int);
void ec_domain_clear(struct kobject *);
int ec_domain_alloc(ec_domain_t *, uint32_t);
void ec_domain_queue(ec_domain_t *);
/*****************************************************************************/
+5 -23
View File
@@ -155,10 +155,8 @@ int ec_eoe_init(ec_eoe_t *eoe /**< EoE handler */)
void ec_eoe_clear(ec_eoe_t *eoe /**< EoE handler */)
{
if (eoe->dev) { // TODO: dev never NULL?
unregister_netdev(eoe->dev);
free_netdev(eoe->dev);
}
unregister_netdev(eoe->dev);
free_netdev(eoe->dev);
// empty transmit queue
ec_eoe_flush(eoe);
@@ -292,22 +290,6 @@ unsigned int ec_eoe_active(const ec_eoe_t *eoe /**< EoE handler */)
return eoe->slave && eoe->opened;
}
/*****************************************************************************/
/**
Prints EoE handler information.
*/
void ec_eoe_print(const ec_eoe_t *eoe /**< EoE handler */)
{
EC_INFO(" EoE handler %s\n", eoe->dev->name);
EC_INFO(" State: %s\n", eoe->opened ? "opened" : "closed");
if (eoe->slave)
EC_INFO(" Coupled to slave %i.\n", eoe->slave->ring_position);
else
EC_INFO(" Not coupled.\n");
}
/******************************************************************************
* STATE PROCESSING FUNCTIONS
*****************************************************************************/
@@ -338,7 +320,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
{
if (eoe->datagram.state != EC_CMD_RECEIVED) {
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
eoe->stats.rx_errors++;
eoe->state = ec_eoe_state_tx_start;
return;
@@ -369,7 +351,7 @@ 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->datagram.state != EC_CMD_RECEIVED) {
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
eoe->stats.rx_errors++;
eoe->state = ec_eoe_state_tx_start;
return;
@@ -570,7 +552,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
{
if (eoe->datagram.state != EC_CMD_RECEIVED) {
if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) {
eoe->stats.tx_errors++;
eoe->state = ec_eoe_state_rx_start;
return;
-1
View File
@@ -98,6 +98,5 @@ int ec_eoe_init(ec_eoe_t *);
void ec_eoe_clear(ec_eoe_t *);
void ec_eoe_run(ec_eoe_t *);
unsigned int ec_eoe_active(const ec_eoe_t *);
void ec_eoe_print(const ec_eoe_t *);
/*****************************************************************************/
+411 -293
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -41,6 +41,7 @@
#ifndef __EC_STATES__
#define __EC_STATES__
#include "globals.h"
#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"
@@ -84,6 +85,14 @@ void ec_fsm_clear(ec_fsm_t *);
void ec_fsm_reset(ec_fsm_t *);
void ec_fsm_execute(ec_fsm_t *);
void ec_fsm_startup(ec_fsm_t *);
int ec_fsm_startup_running(ec_fsm_t *);
int ec_fsm_startup_success(ec_fsm_t *);
void ec_fsm_configuration(ec_fsm_t *);
int ec_fsm_configuration_running(ec_fsm_t *);
int ec_fsm_configuration_success(ec_fsm_t *);
/*****************************************************************************/
#endif
+7 -5
View File
@@ -51,7 +51,7 @@
#define EC_MASTER_VERSION_MAIN 1
/** master sub version (after the dot) */
#define EC_MASTER_VERSION_SUB 0
#define EC_MASTER_VERSION_SUB 1
/** master extra version (just a string) */
#define EC_MASTER_VERSION_EXTRA "trunk"
@@ -65,6 +65,9 @@
/** clock frequency for the EoE state machines */
#define EC_EOE_FREQUENCY 1000
/** datagram timeout in microseconds */
#define EC_IO_TIMEOUT 500
/******************************************************************************
* EtherCAT protocol
*****************************************************************************/
@@ -170,9 +173,9 @@
/*****************************************************************************/
extern void ec_print_data(const uint8_t *, size_t);
extern void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
extern void ec_print_states(uint8_t);
void ec_print_data(const uint8_t *, size_t);
void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
size_t ec_state_string(uint8_t, char *);
/*****************************************************************************/
@@ -192,4 +195,3 @@ ec_code_msg_t;
/*****************************************************************************/
#endif
-80
View File
@@ -165,83 +165,3 @@ uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */
}
/*****************************************************************************/
/**
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_datagram_t *datagram, /**< datagram */
size_t *size /**< size of the received data */
)
{
uint8_t type;
type = EC_READ_U8(datagram->data + 5);
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, datagram, type, size);
}
/*****************************************************************************/
/**
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_datagram_t *datagram, /**< datagram */
uint8_t type, /**< expected protocol */
size_t *size /**< received data size */
)
{
cycles_t start, end, timeout;
start = get_cycles();
timeout = (cycles_t) 100 * cpu_khz; // 100ms
while (1)
{
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;
}
end = get_cycles();
if (ec_slave_mbox_check(datagram))
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, 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;
}
if (unlikely(slave->master->debug_level) > 1)
EC_DBG("Mailbox receive took %ius.\n",
((unsigned int) (end - start) * 1000 / cpu_khz));
return ec_slave_mbox_fetch(slave, datagram, type, size);
}
/*****************************************************************************/
+129 -469
View File
File diff suppressed because it is too large Load Diff
+7 -11
View File
@@ -59,7 +59,7 @@ typedef enum
{
EC_MASTER_MODE_ORPHANED,
EC_MASTER_MODE_IDLE,
EC_MASTER_MODE_RUNNING
EC_MASTER_MODE_OPERATION
}
ec_master_mode_t;
@@ -104,10 +104,6 @@ struct ec_master
struct list_head domains; /**< list of domains */
ec_datagram_t simple_datagram; /**< datagram structure for
initialization */
unsigned int timeout; /**< timeout in synchronous IO */
int debug_level; /**< master debug level */
ec_stats_t stats; /**< cyclic statistics */
@@ -145,18 +141,18 @@ 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_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 *);
// misc.
void ec_master_clear_slaves(ec_master_t *);
void ec_sync_config(const ec_sync_t *, const ec_slave_t *, uint8_t *);
void ec_eeprom_sync_config(const ec_eeprom_sync_t *, const ec_slave_t *,
uint8_t *);
void ec_fmmu_config(const ec_fmmu_t *, const ec_slave_t *, uint8_t *);
void ec_master_output_stats(ec_master_t *);
void ec_master_clear_slaves(ec_master_t *);
// other methods
void ec_sync_config(const ec_sii_sync_t *, const ec_slave_t *, uint8_t *);
void ec_fmmu_config(const ec_fmmu_t *, const ec_slave_t *, uint8_t *);
void ec_master_calc_addressing(ec_master_t *);
/*****************************************************************************/
+16 -11
View File
@@ -237,33 +237,38 @@ void ec_print_data_diff(const uint8_t *d1, /**< first data */
Prints slave states in clear text.
*/
void ec_print_states(const uint8_t states /**< slave states */)
size_t ec_state_string(uint8_t states, /**< slave states */
char *buffer /**< target buffer (min. 25 bytes) */
)
{
off_t off = 0;
unsigned int first = 1;
if (!states) {
printk("(unknown)");
return;
off += sprintf(buffer + off, "(unknown)");
return off;
}
if (states & EC_SLAVE_STATE_INIT) {
printk("INIT");
off += sprintf(buffer + off, "INIT");
first = 0;
}
if (states & EC_SLAVE_STATE_PREOP) {
if (!first) printk(", ");
printk("PREOP");
if (!first) off += sprintf(buffer + off, ", ");
off += sprintf(buffer + off, "PREOP");
first = 0;
}
if (states & EC_SLAVE_STATE_SAVEOP) {
if (!first) printk(", ");
printk("SAVEOP");
if (!first) off += sprintf(buffer + off, ", ");
off += sprintf(buffer + off, "SAVEOP");
first = 0;
}
if (states & EC_SLAVE_STATE_OP) {
if (!first) printk(", ");
printk("OP");
if (!first) off += sprintf(buffer + off, ", ");
off += sprintf(buffer + off, "OP");
}
return off;
}
/******************************************************************************
@@ -426,7 +431,7 @@ ec_master_t *ecrt_request_master(unsigned int master_index
ec_master_idle_stop(master);
ec_master_reset(master);
master->mode = EC_MASTER_MODE_RUNNING;
master->mode = EC_MASTER_MODE_OPERATION;
if (!master->device->link_state) EC_WARN("Link is DOWN.\n");
+203 -828
View File
File diff suppressed because it is too large Load Diff
+53 -61
View File
@@ -44,9 +44,10 @@
#include <linux/list.h>
#include <linux/kobject.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "datagram.h"
#include "types.h"
/*****************************************************************************/
@@ -89,20 +90,6 @@ enum
/*****************************************************************************/
/**
FMMU configuration.
*/
typedef struct
{
const ec_domain_t *domain; /**< domain */
const ec_sync_t *sync; /**< sync manager */
uint32_t logical_start_address; /**< logical start address */
}
ec_fmmu_t;
/*****************************************************************************/
/**
String object (EEPROM).
*/
@@ -113,7 +100,7 @@ typedef struct
size_t size; /**< size in bytes */
char *data; /**< string data */
}
ec_eeprom_string_t;
ec_sii_string_t;
/*****************************************************************************/
@@ -130,7 +117,7 @@ typedef struct
uint8_t control_register; /**< control register value */
uint8_t enable; /**< enable bit */
}
ec_eeprom_sync_t;
ec_sii_sync_t;
/*****************************************************************************/
@@ -143,7 +130,7 @@ typedef enum
EC_RX_PDO, /**< Reveive PDO */
EC_TX_PDO /**< Transmit PDO */
}
ec_pdo_type_t;
ec_sii_pdo_type_t;
/*****************************************************************************/
@@ -154,13 +141,13 @@ ec_pdo_type_t;
typedef struct
{
struct list_head list; /**< list item */
ec_pdo_type_t type; /**< PDO type */
ec_sii_pdo_type_t type; /**< PDO type */
uint16_t index; /**< PDO index */
uint8_t sync_manager; /**< assigned sync manager */
uint8_t sync_index; /**< assigned sync manager */
char *name; /**< PDO name */
struct list_head entries; /**< entry list */
}
ec_eeprom_pdo_t;
ec_sii_pdo_t;
/*****************************************************************************/
@@ -176,7 +163,7 @@ typedef struct
char *name; /**< entry name */
uint8_t bit_length; /**< entry length in bit */
}
ec_eeprom_pdo_entry_t;
ec_sii_pdo_entry_t;
/*****************************************************************************/
@@ -188,7 +175,6 @@ typedef struct
{
struct list_head list; /**< list item */
uint16_t index; /**< SDO index */
//uint16_t type;
uint8_t object_code; /**< object code */
char *name; /**< SDO name */
struct list_head entries; /**< entry list */
@@ -213,6 +199,20 @@ ec_sdo_entry_t;
/*****************************************************************************/
/**
FMMU configuration.
*/
typedef struct
{
const ec_domain_t *domain; /**< domain */
const ec_sii_sync_t *sync; /**< sync manager */
uint32_t logical_start_address; /**< logical start address */
}
ec_fmmu_t;
/*****************************************************************************/
/**
Variable-sized field information.
*/
@@ -220,7 +220,7 @@ ec_sdo_entry_t;
typedef struct
{
struct list_head list; /**< list item */
const ec_field_t *field; /**< data field */
const ec_sii_pdo_t *pdo; /**< PDO */
size_t size; /**< field size */
}
ec_varsize_t;
@@ -237,6 +237,12 @@ struct ec_slave
struct kobject kobj; /**< kobject */
ec_master_t *master; /**< master owning the slave */
ec_slave_state_t requested_state; /**< requested slave state */
ec_slave_state_t current_state; /**< current slave state */
unsigned int error_flag; /**< stop processing after an error */
unsigned int online; /**< non-zero, if the slave responds. */
uint8_t registered; /**< true, if slave has been registered */
// addresses
uint16_t ring_position; /**< ring position */
uint16_t station_address; /**< configured station address */
@@ -255,6 +261,12 @@ struct ec_slave
uint8_t dl_loop[4]; /**< loop closed */
uint8_t dl_signal[4]; /**< detected signal on RX port */
// EEPROM
uint8_t *eeprom_data; /**< Complete EEPROM image */
uint16_t eeprom_size; /**< size of the EEPROM contents in byte */
uint16_t *new_eeprom_data; /**< new EEPROM data to write */
uint16_t new_eeprom_size; /**< size of new EEPROM data in words */
// slave information interface
uint16_t sii_alias; /**< configured station alias */
uint32_t sii_vendor_id; /**< vendor id */
@@ -267,34 +279,19 @@ struct ec_slave
uint16_t sii_tx_mailbox_size; /**< mailbox size (slave to master) */
uint16_t sii_mailbox_protocols; /**< supported mailbox protocols */
uint8_t sii_physical_layer[4]; /**< port media */
const ec_slave_type_t *type; /**< pointer to slave type object */
uint8_t registered; /**< true, if slave has been registered */
struct list_head sii_strings; /**< EEPROM STRING categories */
struct list_head sii_syncs; /**< EEPROM SYNC MANAGER categories */
struct list_head sii_pdos; /**< EEPROM [RT]XPDO categories */
char *sii_group; /**< slave group acc. to EEPROM */
char *sii_image; /**< slave image name acc. to EEPROM */
char *sii_order; /**< slave order number acc. to EEPROM */
char *sii_name; /**< slave name acc. to EEPROM */
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU configurations */
uint8_t fmmu_count; /**< number of FMMUs used */
uint8_t *eeprom_data; /**< Complete EEPROM image */
uint16_t eeprom_size; /**< size of the EEPROM contents in byte */
struct list_head eeprom_strings; /**< EEPROM STRING categories */
struct list_head eeprom_syncs; /**< EEPROM SYNC MANAGER categories */
struct list_head eeprom_pdos; /**< EEPROM [RT]XPDO categories */
char *eeprom_group; /**< slave group acc. to EEPROM */
char *eeprom_image; /**< slave image name acc. to EEPROM */
char *eeprom_order; /**< slave order number acc. to EEPROM */
char *eeprom_name; /**< slave name acc. to EEPROM */
uint16_t *new_eeprom_data; /**< new EEPROM data to write */
size_t new_eeprom_size; /**< size of new EEPROM data in words */
struct list_head sdo_dictionary; /**< SDO directory list */
ec_slave_state_t requested_state; /**< requested slave state */
ec_slave_state_t current_state; /**< current slave state */
unsigned int error_flag; /**< stop processing after an error */
unsigned int online; /**< non-zero, if the slave responds. */
struct list_head varsize_fields; /**< size information for variable-sized
data fields. */
};
@@ -305,32 +302,27 @@ struct ec_slave
int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t);
void ec_slave_clear(struct kobject *);
// slave control
int ec_slave_fetch(ec_slave_t *);
int ec_slave_sii_read16(ec_slave_t *, uint16_t, uint16_t *);
int ec_slave_sii_read32(ec_slave_t *, uint16_t, uint32_t *);
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_prepare_fmmu(ec_slave_t *, const ec_domain_t *,
const ec_sync_t *);
const ec_sii_sync_t *);
// CoE
int ec_slave_fetch_sdo_list(ec_slave_t *);
//int ec_slave_fetch_sdo_list(ec_slave_t *);
// state machine
// SII categories
int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *);
int ec_slave_fetch_general(ec_slave_t *, const uint8_t *);
void ec_slave_fetch_general(ec_slave_t *, const uint8_t *);
int ec_slave_fetch_sync(ec_slave_t *, const uint8_t *, size_t);
int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t, ec_pdo_type_t);
int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t,
ec_sii_pdo_type_t);
int ec_slave_locate_string(ec_slave_t *, unsigned int, char **);
// misc.
size_t ec_slave_calc_sync_size(const ec_slave_t *, const ec_sync_t *);
uint16_t ec_slave_calc_eeprom_sync_size(const ec_slave_t *,
const ec_eeprom_sync_t *);
uint16_t ec_slave_calc_sync_size(const ec_slave_t *,
const ec_sii_sync_t *);
void ec_slave_print(const ec_slave_t *, unsigned int);
int ec_slave_check_crc(ec_slave_t *);
int ec_slave_is_coupler(const ec_slave_t *);
//int ec_slave_check_crc(ec_slave_t *);
/*****************************************************************************/
-280
View File
@@ -1,280 +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
EtherCAT slave descriptions.
\cond
*/
/*****************************************************************************/
#include <linux/module.h>
#include "globals.h"
#include "types.h"
/*****************************************************************************/
const ec_sync_t mailbox_sm0 = {0x1800, 246, 0x26, {NULL}};
const ec_sync_t mailbox_sm1 = {0x18F6, 246, 0x22, {NULL}};
/******************************************************************************
* slave objects
*****************************************************************************/
const ec_slave_type_t Beckhoff_EK1100 = {
"Beckhoff", "EK1100", "Bus Coupler", EC_TYPE_BUS_COUPLER,
{NULL} // no sync managers
};
/*****************************************************************************/
const ec_slave_type_t Beckhoff_EK1110 = {
"Beckhoff", "EK1110", "Extension terminal", EC_TYPE_INFRA,
{NULL} // no sync managers
};
/*****************************************************************************/
const ec_field_t bk1120_out = {"Outputs", 0}; // variable size
const ec_field_t bk1120_in = {"Inputs", 0}; // variable size
const ec_sync_t bk1120_sm0 = {0x1C00, 264, 0x26, {NULL}};
const ec_sync_t bk1120_sm1 = {0x1E00, 264, 0x22, {NULL}};
const ec_sync_t bk1120_sm2 = { // outputs
0x1000, 0, 0x24, // variable size
{&bk1120_out, NULL}
};
const ec_sync_t bk1120_sm3 = { // inputs
0x1600, 0, 0x00, // variable size
{&bk1120_in, NULL}
};
const ec_slave_type_t Beckhoff_BK1120 = {
"Beckhoff", "BK1120", "KBUS Coupler", EC_TYPE_NORMAL,
{&bk1120_sm0, &bk1120_sm1, &bk1120_sm2, &bk1120_sm3, NULL}
};
/*****************************************************************************/
const ec_field_t el1004_in = {"InputValue", 1};
const ec_sync_t el1004_sm0 = { // inputs
0x1000, 1, 0x00,
{&el1004_in, NULL}
};
const ec_slave_type_t Beckhoff_EL1004 = {
"Beckhoff", "EL1004", "4x Digital Input, 3ms", EC_TYPE_NORMAL,
{&el1004_sm0, NULL}
};
/*****************************************************************************/
const ec_field_t el1014_in = {"InputValue", 1};
const ec_sync_t el1014_sm0 = { // inputs
0x1000, 1, 0x00,
{&el1014_in, NULL}
};
const ec_slave_type_t Beckhoff_EL1014 = {
"Beckhoff", "EL1014", "4x Digital Input, 10us", EC_TYPE_NORMAL,
{&el1014_sm0, NULL}
};
/*****************************************************************************/
const ec_field_t el20XX_out = {"OutputValue", 1};
const ec_sync_t el20XX_sm0 = {
0x0F00, 1, 0x46,
{&el20XX_out, NULL}
};
const ec_slave_type_t Beckhoff_EL2004 = {
"Beckhoff", "EL2004", "4x Digital Output", EC_TYPE_NORMAL,
{&el20XX_sm0, NULL}
};
const ec_slave_type_t Beckhoff_EL2032 = {
"Beckhoff", "EL2032", "2x Digital Output (2A)", EC_TYPE_NORMAL,
{&el20XX_sm0, NULL}
};
/*****************************************************************************/
const ec_field_t el31X2_st1 = {"Status", 1};
const ec_field_t el31X2_ip1 = {"InputValue", 2};
const ec_field_t el31X2_st2 = {"Status", 1};
const ec_field_t el31X2_ip2 = {"InputValue", 2};
const ec_sync_t el31X2_sm2 = {0x1000, 4, 0x24, {NULL}};
const ec_sync_t el31X2_sm3 = {
0x1100, 6, 0x20,
{&el31X2_st1, &el31X2_ip1, &el31X2_st2, &el31X2_ip2, NULL}
};
const ec_slave_type_t Beckhoff_EL3102 = {
"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", EC_TYPE_NORMAL,
{&mailbox_sm0, &mailbox_sm1, &el31X2_sm2, &el31X2_sm3, NULL}
};
/*****************************************************************************/
const ec_field_t el41X2_op = {"OutputValue", 2};
const ec_sync_t el41X2_sm2 = {
0x1000, 4, 0x24,
{&el41X2_op, &el41X2_op, NULL}
};
const ec_slave_type_t Beckhoff_EL4102 = {
"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.", EC_TYPE_NORMAL,
{&mailbox_sm0, &mailbox_sm1, &el41X2_sm2, NULL}
};
/*****************************************************************************/
const ec_field_t el5001_st = {"Status", 1};
const ec_field_t el5001_ip = {"InputValue", 4};
const ec_sync_t el5001_sm2 = {
0x1000, 4, 0x24,
{NULL}
};
const ec_sync_t el5001_sm3 = {
0x1100, 5, 0x20,
{&el5001_st, &el5001_ip, NULL}
};
const ec_slave_type_t Beckhoff_EL5001 = {
"Beckhoff", "EL5001", "SSI-Interface", EC_TYPE_NORMAL,
{&mailbox_sm0, &mailbox_sm1, &el5001_sm2, &el5001_sm3, NULL}
};
/*****************************************************************************/
const ec_field_t el5101_ct = {"Control", 1};
const ec_field_t el5101_op = {"OutputValue", 2};
const ec_field_t el5101_st = {"Status", 1};
const ec_field_t el5101_ip = {"InputValue", 2};
const ec_field_t el5101_la = {"LatchValue", 2};
const ec_sync_t el5101_sm2 = {
0x1000, 3, 0x24,
{&el5101_ct, &el5101_op, NULL}
};
const ec_sync_t el5101_sm3 = {
0x1100, 5, 0x20,
{&el5101_st, &el5101_ip, &el5101_la, NULL}
};
const ec_slave_type_t Beckhoff_EL5101 = {
"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}
};
/*****************************************************************************/
const ec_field_t trlinenc2_st = {"Status", 1};
const ec_field_t trlinenc2_ip = {"InputValue", 4};
const ec_sync_t trlinenc2_sm0 = {0x1800, 192, 0x26, {NULL}};
const ec_sync_t trlinenc2_sm1 = {0x1C00, 192, 0x22, {NULL}};
const ec_sync_t trlinenc2_sm2 = {0x1000, 4, 0x24, {NULL}};
const ec_sync_t trlinenc2_sm3 = {
0x1100, 5, 0x20,
{&trlinenc2_st, &trlinenc2_ip, NULL}
};
const ec_slave_type_t TR_Electronic_LinEnc2 = {
"TR-Electronic", "LinEnc2", "SSI-Encoder", EC_TYPE_NORMAL,
{&trlinenc2_sm0, &trlinenc2_sm1, &trlinenc2_sm2, &trlinenc2_sm3, NULL}
};
/** \endcond */
/*****************************************************************************/
/**
Mapping between vendor IDs and product codes <=> slave objects.
*/
ec_slave_ident_t slave_idents[] = {
{0x00000002, 0x03EC3052, &Beckhoff_EL1004},
{0x00000002, 0x03F63052, &Beckhoff_EL1014},
{0x00000002, 0x044C2C52, &Beckhoff_EK1100},
{0x00000002, 0x04562C52, &Beckhoff_EK1110},
{0x00000002, 0x04602C22, &Beckhoff_BK1120},
{0x00000002, 0x07D43052, &Beckhoff_EL2004},
{0x00000002, 0x07F03052, &Beckhoff_EL2032},
{0x00000002, 0x0C1E3052, &Beckhoff_EL3102},
{0x00000002, 0x0C5A3052, &Beckhoff_EL3162},
{0x00000002, 0x10063052, &Beckhoff_EL4102},
{0x00000002, 0x10243052, &Beckhoff_EL4132},
{0x00000002, 0x13893052, &Beckhoff_EL5001},
{0x00000002, 0x13ED3052, &Beckhoff_EL5101},
{0x00000002, 0x19C93052, &Beckhoff_EL6601},
{0x000000D4, 0x00000017, &TR_Electronic_LinEnc2},
{}
};
/*****************************************************************************/
-130
View File
@@ -1,130 +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
EtherCAT slave types.
*/
/*****************************************************************************/
#ifndef _EC_TYPES_H_
#define _EC_TYPES_H_
#include <linux/types.h>
#include "../include/ecrt.h"
/*****************************************************************************/
#define EC_MAX_FIELDS 10 /**< maximal number of data fields per sync manager */
#define EC_MAX_SYNC 16 /**< maximal number of sync managers per type */
/*****************************************************************************/
/**
Special slaves.
*/
typedef enum
{
EC_TYPE_NORMAL, /**< no special slave */
EC_TYPE_BUS_COUPLER, /**< slave is a bus coupler */
EC_TYPE_INFRA, /**< infrastructure slaves, that contain no process data */
EC_TYPE_EOE /**< slave is an EoE switch */
}
ec_special_type_t;
/*****************************************************************************/
/**
Process data field.
*/
typedef struct
{
const char *name; /**< field name */
size_t size; /**< field size in bytes */
}
ec_field_t;
/*****************************************************************************/
/**
Sync manager.
*/
typedef struct
{
uint16_t physical_start_address; /**< physical start address */
uint16_t size; /**< size in bytes */
uint8_t control_byte; /**< control register value */
const ec_field_t *fields[EC_MAX_FIELDS]; /**< field array */
}
ec_sync_t;
/*****************************************************************************/
/**
Slave description type.
*/
typedef struct ec_slave_type
{
const char *vendor_name; /**< vendor name*/
const char *product_name; /**< product name */
const char *description; /**< free description */
ec_special_type_t special; /**< special slave type? */
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< sync managers */
}
ec_slave_type_t;
/*****************************************************************************/
/**
Slave type identification.
*/
typedef struct
{
uint32_t vendor_id; /**< vendor id */
uint32_t product_code; /**< product code */
const ec_slave_type_t *type; /**< associated slave description object */
}
ec_slave_ident_t;
extern ec_slave_ident_t slave_idents[]; /**< array with slave descriptions */
/*****************************************************************************/
#endif
+4 -1
View File
@@ -163,7 +163,7 @@ case "$1" in
fi
# unload conflicting modules at first
for mod in 8139too 8139cp; do
for mod in 8139too; do
if lsmod | grep "^$mod " > /dev/null; then
if ! rmmod $mod; then
/bin/false
@@ -175,6 +175,7 @@ case "$1" in
# load master module
if ! modprobe ec_master ec_eoeif_count=$EOE_INTERFACES; then
modprobe 8139too
/bin/false
rc_status -v
rc_exit
@@ -182,6 +183,8 @@ case "$1" in
# load device module
if ! modprobe ec_8139too ec_device_index=$DEVICE_INDEX; then
rmmod ec_master
modprobe 8139too
/bin/false
rc_status -v
rc_exit
+35 -80
View File
@@ -42,7 +42,6 @@ use Getopt::Std;
my $master_index;
my $master_dir;
my $show_sii_naming;
#------------------------------------------------------------------------------
@@ -63,45 +62,43 @@ sub query_master
sub query_slaves
{
my $dirhandle;
my $slave_dir;
my $entry;
my $slave_index;
my $file_name;
my $vendor_name;
my @slaves;
my $slave;
my $abs;
my $line;
unless (opendir $dirhandle, $master_dir) {
print "Failed to open directory \"$master_dir\".\n";
exit 1;
print "Failed to open directory \"$master_dir\".\n";
exit 1;
}
while ($entry = readdir $dirhandle) {
next unless $entry =~ /^slave(\d+)$/;
$slave_dir = $master_dir . "/" . $entry;
$slave = {};
$slave->{'ring_position'} =
&read_integer("$slave_dir/ring_position");
$slave->{'advanced_position'} =
&read_string("$slave_dir/advanced_position");
unless ($show_sii_naming) {
$slave->{'vendor_name'} =
&read_string("$slave_dir/vendor_name");
$slave->{'product_name'} =
&read_string("$slave_dir/product_name");
$slave->{'product_desc'} =
&read_string("$slave_dir/product_desc");
}
else {
$slave->{'name'} =
&read_string("$slave_dir/name");
}
$slave->{'type'} =
&read_string("$slave_dir/type");
$slave = {};
push @slaves, $slave;
open INFO, "$master_dir/$entry/info" or die
"ERROR: Failed to open $master_dir/$entry/info";
while ($line = <INFO>) {
if ($line =~ /^Name: (.*)$/) {
$slave->{'name'} = $1;
}
elsif ($line =~ /^Ring position: (\d+)$/) {
$slave->{'ring_position'} = $1;
}
elsif ($line =~ /^Advanced position: (\d+:\d+)$/) {
$slave->{'advanced_position'} = $1;
}
elsif ($line =~ /^State: (.+)$/) {
$slave->{'state'} = $1;
}
}
close INFO;
push @slaves, $slave;
}
closedir $dirhandle;
@@ -109,82 +106,40 @@ sub query_slaves
print "EtherCAT bus listing for master $master_index:\n";
for $slave (@slaves) {
if ($slave->{'type'} eq "coupler") {
print "--------------------------------------------------------\n";
}
$abs = sprintf "%i", $slave->{'ring_position'};
printf(" %3s %8s ", $abs, $slave->{'advanced_position'});
unless ($show_sii_naming) {
printf("%-12s %-10s %s\n", $slave->{'vendor_name'},
$slave->{'product_name'}, $slave->{'product_desc'});
}
else {
printf("%s\n", $slave->{'name'});
}
$abs = sprintf "%i", $slave->{'ring_position'};
printf(" %3s %8s %-6s %s\n",
$abs, $slave->{'advanced_position'},
$slave->{'state'}, $slave->{'name'});
}
}
#------------------------------------------------------------------------------
sub read_string
{
(my $file_name) = @_;
my $data;
$data = `cat $file_name 2>/dev/null`;
if ($?) {
print "ERROR: Unable to read string $file_name!\n";
exit 1;
}
chomp $data;
return $data;
}
#------------------------------------------------------------------------------
sub read_integer
{
(my $file_name) = @_;
if (`cat $file_name 2>/dev/null` !~ /^(\d+)$/) {
print "ERROR: Unable to read integer $file_name!\n";
exit 1;
}
return int $1;
}
#------------------------------------------------------------------------------
sub get_options
{
my %opt;
my $optret;
$optret = getopts "m:sh", \%opt;
$optret = getopts "m:h", \%opt;
&print_usage if defined $opt{'h'} or $#ARGV > -1 or !$optret;
if (defined $opt{'m'}) {
$master_index = $opt{'m'};
$master_index = $opt{'m'};
}
else {
$master_index = 0;
$master_index = 0;
}
$show_sii_naming = defined $opt{'s'};
}
#------------------------------------------------------------------------------
sub print_usage
{
print "Usage: $0 [OPTIONS]\n";
my $cmd = `basename $0`;
chomp $cmd;
print "Usage: $cmd [OPTIONS]\n";
print " -m <IDX> Query master <IDX>.\n";
print " -s Show EEPROM name instead of";
print " vendor/product/description.\n";
print " -h Show this help.\n";
exit 0;
}