# HG changeset patch # User Florian Pose # Date 1173090950 0 # Node ID aede068f9a7468b10b54d65faed332873bb6f3b8 # Parent 16498ed938f4cda6dbfcd91484b66c33f737319a Introduced master status, ecrt_master_get_status(), tainted flag, pdos_registered flags and pdo_slaves_offline counter. diff -r 16498ed938f4 -r aede068f9a74 NEWS --- a/NEWS Mon Mar 05 10:00:18 2007 +0000 +++ b/NEWS Mon Mar 05 10:35:50 2007 +0000 @@ -15,12 +15,14 @@ device ID lists. * Changed format of sysconfig file and accordingly adjusted functionality of the init script to handle device ID lists. +* Realtime interface changes: + - Added ecrt_master_get_status() to get information about the bus. * Device interface changes: - Replaced ecdev_register() and ecdev_unregister() with ecdev_offer() and ecdev_withdraw(), respectively. The device modules now offer all their devices to the master, which decides, which ones to register. * All EEPROM write operations from user space are now blocking until - completion and returning appropriate error codes. + writing has finished and return appropriate error codes. * Implemented setting of secondary slave address (alias) via sysfs. * Removed annoying eeprom_write_enable file. EEPROM writing always enabled. * Removed EtherCAT line comments from 8139too drivers. diff -r 16498ed938f4 -r aede068f9a74 TODO --- a/TODO Mon Mar 05 10:00:18 2007 +0000 +++ b/TODO Mon Mar 05 10:35:50 2007 +0000 @@ -10,15 +10,14 @@ - Remove ecrt_master_run(). Make master FSM run in process context instead. - Remove addressing scheme "X:Y". - Allow only MAC address as device ID. - - Interface/buffers for asynchronous domain IO. - Remove ugly ec_slave_is_coupler() and ec_slave_has_subbus(). - - Add statistics object. + +* Future features: - SDO dictionary and -access in operation mode. - SDO write access in sysfs. - Speed up IDLE-FSM through fast mode with schedule(). - Evaluate EEPROM contents after writing. - -* Future features: + - Interface/buffers for asynchronous domain IO. - Distributed clocks. - Read dynamic PDO mapping from SDO dictionary (see can-cia.org: cia301ds4). - Redundancy with 2 network adapters. @@ -27,13 +26,13 @@ - Optimize alignment of process data. - Calculate expected working counter for domains. -* Smaller changes: +* Smaller issues: - Simplify FSMs with _enter() functions. - Dynamic creation of EoE handlers. - Output intermediate results during lsec. - State change FSM: Follow spontaneous state changes. -* Less important changes: +* Less important issues: - Implement all EtherCAT datagram types. - File access over EtherCAT (FoE). - Allow VLAN tagging. diff -r 16498ed938f4 -r aede068f9a74 examples/mini/mini.c --- a/examples/mini/mini.c Mon Mar 05 10:00:18 2007 +0000 +++ b/examples/mini/mini.c Mon Mar 05 10:35:50 2007 +0000 @@ -39,26 +39,29 @@ #include "../../include/ecrt.h" // EtherCAT realtime interface #include "../../include/ecdb.h" // EtherCAT slave database +#define PFX "ec_mini: " + #define FREQUENCY 100 //#define KBUS /*****************************************************************************/ -struct timer_list timer; +static struct timer_list timer; // EtherCAT -ec_master_t *master = NULL; -ec_domain_t *domain1 = NULL; +static ec_master_t *master = NULL; +static ec_domain_t *domain1 = NULL; spinlock_t master_lock = SPIN_LOCK_UNLOCKED; +static ec_master_status_t master_status, old_status = {}; // data fields #ifdef KBUS -void *r_inputs; -void *r_outputs; -#endif - -void *r_dig_out; +static void *r_inputs; +static void *r_outputs; +#endif + +static void *r_dig_out; #if 1 ec_pdo_reg_t domain1_pdos[] = { @@ -90,6 +93,26 @@ else { counter = FREQUENCY; blink = !blink; + + spin_lock(&master_lock); + ecrt_master_get_status(master, &master_status); + spin_unlock(&master_lock); + + if (master_status.bus_status != old_status.bus_status) { + printk(KERN_INFO PFX "bus status changed to %u.\n", + master_status.bus_status); + } + if (master_status.bus_tainted != old_status.bus_tainted) { + printk(KERN_INFO PFX "tainted flag changed to %u.\n", + master_status.bus_tainted); + } + if (master_status.slaves_responding != + old_status.slaves_responding) { + printk(KERN_INFO PFX "slaves_responding changed to %u.\n", + master_status.slaves_responding); + } + + old_status = master_status; } #ifdef KBUS @@ -135,25 +158,25 @@ ec_slave_t *slave; #endif - printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n"); + printk(KERN_INFO PFX "Starting...\n"); if (!(master = ecrt_request_master(0))) { - printk(KERN_ERR "Requesting master 0 failed!\n"); + printk(KERN_ERR PFX "Requesting master 0 failed!\n"); goto out_return; } ecrt_master_callbacks(master, request_lock, release_lock, NULL); - printk(KERN_INFO "Registering domain...\n"); + printk(KERN_INFO PFX "Registering domain...\n"); if (!(domain1 = ecrt_master_create_domain(master))) { - printk(KERN_ERR "Domain creation failed!\n"); - goto out_release_master; - } - - printk(KERN_INFO "Registering PDOs...\n"); + printk(KERN_ERR PFX "Domain creation failed!\n"); + goto out_release_master; + } + + printk(KERN_INFO PFX "Registering PDOs...\n"); #if 1 if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) { - printk(KERN_ERR "PDO registration failed!\n"); + printk(KERN_ERR PFX "PDO registration failed!\n"); goto out_release_master; } #endif @@ -161,12 +184,12 @@ #ifdef KBUS if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120, EC_DIR_OUTPUT, 0, 4, &r_outputs)) { - printk(KERN_ERR "PDO registration failed!\n"); + printk(KERN_ERR PFX "PDO registration failed!\n"); goto out_release_master; } if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120, EC_DIR_INPUT, 0, 4, &r_inputs)) { - printk(KERN_ERR "PDO registration failed!\n"); + printk(KERN_ERR PFX "PDO registration failed!\n"); goto out_release_master; } #endif @@ -179,19 +202,19 @@ goto out_release_master; #endif - printk(KERN_INFO "Activating master...\n"); + printk(KERN_INFO PFX "Activating master...\n"); if (ecrt_master_activate(master)) { - printk(KERN_ERR "Failed to activate master!\n"); - goto out_release_master; - } - - printk("Starting cyclic sample thread.\n"); + printk(KERN_ERR PFX "Failed to activate master!\n"); + goto out_release_master; + } + + printk(KERN_INFO PFX "Starting cyclic sample thread.\n"); init_timer(&timer); timer.function = run; timer.expires = jiffies + 10; add_timer(&timer); - printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n"); + printk(KERN_INFO PFX "Started.\n"); return 0; out_release_master: @@ -204,13 +227,13 @@ void __exit cleanup_mini_module(void) { - printk(KERN_INFO "=== Stopping Minimal EtherCAT environment... ===\n"); + printk(KERN_INFO PFX "Stopping...\n"); del_timer_sync(&timer); - printk(KERN_INFO "Releasing master...\n"); + printk(KERN_INFO PFX "Releasing master...\n"); ecrt_release_master(master); - printk(KERN_INFO "=== Minimal EtherCAT environment stopped. ===\n"); + printk(KERN_INFO PFX "Stopped.\n"); } /*****************************************************************************/ diff -r 16498ed938f4 -r aede068f9a74 include/ecrt.h --- a/include/ecrt.h Mon Mar 05 10:00:18 2007 +0000 +++ b/include/ecrt.h Mon Mar 05 10:35:50 2007 +0000 @@ -77,8 +77,31 @@ typedef struct ec_slave ec_slave_t; /**< \see ec_slave */ /** + * Bus status. + */ + +typedef enum { + EC_BUS_FAILURE, // some slaves offline + EC_BUS_OK, // all slaves online + EC_BUS_REDUNDANCY // bus interrupted, but redundancy active +} +ec_bus_status_t; + +/** + * Master status. + * This is used for the output parameter of ecrt_master_get_status(). + */ + +typedef struct { + ec_bus_status_t bus_status; + unsigned int bus_tainted; + unsigned int slaves_responding; +} +ec_master_status_t; + +/** Initialization type for PDO registrations. - This type is used as a parameter for the ec_domain_register_pdo_list() + This type is used as a parameter for the ecrt_domain_register_pdo_list() function. */ @@ -95,7 +118,7 @@ ec_pdo_reg_t; /** - Direction type for ec_domain_register_pdo_range() + Direction type for ecrt_domain_register_pdo_range() */ typedef enum {EC_DIR_INPUT, EC_DIR_OUTPUT} ec_direction_t; @@ -127,9 +150,7 @@ ec_slave_t *ecrt_master_get_slave(const ec_master_t *, const char *); -/** \cond */ -int ecrt_master_state(const ec_master_t *master); -/** \endcond */ +void ecrt_master_get_status(const ec_master_t *master, ec_master_status_t *); /****************************************************************************** * Domain Methods diff -r 16498ed938f4 -r aede068f9a74 master/fsm_master.c --- a/master/fsm_master.c Mon Mar 05 10:00:18 2007 +0000 +++ b/master/fsm_master.c Mon Mar 05 10:35:50 2007 +0000 @@ -78,6 +78,7 @@ fsm->topology_change_pending = 0; fsm->slave_states = EC_SLAVE_STATE_UNKNOWN; fsm->validate = 0; + fsm->tainted = 0; // init sub-state-machines ec_fsm_slave_init(&fsm->fsm_slave, fsm->datagram); @@ -206,6 +207,7 @@ } else { EC_WARN("Invalid slave count. Bus in tainted state.\n"); + fsm->tainted = 1; } } } @@ -640,6 +642,7 @@ // have all states been validated? if (slave->list.next == &fsm->master->slaves) { + fsm->tainted = 0; fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); // start writing addresses to offline slaves ec_fsm_master_action_addresses(fsm); diff -r 16498ed938f4 -r aede068f9a74 master/fsm_master.h --- a/master/fsm_master.h Mon Mar 05 10:00:18 2007 +0000 +++ b/master/fsm_master.h Mon Mar 05 10:35:50 2007 +0000 @@ -100,6 +100,8 @@ unsigned int topology_change_pending; /**< bus topology changed */ ec_slave_state_t slave_states; /**< states of responding slaves */ unsigned int validate; /**< non-zero, if validation to do */ + unsigned int tainted; /**< non-zero, if the current bus topology does + not meet the initial conditions */ ec_slave_t *slave; /**< current slave */ ec_eeprom_write_request_t *eeprom_request; /**< EEPROM write request */ off_t eeprom_index; /**< index to EEPROM write request data */ diff -r 16498ed938f4 -r aede068f9a74 master/master.c --- a/master/master.c Mon Mar 05 10:00:18 2007 +0000 +++ b/master/master.c Mon Mar 05 10:35:50 2007 +0000 @@ -477,6 +477,7 @@ } master->eoe_checked = 0; // allow starting EoE again + master->pdo_slaves_offline = 0; // assume all PDO slaves online return 0; @@ -1655,6 +1656,22 @@ /*****************************************************************************/ +/** + * Reads the current master status. + */ + +void ecrt_master_get_status(const ec_master_t *master, /**< EtherCAT master */ + ec_master_status_t *status /**< target status object */ + ) +{ + status->bus_status = + master->pdo_slaves_offline ? EC_BUS_FAILURE : EC_BUS_OK; + status->bus_tainted = master->fsm.tainted; + status->slaves_responding = master->fsm.slaves_responding; +} + +/*****************************************************************************/ + /** \cond */ EXPORT_SYMBOL(ecrt_master_create_domain); @@ -1664,6 +1681,7 @@ EXPORT_SYMBOL(ecrt_master_run); EXPORT_SYMBOL(ecrt_master_callbacks); EXPORT_SYMBOL(ecrt_master_get_slave); +EXPORT_SYMBOL(ecrt_master_get_status); /** \endcond */ diff -r 16498ed938f4 -r aede068f9a74 master/master.h --- a/master/master.h Mon Mar 05 10:00:18 2007 +0000 +++ b/master/master.h Mon Mar 05 10:35:50 2007 +0000 @@ -120,6 +120,9 @@ int debug_level; /**< master debug level */ ec_stats_t stats; /**< cyclic statistics */ + unsigned int pdo_slaves_offline; /** number of slaves, for which PDOs + were registered and that are offline + (used for bus status) */ int thread_id; /**< master thread PID */ struct completion thread_exit; /**< thread completion object */ diff -r 16498ed938f4 -r aede068f9a74 master/slave.c --- a/master/slave.c Mon Mar 05 10:00:18 2007 +0000 +++ b/master/slave.c Mon Mar 05 10:35:50 2007 +0000 @@ -118,6 +118,7 @@ slave->error_flag = 0; slave->online_state = EC_SLAVE_ONLINE; slave->fmmu_count = 0; + slave->pdos_registered = 0; slave->coupler_index = 0; slave->coupler_subindex = 0xFFFF; @@ -312,6 +313,7 @@ // remove FMMU configurations slave->fmmu_count = 0; + slave->pdos_registered = 0; // free all SDO configurations list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) { @@ -361,12 +363,16 @@ { if (new_state == EC_SLAVE_OFFLINE && slave->online_state == EC_SLAVE_ONLINE) { + if (slave->pdos_registered) + slave->master->pdo_slaves_offline++; if (slave->master->debug_level) EC_DBG("Slave %i: offline.\n", slave->ring_position); } else if (new_state == EC_SLAVE_ONLINE && slave->online_state == EC_SLAVE_OFFLINE) { slave->error_flag = 0; // clear error flag + if (slave->pdos_registered) + slave->master->pdo_slaves_offline--; if (slave->master->debug_level) { char cur_state[EC_STATE_STRING_SIZE]; ec_state_string(slave->current_state, cur_state); @@ -649,6 +655,7 @@ fmmu->logical_start_address = 0; slave->fmmu_count++; + slave->pdos_registered = 1; ec_slave_request_state(slave, EC_SLAVE_STATE_OP); diff -r 16498ed938f4 -r aede068f9a74 master/slave.h --- a/master/slave.h Mon Mar 05 10:00:18 2007 +0000 +++ b/master/slave.h Mon Mar 05 10:35:50 2007 +0000 @@ -206,6 +206,7 @@ ec_slave_online_state_t online_state; /**< online state */ unsigned int self_configured; /**< slave was configured by this master */ unsigned int error_flag; /**< stop processing after an error */ + unsigned int pdos_registered; /**< non-zero, if PDOs were registered */ // addresses uint16_t ring_position; /**< ring position */