# HG changeset patch # User Florian Pose # Date 1154609477 0 # Node ID 7833cf70c4f2c5f46a9738d39ebb41abc349cfd4 # Parent 9aa51cbdbfae3bf6744ba7be838409d8a0048ead VERSION 1.1: New realtime interface, only state machines. diff -r 9aa51cbdbfae -r 7833cf70c4f2 TODO --- a/TODO Wed Aug 02 23:16:10 2006 +0000 +++ b/TODO Thu Aug 03 12:51:17 2006 +0000 @@ -8,12 +8,6 @@ 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 diff -r 9aa51cbdbfae -r 7833cf70c4f2 examples/mini/mini.c --- a/examples/mini/mini.c Wed Aug 02 23:16:10 2006 +0000 +++ b/examples/mini/mini.c Thu Aug 03 12:51:17 2006 +0000 @@ -42,8 +42,8 @@ #include #include "../../include/ecrt.h" // EtherCAT realtime interface +#include "../../include/ecdb.h" // EtherCAT slave database -#define ASYNC #define FREQUENCY 100 /*****************************************************************************/ @@ -56,16 +56,14 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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: diff -r 9aa51cbdbfae -r 7833cf70c4f2 examples/msr/msr_sample.c --- a/examples/msr/msr_sample.c Wed Aug 02 23:16:10 2006 +0000 +++ b/examples/msr/msr_sample.c Thu Aug 03 12:51:17 2006 +0000 @@ -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_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; - -ec_field_init_t domain1_fields[] = { - {&r_ssi, "0:3", "Beckhoff", "EL5001", "InputValue", 0}, - {&r_ssi_st, "0:3", "Beckhoff", "EL5001", "Status", 0}, +double k_ana_out; + +ec_pdo_reg_t domain1_pdos[] = { + {"3", Beckhoff_EL4132_Output1, &r_ana_out}, {} }; @@ -85,28 +81,16 @@ { 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); + + // Process data + EC_WRITE_S16(r_ana_out, k_ana_out / 10.0 * 0x7FFF); + + // Send 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); - -#ifdef ASYNC - // Senden - ecrt_domain_queue(domain1); - ecrt_master_run(master); - ecrt_master_async_send(master); -#endif + ecrt_master_send(master); rt_sem_signal(&master_sem); @@ -128,8 +112,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ rt_task_delete(&task); out_stop_timer: stop_rt_timer(); - out_deactivate: ecrt_master_deactivate(master); out_release_master: ecrt_release_master(master); diff -r 9aa51cbdbfae -r 7833cf70c4f2 examples/rtai/rtai_sample.c --- a/examples/rtai/rtai_sample.c Wed Aug 02 23:16:10 2006 +0000 +++ b/examples/rtai/rtai_sample.c Thu Aug 03 12:51:17 2006 +0000 @@ -42,6 +42,7 @@ // EtherCAT #include "../../include/ecrt.h" +#include "../../include/ecdb.h" /*****************************************************************************/ @@ -51,12 +52,8 @@ /*****************************************************************************/ -// comment this for synchronous IO -#define ASYNC - // RTAI task frequency in Hz #define FREQUENCY 10000 - #define TIMERTICKS (1000000000 / FREQUENCY) /*****************************************************************************/ @@ -64,22 +61,20 @@ // 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 @@ 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); + + // process data + //k_pos = EC_READ_U32(r_ssi_input); + ecrt_master_run(master); - ecrt_master_sync_io(master); - ecrt_domain_process(domain1); -#endif - - // process data - 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 @@ 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 @@ 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 @@ rt_task_delete(&task); out_stop_timer: stop_rt_timer(); - out_deactivate: ecrt_master_deactivate(master); out_release_master: ecrt_release_master(master); diff -r 9aa51cbdbfae -r 7833cf70c4f2 include/ecdb.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/ecdb.h Thu Aug 03 12:51:17 2006 +0000 @@ -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 diff -r 9aa51cbdbfae -r 7833cf70c4f2 include/ecrt.h --- a/include/ecrt.h Wed Aug 02 23:16:10 2006 +0000 +++ b/include/ecrt.h Thu Aug 03 12:51:17 2006 +0000 @@ -69,23 +69,22 @@ 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 @@ 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_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_prepare(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); - -void ecrt_domain_queue(ec_domain_t *domain); +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_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_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_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_pdo_size(ec_slave_t *slave, uint16_t pdo_index, + uint8_t pdo_subindex, size_t size); /****************************************************************************** * Bitwise read/write macros diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/Makefile --- a/master/Makefile Wed Aug 02 23:16:10 2006 +0000 +++ b/master/Makefile Thu Aug 03 12:51:17 2006 +0000 @@ -42,8 +42,8 @@ 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") diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/canopen.c --- a/master/canopen.c Wed Aug 02 23:16:10 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,726 +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 - Canopen-over-EtherCAT functions. -*/ - -/*****************************************************************************/ - -#include -#include -#include - -#include "master.h" -#include "mailbox.h" - -/*****************************************************************************/ - -void ec_canopen_abort_msg(uint32_t); -int ec_slave_fetch_sdo_descriptions(ec_slave_t *, ec_datagram_t *); -int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_datagram_t *, - ec_sdo_t *, uint8_t); - -/*****************************************************************************/ - -/** - Reads 32 bit of a CANopen SDO in expedited mode. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint8_t *target /**< 4-byte memory */ - ) -{ - ec_datagram_t datagram; - size_t rec_size; - uint8_t *data; - - ec_datagram_init(&datagram); - - if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6))) - goto err; - - EC_WRITE_U16(data, 0x2 << 12); // SDO request - EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer - | 0x2 << 5)); // initiate upload request - EC_WRITE_U16(data + 3, sdo_index); - EC_WRITE_U8 (data + 5, sdo_subindex); - - if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size))) - goto err; - - if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request - EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request - EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", - sdo_index, sdo_subindex, slave->ring_position); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - goto err; - } - - if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response - EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response - EC_READ_U16(data + 3) != sdo_index || // index - EC_READ_U8 (data + 5) != sdo_subindex) { // subindex - EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); - EC_ERR("Invalid SDO upload response at slave %i!\n", - slave->ring_position); - ec_print_data(data, rec_size); - goto err; - } - - memcpy(target, data + 6, 4); - - ec_datagram_clear(&datagram); - return 0; - err: - ec_datagram_clear(&datagram); - return -1; -} - -/*****************************************************************************/ - -/** - Writes a CANopen SDO using expedited mode. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - const uint8_t *sdo_data, /**< new value */ - size_t size /**< Data size in bytes (1 - 4) */ - ) -{ - uint8_t *data; - size_t rec_size; - ec_datagram_t datagram; - - ec_datagram_init(&datagram); - - if (size == 0 || size > 4) { - EC_ERR("Invalid data size!\n"); - goto err; - } - - if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 0x0A))) - goto err; - - EC_WRITE_U16(data, 0x2 << 12); // SDO request - EC_WRITE_U8 (data + 2, (0x1 // size specified - | 0x1 << 1 // expedited transfer - | (4 - size) << 2 // data set size - | 0x1 << 5)); // initiate download request - EC_WRITE_U16(data + 3, sdo_index); - EC_WRITE_U8 (data + 5, sdo_subindex); - memcpy(data + 6, sdo_data, size); - if (size < 4) memset(data + 6 + size, 0x00, 4 - size); - - if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size))) - goto err; - - if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request - EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request - EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n", - sdo_index, sdo_subindex, size, slave->ring_position); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - return -1; - } - - if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response - EC_READ_U8 (data + 2) >> 5 != 0x3 || // download response - EC_READ_U16(data + 3) != sdo_index || // index - EC_READ_U8 (data + 5) != sdo_subindex) { // subindex - EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n", - sdo_index, sdo_subindex, size); - EC_ERR("Invalid SDO download response at slave %i!\n", - slave->ring_position); - ec_print_data(data, rec_size); - return -1; - } - - ec_datagram_clear(&datagram); - return 0; - err: - ec_datagram_clear(&datagram); - return -1; -} - -/*****************************************************************************/ - -/** - Reads a CANopen SDO in normal mode. - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface - \todo Make size non-pointer. -*/ - -int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint8_t *target, /**< memory for value */ - size_t *size /**< target memory size */ - ) -{ - uint8_t *data; - size_t rec_size, data_size; - uint32_t complete_size; - ec_datagram_t datagram; - - ec_datagram_init(&datagram); - - if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6))) - goto err; - - EC_WRITE_U16(data, 0x2 << 12); // SDO request - EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request - EC_WRITE_U16(data + 3, sdo_index); - EC_WRITE_U8 (data + 5, sdo_subindex); - - if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size))) - goto err; - - if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request - EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request - EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n", - sdo_index, sdo_subindex, slave->ring_position); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - goto err; - } - - if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response - EC_READ_U8 (data + 2) >> 5 != 0x2 || // initiate upload response - EC_READ_U16(data + 3) != sdo_index || // index - EC_READ_U8 (data + 5) != sdo_subindex) { // subindex - EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex); - EC_ERR("Invalid SDO upload response at slave %i!\n", - slave->ring_position); - ec_print_data(data, rec_size); - goto err; - } - - if (rec_size < 10) { - EC_ERR("Received currupted SDO upload response!\n"); - ec_print_data(data, rec_size); - goto err; - } - - if ((complete_size = EC_READ_U32(data + 6)) > *size) { - EC_ERR("SDO data does not fit into buffer (%i / %i)!\n", - complete_size, *size); - goto err; - } - - data_size = rec_size - 10; - - if (data_size != complete_size) { - EC_ERR("SDO data incomplete - Fragmenting not implemented.\n"); - goto err; - } - - memcpy(target, data + 10, data_size); - - ec_datagram_clear(&datagram); - return 0; - err: - ec_datagram_clear(&datagram); - return -1; -} - -/*****************************************************************************/ - -/** - Fetches the SDO dictionary of a slave. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */) -{ - uint8_t *data; - size_t rec_size; - unsigned int i, sdo_count; - ec_sdo_t *sdo; - uint16_t sdo_index; - ec_datagram_t datagram; - - ec_datagram_init(&datagram); - - if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 8))) - goto err; - - EC_WRITE_U16(data, 0x8 << 12); // SDO information - EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request - EC_WRITE_U8 (data + 3, 0x00); - EC_WRITE_U16(data + 4, 0x0000); - EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs! - - if (unlikely(ec_master_simple_io(slave->master, &datagram))) { - EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position); - goto err; - } - - do { - if (!(data = ec_slave_mbox_simple_receive(slave, &datagram, - 0x03, &rec_size))) - goto err; - - if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information - (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response - EC_ERR("SDO information error response at slave %i!\n", - slave->ring_position); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - goto err; - } - - if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information - (EC_READ_U8 (data + 2) & 0x7F) != 0x02) { // Get OD List response - EC_ERR("Invalid SDO list response at slave %i!\n", - slave->ring_position); - ec_print_data(data, rec_size); - goto err; - } - - if (rec_size < 8) { - EC_ERR("Invalid data size!\n"); - ec_print_data(data, rec_size); - goto err; - } - - sdo_count = (rec_size - 8) / 2; - for (i = 0; i < sdo_count; i++) { - sdo_index = EC_READ_U16(data + 8 + i * 2); - if (!sdo_index) continue; // sometimes index is 0... ??? - - if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate memory for SDO!\n"); - goto err; - } - - // Initialize SDO object - sdo->index = sdo_index; - //sdo->unkown = 0x0000; - sdo->object_code = 0x00; - sdo->name = NULL; - INIT_LIST_HEAD(&sdo->entries); - - list_add_tail(&sdo->list, &slave->sdo_dictionary); - } - } - while (EC_READ_U8(data + 2) & 0x80); - - // Fetch all SDO descriptions - if (ec_slave_fetch_sdo_descriptions(slave, &datagram)) goto err; - - ec_datagram_clear(&datagram); - return 0; - err: - ec_datagram_clear(&datagram); - return -1; -} - -/*****************************************************************************/ - -/** - Fetches the SDO descriptions for the known SDOs. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */ - ec_datagram_t *datagram /**< datagram */ - ) -{ - uint8_t *data; - size_t rec_size, name_size; - ec_sdo_t *sdo; - - list_for_each_entry(sdo, &slave->sdo_dictionary, list) { - if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) - return -1; - EC_WRITE_U16(data, 0x8 << 12); // SDO information - EC_WRITE_U8 (data + 2, 0x03); // Get object description request - EC_WRITE_U8 (data + 3, 0x00); - EC_WRITE_U16(data + 4, 0x0000); - EC_WRITE_U16(data + 6, sdo->index); // SDO index - - if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size))) - return -1; - - if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information - (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response - EC_ERR("SDO information error response at slave %i while" - " fetching SDO 0x%04X!\n", slave->ring_position, - sdo->index); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - return -1; - } - - if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information - (EC_READ_U8 (data + 2) & 0x7F) != 0x04 || // Object desc. response - EC_READ_U16(data + 6) != sdo->index) { // SDO index - EC_ERR("Invalid object description response at slave %i while" - " fetching SDO 0x%04X!\n", slave->ring_position, - sdo->index); - ec_print_data(data, rec_size); - return -1; - } - - if (rec_size < 12) { - EC_ERR("Invalid data size!\n"); - ec_print_data(data, rec_size); - return -1; - } - -#if 0 - EC_DBG("object desc response:\n"); - ec_print_data(data, rec_size); -#endif - - //sdo->unknown = EC_READ_U16(data + 8); - sdo->object_code = EC_READ_U8(data + 11); - - name_size = rec_size - 12; - if (name_size) { - if (!(sdo->name = kmalloc(name_size + 1, GFP_KERNEL))) { - EC_ERR("Failed to allocate SDO name!\n"); - return -1; - } - - memcpy(sdo->name, data + 12, name_size); - sdo->name[name_size] = 0; - } - - if (EC_READ_U8(data + 2) & 0x80) { - EC_ERR("Fragment follows (not implemented)!\n"); - return -1; - } - - // Fetch all entries (subindices) - if (ec_slave_fetch_sdo_entries(slave, datagram, sdo, - EC_READ_U8(data + 10))) - return -1; - } - - return 0; -} - -/*****************************************************************************/ - -/** - Fetches all entries (subindices) to an SDO. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */ - ec_datagram_t *datagram, /**< datagram */ - ec_sdo_t *sdo, /**< SDO */ - uint8_t subindices /**< number of subindices */ - ) -{ - uint8_t *data; - size_t rec_size, data_size; - uint8_t i; - ec_sdo_entry_t *entry; - - for (i = 1; i <= subindices; i++) { - if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) - return -1; - - EC_WRITE_U16(data, 0x8 << 12); // SDO information - EC_WRITE_U8 (data + 2, 0x05); // Get entry description request - EC_WRITE_U8 (data + 3, 0x00); - EC_WRITE_U16(data + 4, 0x0000); - EC_WRITE_U16(data + 6, sdo->index); // SDO index - EC_WRITE_U8 (data + 8, i); // SDO subindex - EC_WRITE_U8 (data + 9, 0x00); // value info (no values) - - if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size))) - return -1; - - if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information - (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response - EC_ERR("SDO information error response at slave %i while" - " fetching SDO entry 0x%04X:%i!\n", slave->ring_position, - sdo->index, i); - ec_canopen_abort_msg(EC_READ_U32(data + 6)); - return -1; - } - - if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information - (EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response - EC_READ_U16(data + 6) != sdo->index || // SDO index - EC_READ_U8(data + 8) != i) { // SDO subindex - EC_ERR("Invalid entry description response at slave %i while" - " fetching SDO entry 0x%04X:%i!\n", slave->ring_position, - sdo->index, i); - ec_print_data(data, rec_size); - return -1; - } - - if (rec_size < 16) { - EC_ERR("Invalid data size!\n"); - ec_print_data(data, rec_size); - return -1; - } - - if (!EC_READ_U16(data + 12)) // bit length = 0 - continue; - - data_size = rec_size - 16; - - if (!(entry = (ec_sdo_entry_t *) - kmalloc(sizeof(ec_sdo_entry_t) + data_size + 1, GFP_KERNEL))) { - EC_ERR("Failed to allocate entry!\n"); - return -1; - } - - entry->subindex = i; - entry->data_type = EC_READ_U16(data + 10); - entry->bit_length = EC_READ_U16(data + 12); - - // memory for name string appended to entry - entry->name = (uint8_t *) entry + sizeof(ec_sdo_entry_t); - - memcpy(entry->name, data + 16, data_size); - entry->name[data_size] = 0; - - list_add_tail(&entry->list, &sdo->entries); - } - - return 0; -} - -/*****************************************************************************/ - -/** - SDO abort messages. - The "abort SDO transfer request" supplies an abort code, - which can be translated to clear text. This table does - the mapping of the codes and messages. -*/ - -const ec_code_msg_t sdo_abort_messages[] = { - {0x05030000, "Toggle bit not changed"}, - {0x05040000, "SDO protocol timeout"}, - {0x05040001, "Client/Server command specifier not valid or unknown"}, - {0x05040005, "Out of memory"}, - {0x06010000, "Unsupported access to an object"}, - {0x06010001, "Attempt to read a write-only object"}, - {0x06010002, "Attempt to write a read-only object"}, - {0x06020000, "This object does not exist in the object directory"}, - {0x06040041, "The object cannot be mapped into the PDO"}, - {0x06040042, "The number and length of the objects to be mapped would" - " exceed the PDO length"}, - {0x06040043, "General parameter incompatibility reason"}, - {0x06040047, "Gerneral internal incompatibility in device"}, - {0x06060000, "Access failure due to a hardware error"}, - {0x06070010, "Data type does not match, length of service parameter does" - " not match"}, - {0x06070012, "Data type does not match, length of service parameter too" - " high"}, - {0x06070013, "Data type does not match, length of service parameter too" - " low"}, - {0x06090011, "Subindex does not exist"}, - {0x06090030, "Value range of parameter exceeded"}, - {0x06090031, "Value of parameter written too high"}, - {0x06090032, "Value of parameter written too low"}, - {0x06090036, "Maximum value is less than minimum value"}, - {0x08000000, "General error"}, - {0x08000020, "Data cannot be transferred or stored to the application"}, - {0x08000021, "Data cannot be transferred or stored to the application" - " because of local control"}, - {0x08000022, "Data cannot be transferred or stored to the application" - " because of the present device state"}, - {0x08000023, "Object dictionary dynamic generation fails or no object" - " dictionary is present"}, - {} -}; - -/*****************************************************************************/ - -/** - Outputs an SDO abort message. -*/ - -void ec_canopen_abort_msg(uint32_t abort_code) -{ - const ec_code_msg_t *abort_msg; - - for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) { - if (abort_msg->code == abort_code) { - EC_ERR("SDO abort message 0x%08X: \"%s\".\n", - abort_msg->code, abort_msg->message); - return; - } - } - - EC_ERR("Unknown SDO abort code 0x%08X.\n", abort_code); -} - -/****************************************************************************** - * Realtime interface - *****************************************************************************/ - -/** - Reads an 8-bit SDO in expedited mode. - See ec_slave_sdo_read_exp() - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint8_t *target /**< memory for read value */ - ) -{ - uint8_t data[4]; - if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; - *target = EC_READ_U8(data); - return 0; -} - -/*****************************************************************************/ - -/** - Reads a 16-bit SDO in expedited mode. - See ec_slave_sdo_read_exp() - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint16_t *target /**< memory for read value */ - ) -{ - uint8_t data[4]; - if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; - *target = EC_READ_U16(data); - return 0; -} - -/*****************************************************************************/ - -/** - Reads a 32-bit SDO in expedited mode. - See ec_slave_sdo_read_exp() - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint32_t *target /**< memory for read value */ - ) -{ - uint8_t data[4]; - if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1; - *target = EC_READ_U32(data); - return 0; -} - -/*****************************************************************************/ - -/** - Writes an 8-bit SDO in expedited mode. - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint8_t value /**< new value */ - ) -{ - return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1); -} - -/*****************************************************************************/ - -/** - Writes a 16-bit SDO in expedited mode. - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint16_t value /**< new value */ - ) -{ - uint8_t data[2]; - EC_WRITE_U16(data, value); - return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 2); -} - -/*****************************************************************************/ - -/** - Writes a 32-bit SDO in expedited mode. - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t sdo_index, /**< SDO index */ - uint8_t sdo_subindex, /**< SDO subindex */ - uint32_t value /**< new value */ - ) -{ - uint8_t data[4]; - EC_WRITE_U32(data, value); - return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 4); -} - -/*****************************************************************************/ - -/** \cond */ - -EXPORT_SYMBOL(ecrt_slave_sdo_read_exp8); -EXPORT_SYMBOL(ecrt_slave_sdo_read_exp16); -EXPORT_SYMBOL(ecrt_slave_sdo_read_exp32); -EXPORT_SYMBOL(ecrt_slave_sdo_write_exp8); -EXPORT_SYMBOL(ecrt_slave_sdo_write_exp16); -EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32); -EXPORT_SYMBOL(ecrt_slave_sdo_read); - -/** \endcond */ - -/*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/datagram.c --- a/master/datagram.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/datagram.c Thu Aug 03 12:51:17 2006 +0000 @@ -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 @@ 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 @@ 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 @@ ) { 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 @@ ) { 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 @@ ) { 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 @@ ) { 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 @@ ) { EC_FUNC_HEADER; - datagram->type = EC_CMD_LRW; + datagram->type = EC_DATAGRAM_LRW; datagram->address.logical = offset; EC_FUNC_FOOTER; } diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/datagram.h --- a/master/datagram.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/datagram.h Thu Aug 03 12:51:17 2006 +0000 @@ -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 @@ 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; diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/domain.c --- a/master/domain.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/domain.c Thu Aug 03 12:51:17 2006 +0000 @@ -46,7 +46,23 @@ /*****************************************************************************/ -void ec_domain_clear_field_regs(ec_domain_t *); +/** + Data registration type. +*/ + +typedef struct +{ + struct list_head list; /**< list item */ + ec_slave_t *slave; /**< slave */ + const ec_sii_sync_t *sync; /**< sync manager */ + off_t sync_offset; /**< pdo offset */ + void **data_ptr; /**< pointer to process data pointer(s) */ +} +ec_data_reg_t; + +/*****************************************************************************/ + +void ec_domain_clear_data_regs(ec_domain_t *); ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *); /*****************************************************************************/ @@ -91,7 +107,7 @@ domain->base_address = 0; domain->response_count = 0xFFFFFFFF; - INIT_LIST_HEAD(&domain->field_regs); + INIT_LIST_HEAD(&domain->data_regs); INIT_LIST_HEAD(&domain->datagrams); // init kobject and add it to the hierarchy @@ -127,7 +143,7 @@ kfree(datagram); } - ec_domain_clear_field_regs(domain); + ec_domain_clear_data_regs(domain); kfree(domain); } @@ -139,34 +155,70 @@ \return 0 in case of success, else < 0 */ -int ec_domain_reg_field(ec_domain_t *domain, /**< EtherCAT domain */ - ec_slave_t *slave, /**< slave */ - const ec_sync_t *sync, /**< sync manager */ - uint32_t field_offset, /**< data field offset */ - void **data_ptr /**< pointer to the process data - pointer */ - ) -{ - ec_field_reg_t *field_reg; - - if (!(field_reg = - (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate field registration.\n"); +int ec_domain_reg_pdo_entry(ec_domain_t *domain, /**< EtherCAT domain */ + ec_slave_t *slave, /**< slave */ + const ec_sii_pdo_t *pdo, + const ec_sii_pdo_entry_t *entry, + /**< PDO registration entry */ + void **data_ptr /**< pointer to the process data + pointer */ + ) +{ + ec_data_reg_t *data_reg; + const ec_sii_sync_t *sync; + const ec_sii_pdo_t *other_pdo; + const ec_sii_pdo_entry_t *other_entry; + unsigned int bit_offset, byte_offset, sync_found; + + // Find sync manager for PDO + sync_found = 0; + list_for_each_entry(sync, &slave->sii_syncs, list) { + if (sync->index == pdo->sync_index) { + sync_found = 1; + break; + } + } + + if (!sync_found) { + EC_ERR("No sync manager for PDO 0x%04X:%i.", + pdo->index, entry->subindex); + return -1; + } + + // Calculate offset for process data pointer + bit_offset = 0; + byte_offset = 0; + list_for_each_entry(other_pdo, &slave->sii_pdos, list) { + if (other_pdo->sync_index != sync->index) continue; + + list_for_each_entry(other_entry, &pdo->entries, list) { + if (other_entry == entry) { + byte_offset = bit_offset / 8; + break; + } + bit_offset += other_entry->bit_length; + } + } + + // Allocate memory for data registration object + if (!(data_reg = + (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate data registration.\n"); return -1; } if (ec_slave_prepare_fmmu(slave, domain, sync)) { EC_ERR("FMMU configuration failed.\n"); - kfree(field_reg); + kfree(data_reg); return -1; } - field_reg->slave = slave; - field_reg->sync = sync; - field_reg->field_offset = field_offset; - field_reg->data_ptr = data_ptr; - - list_add_tail(&field_reg->list, &domain->field_regs); + data_reg->slave = slave; + data_reg->sync = sync; + data_reg->sync_offset = byte_offset; + data_reg->data_ptr = data_ptr; + + list_add_tail(&data_reg->list, &domain->data_regs); return 0; } @@ -176,13 +228,13 @@ Clears the list of the registered data fields. */ -void ec_domain_clear_field_regs(ec_domain_t *domain /**< EtherCAT domain */) -{ - ec_field_reg_t *field_reg, *next; - - list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) { - list_del(&field_reg->list); - kfree(field_reg); +void ec_domain_clear_data_regs(ec_domain_t *domain /**< EtherCAT domain */) +{ + ec_data_reg_t *data_reg, *next; + + list_for_each_entry_safe(data_reg, next, &domain->data_regs, list) { + list_del(&data_reg->list); + kfree(data_reg); } } @@ -222,7 +274,7 @@ Creates a domain. Reserves domain memory, calculates the logical addresses of the corresponding FMMUs and sets the process data pointer of the registered - data fields. + process data. \return 0 in case of success, else < 0 */ @@ -230,22 +282,22 @@ uint32_t base_address /**< logical base address */ ) { - ec_field_reg_t *field_reg; + ec_data_reg_t *data_reg; ec_slave_t *slave; ec_fmmu_t *fmmu; - unsigned int i, j, cmd_count; - uint32_t field_off, field_off_cmd; - uint32_t cmd_offset; - size_t cmd_data_size, sync_size; + unsigned int i, j, datagram_count; + uint32_t pdo_off, pdo_off_datagram; + uint32_t datagram_offset; + size_t datagram_data_size, sync_size; ec_datagram_t *datagram; domain->base_address = base_address; // calculate size of process data and allocate memory domain->data_size = 0; - cmd_offset = base_address; - cmd_data_size = 0; - cmd_count = 0; + datagram_offset = base_address; + datagram_data_size = 0; + datagram_count = 0; list_for_each_entry(slave, &domain->master->slaves, list) { for (j = 0; j < slave->fmmu_count; j++) { fmmu = &slave->fmmus[j]; @@ -253,47 +305,48 @@ fmmu->logical_start_address = base_address + domain->data_size; sync_size = ec_slave_calc_sync_size(slave, fmmu->sync); domain->data_size += sync_size; - if (cmd_data_size + sync_size > EC_MAX_DATA_SIZE) { - if (ec_domain_add_datagram(domain, cmd_offset, - cmd_data_size)) return -1; - cmd_offset += cmd_data_size; - cmd_data_size = 0; - cmd_count++; + if (datagram_data_size + sync_size > EC_MAX_DATA_SIZE) { + if (ec_domain_add_datagram(domain, datagram_offset, + datagram_data_size)) return -1; + datagram_offset += datagram_data_size; + datagram_data_size = 0; + datagram_count++; } - cmd_data_size += sync_size; + datagram_data_size += sync_size; } } } // allocate last datagram - if (cmd_data_size) { - if (ec_domain_add_datagram(domain, cmd_offset, cmd_data_size)) + if (datagram_data_size) { + if (ec_domain_add_datagram(domain, datagram_offset, + datagram_data_size)) return -1; - cmd_count++; - } - - if (!cmd_count) { + datagram_count++; + } + + if (!datagram_count) { EC_WARN("Domain %i contains no data!\n", domain->index); - ec_domain_clear_field_regs(domain); + ec_domain_clear_data_regs(domain); return 0; } // set all process data pointers - list_for_each_entry(field_reg, &domain->field_regs, list) { - for (i = 0; i < field_reg->slave->fmmu_count; i++) { - fmmu = &field_reg->slave->fmmus[i]; - if (fmmu->domain == domain && fmmu->sync == field_reg->sync) { - field_off = fmmu->logical_start_address + - field_reg->field_offset; + list_for_each_entry(data_reg, &domain->data_regs, list) { + for (i = 0; i < data_reg->slave->fmmu_count; i++) { + fmmu = &data_reg->slave->fmmus[i]; + if (fmmu->domain == domain && fmmu->sync == data_reg->sync) { + pdo_off = fmmu->logical_start_address + data_reg->sync_offset; // search datagram list_for_each_entry(datagram, &domain->datagrams, list) { - field_off_cmd = field_off - datagram->address.logical; - if (field_off >= datagram->address.logical && - field_off_cmd < datagram->mem_size) { - *field_reg->data_ptr = datagram->data + field_off_cmd; + pdo_off_datagram = pdo_off - datagram->address.logical; + if (pdo_off >= datagram->address.logical && + pdo_off_datagram < datagram->mem_size) { + *data_reg->data_ptr = datagram->data + + pdo_off_datagram; } } - if (!field_reg->data_ptr) { + if (!data_reg->data_ptr) { EC_ERR("Failed to assign data pointer!\n"); return -1; } @@ -303,31 +356,26 @@ } EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s\n", - domain->index, domain->data_size, cmd_count, - cmd_count == 1 ? "" : "s"); - - ec_domain_clear_field_regs(domain); - - return 0; -} - -/*****************************************************************************/ - -/** - Sets the number of responding slaves and outputs it on demand. - This number isn't really the number of responding slaves, but the sum of - the working counters of all domain datagrams. Some slaves increase the - working counter by 2, some by 1. -*/ - -void ec_domain_response_count(ec_domain_t *domain, /**< EtherCAT domain */ - unsigned int count /**< new WC sum */ - ) -{ - if (count != domain->response_count) { - domain->response_count = count; - EC_INFO("Domain %i working counter change: %i\n", domain->index, - count); + domain->index, domain->data_size, datagram_count, + datagram_count == 1 ? "" : "s"); + + ec_domain_clear_data_regs(domain); + + return 0; +} + +/*****************************************************************************/ + +/** + Places all process data datagrams in the masters datagram queue. +*/ + +void ec_domain_queue(ec_domain_t *domain /**< EtherCAT domain */) +{ + ec_datagram_t *datagram; + + list_for_each_entry(datagram, &domain->datagrams, list) { + ec_master_queue_datagram(domain->master, datagram); } } @@ -357,62 +405,45 @@ *****************************************************************************/ /** - Registers a data field in a domain. - - If \a data_ptr is NULL, the slave is only checked against its type. - - If \a field_count is 0, it is assumed that one data field is to be - registered. - - If \a field_count is greater then 1, it is assumed that \a data_ptr - is an array of the respective size. + Registers a PDO in a domain. + - If \a data_ptr is NULL, the slave is only validated. \return pointer to the slave on success, else NULL \ingroup RealtimeInterface */ -ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain, - /**< EtherCAT domain */ - const char *address, - /**< ASCII address of the slave, - see ecrt_master_get_slave() */ - const char *vendor_name, - /**< vendor name */ - const char *product_name, - /**< product name */ - void **data_ptr, - /**< address of the process data - pointer */ - const char *field_name, - /**< data field name */ - unsigned int field_index, - /**< offset of data fields with - \a field_type */ - unsigned int field_count - /**< number of data fields (with - the same type) to register */ - ) +ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain, + /**< EtherCAT domain */ + const char *address, + /**< ASCII address of the slave, + see ecrt_master_get_slave() */ + 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_slave_t *slave; - const ec_slave_type_t *type; ec_master_t *master; - const ec_sync_t *sync; - const ec_field_t *field; - unsigned int field_counter, i, j, orig_field_index, orig_field_count; - uint32_t field_offset; + const ec_sii_pdo_t *pdo; + const ec_sii_pdo_entry_t *entry; master = domain->master; // translate address if (!(slave = ecrt_master_get_slave(master, address))) return NULL; - if (!(type = slave->type)) { - EC_ERR("Slave \"%s\" (position %i) has unknown type!\n", address, - slave->ring_position); - return NULL; - } - - if (strcmp(vendor_name, type->vendor_name) || - strcmp(product_name, type->product_name)) { - EC_ERR("Invalid slave type at position %i - Requested: \"%s %s\"," - " found: \"%s %s\".\n", slave->ring_position, vendor_name, - product_name, type->vendor_name, type->product_name); + if (vendor_id != slave->sii_vendor_id || + product_code != slave->sii_product_code) { + EC_ERR("Invalid slave type at position %i - Requested: 0x%08X 0x%08X," + " found: 0x%08X 0x%08X\".\n", slave->ring_position, vendor_id, + product_code, slave->sii_vendor_id, slave->sii_product_code); return NULL; } @@ -421,32 +452,22 @@ slave->registered = 1; } - if (!field_count) field_count = 1; - orig_field_index = field_index; - orig_field_count = field_count; - - field_counter = 0; - for (i = 0; type->sync_managers[i]; i++) { - sync = type->sync_managers[i]; - field_offset = 0; - for (j = 0; sync->fields[j]; j++) { - field = sync->fields[j]; - if (!strcmp(field->name, field_name)) { - if (field_counter++ == field_index) { - if (data_ptr) - ec_domain_reg_field(domain, slave, sync, field_offset, - data_ptr++); - if (!(--field_count)) return slave; - field_index++; - } + list_for_each_entry(pdo, &slave->sii_pdos, list) { + list_for_each_entry(entry, &pdo->entries, list) { + if (entry->index != pdo_index + || entry->subindex != pdo_subindex) continue; + + if (data_ptr) { + ec_domain_reg_pdo_entry(domain, slave, pdo, entry, data_ptr); } - field_offset += field->size; + + return slave; } } - EC_ERR("Slave %i (\"%s %s\") registration mismatch: Field \"%s\"," - " index %i, count %i.\n", slave->ring_position, vendor_name, - product_name, field_name, orig_field_index, orig_field_count); + EC_ERR("Slave %i does not provide PDO 0x%04X:%i.\n", + slave->ring_position, pdo_index, pdo_subindex); + slave->registered = 0; return NULL; } @@ -459,20 +480,21 @@ \ingroup RealtimeInterface */ -int ecrt_domain_register_field_list(ec_domain_t *domain, - /**< EtherCAT domain */ - const ec_field_init_t *fields - /**< array of data field registrations */ - ) -{ - const ec_field_init_t *field; - - for (field = fields; field->slave_address; field++) - if (!ecrt_domain_register_field(domain, field->slave_address, - field->vendor_name, - field->product_name, field->data_ptr, - field->field_name, field->field_index, - field->field_count)) +int ecrt_domain_register_pdo_list(ec_domain_t *domain, + /**< EtherCAT domain */ + const ec_pdo_reg_t *pdos + /**< array of PDO registrations */ + ) +{ + const ec_pdo_reg_t *pdo; + + for (pdo = pdos; pdo->slave_address; pdo++) + if (!ecrt_domain_register_pdo(domain, pdo->slave_address, + pdo->vendor_id, + pdo->product_code, + pdo->pdo_index, + pdo->pdo_subindex, + pdo->data_ptr)) return -1; return 0; @@ -481,23 +503,7 @@ /*****************************************************************************/ /** - Places all process data datagrams in the masters datagram queue. - \ingroup RealtimeInterface -*/ - -void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */) -{ - ec_datagram_t *datagram; - - list_for_each_entry(datagram, &domain->datagrams, list) { - ec_master_queue_datagram(domain->master, datagram); - } -} - -/*****************************************************************************/ - -/** - Processes received process data. + Processes received process data and requeues the domain datagram(s). \ingroup RealtimeInterface */ @@ -507,14 +513,19 @@ ec_datagram_t *datagram; working_counter_sum = 0; - list_for_each_entry(datagram, &domain->datagrams, list) { - if (datagram->state == EC_CMD_RECEIVED) { + if (datagram->state == EC_DATAGRAM_RECEIVED) { working_counter_sum += datagram->working_counter; } } - ec_domain_response_count(domain, working_counter_sum); + if (working_counter_sum != domain->response_count) { + domain->response_count = working_counter_sum; + EC_INFO("Domain %i working counter change: %i\n", domain->index, + domain->response_count); + } + + ec_domain_queue(domain); } /*****************************************************************************/ @@ -525,12 +536,12 @@ \ingroup RealtimeInterface */ -int ecrt_domain_state(ec_domain_t *domain /**< EtherCAT domain */) +int ecrt_domain_state(const ec_domain_t *domain /**< EtherCAT domain */) { ec_datagram_t *datagram; list_for_each_entry(datagram, &domain->datagrams, list) { - if (datagram->state != EC_CMD_RECEIVED) return -1; + if (datagram->state != EC_DATAGRAM_RECEIVED) return -1; } return 0; @@ -540,9 +551,8 @@ /** \cond */ -EXPORT_SYMBOL(ecrt_domain_register_field); -EXPORT_SYMBOL(ecrt_domain_register_field_list); -EXPORT_SYMBOL(ecrt_domain_queue); +EXPORT_SYMBOL(ecrt_domain_register_pdo); +EXPORT_SYMBOL(ecrt_domain_register_pdo_list); EXPORT_SYMBOL(ecrt_domain_process); EXPORT_SYMBOL(ecrt_domain_state); diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/domain.h --- a/master/domain.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/domain.h Thu Aug 03 12:51:17 2006 +0000 @@ -45,24 +45,8 @@ #include #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 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 @@ 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 *); /*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/ethernet.c --- a/master/ethernet.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/ethernet.c Thu Aug 03 12:51:17 2006 +0000 @@ -155,10 +155,8 @@ 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 @@ 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_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 @@ 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_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; diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/ethernet.h --- a/master/ethernet.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/ethernet.h Thu Aug 03 12:51:17 2006 +0000 @@ -98,6 +98,5 @@ 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 *); /*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/fsm.c --- a/master/fsm.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/fsm.c Thu Aug 03 12:51:17 2006 +0000 @@ -54,6 +54,13 @@ void ec_fsm_master_scan_slaves(ec_fsm_t *); void ec_fsm_master_write_eeprom(ec_fsm_t *); +void ec_fsm_startup_start(ec_fsm_t *); +void ec_fsm_startup_broadcast(ec_fsm_t *); +void ec_fsm_startup_scan(ec_fsm_t *); + +void ec_fsm_configuration_start(ec_fsm_t *); +void ec_fsm_configuration_conf(ec_fsm_t *); + void ec_fsm_slavescan_start(ec_fsm_t *); void ec_fsm_slavescan_address(ec_fsm_t *); void ec_fsm_slavescan_state(ec_fsm_t *); @@ -61,7 +68,6 @@ void ec_fsm_slavescan_datalink(ec_fsm_t *); void ec_fsm_slavescan_eeprom_size(ec_fsm_t *); void ec_fsm_slavescan_eeprom_data(ec_fsm_t *); -void ec_fsm_slavescan_end(ec_fsm_t *); void ec_fsm_slaveconf_init(ec_fsm_t *); void ec_fsm_slaveconf_sync(ec_fsm_t *); @@ -69,7 +75,6 @@ void ec_fsm_slaveconf_fmmu(ec_fsm_t *); void ec_fsm_slaveconf_saveop(ec_fsm_t *); void ec_fsm_slaveconf_op(ec_fsm_t *); -void ec_fsm_slaveconf_end(ec_fsm_t *); void ec_fsm_sii_start_reading(ec_fsm_t *); void ec_fsm_sii_read_check(ec_fsm_t *); @@ -77,8 +82,6 @@ void ec_fsm_sii_start_writing(ec_fsm_t *); void ec_fsm_sii_write_check(ec_fsm_t *); void ec_fsm_sii_write_check2(ec_fsm_t *); -void ec_fsm_sii_end(ec_fsm_t *); -void ec_fsm_sii_error(ec_fsm_t *); void ec_fsm_change_start(ec_fsm_t *); void ec_fsm_change_check(ec_fsm_t *); @@ -86,8 +89,9 @@ void ec_fsm_change_code(ec_fsm_t *); void ec_fsm_change_ack(ec_fsm_t *); void ec_fsm_change_check_ack(ec_fsm_t *); -void ec_fsm_change_end(ec_fsm_t *); -void ec_fsm_change_error(ec_fsm_t *); + +void ec_fsm_end(ec_fsm_t *); +void ec_fsm_error(ec_fsm_t *); /*****************************************************************************/ @@ -97,7 +101,7 @@ int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ ec_master_t *master /**< EtherCAT master */ - ) + ) { fsm->master = master; fsm->master_state = ec_fsm_master_start; @@ -149,8 +153,224 @@ fsm->master_state(fsm); } +/*****************************************************************************/ + +void ec_fsm_startup(ec_fsm_t *fsm) +{ + fsm->master_state = ec_fsm_startup_start; +} + +/*****************************************************************************/ + +int ec_fsm_startup_running(ec_fsm_t *fsm) +{ + return fsm->master_state != ec_fsm_end && + fsm->master_state != ec_fsm_error; +} + +/*****************************************************************************/ + +int ec_fsm_startup_success(ec_fsm_t *fsm) +{ + return fsm->master_state == ec_fsm_end; +} + +/*****************************************************************************/ + +void ec_fsm_configuration(ec_fsm_t *fsm) +{ + fsm->master_state = ec_fsm_configuration_start; +} + +/*****************************************************************************/ + +int ec_fsm_configuration_running(ec_fsm_t *fsm) +{ + return fsm->master_state != ec_fsm_end && + fsm->master_state != ec_fsm_error; +} + +/*****************************************************************************/ + +int ec_fsm_configuration_success(ec_fsm_t *fsm) +{ + return fsm->master_state == ec_fsm_end; +} + /****************************************************************************** - * master state machine + * master startup state machine + *****************************************************************************/ + +/** + Master state: START. + Starts with getting slave count and slave states. +*/ + +void ec_fsm_startup_start(ec_fsm_t *fsm) +{ + ec_datagram_brd(&fsm->datagram, 0x0130, 2); + ec_master_queue_datagram(fsm->master, &fsm->datagram); + fsm->master_state = ec_fsm_startup_broadcast; +} + +/*****************************************************************************/ + +/** + Master state: BROADCAST. + Processes the broadcast read slave count and slaves states. +*/ + +void ec_fsm_startup_broadcast(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_datagram_t *datagram = &fsm->datagram; + unsigned int i; + ec_slave_t *slave; + ec_master_t *master = fsm->master; + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_ERR("Failed tor receive broadcast datagram.\n"); + fsm->master_state = ec_fsm_error; + return; + } + + EC_INFO("Scanning bus.\n"); + + ec_master_clear_slaves(master); + + master->slave_count = datagram->working_counter; + + if (!master->slave_count) { + // no slaves present -> finish state machine. + fsm->master_state = ec_fsm_end; + return; + } + + // init slaves + for (i = 0; i < master->slave_count; i++) { + if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), + GFP_KERNEL))) { + EC_ERR("Failed to allocate slave %i!\n", i); + fsm->master_state = ec_fsm_error; + return; + } + + if (ec_slave_init(slave, master, i, i + 1)) { + fsm->master_state = ec_fsm_error; + return; + } + + if (kobject_add(&slave->kobj)) { + EC_ERR("Failed to add kobject.\n"); + kobject_put(&slave->kobj); // free + fsm->master_state = ec_fsm_error; + return; + } + + list_add_tail(&slave->list, &master->slaves); + } + + // begin scanning of slaves + fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); + fsm->slave_state = ec_fsm_slavescan_start; + fsm->master_state = ec_fsm_startup_scan; + fsm->master_state(fsm); // execute immediately + return; +} + +/*****************************************************************************/ + +/** + Master state: SCAN. + Executes the sub-statemachine for the scanning of a slave. +*/ + +void ec_fsm_startup_scan(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_master_t *master = fsm->master; + ec_slave_t *slave = fsm->slave; + + fsm->slave_state(fsm); // execute slave state machine + + if (fsm->slave_state == ec_fsm_error) { + EC_ERR("Slave scanning failed.\n"); + fsm->master_state = ec_fsm_error; + return; + } + + if (fsm->slave_state != ec_fsm_end) return; + + // another slave to scan? + if (slave->list.next != &master->slaves) { + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + fsm->slave_state = ec_fsm_slavescan_start; + fsm->slave_state(fsm); // execute immediately + return; + } + + EC_INFO("Bus scanning completed.\n"); + + ec_master_calc_addressing(master); + + fsm->master_state = ec_fsm_end; +} + +/****************************************************************************** + * master configuration state machine + *****************************************************************************/ + +void ec_fsm_configuration_start(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_master_t *master = fsm->master; + + if (list_empty(&master->slaves)) { + fsm->master_state = ec_fsm_end; + return; + } + + // begin configuring slaves + fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); + fsm->slave_state = ec_fsm_slaveconf_init; + fsm->change_new = EC_SLAVE_STATE_INIT; + fsm->change_state = ec_fsm_change_start; + fsm->master_state = ec_fsm_configuration_conf; + fsm->master_state(fsm); // execute immediately +} + +/*****************************************************************************/ + +/** + Master state: CONF. +*/ + +void ec_fsm_configuration_conf(ec_fsm_t *fsm /**< finite state machine */) +{ + ec_master_t *master = fsm->master; + ec_slave_t *slave = fsm->slave; + + fsm->slave_state(fsm); // execute slave's state machine + + if (fsm->slave_state == ec_fsm_error) { + fsm->master_state = ec_fsm_error; + return; + } + + if (fsm->slave_state != ec_fsm_end) return; + + // another slave to configure? + if (slave->list.next != &master->slaves) { + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + fsm->slave_state = ec_fsm_slaveconf_init; + fsm->change_new = EC_SLAVE_STATE_INIT; + fsm->change_state = ec_fsm_change_start; + fsm->master_state(fsm); // execute immediately + return; + } + + fsm->master_state = ec_fsm_end; +} + +/****************************************************************************** + * operation / idle state machine *****************************************************************************/ /** @@ -179,7 +399,7 @@ ec_slave_t *slave; ec_master_t *master = fsm->master; - if (datagram->state != EC_CMD_RECEIVED) { + if (datagram->state != EC_DATAGRAM_RECEIVED) { if (!master->device->link_state) { fsm->master_slaves_responding = 0; list_for_each_entry(slave, &master->slaves, list) { @@ -203,7 +423,7 @@ fsm->master_slaves_responding, fsm->master_slaves_responding == 1 ? "" : "s"); - if (master->mode == EC_MASTER_MODE_RUNNING) { + if (master->mode == EC_MASTER_MODE_OPERATION) { if (fsm->master_slaves_responding == master->slave_count) { fsm->master_validation = 1; // start validation later } @@ -214,9 +434,9 @@ } if (states_change) { - EC_INFO("Slave states: "); - ec_print_states(fsm->master_slave_states); - printk(".\n"); + char states[25]; + ec_state_string(fsm->master_slave_states, states); + EC_INFO("Slave states: %s.\n", states); } // topology change in idle mode: clear all slaves and scan the bus @@ -226,7 +446,9 @@ ec_master_eoe_stop(master); ec_master_clear_slaves(master); - if (!fsm->master_slaves_responding) { + master->slave_count = datagram->working_counter; + + if (!master->slave_count) { // no slaves present -> finish state machine. fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately @@ -234,16 +456,19 @@ } // init slaves - for (i = 0; i < fsm->master_slaves_responding; i++) { + for (i = 0; i < master->slave_count; i++) { if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_ATOMIC))) { EC_ERR("Failed to allocate slave %i!\n", i); + ec_master_clear_slaves(master); fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; } if (ec_slave_init(slave, master, i, i + 1)) { + // freeing of "slave" already done + ec_master_clear_slaves(master); fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; @@ -252,6 +477,7 @@ if (kobject_add(&slave->kobj)) { EC_ERR("Failed to add kobject.\n"); kobject_put(&slave->kobj); // free + ec_master_clear_slaves(master); fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; @@ -288,6 +514,7 @@ { ec_master_t *master = fsm->master; ec_slave_t *slave; + char old_state[25], new_state[25]; // check if any slaves are not in the state, they're supposed to be list_for_each_entry(slave, &master->slaves, list) { @@ -296,11 +523,10 @@ slave->requested_state == EC_SLAVE_STATE_UNKNOWN || slave->current_state == slave->requested_state) continue; - EC_INFO("Changing state of slave %i from ", slave->ring_position); - ec_print_states(slave->current_state); - printk(" to "); - ec_print_states(slave->requested_state); - printk(".\n"); + ec_state_string(slave->current_state, old_state); + ec_state_string(slave->requested_state, new_state); + EC_INFO("Changing state of slave %i from %s to %s.\n", + slave->ring_position, old_state, new_state); fsm->slave = slave; fsm->slave_state = ec_fsm_slaveconf_init; @@ -311,6 +537,9 @@ return; } + // Check, if EoE processing has to be started + ec_master_eoe_start(master); + if (master->mode == EC_MASTER_MODE_IDLE) { // nothing to configure. check for pending EEPROM write operations. list_for_each_entry(slave, &master->slaves, list) { @@ -401,7 +630,7 @@ ec_datagram_t *datagram = &fsm->datagram; uint8_t new_state; - if (datagram->state != EC_CMD_RECEIVED) { + if (datagram->state != EC_DATAGRAM_RECEIVED) { fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; @@ -420,19 +649,19 @@ // slave responded new_state = EC_READ_U8(datagram->data); if (!slave->online) { // slave was offline before + char cur_state[25]; slave->online = 1; slave->error_flag = 0; // clear error flag slave->current_state = new_state; - EC_INFO("Slave %i: online (", slave->ring_position); - ec_print_states(new_state); - printk(").\n"); + ec_state_string(slave->current_state, cur_state); + EC_INFO("Slave %i: online (%s).\n", slave->ring_position, cur_state); } else if (new_state != slave->current_state) { - EC_INFO("Slave %i: ", slave->ring_position); - ec_print_states(slave->current_state); - printk(" -> "); - ec_print_states(new_state); - printk(".\n"); + char old_state[25], cur_state[25]; + ec_state_string(slave->current_state, old_state); + ec_state_string(new_state, cur_state); + EC_INFO("Slave %i: %s -> %s.\n", + slave->ring_position, old_state, cur_state); slave->current_state = new_state; } @@ -452,7 +681,7 @@ fsm->sii_state(fsm); // execute SII state machine - if (fsm->sii_state == ec_fsm_sii_error) { + if (fsm->sii_state == ec_fsm_error) { fsm->slave->error_flag = 1; EC_ERR("Failed to validate vendor ID of slave %i.\n", slave->ring_position); @@ -461,7 +690,7 @@ return; } - if (fsm->sii_state != ec_fsm_sii_end) return; + if (fsm->sii_state != ec_fsm_end) return; if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); @@ -522,7 +751,7 @@ fsm->sii_state(fsm); // execute SII state machine - if (fsm->sii_state == ec_fsm_sii_error) { + if (fsm->sii_state == ec_fsm_error) { fsm->slave->error_flag = 1; EC_ERR("Failed to validate product code of slave %i.\n", slave->ring_position); @@ -531,7 +760,7 @@ return; } - if (fsm->sii_state != ec_fsm_sii_end) return; + if (fsm->sii_state != ec_fsm_end) return; if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); @@ -573,7 +802,8 @@ ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { EC_ERR("Failed to write station address on slave %i.\n", slave->ring_position); } @@ -601,89 +831,40 @@ { ec_master_t *master = fsm->master; ec_slave_t *slave = fsm->slave; - uint16_t coupler_index, coupler_subindex; - uint16_t reverse_coupler_index, current_coupler_index; - ec_slave_ident_t *ident; + fsm->slave_state(fsm); // execute slave state machine - if (fsm->slave_state != ec_fsm_slavescan_end) return; - - // have all slaves been fetched? - if (slave->list.next == &master->slaves) { - EC_INFO("Bus scanning completed.\n"); - - // identify all slaves and calculate coupler addressing - - coupler_index = 0; - reverse_coupler_index = 0xFFFF; - current_coupler_index = 0x3FFF; - coupler_subindex = 0; - - list_for_each_entry(slave, &master->slaves, list) - { - // search for identification in "database" - ident = slave_idents; - while (ident->type) { - if (ident->vendor_id == slave->sii_vendor_id - && ident->product_code == slave->sii_product_code) { - slave->type = ident->type; - break; - } - ident++; - } - - if (!slave->type) { - EC_WARN("Unknown slave device (vendor 0x%08X," - " code 0x%08X) at position %i.\n", - slave->sii_vendor_id, slave->sii_product_code, - slave->ring_position); - } - else { - // if the slave is a bus coupler, change adressing base - if (slave->type->special == EC_TYPE_BUS_COUPLER) { - if (slave->sii_alias) - current_coupler_index = reverse_coupler_index--; - else - current_coupler_index = coupler_index++; - coupler_subindex = 0; - } - } - - // determine initial state. - if ((slave->type && - (slave->type->special == EC_TYPE_BUS_COUPLER || - slave->type->special == EC_TYPE_INFRA))) { - slave->requested_state = EC_SLAVE_STATE_OP; - } - else { - if (master->mode == EC_MASTER_MODE_RUNNING) - slave->requested_state = EC_SLAVE_STATE_PREOP; - else - slave->requested_state = EC_SLAVE_STATE_INIT; - } - slave->error_flag = 0; - - // calculate coupler-based slave address - slave->coupler_index = current_coupler_index; - slave->coupler_subindex = coupler_subindex; - coupler_subindex++; - } - - if (master->mode == EC_MASTER_MODE_IDLE) { - // start EoE processing - ec_master_eoe_start(master); - } - - fsm->master_state = ec_fsm_master_start; - fsm->master_state(fsm); // execute immediately - return; - } - - // process next slave - fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); - fsm->slave_state = ec_fsm_slavescan_start; - fsm->slave_state(fsm); // execute immediately + if (fsm->slave_state != ec_fsm_end + && fsm->slave_state != ec_fsm_error) return; + + // another slave to fetch? + if (slave->list.next != &master->slaves) { + fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); + fsm->slave_state = ec_fsm_slavescan_start; + fsm->slave_state(fsm); // execute immediately + return; + } + + EC_INFO("Bus scanning completed.\n"); + + ec_master_calc_addressing(master); + + // determine initial states. + list_for_each_entry(slave, &master->slaves, list) { + if (ec_slave_is_coupler(slave)) { + slave->requested_state = EC_SLAVE_STATE_OP; + } + else { + if (master->mode == EC_MASTER_MODE_OPERATION) + slave->requested_state = EC_SLAVE_STATE_PREOP; + else + slave->requested_state = EC_SLAVE_STATE_INIT; + } + } + + fsm->master_state = ec_fsm_master_start; + fsm->master_state(fsm); // execute immediately } /*****************************************************************************/ @@ -698,7 +879,9 @@ ) { fsm->slave_state(fsm); // execute slave's state machine - if (fsm->slave_state != ec_fsm_slaveconf_end) return; + + if (fsm->slave_state != ec_fsm_end + && fsm->slave_state != ec_fsm_error) return; ec_fsm_master_action_process_states(fsm); } @@ -715,7 +898,7 @@ fsm->sii_state(fsm); // execute SII state machine - if (fsm->sii_state == ec_fsm_sii_error) { + if (fsm->sii_state == ec_fsm_error) { fsm->slave->error_flag = 1; EC_ERR("Failed to write EEPROM contents to slave %i.\n", slave->ring_position); @@ -726,7 +909,7 @@ return; } - if (fsm->sii_state != ec_fsm_sii_end) return; + if (fsm->sii_state != ec_fsm_end) return; fsm->sii_offset++; if (fsm->sii_offset < slave->new_eeprom_size) { @@ -741,14 +924,16 @@ kfree(slave->new_eeprom_data); slave->new_eeprom_data = NULL; + // TODO: Evaluate new EEPROM contents! + // restart master state machine. - fsm->master_state = ec_fsm_master_start; // TODO: Evaluate new contents! + fsm->master_state = ec_fsm_master_start; fsm->master_state(fsm); // execute immediately return; } /****************************************************************************** - * slave scan sub state machine + * slave scan state machine *****************************************************************************/ /** @@ -778,9 +963,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to write station address of slave %i.\n", fsm->slave->ring_position); return; @@ -803,9 +989,10 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to read AL state of slave %i.\n", fsm->slave->ring_position); return; @@ -835,9 +1022,10 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to read base data of slave %i.\n", slave->ring_position); return; @@ -871,9 +1059,10 @@ uint16_t dl_status; unsigned int i; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to read DL status of slave %i.\n", slave->ring_position); return; @@ -909,15 +1098,15 @@ // execute SII state machine fsm->sii_state(fsm); - if (fsm->sii_state == ec_fsm_sii_error) { + if (fsm->sii_state == ec_fsm_error) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to read EEPROM size of slave %i.\n", slave->ring_position); return; } - if (fsm->sii_state != ec_fsm_sii_end) return; + if (fsm->sii_state != ec_fsm_end) return; cat_type = EC_READ_U16(fsm->sii_value); cat_size = EC_READ_U16(fsm->sii_value + 2); @@ -940,7 +1129,7 @@ if (!(slave->eeprom_data = (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to allocate EEPROM data on slave %i.\n", slave->ring_position); return; @@ -969,15 +1158,15 @@ // execute SII state machine fsm->sii_state(fsm); - if (fsm->sii_state == ec_fsm_sii_error) { + if (fsm->sii_state == ec_fsm_error) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", slave->ring_position); return; } - if (fsm->sii_state != ec_fsm_sii_end) return; + if (fsm->sii_state != ec_fsm_end) return; // 2 words fetched @@ -1031,8 +1220,7 @@ goto end; break; case 0x001E: - if (ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2))) - goto end; + ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2)); break; case 0x0028: break; @@ -1059,26 +1247,17 @@ cat_word += cat_size + 2; } - fsm->slave_state = ec_fsm_slavescan_end; + fsm->slave_state = ec_fsm_end; + return; end: + EC_ERR("Failed to analyze category data.\n"); fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slavescan_end; -} - -/*****************************************************************************/ - -/** - Slave state: END. - End state of the slave state machine. -*/ - -void ec_fsm_slavescan_end(ec_fsm_t *fsm /**< finite state machine */) -{ + fsm->slave_state = ec_fsm_error; } /****************************************************************************** - * slave configuration sub state machine + * slave configuration state machine *****************************************************************************/ /** @@ -1089,34 +1268,27 @@ { ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = &fsm->datagram; - const ec_sync_t *sync; - ec_eeprom_sync_t *eeprom_sync, mbox_sync; - unsigned int j; + const ec_sii_sync_t *sync; fsm->change_state(fsm); // execute state change state machine - if (fsm->change_state == ec_fsm_change_error) { + if (fsm->change_state == ec_fsm_error) { slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; - return; - } - - if (fsm->change_state != ec_fsm_change_end) return; + fsm->slave_state = ec_fsm_error; + return; + } + + if (fsm->change_state != ec_fsm_end) return; // slave is now in INIT if (slave->current_state == slave->requested_state) { - fsm->slave_state = ec_fsm_slaveconf_end; // successful - return; - } - - // check for slave registration - if (!slave->type) { - EC_WARN("Slave %i has unknown type!\n", slave->ring_position); + fsm->slave_state = ec_fsm_end; // successful + return; } // check and reset CRC fault counters //ec_slave_check_crc(slave); - // TODO! + // TODO: Implement state machine for CRC checking. if (!slave->base_sync_count) { // no sync managers fsm->slave_state = ec_fsm_slaveconf_preop; @@ -1131,50 +1303,15 @@ EC_SYNC_SIZE * slave->base_sync_count); memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); - // does the slave supply sync manager configurations in its EEPROM? - if (!list_empty(&slave->eeprom_syncs)) { - list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { - if (eeprom_sync->index >= slave->base_sync_count) { - fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; - EC_ERR("Invalid sync manager configuration found!"); - return; - } - ec_eeprom_sync_config(eeprom_sync, slave, - datagram->data + EC_SYNC_SIZE - * eeprom_sync->index); - } - } - - // known slave type, take type's SM information - else if (slave->type) { - for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { - sync = slave->type->sync_managers[j]; - ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j); - } - } - - // unknown type, but slave has mailbox - else if (slave->sii_mailbox_protocols) - { - // guess mailbox settings - mbox_sync.physical_start_address = - slave->sii_rx_mailbox_offset; - mbox_sync.length = slave->sii_rx_mailbox_size; - mbox_sync.control_register = 0x26; - mbox_sync.enable = 1; - ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); - - mbox_sync.physical_start_address = - slave->sii_tx_mailbox_offset; - mbox_sync.length = slave->sii_tx_mailbox_size; - mbox_sync.control_register = 0x22; - mbox_sync.enable = 1; - ec_eeprom_sync_config(&mbox_sync, slave, - datagram->data + EC_SYNC_SIZE); - - EC_INFO("Mailbox configured for unknown slave %i\n", - slave->ring_position); + list_for_each_entry(sync, &slave->sii_syncs, list) { + if (sync->index >= slave->base_sync_count) { + EC_ERR("Invalid sync manager configuration found!"); + fsm->slave->error_flag = 1; + fsm->slave_state = ec_fsm_error; + return; + } + ec_sync_config(sync, slave, + datagram->data + EC_SYNC_SIZE * sync->index); } ec_master_queue_datagram(fsm->master, datagram); @@ -1192,9 +1329,10 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to set sync managers on slave %i.\n", slave->ring_position); return; @@ -1221,23 +1359,17 @@ fsm->change_state(fsm); // execute state change state machine - if (fsm->change_state == ec_fsm_change_error) { + if (fsm->change_state == ec_fsm_error) { slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; - return; - } - - if (fsm->change_state != ec_fsm_change_end) return; + fsm->slave_state = ec_fsm_error; + return; + } + + if (fsm->change_state != ec_fsm_end) return; // slave is now in PREOP if (slave->current_state == slave->requested_state) { - fsm->slave_state = ec_fsm_slaveconf_end; // successful - return; - } - - // stop activation here for slaves without type - if (!slave->type) { - fsm->slave_state = ec_fsm_slaveconf_end; // successful + fsm->slave_state = ec_fsm_end; // successful return; } @@ -1272,9 +1404,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; + fsm->slave_state = ec_fsm_error; EC_ERR("Failed to set FMMUs on slave %i.\n", fsm->slave->ring_position); return; @@ -1297,17 +1430,17 @@ { fsm->change_state(fsm); // execute state change state machine - if (fsm->change_state == ec_fsm_change_error) { + if (fsm->change_state == ec_fsm_error) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; - return; - } - - if (fsm->change_state != ec_fsm_change_end) return; + fsm->slave_state = ec_fsm_error; + return; + } + + if (fsm->change_state != ec_fsm_end) return; // slave is now in SAVEOP if (fsm->slave->current_state == fsm->slave->requested_state) { - fsm->slave_state = ec_fsm_slaveconf_end; // successful + fsm->slave_state = ec_fsm_end; // successful return; } @@ -1328,31 +1461,20 @@ { fsm->change_state(fsm); // execute state change state machine - if (fsm->change_state == ec_fsm_change_error) { + if (fsm->change_state == ec_fsm_error) { fsm->slave->error_flag = 1; - fsm->slave_state = ec_fsm_slaveconf_end; - return; - } - - if (fsm->change_state != ec_fsm_change_end) return; + fsm->slave_state = ec_fsm_error; + return; + } + + if (fsm->change_state != ec_fsm_end) return; // slave is now in OP - fsm->slave_state = ec_fsm_slaveconf_end; // successful -} - -/*****************************************************************************/ - -/** - Slave state: END. - End state of the slave state machine. -*/ - -void ec_fsm_slaveconf_end(ec_fsm_t *fsm /**< finite state machine */) -{ + fsm->slave_state = ec_fsm_end; // successful } /****************************************************************************** - * SII sub state machine + * SII state machine *****************************************************************************/ /** @@ -1390,9 +1512,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { EC_ERR("SII: Reception of read datagram failed.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; return; } @@ -1421,9 +1544,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { EC_ERR("SII: Reception of check/fetch datagram failed.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; return; } @@ -1432,7 +1556,7 @@ // still busy... timeout? if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { EC_ERR("SII: Timeout.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; #if 0 EC_DBG("SII busy: %02X %02X %02X %02X\n", EC_READ_U8(datagram->data + 0), @@ -1463,7 +1587,7 @@ // SII value received. memcpy(fsm->sii_value, datagram->data + 6, 4); - fsm->sii_state = ec_fsm_sii_end; + fsm->sii_state = ec_fsm_end; } /*****************************************************************************/ @@ -1497,9 +1621,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { EC_ERR("SII: Reception of write datagram failed.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; return; } @@ -1521,9 +1646,10 @@ { ec_datagram_t *datagram = &fsm->datagram; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { EC_ERR("SII: Reception of write check datagram failed.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; return; } @@ -1531,7 +1657,7 @@ // still busy... timeout? if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { EC_ERR("SII: Write timeout.\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; } // issue check/fetch datagram again @@ -1539,37 +1665,15 @@ } else if (EC_READ_U8(datagram->data + 1) & 0x40) { EC_ERR("SII: Write operation failed!\n"); - fsm->sii_state = ec_fsm_sii_error; + fsm->sii_state = ec_fsm_error; } else { // success - fsm->sii_state = ec_fsm_sii_end; - } -} - -/*****************************************************************************/ - -/** - SII state: END. - End state of the slave SII state machine. -*/ - -void ec_fsm_sii_end(ec_fsm_t *fsm /**< finite state machine */) -{ -} - -/*****************************************************************************/ - -/** - SII state: ERROR. - End state of the slave SII state machine. -*/ - -void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */) -{ + fsm->sii_state = ec_fsm_end; + } } /****************************************************************************** - * state change sub state machine + * state change state machine *****************************************************************************/ /** @@ -1581,6 +1685,8 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; + fsm->change_start = get_cycles(); + // write new state to slave ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); EC_WRITE_U16(datagram->data, fsm->change_new); @@ -1599,17 +1705,25 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED) { - fsm->change_state = ec_fsm_change_error; + if (datagram->state != EC_DATAGRAM_RECEIVED) { + fsm->change_state = ec_fsm_error; EC_ERR("Failed to send state datagram to slave %i!\n", fsm->slave->ring_position); return; } if (datagram->working_counter != 1) { - fsm->change_state = ec_fsm_change_error; - EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" - " respond.\n", fsm->change_new, fsm->slave->ring_position); + if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { + fsm->change_state = ec_fsm_error; + EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" + " respond.\n", fsm->change_new, fsm->slave->ring_position); + return; + } + + // repeat writing new state to slave + ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2); + EC_WRITE_U16(datagram->data, fsm->change_new); + ec_master_queue_datagram(fsm->master, datagram); return; } @@ -1632,8 +1746,9 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { - fsm->change_state = ec_fsm_change_error; + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + fsm->change_state = ec_fsm_error; EC_ERR("Failed to check state 0x%02X on slave %i.\n", fsm->change_new, slave->ring_position); return; @@ -1643,7 +1758,7 @@ if (slave->current_state == fsm->change_new) { // state has been set successfully - fsm->change_state = ec_fsm_change_end; + fsm->change_state = ec_fsm_end; return; } @@ -1662,7 +1777,7 @@ if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { // timeout while checking - fsm->change_state = ec_fsm_change_error; + fsm->change_state = ec_fsm_error; EC_ERR("Timeout while setting state 0x%02X on slave %i.\n", fsm->change_new, slave->ring_position); return; @@ -1726,8 +1841,9 @@ uint32_t code; const ec_code_msg_t *al_msg; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { - fsm->change_state = ec_fsm_change_error; + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + fsm->change_state = ec_fsm_error; EC_ERR("Reception of AL status code datagram failed.\n"); return; } @@ -1761,8 +1877,9 @@ ec_datagram_t *datagram = &fsm->datagram; ec_slave_t *slave = fsm->slave; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { - fsm->change_state = ec_fsm_change_error; + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + fsm->change_state = ec_fsm_error; EC_ERR("Reception of state ack datagram failed.\n"); return; } @@ -1787,8 +1904,9 @@ ec_slave_t *slave = fsm->slave; ec_slave_state_t ack_state; - if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) { - fsm->change_state = ec_fsm_change_error; + if (datagram->state != EC_DATAGRAM_RECEIVED + || datagram->working_counter != 1) { + fsm->change_state = ec_fsm_error; EC_ERR("Reception of state ack check datagram failed.\n"); return; } @@ -1796,7 +1914,7 @@ ack_state = EC_READ_U8(datagram->data); if (ack_state == slave->current_state) { - fsm->change_state = ec_fsm_change_error; + fsm->change_state = ec_fsm_error; EC_INFO("Acknowleged state 0x%02X on slave %i.\n", slave->current_state, slave->ring_position); return; @@ -1805,7 +1923,7 @@ if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) { // timeout while checking slave->current_state = EC_SLAVE_STATE_UNKNOWN; - fsm->change_state = ec_fsm_change_error; + fsm->change_state = ec_fsm_error; EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n", fsm->change_new, slave->ring_position); return; @@ -1819,21 +1937,21 @@ /*****************************************************************************/ /** - Change state: END. -*/ - -void ec_fsm_change_end(ec_fsm_t *fsm /**< finite state machine */) -{ -} - -/*****************************************************************************/ - -/** - Change state: ERROR. -*/ - -void ec_fsm_change_error(ec_fsm_t *fsm /**< finite state machine */) -{ -} - -/*****************************************************************************/ + State: ERROR. +*/ + +void ec_fsm_error(ec_fsm_t *fsm /**< finite state machine */) +{ +} + +/*****************************************************************************/ + +/** + State: END. +*/ + +void ec_fsm_end(ec_fsm_t *fsm /**< finite state machine */) +{ +} + +/*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/fsm.h --- a/master/fsm.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/fsm.h Thu Aug 03 12:51:17 2006 +0000 @@ -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_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 diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/globals.h --- a/master/globals.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/globals.h Thu Aug 03 12:51:17 2006 +0000 @@ -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 @@ /*****************************************************************************/ #endif - diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/mailbox.c --- a/master/mailbox.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/mailbox.c Thu Aug 03 12:51:17 2006 +0000 @@ -165,83 +165,3 @@ } /*****************************************************************************/ - -/** - 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); -} - -/*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/master.c --- a/master/master.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/master.c Thu Aug 03 12:51:17 2006 +0000 @@ -48,13 +48,13 @@ #include "globals.h" #include "master.h" #include "slave.h" -#include "types.h" #include "device.h" #include "datagram.h" #include "ethernet.h" /*****************************************************************************/ +void ec_master_sync_io(ec_master_t *); void ec_master_idle_run(void *); void ec_master_eoe_run(unsigned long); ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); @@ -115,7 +115,6 @@ INIT_LIST_HEAD(&master->datagram_queue); INIT_LIST_HEAD(&master->domains); INIT_LIST_HEAD(&master->eoe_handlers); - ec_datagram_init(&master->simple_datagram); INIT_WORK(&master->idle_work, ec_master_idle_run, (void *) master); init_timer(&master->eoe_timer); master->eoe_timer.function = ec_master_eoe_run; @@ -186,7 +185,6 @@ ec_master_reset(master); ec_fsm_clear(&master->fsm); - ec_datagram_clear(&master->simple_datagram); destroy_workqueue(master->workqueue); // clear EoE objects @@ -225,7 +223,7 @@ list_for_each_entry_safe(datagram, next_c, &master->datagram_queue, queue) { list_del_init(&datagram->queue); - datagram->state = EC_CMD_ERROR; + datagram->state = EC_DATAGRAM_ERROR; } // clear domains @@ -237,7 +235,6 @@ master->datagram_index = 0; master->debug_level = 0; - master->timeout = 500; // 500us master->stats.timeouts = 0; master->stats.delayed = 0; @@ -289,7 +286,7 @@ // check, if the datagram is already queued list_for_each_entry(queued_datagram, &master->datagram_queue, queue) { if (queued_datagram == datagram) { - datagram->state = EC_CMD_QUEUED; + datagram->state = EC_DATAGRAM_QUEUED; if (unlikely(master->debug_level)) EC_WARN("datagram already queued.\n"); return; @@ -297,7 +294,7 @@ } list_add_tail(&datagram->queue, &master->datagram_queue); - datagram->state = EC_CMD_QUEUED; + datagram->state = EC_DATAGRAM_QUEUED; } /*****************************************************************************/ @@ -331,7 +328,7 @@ // fill current frame with datagrams list_for_each_entry(datagram, &master->datagram_queue, queue) { - if (datagram->state != EC_CMD_QUEUED) continue; + if (datagram->state != EC_DATAGRAM_QUEUED) continue; // does the current datagram fit in the frame? datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size @@ -341,7 +338,7 @@ break; } - datagram->state = EC_CMD_SENT; + datagram->state = EC_DATAGRAM_SENT; datagram->t_sent = t_start; datagram->index = master->datagram_index++; @@ -456,7 +453,7 @@ // search for matching datagram in the queue matched = 0; list_for_each_entry(datagram, &master->datagram_queue, queue) { - if (datagram->state == EC_CMD_SENT + if (datagram->state == EC_DATAGRAM_SENT && datagram->type == datagram_type && datagram->index == datagram_index && datagram->data_size == data_size) { @@ -482,7 +479,7 @@ cur_data += EC_DATAGRAM_FOOTER_SIZE; // dequeue the received datagram - datagram->state = EC_CMD_RECEIVED; + datagram->state = EC_DATAGRAM_RECEIVED; list_del_init(&datagram->queue); } } @@ -490,50 +487,6 @@ /*****************************************************************************/ /** - Sends a single datagram and waits for its reception. - If the slave doesn't respond, the datagram is sent again. - \return 0 in case of success, else < 0 -*/ - -int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */ - ec_datagram_t *datagram /**< datagram */ - ) -{ - unsigned int response_tries_left; - - response_tries_left = 10000; - - while (1) - { - ec_master_queue_datagram(master, datagram); - ecrt_master_sync_io(master); - - if (datagram->state == EC_CMD_RECEIVED) { - if (likely(datagram->working_counter)) - return 0; - } - else if (datagram->state == EC_CMD_TIMEOUT) { - EC_ERR("Simple-IO TIMEOUT!\n"); - return -1; - } - else if (datagram->state == EC_CMD_ERROR) { - EC_ERR("Simple-IO datagram error!\n"); - return -1; - } - - // no direct response, wait a little bit... - udelay(100); - - if (unlikely(--response_tries_left)) { - EC_ERR("No response in simple-IO!\n"); - return -1; - } - } -} - -/*****************************************************************************/ - -/** Scans the EtherCAT bus for slaves. Creates a list of slave structures for further processing. \return 0 in case of success, else < 0 @@ -541,102 +494,22 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */) { - ec_slave_t *slave; - ec_slave_ident_t *ident; - ec_datagram_t *datagram; - unsigned int i; - uint16_t coupler_index, coupler_subindex; - uint16_t reverse_coupler_index, current_coupler_index; - - if (!list_empty(&master->slaves)) { - EC_ERR("Slave scan already done!\n"); + ec_fsm_t *fsm = &master->fsm; + + ec_fsm_startup(fsm); // init startup state machine + + do { + ec_fsm_execute(fsm); + ec_master_sync_io(master); + } + while (ec_fsm_startup_running(fsm)); + + if (!ec_fsm_startup_success(fsm)) { + ec_master_clear_slaves(master); return -1; } - datagram = &master->simple_datagram; - - // determine number of slaves on bus - if (ec_datagram_brd(datagram, 0x0000, 4)) return -1; - if (unlikely(ec_master_simple_io(master, datagram))) return -1; - master->slave_count = datagram->working_counter; - EC_INFO("Found %i slaves on bus.\n", master->slave_count); - - if (!master->slave_count) return 0; - - // init slaves - for (i = 0; i < master->slave_count; i++) { - if (!(slave = - (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate slave %i!\n", i); - goto out_free; - } - - if (ec_slave_init(slave, master, i, i + 1)) goto out_free; - - if (kobject_add(&slave->kobj)) { - EC_ERR("Failed to add kobject.\n"); - kobject_put(&slave->kobj); // free - goto out_free; - } - - list_add_tail(&slave->list, &master->slaves); - } - - coupler_index = 0; - reverse_coupler_index = 0xFFFF; - current_coupler_index = 0x3FFF; - coupler_subindex = 0; - - // for every slave on the bus - list_for_each_entry(slave, &master->slaves, list) { - - // write station address - if (ec_datagram_apwr(datagram, slave->ring_position, 0x0010, - sizeof(uint16_t))) goto out_free; - EC_WRITE_U16(datagram->data, slave->station_address); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Writing station address failed on slave %i!\n", - slave->ring_position); - goto out_free; - } - - // fetch all slave information - if (ec_slave_fetch(slave)) goto out_free; - - // search for identification in "database" - ident = slave_idents; - while (ident->type) { - if (unlikely(ident->vendor_id == slave->sii_vendor_id - && ident->product_code == slave->sii_product_code)) { - slave->type = ident->type; - break; - } - ident++; - } - - if (!slave->type) { - EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" - " position %i.\n", slave->sii_vendor_id, - slave->sii_product_code, slave->ring_position); - } - else if (slave->type->special == EC_TYPE_BUS_COUPLER) { - if (slave->sii_alias) - current_coupler_index = reverse_coupler_index--; - else - current_coupler_index = coupler_index++; - coupler_subindex = 0; - } - - slave->coupler_index = current_coupler_index; - slave->coupler_subindex = coupler_subindex; - coupler_subindex++; - } - return 0; - - out_free: - ec_master_clear_slaves(master); - return -1; } /*****************************************************************************/ @@ -682,7 +555,7 @@ { if (master->mode == EC_MASTER_MODE_IDLE) return; - if (master->mode == EC_MASTER_MODE_RUNNING) { + if (master->mode == EC_MASTER_MODE_OPERATION) { EC_ERR("ec_master_idle_start: Master already running!\n"); return; } @@ -731,12 +604,12 @@ // aquire master lock spin_lock_bh(&master->internal_lock); - ecrt_master_async_receive(master); + ecrt_master_receive(master); // execute master state machine ec_fsm_execute(&master->fsm); - ecrt_master_async_send(master); + ecrt_master_send(master); // release master lock spin_unlock_bh(&master->internal_lock); @@ -748,11 +621,11 @@ /*****************************************************************************/ /** - Initializes a sync manager configuration page. + Initializes a sync manager configuration page with EEPROM data. The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. */ -void ec_sync_config(const ec_sync_t *sync, /**< sync manager */ +void ec_sync_config(const ec_sii_sync_t *sync, /**< sync manager */ const ec_slave_t *slave, /**< EtherCAT slave */ uint8_t *data /**> configuration memory */ ) @@ -761,29 +634,6 @@ sync_size = ec_slave_calc_sync_size(slave, sync); - EC_WRITE_U16(data, sync->physical_start_address); - EC_WRITE_U16(data + 2, sync_size); - EC_WRITE_U8 (data + 4, sync->control_byte); - EC_WRITE_U8 (data + 5, 0x00); // status byte (read only) - EC_WRITE_U16(data + 6, 0x0001); // enable -} - -/*****************************************************************************/ - -/** - Initializes a sync manager configuration page with EEPROM data. - The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes. -*/ - -void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */ - const ec_slave_t *slave, /**< EtherCAT slave */ - uint8_t *data /**> configuration memory */ - ) -{ - size_t sync_size; - - sync_size = ec_slave_calc_eeprom_sync_size(slave, sync); - if (slave->master->debug_level) { EC_INFO("Slave %i, sync manager %i:\n", slave->ring_position, sync->index); @@ -821,7 +671,8 @@ EC_WRITE_U8 (data + 7, 0x07); // logical end bit EC_WRITE_U16(data + 8, fmmu->sync->physical_start_address); EC_WRITE_U8 (data + 10, 0x00); // physical start bit - EC_WRITE_U8 (data + 11, (fmmu->sync->control_byte & 0x04) ? 0x02 : 0x01); + EC_WRITE_U8 (data + 11, ((fmmu->sync->control_register & 0x04) + ? 0x02 : 0x01)); EC_WRITE_U16(data + 12, 0x0001); // enable EC_WRITE_U16(data + 14, 0x0000); // reserved } @@ -849,8 +700,8 @@ return sprintf(buffer, "ORPHANED\n"); case EC_MASTER_MODE_IDLE: return sprintf(buffer, "IDLE\n"); - case EC_MASTER_MODE_RUNNING: - return sprintf(buffer, "RUNNING\n"); + case EC_MASTER_MODE_OPERATION: + return sprintf(buffer, "OPERATION\n"); } } else if (attr == &attr_debug_level) { @@ -922,7 +773,7 @@ /*****************************************************************************/ /** - Starts Ethernet-over-EtherCAT processing for all EoE-capable slaves. + Starts/Stops Ethernet-over-EtherCAT processing on demand. */ void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */) @@ -933,12 +784,17 @@ if (master->eoe_running) return; + // if the locking callbacks are not set in operation mode, + // the EoE timer my not be started. + if (master->mode == EC_MASTER_MODE_OPERATION + && (!master->request_cb || !master->release_cb)) return; + // decouple all EoE handlers list_for_each_entry(eoe, &master->eoe_handlers, list) eoe->slave = NULL; + + // couple a free EoE handler to every EoE-capable slave coupled = 0; - - // couple a free EoE handler to every EoE-capable slave list_for_each_entry(slave, &master->slaves, list) { if (!(slave->sii_mailbox_protocols & EC_MBOX_EOE)) continue; @@ -950,12 +806,8 @@ coupled++; EC_INFO("Coupling device %s to slave %i.\n", eoe->dev->name, slave->ring_position); - if (eoe->opened) { - slave->requested_state = EC_SLAVE_STATE_OP; - } - else { - slave->requested_state = EC_SLAVE_STATE_INIT; - } + if (eoe->opened) slave->requested_state = EC_SLAVE_STATE_OP; + else slave->requested_state = EC_SLAVE_STATE_INIT; slave->error_flag = 0; break; } @@ -1026,7 +878,7 @@ if (!active) goto queue_timer; // aquire master lock... - if (master->mode == EC_MASTER_MODE_RUNNING) { + if (master->mode == EC_MASTER_MODE_OPERATION) { // request_cb must return 0, if the lock has been aquired! if (master->request_cb(master->cb_data)) goto queue_timer; @@ -1038,14 +890,14 @@ goto queue_timer; // actual EoE stuff - ecrt_master_async_receive(master); + ecrt_master_receive(master); list_for_each_entry(eoe, &master->eoe_handlers, list) { ec_eoe_run(eoe); } - ecrt_master_async_send(master); + ecrt_master_send(master); // release lock... - if (master->mode == EC_MASTER_MODE_RUNNING) { + if (master->mode == EC_MASTER_MODE_OPERATION) { master->release_cb(master->cb_data); } else if (master->mode == EC_MASTER_MODE_IDLE) { @@ -1057,6 +909,38 @@ add_timer(&master->eoe_timer); } +/*****************************************************************************/ + +/** + Calculates Advanced Position Adresses. +*/ + +void ec_master_calc_addressing(ec_master_t *master /**< EtherCAT master */) +{ + uint16_t coupler_index, coupler_subindex; + uint16_t reverse_coupler_index, current_coupler_index; + ec_slave_t *slave; + + coupler_index = 0; + reverse_coupler_index = 0xFFFF; + current_coupler_index = 0x0000; + coupler_subindex = 0; + + list_for_each_entry(slave, &master->slaves, list) { + if (ec_slave_is_coupler(slave)) { + if (slave->sii_alias) + current_coupler_index = reverse_coupler_index--; + else + current_coupler_index = coupler_index++; + coupler_subindex = 0; + } + + slave->coupler_index = current_coupler_index; + slave->coupler_subindex = coupler_subindex; + coupler_subindex++; + } +} + /****************************************************************************** * Realtime interface *****************************************************************************/ @@ -1115,17 +999,10 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */) { - unsigned int j; - ec_slave_t *slave; - ec_datagram_t *datagram; - const ec_sync_t *sync; - const ec_slave_type_t *type; - const ec_fmmu_t *fmmu; uint32_t domain_offset; ec_domain_t *domain; - ec_eeprom_sync_t *eeprom_sync, mbox_sync; - - datagram = &master->simple_datagram; + ec_fsm_t *fsm = &master->fsm; + ec_slave_t *slave; // allocate all domains domain_offset = 0; @@ -1137,149 +1014,29 @@ domain_offset += domain->data_size; } - // configure and activate slaves + // determine initial states. list_for_each_entry(slave, &master->slaves, list) { - - // change state to INIT - if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) - return -1; - - // check for slave registration - type = slave->type; - if (!type) - EC_WARN("Slave %i has unknown type!\n", slave->ring_position); - - // check and reset CRC fault counters - ec_slave_check_crc(slave); - - // reset FMMUs - if (slave->base_fmmu_count) { - if (ec_datagram_npwr(datagram, slave->station_address, 0x0600, - EC_FMMU_SIZE * slave->base_fmmu_count)) - return -1; - memset(datagram->data, 0x00, - EC_FMMU_SIZE * slave->base_fmmu_count); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Resetting FMMUs failed on slave %i!\n", - slave->ring_position); - return -1; - } - } - - // reset sync managers - if (slave->base_sync_count) { - if (ec_datagram_npwr(datagram, slave->station_address, 0x0800, - EC_SYNC_SIZE * slave->base_sync_count)) - return -1; - memset(datagram->data, 0x00, - EC_SYNC_SIZE * slave->base_sync_count); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Resetting sync managers failed on slave %i!\n", - slave->ring_position); - return -1; - } - } - - // configure sync managers - - // does the slave provide sync manager information? - if (!list_empty(&slave->eeprom_syncs)) { - list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { - if (ec_datagram_npwr(datagram, slave->station_address, - 0x800 + eeprom_sync->index * - EC_SYNC_SIZE, - EC_SYNC_SIZE)) return -1; - ec_eeprom_sync_config(eeprom_sync, slave, datagram->data); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Setting sync manager %i failed on slave %i!\n", - eeprom_sync->index, slave->ring_position); - return -1; - } - } - } - - else if (type) { // known slave type, take type's SM information - for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { - sync = type->sync_managers[j]; - if (ec_datagram_npwr(datagram, slave->station_address, - 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) - return -1; - ec_sync_config(sync, slave, datagram->data); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Setting sync manager %i failed on slave %i!\n", - j, slave->ring_position); - return -1; - } - } - } - - // no sync manager information; guess mailbox settings - else if (slave->sii_mailbox_protocols) { - mbox_sync.physical_start_address = - slave->sii_rx_mailbox_offset; - mbox_sync.length = slave->sii_rx_mailbox_size; - mbox_sync.control_register = 0x26; - mbox_sync.enable = 1; - if (ec_datagram_npwr(datagram, slave->station_address, - 0x800,EC_SYNC_SIZE)) return -1; - ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Setting sync manager 0 failed on slave %i!\n", - slave->ring_position); - return -1; - } - - mbox_sync.physical_start_address = - slave->sii_tx_mailbox_offset; - mbox_sync.length = slave->sii_tx_mailbox_size; - mbox_sync.control_register = 0x22; - mbox_sync.enable = 1; - if (ec_datagram_npwr(datagram, slave->station_address, - 0x808, EC_SYNC_SIZE)) return -1; - ec_eeprom_sync_config(&mbox_sync, slave, datagram->data); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Setting sync manager 1 failed on slave %i!\n", - slave->ring_position); - return -1; - } - } - - // change state to PREOP - if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP))) - return -1; - - // stop activation here for slaves without type - if (!type) continue; - - // slaves that are not registered are only brought into PREOP - // state -> nice blinking and mailbox communication possible - if (!slave->registered && !slave->type->special) { - EC_WARN("Slave %i was not registered!\n", slave->ring_position); - continue; - } - - // configure FMMUs - for (j = 0; j < slave->fmmu_count; j++) { - fmmu = &slave->fmmus[j]; - if (ec_datagram_npwr(datagram, slave->station_address, - 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE)) - return -1; - ec_fmmu_config(fmmu, slave, datagram->data); - if (unlikely(ec_master_simple_io(master, datagram))) { - EC_ERR("Setting FMMU %i failed on slave %i!\n", - j, slave->ring_position); - return -1; - } - } - - // change state to SAVEOP - if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_SAVEOP))) - return -1; - - // change state to OP - if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_OP))) - return -1; - } + if (ec_slave_is_coupler(slave) || slave->registered) { + slave->requested_state = EC_SLAVE_STATE_OP; + } + else { + slave->requested_state = EC_SLAVE_STATE_PREOP; + } + } + + ec_fsm_configuration(fsm); // init configuration state machine + + do { + ec_fsm_execute(fsm); + ec_master_sync_io(master); + } + while (ec_fsm_configuration_running(fsm)); + + if (!ec_fsm_configuration_success(fsm)) { + return -1; + } + + ec_fsm_reset(&master->fsm); // prepare for operation state machine return 0; } @@ -1293,59 +1050,39 @@ void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */) { + ec_fsm_t *fsm = &master->fsm; ec_slave_t *slave; list_for_each_entry(slave, &master->slaves, list) { - ec_slave_check_crc(slave); - ec_slave_state_change(slave, EC_SLAVE_STATE_INIT); - } -} - - -/*****************************************************************************/ - -/** - Fetches the SDO dictionaries of all slaves. - Slaves that do not support the CoE protocol are left out. - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT master */) -{ - ec_slave_t *slave; - - list_for_each_entry(slave, &master->slaves, list) { - if (slave->sii_mailbox_protocols & EC_MBOX_COE) { - if (unlikely(ec_slave_fetch_sdo_list(slave))) { - EC_ERR("Failed to fetch SDO list on slave %i!\n", - slave->ring_position); - return -1; - } - } - } - - return 0; + slave->requested_state = EC_SLAVE_STATE_INIT; + } + + ec_fsm_configuration(fsm); // init configuration state machine + + do { + ec_fsm_execute(fsm); + ec_master_sync_io(master); + } + while (ec_fsm_configuration_running(fsm)); } /*****************************************************************************/ /** Sends queued datagrams and waits for their reception. - \ingroup RealtimeInterface -*/ - -void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */) +*/ + +void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */) { ec_datagram_t *datagram, *n; unsigned int datagrams_sent; cycles_t t_start, t_end, t_timeout; // send datagrams - ecrt_master_async_send(master); + ecrt_master_send(master); t_start = get_cycles(); // measure io time - t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); + t_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); while (1) { // active waiting ec_device_call_isr(master->device); @@ -1355,9 +1092,9 @@ datagrams_sent = 0; list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { - if (datagram->state == EC_CMD_RECEIVED) + if (datagram->state == EC_DATAGRAM_RECEIVED) list_del_init(&datagram->queue); - else if (datagram->state == EC_CMD_SENT) + else if (datagram->state == EC_DATAGRAM_SENT) datagrams_sent++; } @@ -1367,13 +1104,13 @@ // timeout; dequeue all datagrams list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { switch (datagram->state) { - case EC_CMD_SENT: - case EC_CMD_QUEUED: - datagram->state = EC_CMD_TIMEOUT; + case EC_DATAGRAM_SENT: + case EC_DATAGRAM_QUEUED: + datagram->state = EC_DATAGRAM_TIMED_OUT; master->stats.timeouts++; ec_master_output_stats(master); break; - case EC_CMD_RECEIVED: + case EC_DATAGRAM_RECEIVED: master->stats.delayed++; ec_master_output_stats(master); break; @@ -1391,14 +1128,14 @@ \ingroup RealtimeInterface */ -void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */) +void ecrt_master_send(ec_master_t *master /**< EtherCAT master */) { ec_datagram_t *datagram, *n; if (unlikely(!master->device->link_state)) { // link is down, no datagram can be sent list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { - datagram->state = EC_CMD_ERROR; + datagram->state = EC_DATAGRAM_ERROR; list_del_init(&datagram->queue); } @@ -1418,7 +1155,7 @@ \ingroup RealtimeInterface */ -void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) +void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */) { ec_datagram_t *datagram, *next; cycles_t t_received, t_timeout; @@ -1426,21 +1163,21 @@ ec_device_call_isr(master->device); t_received = get_cycles(); - t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); + t_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); // dequeue all received datagrams list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) - if (datagram->state == EC_CMD_RECEIVED) + if (datagram->state == EC_DATAGRAM_RECEIVED) list_del_init(&datagram->queue); // dequeue all datagrams that timed out list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { switch (datagram->state) { - case EC_CMD_SENT: - case EC_CMD_QUEUED: + case EC_DATAGRAM_SENT: + case EC_DATAGRAM_QUEUED: if (t_received - datagram->t_sent > t_timeout) { list_del_init(&datagram->queue); - datagram->state = EC_CMD_TIMEOUT; + datagram->state = EC_DATAGRAM_TIMED_OUT; master->stats.timeouts++; ec_master_output_stats(master); } @@ -1456,23 +1193,23 @@ /** Prepares synchronous IO. Queues all domain datagrams and sends them. Then waits a certain time, so - that ecrt_master_sasync_receive() can be called securely. + that ecrt_master_receive() can be called securely. \ingroup RealtimeInterface */ -void ecrt_master_prepare_async_io(ec_master_t *master /**< EtherCAT master */) +void ecrt_master_prepare(ec_master_t *master /**< EtherCAT master */) { ec_domain_t *domain; cycles_t t_start, t_end, t_timeout; // queue datagrams of all domains list_for_each_entry(domain, &master->domains, list) - ecrt_domain_queue(domain); - - ecrt_master_async_send(master); + ec_domain_queue(domain); + + ecrt_master_send(master); t_start = get_cycles(); // take sending time - t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); + t_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); // active waiting while (1) { @@ -1576,8 +1313,7 @@ } if (alias_requested) { - if (!alias_slave->type || - alias_slave->type->special != EC_TYPE_BUS_COUPLER) { + if (!ec_slave_is_coupler(alias_slave)) { EC_ERR("Slave address \"%s\": Alias slave must be bus coupler" " in colon mode.\n", address); return NULL; @@ -1628,92 +1364,16 @@ /*****************************************************************************/ -/** - Starts Ethernet-over-EtherCAT processing for all EoE-capable slaves. - \ingroup RealtimeInterface -*/ - -int ecrt_master_start_eoe(ec_master_t *master /**< EtherCAT master */) -{ - if (!master->request_cb || !master->release_cb) { - EC_ERR("EoE requires master callbacks to be set!\n"); - return -1; - } - - ec_master_eoe_start(master); - return 0; -} - -/*****************************************************************************/ - -/** - Sets the debug level of the master. - The following levels are valid: - - 1: only output positions marks and basic data - - 2: additional frame data output - \ingroup RealtimeInterface -*/ - -void ecrt_master_debug(ec_master_t *master, /**< EtherCAT master */ - int level /**< debug level */ - ) -{ - if (level != master->debug_level) { - master->debug_level = level; - EC_INFO("Master debug level set to %i.\n", level); - } -} - -/*****************************************************************************/ - -/** - Outputs all master information. - Verbosity: - - 0: Only slave types and positions - - 1: with EEPROM contents - - >1: with SDO dictionaries - \ingroup RealtimeInterface -*/ - -void ecrt_master_print(const ec_master_t *master, /**< EtherCAT master */ - unsigned int verbosity /**< verbosity level */ - ) -{ - ec_slave_t *slave; - ec_eoe_t *eoe; - - EC_INFO("*** Begin master information ***\n"); - if (master->slave_count) { - EC_INFO("Slave list:\n"); - list_for_each_entry(slave, &master->slaves, list) - ec_slave_print(slave, verbosity); - } - if (!list_empty(&master->eoe_handlers)) { - EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n"); - list_for_each_entry(eoe, &master->eoe_handlers, list) { - ec_eoe_print(eoe); - } - } - EC_INFO("*** End master information ***\n"); -} - -/*****************************************************************************/ - /** \cond */ EXPORT_SYMBOL(ecrt_master_create_domain); EXPORT_SYMBOL(ecrt_master_activate); EXPORT_SYMBOL(ecrt_master_deactivate); -EXPORT_SYMBOL(ecrt_master_fetch_sdo_lists); -EXPORT_SYMBOL(ecrt_master_prepare_async_io); -EXPORT_SYMBOL(ecrt_master_sync_io); -EXPORT_SYMBOL(ecrt_master_async_send); -EXPORT_SYMBOL(ecrt_master_async_receive); +EXPORT_SYMBOL(ecrt_master_prepare); +EXPORT_SYMBOL(ecrt_master_send); +EXPORT_SYMBOL(ecrt_master_receive); EXPORT_SYMBOL(ecrt_master_run); EXPORT_SYMBOL(ecrt_master_callbacks); -EXPORT_SYMBOL(ecrt_master_start_eoe); -EXPORT_SYMBOL(ecrt_master_debug); -EXPORT_SYMBOL(ecrt_master_print); EXPORT_SYMBOL(ecrt_master_get_slave); /** \endcond */ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/master.h --- a/master/master.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/master.h Thu Aug 03 12:51:17 2006 +0000 @@ -59,7 +59,7 @@ { 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 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 @@ // 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_output_stats(ec_master_t *); 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 *); + +// 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_output_stats(ec_master_t *); +void ec_master_calc_addressing(ec_master_t *); /*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/module.c --- a/master/module.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/module.c Thu Aug 03 12:51:17 2006 +0000 @@ -237,33 +237,38 @@ 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_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"); diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/slave.c --- a/master/slave.c Wed Aug 02 23:16:10 2006 +0000 +++ b/master/slave.c Thu Aug 03 12:51:17 2006 +0000 @@ -52,7 +52,6 @@ /*****************************************************************************/ -int ec_slave_fetch_categories(ec_slave_t *); ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *); ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *, const char *, size_t); @@ -61,24 +60,12 @@ /** \cond */ -EC_SYSFS_READ_ATTR(ring_position); -EC_SYSFS_READ_ATTR(advanced_position); -EC_SYSFS_READ_ATTR(vendor_name); // deprecated -EC_SYSFS_READ_ATTR(product_name); // deprecated -EC_SYSFS_READ_ATTR(product_desc); // deprecated -EC_SYSFS_READ_ATTR(name); -EC_SYSFS_READ_ATTR(type); // deprecated +EC_SYSFS_READ_ATTR(info); EC_SYSFS_READ_WRITE_ATTR(state); EC_SYSFS_READ_WRITE_ATTR(eeprom); static struct attribute *def_attrs[] = { - &attr_ring_position, - &attr_advanced_position, - &attr_vendor_name, - &attr_product_name, - &attr_product_desc, - &attr_name, - &attr_type, + &attr_info, &attr_state, &attr_eeprom, NULL, @@ -127,13 +114,28 @@ } slave->master = master; + + slave->requested_state = EC_SLAVE_STATE_UNKNOWN; + slave->current_state = EC_SLAVE_STATE_UNKNOWN; + slave->error_flag = 0; + slave->online = 1; + slave->fmmu_count = 0; + slave->registered = 0; + slave->coupler_index = 0; slave->coupler_subindex = 0xFFFF; + slave->base_type = 0; slave->base_revision = 0; slave->base_build = 0; slave->base_fmmu_count = 0; slave->base_sync_count = 0; + + slave->eeprom_data = NULL; + slave->eeprom_size = 0; + slave->new_eeprom_data = NULL; + slave->new_eeprom_size = 0; + slave->sii_alias = 0; slave->sii_vendor_id = 0; slave->sii_product_code = 0; @@ -144,25 +146,14 @@ slave->sii_tx_mailbox_offset = 0; slave->sii_tx_mailbox_size = 0; slave->sii_mailbox_protocols = 0; - slave->type = NULL; - slave->registered = 0; - slave->fmmu_count = 0; - slave->eeprom_data = NULL; - slave->eeprom_size = 0; - slave->eeprom_group = NULL; - slave->eeprom_image = NULL; - slave->eeprom_order = NULL; - slave->eeprom_name = NULL; - slave->requested_state = EC_SLAVE_STATE_UNKNOWN; - slave->current_state = EC_SLAVE_STATE_UNKNOWN; - slave->error_flag = 0; - slave->online = 1; - slave->new_eeprom_data = NULL; - slave->new_eeprom_size = 0; - - INIT_LIST_HEAD(&slave->eeprom_strings); - INIT_LIST_HEAD(&slave->eeprom_syncs); - INIT_LIST_HEAD(&slave->eeprom_pdos); + slave->sii_group = NULL; + slave->sii_image = NULL; + slave->sii_order = NULL; + slave->sii_name = NULL; + + INIT_LIST_HEAD(&slave->sii_strings); + INIT_LIST_HEAD(&slave->sii_syncs); + INIT_LIST_HEAD(&slave->sii_pdos); INIT_LIST_HEAD(&slave->sdo_dictionary); INIT_LIST_HEAD(&slave->varsize_fields); @@ -185,10 +176,10 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */) { ec_slave_t *slave; - ec_eeprom_string_t *string, *next_str; - ec_eeprom_sync_t *sync, *next_sync; - ec_eeprom_pdo_t *pdo, *next_pdo; - ec_eeprom_pdo_entry_t *entry, *next_ent; + ec_sii_string_t *string, *next_str; + ec_sii_sync_t *sync, *next_sync; + ec_sii_pdo_t *pdo, *next_pdo; + ec_sii_pdo_entry_t *entry, *next_ent; ec_sdo_t *sdo, *next_sdo; ec_sdo_entry_t *en, *next_en; ec_varsize_t *var, *next_var; @@ -196,19 +187,19 @@ slave = container_of(kobj, ec_slave_t, kobj); // free all string objects - list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { + list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) { list_del(&string->list); kfree(string); } // free all sync managers - list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) { + list_for_each_entry_safe(sync, next_sync, &slave->sii_syncs, list) { list_del(&sync->list); kfree(sync); } // free all PDOs - list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) { + list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) { list_del(&pdo->list); if (pdo->name) kfree(pdo->name); @@ -222,10 +213,10 @@ kfree(pdo); } - if (slave->eeprom_group) kfree(slave->eeprom_group); - if (slave->eeprom_image) kfree(slave->eeprom_image); - if (slave->eeprom_order) kfree(slave->eeprom_order); - if (slave->eeprom_name) kfree(slave->eeprom_name); + if (slave->sii_group) kfree(slave->sii_group); + if (slave->sii_image) kfree(slave->sii_image); + if (slave->sii_order) kfree(slave->sii_order); + if (slave->sii_name) kfree(slave->sii_name); // free all SDOs list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) { @@ -253,371 +244,6 @@ /*****************************************************************************/ /** - Reads all necessary information from a slave. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT slave */) -{ - ec_datagram_t *datagram; - unsigned int i; - uint16_t dl_status; - - datagram = &slave->master->simple_datagram; - - // read base data - if (ec_datagram_nprd(datagram, slave->station_address, 0x0000, 6)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Reading base data from slave %i failed!\n", - slave->ring_position); - return -1; - } - - slave->base_type = EC_READ_U8 (datagram->data); - slave->base_revision = EC_READ_U8 (datagram->data + 1); - slave->base_build = EC_READ_U16(datagram->data + 2); - slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4); - slave->base_sync_count = EC_READ_U8 (datagram->data + 5); - - if (slave->base_fmmu_count > EC_MAX_FMMUS) - slave->base_fmmu_count = EC_MAX_FMMUS; - - // read data link status - if (ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Reading DL status from slave %i failed!\n", - slave->ring_position); - return -1; - } - - dl_status = EC_READ_U16(datagram->data); - for (i = 0; i < 4; i++) { - slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; - slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; - slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; - } - - // read EEPROM data - if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias)) - return -1; - if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id)) - return -1; - if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code)) - return -1; - if (ec_slave_sii_read32(slave, 0x000C, &slave->sii_revision_number)) - return -1; - if (ec_slave_sii_read32(slave, 0x000E, &slave->sii_serial_number)) - return -1; - if (ec_slave_sii_read16(slave, 0x0018, &slave->sii_rx_mailbox_offset)) - return -1; - if (ec_slave_sii_read16(slave, 0x0019, &slave->sii_rx_mailbox_size)) - return -1; - if (ec_slave_sii_read16(slave, 0x001A, &slave->sii_tx_mailbox_offset)) - return -1; - if (ec_slave_sii_read16(slave, 0x001B, &slave->sii_tx_mailbox_size)) - return -1; - if (ec_slave_sii_read16(slave, 0x001C, &slave->sii_mailbox_protocols)) - return -1; - - if (unlikely(ec_slave_fetch_categories(slave))) { - EC_ERR("Failed to fetch category data!\n"); - return -1; - } - - return 0; -} - -/*****************************************************************************/ - -/** - Reads 16 bit from the slave information interface (SII). - \return 0 in case of success, else < 0 -*/ - -int ec_slave_sii_read16(ec_slave_t *slave, - /**< EtherCAT slave */ - uint16_t offset, - /**< address of the SII register to read */ - uint16_t *target - /**< target memory */ - ) -{ - ec_datagram_t *datagram; - cycles_t start, end, timeout; - - datagram = &slave->master->simple_datagram; - - // initiate read operation - if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6)) - return -1; - EC_WRITE_U8 (datagram->data, 0x00); // read-only access - EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation - EC_WRITE_U32(datagram->data + 2, offset); - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); - return -1; - } - - start = get_cycles(); - timeout = (cycles_t) 100 * cpu_khz; // 100ms - - while (1) - { - udelay(10); - - if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Getting SII-read status failed on slave %i!\n", - slave->ring_position); - return -1; - } - - end = get_cycles(); - - // check for "busy bit" - if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) { - *target = EC_READ_U16(datagram->data + 6); - return 0; - } - - if (unlikely((end - start) >= timeout)) { - EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position); - return -1; - } - } -} - -/*****************************************************************************/ - -/** - Reads 32 bit from the slave information interface (SII). - \return 0 in case of success, else < 0 -*/ - -int ec_slave_sii_read32(ec_slave_t *slave, - /**< EtherCAT slave */ - uint16_t offset, - /**< address of the SII register to read */ - uint32_t *target - /**< target memory */ - ) -{ - ec_datagram_t *datagram; - cycles_t start, end, timeout; - - datagram = &slave->master->simple_datagram; - - // initiate read operation - if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 6)) - return -1; - EC_WRITE_U8 (datagram->data, 0x00); // read-only access - EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation - EC_WRITE_U32(datagram->data + 2, offset); - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); - return -1; - } - - start = get_cycles(); - timeout = (cycles_t) 100 * cpu_khz; // 100ms - - while (1) - { - udelay(10); - - if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 10)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Getting SII-read status failed on slave %i!\n", - slave->ring_position); - return -1; - } - - end = get_cycles(); - - // check "busy bit" - if (likely((EC_READ_U8(datagram->data + 1) & 0x81) == 0)) { - *target = EC_READ_U32(datagram->data + 6); - return 0; - } - - if (unlikely((end - start) >= timeout)) { - EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position); - return -1; - } - } -} - -/*****************************************************************************/ - -/** - Writes 16 bit of data to the slave information interface (SII). - \return 0 in case of success, else < 0 -*/ - -int ec_slave_sii_write16(ec_slave_t *slave, - /**< EtherCAT slave */ - uint16_t offset, - /**< address of the SII register to write */ - uint16_t value - /**< new value */ - ) -{ - ec_datagram_t *datagram; - cycles_t start, end, timeout; - - datagram = &slave->master->simple_datagram; - - EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n", - slave->ring_position, offset, value); - - // initiate write operation - if (ec_datagram_npwr(datagram, slave->station_address, 0x502, 8)) - return -1; - EC_WRITE_U8 (datagram->data, 0x01); // enable write access - EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation - EC_WRITE_U32(datagram->data + 2, offset); - EC_WRITE_U16(datagram->data + 6, value); - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); - return -1; - } - - start = get_cycles(); - timeout = (cycles_t) 100 * cpu_khz; // 100ms - - while (1) - { - udelay(10); - - if (ec_datagram_nprd(datagram, slave->station_address, 0x502, 2)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Getting SII-write status failed on slave %i!\n", - slave->ring_position); - return -1; - } - - end = get_cycles(); - - // check "busy bit" - if (likely((EC_READ_U8(datagram->data + 1) & 0x82) == 0)) { - if (EC_READ_U8(datagram->data + 1) & 0x40) { - EC_ERR("SII-write failed!\n"); - return -1; - } - else { - EC_INFO("SII-write succeeded!\n"); - return 0; - } - } - - if (unlikely((end - start) >= timeout)) { - EC_ERR("SII-write: Slave %i timed out!\n", slave->ring_position); - return -1; - } - } -} - -/*****************************************************************************/ - -/** - Fetches data from slave's EEPROM. - \return 0 in case of success, else < 0 - \todo memory allocation -*/ - -int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */) -{ - uint16_t word_offset, cat_type, word_count; - uint32_t value; - uint8_t *cat_data; - unsigned int i; - - word_offset = 0x0040; - - if (!(cat_data = (uint8_t *) kmalloc(0x10000, GFP_ATOMIC))) { - EC_ERR("Failed to allocate 64k bytes for category data.\n"); - return -1; - } - - while (1) { - // read category type - if (ec_slave_sii_read32(slave, word_offset, &value)) { - EC_ERR("Unable to read category header.\n"); - goto out_free; - } - - // last category? - if ((value & 0xFFFF) == 0xFFFF) break; - - cat_type = value & 0x7FFF; - word_count = (value >> 16) & 0xFFFF; - - // fetch category data - for (i = 0; i < word_count; i++) { - if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) { - EC_ERR("Unable to read category data word %i.\n", i); - goto out_free; - } - - cat_data[i * 2] = (value >> 0) & 0xFF; - cat_data[i * 2 + 1] = (value >> 8) & 0xFF; - - // read second word "on the fly" - if (i + 1 < word_count) { - i++; - cat_data[i * 2] = (value >> 16) & 0xFF; - cat_data[i * 2 + 1] = (value >> 24) & 0xFF; - } - } - - switch (cat_type) - { - case 0x000A: - if (ec_slave_fetch_strings(slave, cat_data)) - goto out_free; - break; - case 0x001E: - if (ec_slave_fetch_general(slave, cat_data)) - goto out_free; - break; - case 0x0028: - break; - case 0x0029: - if (ec_slave_fetch_sync(slave, cat_data, word_count)) - goto out_free; - break; - case 0x0032: - if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_TX_PDO)) - goto out_free; - break; - case 0x0033: - if (ec_slave_fetch_pdo(slave, cat_data, word_count, EC_RX_PDO)) - goto out_free; - break; - default: - EC_WARN("Unknown category type 0x%04X in slave %i.\n", - cat_type, slave->ring_position); - } - - word_offset += 2 + word_count; - } - - kfree(cat_data); - return 0; - - out_free: - kfree(cat_data); - return -1; -} - -/*****************************************************************************/ - -/** Fetches data from a STRING category. \return 0 in case of success, else < 0 */ @@ -629,24 +255,24 @@ unsigned int string_count, i; size_t size; off_t offset; - ec_eeprom_string_t *string; + ec_sii_string_t *string; string_count = data[0]; offset = 1; for (i = 0; i < string_count; i++) { size = data[offset]; // allocate memory for string structure and data at a single blow - if (!(string = (ec_eeprom_string_t *) - kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_ATOMIC))) { + if (!(string = (ec_sii_string_t *) + kmalloc(sizeof(ec_sii_string_t) + size + 1, GFP_ATOMIC))) { EC_ERR("Failed to allocate string memory.\n"); return -1; } string->size = size; // string memory appended to string structure - string->data = (char *) string + sizeof(ec_eeprom_string_t); + string->data = (char *) string + sizeof(ec_sii_string_t); memcpy(string->data, data + offset + 1, size); string->data[size] = 0x00; - list_add_tail(&string->list, &slave->eeprom_strings); + list_add_tail(&string->list, &slave->sii_strings); offset += 1 + size; } @@ -660,26 +286,20 @@ \return 0 in case of success, else < 0 */ -int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT slave */ - const uint8_t *data /**< category data */ - ) +void ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT slave */ + const uint8_t *data /**< category data */ + ) { unsigned int i; - if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group)) - return -1; - if (ec_slave_locate_string(slave, data[1], &slave->eeprom_image)) - return -1; - if (ec_slave_locate_string(slave, data[2], &slave->eeprom_order)) - return -1; - if (ec_slave_locate_string(slave, data[3], &slave->eeprom_name)) - return -1; + ec_slave_locate_string(slave, data[0], &slave->sii_group); + ec_slave_locate_string(slave, data[1], &slave->sii_image); + ec_slave_locate_string(slave, data[2], &slave->sii_order); + ec_slave_locate_string(slave, data[3], &slave->sii_name); for (i = 0; i < 4; i++) slave->sii_physical_layer[i] = (data[4] & (0x03 << (i * 2))) >> (i * 2); - - return 0; } /*****************************************************************************/ @@ -695,24 +315,24 @@ ) { unsigned int sync_count, i; - ec_eeprom_sync_t *sync; + ec_sii_sync_t *sync; sync_count = word_count / 4; // sync manager struct is 4 words long for (i = 0; i < sync_count; i++, data += 8) { - if (!(sync = (ec_eeprom_sync_t *) - kmalloc(sizeof(ec_eeprom_sync_t), GFP_ATOMIC))) { + if (!(sync = (ec_sii_sync_t *) + kmalloc(sizeof(ec_sii_sync_t), GFP_ATOMIC))) { EC_ERR("Failed to allocate Sync-Manager memory.\n"); return -1; } sync->index = i; - sync->physical_start_address = *((uint16_t *) (data + 0)); - sync->length = *((uint16_t *) (data + 2)); - sync->control_register = data[4]; - sync->enable = data[6]; - - list_add_tail(&sync->list, &slave->eeprom_syncs); + sync->physical_start_address = EC_READ_U16(data); + sync->length = EC_READ_U16(data + 2); + sync->control_register = EC_READ_U8 (data + 4); + sync->enable = EC_READ_U8 (data + 6); + + list_add_tail(&sync->list, &slave->sii_syncs); } return 0; @@ -728,16 +348,16 @@ int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */ const uint8_t *data, /**< category data */ size_t word_count, /**< number of words */ - ec_pdo_type_t pdo_type /**< PDO type */ + ec_sii_pdo_type_t pdo_type /**< PDO type */ ) { - ec_eeprom_pdo_t *pdo; - ec_eeprom_pdo_entry_t *entry; + ec_sii_pdo_t *pdo; + ec_sii_pdo_entry_t *entry; unsigned int entry_count, i; while (word_count >= 4) { - if (!(pdo = (ec_eeprom_pdo_t *) - kmalloc(sizeof(ec_eeprom_pdo_t), GFP_ATOMIC))) { + if (!(pdo = (ec_sii_pdo_t *) + kmalloc(sizeof(ec_sii_pdo_t), GFP_ATOMIC))) { EC_ERR("Failed to allocate PDO memory.\n"); return -1; } @@ -745,29 +365,29 @@ INIT_LIST_HEAD(&pdo->entries); pdo->type = pdo_type; - pdo->index = *((uint16_t *) data); - entry_count = data[2]; - pdo->sync_manager = data[3]; + pdo->index = EC_READ_U16(data); + entry_count = EC_READ_U8(data + 2); + pdo->sync_index = EC_READ_U8(data + 3); pdo->name = NULL; - ec_slave_locate_string(slave, data[5], &pdo->name); - - list_add_tail(&pdo->list, &slave->eeprom_pdos); + ec_slave_locate_string(slave, EC_READ_U8(data + 5), &pdo->name); + + list_add_tail(&pdo->list, &slave->sii_pdos); word_count -= 4; data += 8; for (i = 0; i < entry_count; i++) { - if (!(entry = (ec_eeprom_pdo_entry_t *) - kmalloc(sizeof(ec_eeprom_pdo_entry_t), GFP_ATOMIC))) { + if (!(entry = (ec_sii_pdo_entry_t *) + kmalloc(sizeof(ec_sii_pdo_entry_t), GFP_ATOMIC))) { EC_ERR("Failed to allocate PDO entry memory.\n"); return -1; } - entry->index = *((uint16_t *) data); - entry->subindex = data[2]; + entry->index = EC_READ_U16(data); + entry->subindex = EC_READ_U8(data + 2); entry->name = NULL; - ec_slave_locate_string(slave, data[3], &entry->name); - entry->bit_length = data[5]; + ec_slave_locate_string(slave, EC_READ_U8(data + 3), &entry->name); + entry->bit_length = EC_READ_U8(data + 5); list_add_tail(&entry->list, &pdo->entries); @@ -792,7 +412,7 @@ char **ptr /**< Address of the string pointer */ ) { - ec_eeprom_string_t *string; + ec_sii_string_t *string; char *err_string; // Erst alten Speicher freigeben @@ -805,7 +425,7 @@ if (!index) return 0; // EEPROM-String mit Index finden und kopieren - list_for_each_entry(string, &slave->eeprom_strings, list) { + list_for_each_entry(string, &slave->sii_strings, list) { if (--index) continue; if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) { @@ -821,7 +441,7 @@ err_string = "(string not found)"; if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) { - EC_ERR("Unable to allocate string memory.\n"); + EC_WARN("Unable to allocate string memory.\n"); return -1; } @@ -832,174 +452,11 @@ /*****************************************************************************/ /** - Acknowledges an error after a state transition. -*/ - -void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */ - uint8_t state /**< previous state */ - ) -{ - ec_datagram_t *datagram; - cycles_t start, end, timeout; - - datagram = &slave->master->simple_datagram; - - if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) return; - EC_WRITE_U16(datagram->data, state | EC_ACK); - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_WARN("Acknowledge sending failed on slave %i!\n", - slave->ring_position); - return; - } - - start = get_cycles(); - timeout = (cycles_t) 100 * cpu_khz; // 100ms - - while (1) { - udelay(100); // wait a little bit... - - if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2)) - return; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - slave->current_state = EC_SLAVE_STATE_UNKNOWN; - EC_WARN("Acknowledge checking failed on slave %i!\n", - slave->ring_position); - return; - } - - end = get_cycles(); - - if (EC_READ_U8(datagram->data) == state) { - slave->current_state = state; - EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state, - slave->ring_position); - return; - } - - if (end - start >= timeout) { - slave->current_state = EC_SLAVE_STATE_UNKNOWN; - EC_WARN("Failed to acknowledge state 0x%02X on slave %i" - " - Timeout!\n", state, slave->ring_position); - return; - } - } -} - -/*****************************************************************************/ - -/** - Reads the AL status code of a slave and displays it. - If the AL status code is not supported, or if no error occurred (both - resulting in code = 0), nothing is displayed. -*/ - -void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT slave */) -{ - ec_datagram_t *datagram; - uint16_t code; - const ec_code_msg_t *al_msg; - - datagram = &slave->master->simple_datagram; - - if (ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2)) return; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_WARN("Failed to read AL status code on slave %i!\n", - slave->ring_position); - return; - } - - if (!(code = EC_READ_U16(datagram->data))) return; - - for (al_msg = al_status_messages; al_msg->code; al_msg++) { - if (al_msg->code == code) { - EC_ERR("AL status message 0x%04X: \"%s\".\n", - al_msg->code, al_msg->message); - return; - } - } - - EC_ERR("Unknown AL status code 0x%04X.\n", code); -} - -/*****************************************************************************/ - -/** - Does a state transition. - \return 0 in case of success, else < 0 -*/ - -int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */ - uint8_t state /**< new state */ - ) -{ - ec_datagram_t *datagram; - cycles_t start, end, timeout; - - datagram = &slave->master->simple_datagram; - - slave->requested_state = state; - - if (ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2)) - return -1; - EC_WRITE_U16(datagram->data, state); - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - EC_ERR("Failed to set state 0x%02X on slave %i!\n", - state, slave->ring_position); - return -1; - } - - start = get_cycles(); - timeout = (cycles_t) 10 * cpu_khz; // 10ms - - while (1) - { - udelay(100); // wait a little bit - - if (ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2)) - return -1; - if (unlikely(ec_master_simple_io(slave->master, datagram))) { - slave->current_state = EC_SLAVE_STATE_UNKNOWN; - EC_ERR("Failed to check state 0x%02X on slave %i!\n", - state, slave->ring_position); - return -1; - } - - end = get_cycles(); - - if (unlikely(EC_READ_U8(datagram->data) & 0x10)) { - // state change error - EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" - " (code 0x%02X)!\n", state, slave->ring_position, - EC_READ_U8(datagram->data)); - slave->current_state = EC_READ_U8(datagram->data); - state = slave->current_state & 0x0F; - ec_slave_read_al_status_code(slave); - ec_slave_state_ack(slave, state); - return -1; - } - - if (likely(EC_READ_U8(datagram->data) == (state & 0x0F))) { - slave->current_state = state; - return 0; // state change successful - } - - if (unlikely((end - start) >= timeout)) { - slave->current_state = EC_SLAVE_STATE_UNKNOWN; - EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", - state, slave->ring_position); - return -1; - } - } -} - -/*****************************************************************************/ - -/** Prepares an FMMU configuration. Configuration data for the FMMU is saved in the slave structure and is written to the slave in ecrt_master_activate(). The FMMU configuration is done in a way, that the complete data range - of the corresponding sync manager is covered. Seperate FMMUs arce configured + of the corresponding sync manager is covered. Seperate FMMUs are configured for each domain. If the FMMU configuration is already prepared, the function returns with success. @@ -1008,7 +465,7 @@ int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */ const ec_domain_t *domain, /**< domain */ - const ec_sync_t *sync /**< sync manager */ + const ec_sii_sync_t *sync /**< sync manager */ ) { unsigned int i; @@ -1038,171 +495,152 @@ /** Outputs all information about a certain slave. - Verbosity: - - 0: Only slave types and addresses - - 1: with EEPROM information - - >1: with SDO dictionaries -*/ - -void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT slave */ - unsigned int verbosity /**< verbosity level */ - ) -{ - ec_eeprom_sync_t *sync; - ec_eeprom_pdo_t *pdo; - ec_eeprom_pdo_entry_t *pdo_entry; - ec_sdo_t *sdo; - ec_sdo_entry_t *sdo_entry; +*/ + +size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ + char *buffer /**< Output buffer */ + ) +{ + off_t off = 0; + ec_sii_sync_t *sync; + ec_sii_pdo_t *pdo; + ec_sii_pdo_entry_t *pdo_entry; int first, i; - if (slave->type) { - EC_INFO("%i) %s %s: %s\n", slave->ring_position, - slave->type->vendor_name, slave->type->product_name, - slave->type->description); - } - else { - EC_INFO("%i) UNKNOWN SLAVE: vendor 0x%08X, product 0x%08X\n", - slave->ring_position, slave->sii_vendor_id, - slave->sii_product_code); - } - - if (!verbosity) return; - - EC_INFO(" Station address: 0x%04X\n", slave->station_address); - - EC_INFO(" Data link status:\n"); + off += sprintf(buffer + off, "\nName: "); + + if (slave->sii_name) + off += sprintf(buffer + off, "%s", slave->sii_name); + + off += sprintf(buffer + off, "\n\nVendor ID: 0x%08X\n", + slave->sii_vendor_id); + off += sprintf(buffer + off, "Product code: 0x%08X\n\n", + slave->sii_product_code); + + off += sprintf(buffer + off, "Ring position: %i\n", slave->ring_position); + off += sprintf(buffer + off, "Advanced position: %i:%i\n\n", + slave->coupler_index, slave->coupler_subindex); + + off += sprintf(buffer + off, "State: "); + off += ec_state_string(slave->current_state, buffer + off); + off += sprintf(buffer + off, "\n\n"); + + off += sprintf(buffer + off, "Data link status:\n"); for (i = 0; i < 4; i++) { - EC_INFO(" Port %i (", i); + off += sprintf(buffer + off, " Port %i (", i); switch (slave->sii_physical_layer[i]) { case 0x00: - printk("EBUS"); + off += sprintf(buffer + off, "EBUS"); break; case 0x01: - printk("100BASE-TX"); + off += sprintf(buffer + off, "100BASE-TX"); break; case 0x02: - printk("100BASE-FX"); + off += sprintf(buffer + off, "100BASE-FX"); break; default: - printk("unknown"); - } - printk(")\n"); - EC_INFO(" link %s, loop %s, %s\n", - slave->dl_link[i] ? "up" : "down", - slave->dl_loop[i] ? "closed" : "open", - slave->dl_signal[i] ? "signal detected" : "no signal"); - } - - EC_INFO(" Base information:\n"); - EC_INFO(" Type %u, revision %i, build %i\n", - slave->base_type, slave->base_revision, slave->base_build); - EC_INFO(" Supported FMMUs: %i, sync managers: %i\n", - slave->base_fmmu_count, slave->base_sync_count); + off += sprintf(buffer + off, "unknown (%i)", + slave->sii_physical_layer[i]); + } + off += sprintf(buffer + off, ") Link %s, Loop %s, %s\n", + slave->dl_link[i] ? "up" : "down", + slave->dl_loop[i] ? "closed" : "open", + slave->dl_signal[i] ? "Signal detected" : "No signal"); + } if (slave->sii_mailbox_protocols) { - EC_INFO(" Mailbox communication:\n"); - EC_INFO(" RX mailbox: 0x%04X/%i, TX mailbox: 0x%04X/%i\n", - slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size, - slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size); - EC_INFO(" Supported protocols: "); + off += sprintf(buffer + off, "\nMailboxes:\n"); + off += sprintf(buffer + off, " RX mailbox: 0x%04X/%i," + " TX mailbox: 0x%04X/%i\n", + slave->sii_rx_mailbox_offset, + slave->sii_rx_mailbox_size, + slave->sii_tx_mailbox_offset, + slave->sii_tx_mailbox_size); + off += sprintf(buffer + off, " Supported protocols: "); first = 1; if (slave->sii_mailbox_protocols & EC_MBOX_AOE) { - printk("AoE"); + off += sprintf(buffer + off, "AoE"); first = 0; } if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { - if (!first) printk(", "); - printk("EoE"); + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "EoE"); first = 0; } if (slave->sii_mailbox_protocols & EC_MBOX_COE) { - if (!first) printk(", "); - printk("CoE"); + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "CoE"); first = 0; } if (slave->sii_mailbox_protocols & EC_MBOX_FOE) { - if (!first) printk(", "); - printk("FoE"); + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "FoE"); first = 0; } if (slave->sii_mailbox_protocols & EC_MBOX_SOE) { - if (!first) printk(", "); - printk("SoE"); + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "SoE"); first = 0; } if (slave->sii_mailbox_protocols & EC_MBOX_VOE) { - if (!first) printk(", "); - printk("VoE"); - } - printk("\n"); - } - - EC_INFO(" EEPROM data:\n"); - - EC_INFO(" EEPROM content size: %i Bytes\n", slave->eeprom_size); + if (!first) off += sprintf(buffer + off, ", "); + off += sprintf(buffer + off, "VoE"); + } + off += sprintf(buffer + off, "\n"); + } + + if (slave->sii_alias || slave->sii_group + || slave->sii_image || slave->sii_order) + off += sprintf(buffer + off, "\nSII data:\n"); if (slave->sii_alias) - EC_INFO(" Configured station alias: 0x%04X (%i)\n", - slave->sii_alias, slave->sii_alias); - - EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", - slave->sii_vendor_id, slave->sii_product_code); - EC_INFO(" Revision number: 0x%08X, Serial number: 0x%08X\n", - slave->sii_revision_number, slave->sii_serial_number); - - if (slave->eeprom_group) - EC_INFO(" Group: %s\n", slave->eeprom_group); - if (slave->eeprom_image) - EC_INFO(" Image: %s\n", slave->eeprom_image); - if (slave->eeprom_order) - EC_INFO(" Order#: %s\n", slave->eeprom_order); - if (slave->eeprom_name) - EC_INFO(" Name: %s\n", slave->eeprom_name); - - if (!list_empty(&slave->eeprom_syncs)) { - EC_INFO(" Sync-Managers:\n"); - list_for_each_entry(sync, &slave->eeprom_syncs, list) { - EC_INFO(" %i: 0x%04X, length %i, control 0x%02X, %s\n", - sync->index, sync->physical_start_address, - sync->length, sync->control_register, - sync->enable ? "enable" : "disable"); - } - } - - list_for_each_entry(pdo, &slave->eeprom_pdos, list) { - EC_INFO(" %s \"%s\" (0x%04X), -> Sync-Manager %i\n", - pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", - pdo->name ? pdo->name : "???", - pdo->index, pdo->sync_manager); + off += sprintf(buffer + off, " Configured station alias:" + " 0x%04X (%i)\n", slave->sii_alias, slave->sii_alias); + if (slave->sii_group) + off += sprintf(buffer + off, " Group: %s\n", slave->sii_group); + if (slave->sii_image) + off += sprintf(buffer + off, " Image: %s\n", slave->sii_image); + if (slave->sii_order) + off += sprintf(buffer + off, " Order#: %s\n", slave->sii_order); + + if (!list_empty(&slave->sii_syncs)) + off += sprintf(buffer + off, "\nSync-Managers:\n"); + + list_for_each_entry(sync, &slave->sii_syncs, list) { + off += sprintf(buffer + off, " %i: 0x%04X, length %i," + " control 0x%02X, %s\n", + sync->index, sync->physical_start_address, + sync->length, sync->control_register, + sync->enable ? "enable" : "disable"); + } + + if (!list_empty(&slave->sii_pdos)) + off += sprintf(buffer + off, "\nPDOs:\n"); + + list_for_each_entry(pdo, &slave->sii_pdos, list) { + off += sprintf(buffer + off, + " %s \"%s\" (0x%04X), -> Sync-Manager %i\n", + pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", + pdo->name ? pdo->name : "???", + pdo->index, pdo->sync_index); list_for_each_entry(pdo_entry, &pdo->entries, list) { - EC_INFO(" \"%s\" 0x%04X:%X, %i Bit\n", - pdo_entry->name ? pdo_entry->name : "???", - pdo_entry->index, pdo_entry->subindex, - pdo_entry->bit_length); - } - } - - if (verbosity < 2) return; - - if (!list_empty(&slave->sdo_dictionary)) { - EC_INFO(" SDO-Dictionary:\n"); - list_for_each_entry(sdo, &slave->sdo_dictionary, list) { - EC_INFO(" 0x%04X \"%s\"\n", sdo->index, - sdo->name ? sdo->name : ""); - EC_INFO(" Object code: 0x%02X\n", sdo->object_code); - list_for_each_entry(sdo_entry, &sdo->entries, list) { - EC_INFO(" 0x%04X:%i \"%s\", type 0x%04X, %i bits\n", - sdo->index, sdo_entry->subindex, - sdo_entry->name ? sdo_entry->name : "", - sdo_entry->data_type, sdo_entry->bit_length); - } - } - } -} - -/*****************************************************************************/ + off += sprintf(buffer + off, " \"%s\" 0x%04X:%X, %i Bit\n", + pdo_entry->name ? pdo_entry->name : "???", + pdo_entry->index, pdo_entry->subindex, + pdo_entry->bit_length); + } + } + + off += sprintf(buffer + off, "\n"); + + return off; +} + +/*****************************************************************************/ + +#if 0 /** Outputs the values of the CRC faoult counters and resets them. @@ -1259,6 +697,8 @@ return 0; } +#endif + /*****************************************************************************/ /** @@ -1350,38 +790,8 @@ { ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); - if (attr == &attr_ring_position) { - return sprintf(buffer, "%i\n", slave->ring_position); - } - else if (attr == &attr_advanced_position) { - return sprintf(buffer, "%i:%i\n", slave->coupler_index, - slave->coupler_subindex); - } - else if (attr == &attr_vendor_name) { - if (slave->type) - return sprintf(buffer, "%s\n", slave->type->vendor_name); - } - else if (attr == &attr_product_name) { - if (slave->type) - return sprintf(buffer, "%s\n", slave->type->product_name); - } - else if (attr == &attr_product_desc) { - if (slave->type) - return sprintf(buffer, "%s\n", slave->type->description); - } - else if (attr == &attr_name) { - if (slave->eeprom_name) - return sprintf(buffer, "%s\n", slave->eeprom_name); - } - else if (attr == &attr_type) { - if (slave->type) { - if (slave->type->special == EC_TYPE_BUS_COUPLER) - return sprintf(buffer, "coupler\n"); - else if (slave->type->special == EC_TYPE_INFRA) - return sprintf(buffer, "infrastructure\n"); - else - return sprintf(buffer, "normal\n"); - } + if (attr == &attr_info) { + return ec_slave_info(slave, buffer); } else if (attr == &attr_state) { switch (slave->current_state) { @@ -1459,62 +869,25 @@ /*****************************************************************************/ /** - \return size of sync manager contents -*/ - -size_t ec_slave_calc_sync_size(const ec_slave_t *slave, /**< EtherCAT slave */ - const ec_sync_t *sync /**< sync manager */ - ) -{ - unsigned int i, found; - const ec_field_t *field; - const ec_varsize_t *var; - size_t size; - - // if size is specified, return size - if (sync->size) return sync->size; - - // sync manager has variable size (size == 0). - - size = 0; - for (i = 0; (field = sync->fields[i]); i++) { - found = 0; - list_for_each_entry(var, &slave->varsize_fields, list) { - if (var->field != field) continue; - size += var->size; - found = 1; - } - - if (!found) { - EC_WARN("Variable data field \"%s\" of slave %i has no size" - " information!\n", field->name, slave->ring_position); - } - } - return size; -} - -/*****************************************************************************/ - -/** Calculates the size of a sync manager by evaluating PDO sizes. \return sync manager size */ -uint16_t ec_slave_calc_eeprom_sync_size(const ec_slave_t *slave, - /**< EtherCAT slave */ - const ec_eeprom_sync_t *sync - /**< sync manager */ - ) -{ - ec_eeprom_pdo_t *pdo; - ec_eeprom_pdo_entry_t *pdo_entry; +uint16_t ec_slave_calc_sync_size(const ec_slave_t *slave, + /**< EtherCAT slave */ + const ec_sii_sync_t *sync + /**< sync manager */ + ) +{ + ec_sii_pdo_t *pdo; + ec_sii_pdo_entry_t *pdo_entry; unsigned int bit_size; if (sync->length) return sync->length; bit_size = 0; - list_for_each_entry(pdo, &slave->eeprom_pdos, list) { - if (pdo->sync_manager != sync->index) continue; + list_for_each_entry(pdo, &slave->sii_pdos, list) { + if (pdo->sync_index != sync->index) continue; list_for_each_entry(pdo_entry, &pdo->entries, list) { bit_size += pdo_entry->bit_length; @@ -1527,39 +900,41 @@ return bit_size / 8; } +/*****************************************************************************/ + +/** + \return non-zero if slave is a bus coupler +*/ + +int ec_slave_is_coupler(const ec_slave_t *slave) +{ + // TODO: Better bus coupler criterion + return slave->sii_vendor_id == 0x00000002 + && slave->sii_product_code == 0x044C2C52; +} + /****************************************************************************** * Realtime interface *****************************************************************************/ /** - Writes the "configured station alias" to the slave's EEPROM. \return 0 in case of success, else < 0 \ingroup RealtimeInterface */ -int ecrt_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */ - uint16_t alias /**< new alias */ - ) -{ - return ec_slave_sii_write16(slave, 0x0004, alias); -} - -/*****************************************************************************/ - -/** - \return 0 in case of success, else < 0 - \ingroup RealtimeInterface -*/ - -int ecrt_slave_field_size(ec_slave_t *slave, /**< EtherCAT slave */ - const char *field_name, /**< data field name */ - unsigned int field_index, /**< data field index */ - size_t size /**< new data field size */ - ) -{ +int ecrt_slave_pdo_size(ec_slave_t *slave, /**< EtherCAT slave */ + uint16_t pdo_index, /**< PDO index */ + uint8_t pdo_subindex, /**< PDO subindex */ + size_t size /**< new PDO size */ + ) +{ + EC_WARN("ecrt_slave_pdo_size() currently not available.\n"); + return -1; + +#if 0 unsigned int i, j, field_counter; - const ec_sync_t *sync; - const ec_field_t *field; + const ec_sii_sync_t *sync; + const ec_pdo_t *pdo; ec_varsize_t *var; if (!slave->type) { @@ -1607,14 +982,14 @@ slave->ring_position, slave->type->vendor_name, slave->type->product_name, field_name, field_index); return -1; +#endif } /*****************************************************************************/ /**< \cond */ -EXPORT_SYMBOL(ecrt_slave_write_alias); -EXPORT_SYMBOL(ecrt_slave_field_size); +EXPORT_SYMBOL(ecrt_slave_pdo_size); /**< \endcond */ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/slave.h --- a/master/slave.h Wed Aug 02 23:16:10 2006 +0000 +++ b/master/slave.h Thu Aug 03 12:51:17 2006 +0000 @@ -44,9 +44,10 @@ #include #include +#include "../include/ecrt.h" + #include "globals.h" #include "datagram.h" -#include "types.h" /*****************************************************************************/ @@ -90,20 +91,6 @@ /*****************************************************************************/ /** - 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 @@ size_t size; /**< size in bytes */ char *data; /**< string data */ } -ec_eeprom_string_t; +ec_sii_string_t; /*****************************************************************************/ @@ -130,7 +117,7 @@ uint8_t control_register; /**< control register value */ uint8_t enable; /**< enable bit */ } -ec_eeprom_sync_t; +ec_sii_sync_t; /*****************************************************************************/ @@ -143,7 +130,7 @@ EC_RX_PDO, /**< Reveive PDO */ EC_TX_PDO /**< Transmit PDO */ } -ec_pdo_type_t; +ec_sii_pdo_type_t; /*****************************************************************************/ @@ -154,13 +141,13 @@ 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 @@ 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 @@ { 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 */ @@ -214,13 +200,27 @@ /*****************************************************************************/ /** + 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. */ 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 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 @@ 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 @@ 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 @@ 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 *); - -// state machine +//int ec_slave_fetch_sdo_list(ec_slave_t *); + +// 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 *); /*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/types.c --- a/master/types.c Wed Aug 02 23:16:10 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 - -#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}, - {} -}; - -/*****************************************************************************/ diff -r 9aa51cbdbfae -r 7833cf70c4f2 master/types.h --- a/master/types.h Wed Aug 02 23:16:10 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 - -#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 diff -r 9aa51cbdbfae -r 7833cf70c4f2 script/ethercat.sh --- a/script/ethercat.sh Wed Aug 02 23:16:10 2006 +0000 +++ b/script/ethercat.sh Thu Aug 03 12:51:17 2006 +0000 @@ -163,7 +163,7 @@ 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 @@ # 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 @@ # 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 diff -r 9aa51cbdbfae -r 7833cf70c4f2 script/lsec.pl --- a/script/lsec.pl Wed Aug 02 23:16:10 2006 +0000 +++ b/script/lsec.pl Thu Aug 03 12:51:17 2006 +0000 @@ -42,7 +42,6 @@ my $master_index; my $master_dir; -my $show_sii_naming; #------------------------------------------------------------------------------ @@ -63,45 +62,43 @@ 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 = ) { + 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 @@ 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 Query master .\n"; - print " -s Show EEPROM name instead of"; - print " vendor/product/description.\n"; print " -h Show this help.\n"; exit 0; }