# HG changeset patch # User Florian Pose # Date 1250840789 -7200 # Node ID 4844a843391551c0da3c045d2ae6417e31af2545 # Parent bd150d066ea21ab771be2c8c76983d283a7cc46d# Parent b1d1317f1c7ad0c0403eaa415b251f28230c984e Merge diff -r bd150d066ea2 -r 4844a8433915 TODO --- a/TODO Fri Aug 21 09:45:53 2009 +0200 +++ b/TODO Fri Aug 21 09:46:29 2009 +0200 @@ -50,6 +50,10 @@ * Check for Enable SDO Complete Access flag. * Implement CompleteAccess for command-line tool. * Implement CompleteAccess for SDO uploads. +* Implement identifier parameter for cstruct command. +* Implement sync delimiter for cstruct command. +* Change SDO index at runtime for SDO request. +* Implement ecrt_slave_config_request_state(). Future issues: diff -r bd150d066ea2 -r 4844a8433915 include/ecrt.h --- a/include/ecrt.h Fri Aug 21 09:45:53 2009 +0200 +++ b/include/ecrt.h Fri Aug 21 09:46:29 2009 +0200 @@ -55,6 +55,7 @@ * ecrt_slave_config_sync_manager()). * - Added ecrt_slave_config_complete_sdo() method to download an SDO during * configuration via CompleteAccess. + * - Added ecrt_master_deactivate() to remove the bus configuration. * - Added ecrt_open_master() and ecrt_master_reserve() separation for * userspace. * - Added bus information interface (methods ecrt_master(), @@ -682,6 +683,18 @@ ec_master_t *master /**< EtherCAT master. */ ); +/** Deactivates the master. + * + * Removes the bus configuration. All objects created by + * ecrt_master_create_domain(), ecrt_master_slave_config(), ecrt_domain_data() + * ecrt_slave_config_create_sdo_request() and + * ecrt_slave_config_create_voe_handler() are freed, so pointers to them + * become invalid. + */ +void ecrt_master_deactivate( + ec_master_t *master /**< EtherCAT master. */ + ); + /** Sends all datagrams in the queue. * * This method takes all datagrams, that have been queued for transmission, diff -r bd150d066ea2 -r 4844a8433915 lib/master.c --- a/lib/master.c Fri Aug 21 09:45:53 2009 +0200 +++ b/lib/master.c Fri Aug 21 09:46:29 2009 +0200 @@ -335,6 +335,16 @@ /*****************************************************************************/ +void ecrt_master_deactivate(ec_master_t *master) +{ + if (ioctl(master->fd, EC_IOCTL_DEACTIVATE, NULL) == -1) { + fprintf(stderr, "Failed to deactivate master: %s\n", strerror(errno)); + return; + } +} + +/*****************************************************************************/ + void ecrt_master_send(ec_master_t *master) { if (ioctl(master->fd, EC_IOCTL_SEND, NULL) == -1) { diff -r bd150d066ea2 -r 4844a8433915 master/cdev.c --- a/master/cdev.c Fri Aug 21 09:45:53 2009 +0200 +++ b/master/cdev.c Fri Aug 21 09:46:29 2009 +0200 @@ -175,6 +175,7 @@ data.eoe_handler_count = ec_master_eoe_handler_count(master); #endif data.phase = (uint8_t) master->phase; + data.active = (uint8_t) master->active; data.scan_busy = master->scan_busy; up(&master->master_sem); @@ -1647,6 +1648,23 @@ /*****************************************************************************/ +/** Deactivates the master. + */ +int ec_cdev_ioctl_deactivate( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + if (unlikely(!priv->requested)) + return -EPERM; + + ecrt_master_deactivate(master); + return 0; +} + +/*****************************************************************************/ + /** Send frames. */ int ec_cdev_ioctl_send( @@ -3262,6 +3280,10 @@ if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_activate(master, arg, priv); + case EC_IOCTL_DEACTIVATE: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_deactivate(master, arg, priv); case EC_IOCTL_SEND: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; diff -r bd150d066ea2 -r 4844a8433915 master/ioctl.h --- a/master/ioctl.h Fri Aug 21 09:45:53 2009 +0200 +++ b/master/ioctl.h Fri Aug 21 09:46:29 2009 +0200 @@ -86,40 +86,41 @@ #define EC_IOCTL_CREATE_DOMAIN EC_IO(0x1a) #define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x1b, ec_ioctl_config_t) #define EC_IOCTL_ACTIVATE EC_IOR(0x1c, size_t) -#define EC_IOCTL_SEND EC_IO(0x1d) -#define EC_IOCTL_RECEIVE EC_IO(0x1e) -#define EC_IOCTL_MASTER_STATE EC_IOR(0x1f, ec_master_state_t) -#define EC_IOCTL_APP_TIME EC_IOW(0x20, ec_ioctl_app_time_t) -#define EC_IOCTL_SYNC_REF EC_IO(0x21) -#define EC_IOCTL_SYNC_SLAVES EC_IO(0x22) -#define EC_IOCTL_SC_SYNC EC_IOW(0x23, ec_ioctl_config_t) -#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x24, ec_ioctl_config_t) -#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x25, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x26, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x27, ec_ioctl_add_pdo_entry_t) -#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x28, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x29, ec_ioctl_reg_pdo_entry_t) -#define EC_IOCTL_SC_DC EC_IOW(0x2a, ec_ioctl_config_t) -#define EC_IOCTL_SC_SDO EC_IOW(0x2b, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x2c, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x2d, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x2e, ec_ioctl_sc_state_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x2f) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x20) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x31) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x32, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x33, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x34, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x35, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x36, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x37, ec_ioctl_sdo_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x38, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x39, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x3a, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3b, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x3c, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x3d, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x3e, ec_ioctl_voe_t) +#define EC_IOCTL_DEACTIVATE EC_IO(0x1d) +#define EC_IOCTL_SEND EC_IO(0x1e) +#define EC_IOCTL_RECEIVE EC_IO(0x1f) +#define EC_IOCTL_MASTER_STATE EC_IOR(0x20, ec_master_state_t) +#define EC_IOCTL_APP_TIME EC_IOW(0x21, ec_ioctl_app_time_t) +#define EC_IOCTL_SYNC_REF EC_IO(0x22) +#define EC_IOCTL_SYNC_SLAVES EC_IO(0x23) +#define EC_IOCTL_SC_SYNC EC_IOW(0x24, ec_ioctl_config_t) +#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x25, ec_ioctl_config_t) +#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x26, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x27, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x28, ec_ioctl_add_pdo_entry_t) +#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x29, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x2a, ec_ioctl_reg_pdo_entry_t) +#define EC_IOCTL_SC_DC EC_IOW(0x2b, ec_ioctl_config_t) +#define EC_IOCTL_SC_SDO EC_IOW(0x2c, ec_ioctl_sc_sdo_t) +#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x2d, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x2e, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x2f, ec_ioctl_sc_state_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x20) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x31) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x32) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x33, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x34, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x35, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x36, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x37, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x38, ec_ioctl_sdo_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x39, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x3a, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x3b, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3c, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x3d, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x3e, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x3f, ec_ioctl_voe_t) /*****************************************************************************/ @@ -135,6 +136,7 @@ uint32_t eoe_handler_count; #endif uint8_t phase; + uint8_t active; uint8_t scan_busy; struct { uint8_t address[6]; diff -r bd150d066ea2 -r 4844a8433915 master/master.c --- a/master/master.c Fri Aug 21 09:45:53 2009 +0200 +++ b/master/master.c Fri Aug 21 09:46:29 2009 +0200 @@ -121,6 +121,7 @@ init_MUTEX(&master->device_sem); master->phase = EC_ORPHANED; + master->active = 0; master->injection_seq_fsm = 0; master->injection_seq_rt = 0; @@ -592,67 +593,17 @@ /** Transition function from OPERATION to IDLE phase. */ -void ec_master_leave_operation_phase(ec_master_t *master - /**< EtherCAT master */) -{ - ec_slave_t *slave; -#ifdef EC_EOE - ec_eoe_t *eoe; -#endif +void ec_master_leave_operation_phase( + ec_master_t *master /**< EtherCAT master */ + ) +{ + if (master->active) + ecrt_master_deactivate(master); if (master->debug_level) EC_DBG("OPERATION -> IDLE.\n"); master->phase = EC_IDLE; - -#ifdef EC_EOE - ec_master_eoe_stop(master); -#endif - ec_master_thread_stop(master); - - master->send_cb = ec_master_internal_send_cb; - master->receive_cb = ec_master_internal_receive_cb; - master->cb_data = master; - - down(&master->master_sem); - ec_master_clear_domains(master); - ec_master_clear_slave_configs(master); - up(&master->master_sem); - - for (slave = master->slaves; - slave < master->slaves + master->slave_count; - slave++) { - - // set states for all slaves - ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); - - // mark for reconfiguration, because the master could have no - // possibility for a reconfiguration between two sequential operation - // phases. - slave->force_config = 1; - } - -#ifdef EC_EOE - // ... but leave EoE slaves in OP - list_for_each_entry(eoe, &master->eoe_handlers, list) { - if (ec_eoe_is_open(eoe)) - ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP); - } -#endif - - master->app_time = 0ULL; - master->app_start_time = 0ULL; - master->has_start_time = 0; - - if (ec_master_thread_start(master, ec_master_idle_thread, - "EtherCAT-IDLE")) - EC_WARN("Failed to restart master thread!\n"); -#ifdef EC_EOE - ec_master_eoe_start(master); -#endif - - master->allow_scan = 1; - master->allow_config = 1; } /*****************************************************************************/ @@ -1635,6 +1586,11 @@ if (master->debug_level) EC_DBG("ecrt_master_activate(master = 0x%x)\n", (u32) master); + if (master->active) { + EC_WARN("%s: Master already active!\n", __func__); + return 0; + } + down(&master->master_sem); // finish all domains @@ -1684,11 +1640,80 @@ master->allow_config = 1; // request the current configuration master->allow_scan = 1; // allow re-scanning on topology change + master->active = 1; return 0; } /*****************************************************************************/ +void ecrt_master_deactivate(ec_master_t *master) +{ + ec_slave_t *slave; +#ifdef EC_EOE + ec_eoe_t *eoe; +#endif + + if (master->debug_level) + EC_DBG("ecrt_master_deactivate(master = 0x%x)\n", (u32) master); + + if (!master->active) { + EC_WARN("%s: Master not active.\n", __func__); + return; + } + +#ifdef EC_EOE + ec_master_eoe_stop(master); +#endif + ec_master_thread_stop(master); + + master->send_cb = ec_master_internal_send_cb; + master->receive_cb = ec_master_internal_receive_cb; + master->cb_data = master; + + down(&master->master_sem); + ec_master_clear_domains(master); + ec_master_clear_slave_configs(master); + up(&master->master_sem); + + for (slave = master->slaves; + slave < master->slaves + master->slave_count; + slave++) { + + // set states for all slaves + ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); + + // mark for reconfiguration, because the master could have no + // possibility for a reconfiguration between two sequential operation + // phases. + slave->force_config = 1; + } + +#ifdef EC_EOE + // ... but leave EoE slaves in OP + list_for_each_entry(eoe, &master->eoe_handlers, list) { + if (ec_eoe_is_open(eoe)) + ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP); + } +#endif + + master->app_time = 0ULL; + master->app_start_time = 0ULL; + master->has_start_time = 0; + + if (ec_master_thread_start(master, ec_master_idle_thread, + "EtherCAT-IDLE")) + EC_WARN("Failed to restart master thread!\n"); +#ifdef EC_EOE + ec_master_eoe_start(master); +#endif + + master->allow_scan = 1; + master->allow_config = 1; + master->active = 0; +} + +/*****************************************************************************/ + void ecrt_master_send(ec_master_t *master) { ec_datagram_t *datagram, *n; @@ -1903,6 +1928,7 @@ EXPORT_SYMBOL(ecrt_master_create_domain); EXPORT_SYMBOL(ecrt_master_activate); +EXPORT_SYMBOL(ecrt_master_deactivate); EXPORT_SYMBOL(ecrt_master_send); EXPORT_SYMBOL(ecrt_master_send_ext); EXPORT_SYMBOL(ecrt_master_receive); diff -r bd150d066ea2 -r 4844a8433915 master/master.h --- a/master/master.h Fri Aug 21 09:45:53 2009 +0200 +++ b/master/master.h Fri Aug 21 09:46:29 2009 +0200 @@ -108,6 +108,7 @@ ec_fsm_master_t fsm; /**< Master state machine. */ ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */ ec_master_phase_t phase; /**< Master phase. */ + unsigned int active; /**< Master has been activated. */ unsigned int injection_seq_fsm; /**< Datagram injection sequence number for the FSM side. */ unsigned int injection_seq_rt; /**< Datagram injection sequence number diff -r bd150d066ea2 -r 4844a8433915 tool/CommandMaster.cpp --- a/tool/CommandMaster.cpp Fri Aug 21 09:45:53 2009 +0200 +++ b/tool/CommandMaster.cpp Fri Aug 21 09:46:29 2009 +0200 @@ -91,6 +91,7 @@ } cout << endl + << " Active: " << (data.active ? "yes" : "no") << endl << " Slaves: " << data.slave_count << endl << " Ethernet devices:" << endl;