mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-09-21 01:23:45 +08:00
VERSION 1.1: New realtime interface, only state machines.
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+3
-18
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+7
-11
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+53
-61
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user