Merge
This commit is contained in:
commit
da10aa7043
4
TODO
4
TODO
|
|
@ -50,6 +50,10 @@ Version 1.5.0:
|
|||
* 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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ int ecrt_master_activate(
|
|||
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,
|
||||
|
|
|
|||
10
lib/master.c
10
lib/master.c
|
|
@ -335,6 +335,16 @@ int ecrt_master_activate(ec_master_t *master)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ int ec_cdev_ioctl_master(
|
|||
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 @@ int ec_cdev_ioctl_activate(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** 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 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -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 @@ typedef struct {
|
|||
uint32_t eoe_handler_count;
|
||||
#endif
|
||||
uint8_t phase;
|
||||
uint8_t active;
|
||||
uint8_t scan_busy;
|
||||
struct {
|
||||
uint8_t address[6];
|
||||
|
|
|
|||
136
master/master.c
136
master/master.c
|
|
@ -121,6 +121,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
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 @@ out_allow:
|
|||
|
||||
/** Transition function from OPERATION to IDLE phase.
|
||||
*/
|
||||
void ec_master_leave_operation_phase(ec_master_t *master
|
||||
/**< EtherCAT master */)
|
||||
void ec_master_leave_operation_phase(
|
||||
ec_master_t *master /**< EtherCAT master */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave;
|
||||
#ifdef EC_EOE
|
||||
ec_eoe_t *eoe;
|
||||
#endif
|
||||
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 @@ int ecrt_master_activate(ec_master_t *master)
|
|||
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 @@ int ecrt_master_activate(ec_master_t *master)
|
|||
|
||||
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 @@ void ecrt_master_sync_slave_clocks(ec_master_t *master)
|
|||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ struct ec_master {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ void CommandMaster::execute(MasterDevice &m, const StringVector &args)
|
|||
}
|
||||
|
||||
cout << endl
|
||||
<< " Active: " << (data.active ? "yes" : "no") << endl
|
||||
<< " Slaves: " << data.slave_count << endl
|
||||
<< " Ethernet devices:" << endl;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue