Persistent slave lists.
This commit is contained in:
parent
66f345ae29
commit
b6e88ad403
|
|
@ -56,13 +56,16 @@ ec_domain_t *domain1 = NULL;
|
|||
spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
// data fields
|
||||
#if 0
|
||||
void *r_inputs;
|
||||
void *r_outputs;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void *r_ana_in;
|
||||
|
||||
#if 1
|
||||
ec_pdo_reg_t domain1_pdos[] = {
|
||||
{"2", Beckhoff_EL4132_Output1, &r_ana_out},
|
||||
{"3", Beckhoff_EL5001_Value, NULL},
|
||||
{"2", Beckhoff_EL3102_Input1, &r_ana_in},
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
|
@ -82,8 +85,7 @@ void run(unsigned long data)
|
|||
|
||||
// process data
|
||||
//k_pos = EC_READ_U32(r_ssi);
|
||||
EC_WRITE_U8(r_outputs + 2, einaus ? 0xFF : 0x00);
|
||||
|
||||
//EC_WRITE_U8(r_outputs + 2, einaus ? 0xFF : 0x00);
|
||||
|
||||
// send
|
||||
ecrt_master_run(master);
|
||||
|
|
@ -142,12 +144,14 @@ int __init init_mini_module(void)
|
|||
}
|
||||
|
||||
printk(KERN_INFO "Registering PDOs...\n");
|
||||
#if 0
|
||||
#if 1
|
||||
if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) {
|
||||
printk(KERN_ERR "PDO registration failed!\n");
|
||||
goto out_release_master;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120,
|
||||
EC_DIR_OUTPUT, 0, 4, &r_outputs)) {
|
||||
printk(KERN_ERR "PDO registration failed!\n");
|
||||
|
|
@ -158,6 +162,7 @@ int __init init_mini_module(void)
|
|||
printk(KERN_ERR "PDO registration failed!\n");
|
||||
goto out_release_master;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (!(slave = ecrt_master_get_slave(master, "3")))
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
|
||||
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
|
||||
{
|
||||
INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
|
||||
datagram->type = EC_DATAGRAM_NONE;
|
||||
datagram->address.logical = 0x00000000;
|
||||
datagram->data = NULL;
|
||||
|
|
|
|||
|
|
@ -139,8 +139,6 @@ void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
|
|||
|
||||
domain = container_of(kobj, ec_domain_t, kobj);
|
||||
|
||||
EC_INFO("Clearing domain %i.\n", domain->index);
|
||||
|
||||
list_for_each_entry_safe(datagram, next, &domain->datagrams, list) {
|
||||
ec_datagram_clear(datagram);
|
||||
kfree(datagram);
|
||||
|
|
@ -222,6 +220,9 @@ int ec_domain_reg_pdo_entry(ec_domain_t *domain, /**< EtherCAT domain */
|
|||
data_reg->data_ptr = data_ptr;
|
||||
|
||||
list_add_tail(&data_reg->list, &domain->data_regs);
|
||||
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -297,6 +298,9 @@ int ec_domain_reg_pdo_range(ec_domain_t *domain, /**< EtherCAT domain */
|
|||
}
|
||||
|
||||
list_add_tail(&data_reg->list, &domain->data_regs);
|
||||
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +452,7 @@ int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
|||
Places all process data datagrams in the masters datagram queue.
|
||||
*/
|
||||
|
||||
void ec_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
void ec_domain_queue_datagrams(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
|
|
@ -459,6 +463,22 @@ void ec_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Dequeues all datagrams from the masters datagram queue.
|
||||
*/
|
||||
|
||||
void ec_domain_dequeue_datagrams(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_datagram_t *datagram;
|
||||
|
||||
list_for_each_entry(datagram, &domain->datagrams, list) {
|
||||
if (!list_empty(&datagram->queue)) // datagram queued?
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Formats attribute data for SysFS reading.
|
||||
\return number of bytes to read
|
||||
|
|
@ -518,18 +538,15 @@ ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
|
|||
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
|
||||
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
|
||||
|
||||
if (!data_ptr) {
|
||||
// data_ptr is NULL => mark slave as "registered" (do not warn)
|
||||
slave->registered = 1;
|
||||
}
|
||||
if (!data_ptr) return slave;
|
||||
|
||||
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);
|
||||
if (ec_domain_reg_pdo_entry(domain, slave, pdo, entry, data_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return slave;
|
||||
|
|
@ -538,7 +555,6 @@ ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
|
|||
|
||||
EC_ERR("Slave %i does not provide PDO 0x%04X:%i.\n",
|
||||
slave->ring_position, pdo_index, pdo_subindex);
|
||||
slave->registered = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -609,11 +625,7 @@ ec_slave_t *ecrt_domain_register_pdo_range(ec_domain_t *domain,
|
|||
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
|
||||
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
|
||||
|
||||
if (!data_ptr) {
|
||||
// data_ptr is NULL => mark slave as "registered" (do not warn)
|
||||
slave->registered = 1;
|
||||
return slave;
|
||||
}
|
||||
if (!data_ptr) return slave;
|
||||
|
||||
if (ec_domain_reg_pdo_range(domain, slave,
|
||||
direction, offset, length, data_ptr)) {
|
||||
|
|
@ -666,7 +678,7 @@ void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
|
|||
domain->working_counter_changes = 0;
|
||||
}
|
||||
|
||||
ec_domain_queue(domain);
|
||||
ec_domain_queue_datagrams(domain);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -76,8 +76,11 @@ struct ec_domain
|
|||
/*****************************************************************************/
|
||||
|
||||
int ec_domain_init(ec_domain_t *, ec_master_t *, unsigned int);
|
||||
|
||||
int ec_domain_alloc(ec_domain_t *, uint32_t);
|
||||
void ec_domain_queue(ec_domain_t *);
|
||||
|
||||
void ec_domain_queue_datagrams(ec_domain_t *);
|
||||
void ec_domain_dequeue_datagrams(ec_domain_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -629,8 +629,7 @@ int ec_eoedev_open(struct net_device *dev /**< EoE net_device */)
|
|||
if (!eoe->slave)
|
||||
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
|
||||
else {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_OP;
|
||||
eoe->slave->error_flag = 0;
|
||||
ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -652,8 +651,7 @@ int ec_eoedev_stop(struct net_device *dev /**< EoE net_device */)
|
|||
if (!eoe->slave)
|
||||
EC_WARN("device %s is not coupled to any EoE slave!\n", dev->name);
|
||||
else {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
eoe->slave->error_flag = 0;
|
||||
ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_PREOP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
410
master/fsm.c
410
master/fsm.c
|
|
@ -56,13 +56,8 @@ void ec_fsm_master_scan_slaves(ec_fsm_t *);
|
|||
void ec_fsm_master_write_eeprom(ec_fsm_t *);
|
||||
void ec_fsm_master_sdodict(ec_fsm_t *);
|
||||
void ec_fsm_master_sdo_request(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_master_end(ec_fsm_t *);
|
||||
void ec_fsm_master_error(ec_fsm_t *);
|
||||
|
||||
void ec_fsm_slavescan_start(ec_fsm_t *);
|
||||
void ec_fsm_slavescan_address(ec_fsm_t *);
|
||||
|
|
@ -80,8 +75,8 @@ void ec_fsm_slaveconf_sdoconf(ec_fsm_t *);
|
|||
void ec_fsm_slaveconf_saveop(ec_fsm_t *);
|
||||
void ec_fsm_slaveconf_op(ec_fsm_t *);
|
||||
|
||||
void ec_fsm_end(ec_fsm_t *);
|
||||
void ec_fsm_error(ec_fsm_t *);
|
||||
void ec_fsm_slave_end(ec_fsm_t *);
|
||||
void ec_fsm_slave_error(ec_fsm_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -131,19 +126,6 @@ void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Resets the state machine.
|
||||
*/
|
||||
|
||||
void ec_fsm_reset(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_slaves_responding = 0;
|
||||
fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Executes the current state of the state machine.
|
||||
\return false, if state machine has terminated
|
||||
|
|
@ -153,232 +135,23 @@ int ec_fsm_exec(ec_fsm_t *fsm /**< finite state machine */)
|
|||
{
|
||||
fsm->master_state(fsm);
|
||||
|
||||
return fsm->master_state != ec_fsm_end &&
|
||||
fsm->master_state != ec_fsm_error;
|
||||
return fsm->master_state != ec_fsm_master_end
|
||||
&& fsm->master_state != ec_fsm_master_error;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes the master startup state machine.
|
||||
\return true, if the master state machine terminated gracefully
|
||||
*/
|
||||
|
||||
void ec_fsm_startup(ec_fsm_t *fsm)
|
||||
int ec_fsm_success(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
fsm->master_state = ec_fsm_startup_start;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Returns, if the master startup state machine terminated with success.
|
||||
\return non-zero if successful.
|
||||
*/
|
||||
|
||||
int ec_fsm_startup_success(ec_fsm_t *fsm /**< Finite state machine */)
|
||||
{
|
||||
return fsm->master_state == ec_fsm_end;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initializes the master configuration state machine.
|
||||
*/
|
||||
|
||||
void ec_fsm_configuration(ec_fsm_t *fsm)
|
||||
{
|
||||
fsm->master_state = ec_fsm_configuration_start;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Returns, if the master confuguration state machine terminated with success.
|
||||
\return non-zero if successful.
|
||||
*/
|
||||
|
||||
int ec_fsm_configuration_success(ec_fsm_t *fsm /**< Finite state machine */)
|
||||
{
|
||||
return fsm->master_state == ec_fsm_end;
|
||||
return fsm->master_state == ec_fsm_master_end;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* 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 to 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
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Master configuration state machine: START.
|
||||
*/
|
||||
|
||||
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;
|
||||
ec_fsm_change(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
|
||||
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;
|
||||
ec_fsm_change(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->master_state = ec_fsm_end;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* operation / idle state machine
|
||||
* operation/idle state machine
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
@ -414,8 +187,10 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
slave->online = 0;
|
||||
}
|
||||
}
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
else {
|
||||
EC_ERR("Failed to receive broadcast datagram.\n");
|
||||
}
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +224,6 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
// topology change in idle mode: clear all slaves and scan the bus
|
||||
if (topology_change && master->mode == EC_MASTER_MODE_IDLE) {
|
||||
EC_INFO("Scanning bus.\n");
|
||||
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_clear_slaves(master);
|
||||
|
|
@ -458,8 +232,7 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!master->slave_count) {
|
||||
// no slaves present -> finish state machine.
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_end;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -469,16 +242,14 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
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
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
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
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -486,14 +257,15 @@ void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
|
|||
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
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
list_add_tail(&slave->list, &master->slaves);
|
||||
}
|
||||
|
||||
EC_INFO("Scanning bus.\n");
|
||||
|
||||
// begin scanning of slaves
|
||||
fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
|
||||
fsm->slave_state = ec_fsm_slavescan_start;
|
||||
|
|
@ -533,17 +305,18 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
|||
&& (slave->configured
|
||||
|| slave->current_state == EC_SLAVE_STATE_INIT))) continue;
|
||||
|
||||
ec_state_string(slave->current_state, old_state);
|
||||
ec_state_string(slave->requested_state, new_state);
|
||||
|
||||
if (!slave->configured
|
||||
&& slave->current_state != EC_SLAVE_STATE_INIT) {
|
||||
EC_INFO("Reconfiguring slave %i (%s -> %s).\n",
|
||||
slave->ring_position, old_state, new_state);
|
||||
}
|
||||
else if (slave->current_state != slave->requested_state) {
|
||||
EC_INFO("Changing state of slave %i (%s -> %s).\n",
|
||||
slave->ring_position, old_state, new_state);
|
||||
if (master->debug_level) {
|
||||
ec_state_string(slave->current_state, old_state);
|
||||
if (!slave->configured
|
||||
&& slave->current_state != EC_SLAVE_STATE_INIT) {
|
||||
EC_INFO("Reconfiguring slave %i (%s).\n",
|
||||
slave->ring_position, old_state);
|
||||
}
|
||||
else if (slave->current_state != slave->requested_state) {
|
||||
ec_state_string(slave->requested_state, new_state);
|
||||
EC_INFO("Changing state of slave %i (%s -> %s).\n",
|
||||
slave->ring_position, old_state, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fsm->slave = slave;
|
||||
|
|
@ -601,8 +374,7 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
|||
EC_ERR("Failed to add SDO kobj of slave %i.\n",
|
||||
slave->ring_position);
|
||||
slave->error_flag = 1;
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -639,9 +411,7 @@ void ec_fsm_master_action_process_states(ec_fsm_t *fsm
|
|||
}
|
||||
}
|
||||
|
||||
// nothing to do. restart master state machine.
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_end;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -702,8 +472,9 @@ void ec_fsm_master_read_states(ec_fsm_t *fsm /**< finite state machine */)
|
|||
uint8_t new_state;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
EC_ERR("Failed to receive AL state datagram for slave %i!\n",
|
||||
slave->ring_position);
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -756,15 +527,13 @@ void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */)
|
|||
fsm->slave->error_flag = 1;
|
||||
EC_ERR("Failed to validate vendor ID of slave %i.\n",
|
||||
slave->ring_position);
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_vendor_id) {
|
||||
EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position);
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
EC_ERR("Slave %i has an invalid vendor ID!\n", slave->ring_position);
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -796,7 +565,8 @@ void ec_fsm_master_action_addresses(ec_fsm_t *fsm /**< finite state machine */)
|
|||
fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
|
||||
}
|
||||
|
||||
EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
|
||||
if (fsm->master->debug_level)
|
||||
EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position);
|
||||
|
||||
// write station address
|
||||
ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
|
||||
|
|
@ -822,8 +592,7 @@ void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */)
|
|||
fsm->slave->error_flag = 1;
|
||||
EC_ERR("Failed to validate product code of slave %i.\n",
|
||||
slave->ring_position);
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -831,8 +600,7 @@ void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */)
|
|||
EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
|
||||
EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
|
||||
EC_READ_U32(fsm->fsm_sii.value));
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -897,8 +665,8 @@ void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
fsm->slave_state(fsm); // execute slave state machine
|
||||
|
||||
if (fsm->slave_state != ec_fsm_end
|
||||
&& fsm->slave_state != ec_fsm_error) return;
|
||||
if (fsm->slave_state != ec_fsm_slave_end
|
||||
&& fsm->slave_state != ec_fsm_slave_error) return;
|
||||
|
||||
// another slave to fetch?
|
||||
if (slave->list.next != &master->slaves) {
|
||||
|
|
@ -915,11 +683,10 @@ void ec_fsm_master_scan_slaves(ec_fsm_t *fsm /**< finite state machine */)
|
|||
// set initial states of all slaves to PREOP to make mailbox
|
||||
// communication possible
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
slave->requested_state = EC_SLAVE_STATE_PREOP;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
|
||||
}
|
||||
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_end;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -935,8 +702,8 @@ void ec_fsm_master_configure_slave(ec_fsm_t *fsm
|
|||
{
|
||||
fsm->slave_state(fsm); // execute slave's state machine
|
||||
|
||||
if (fsm->slave_state != ec_fsm_end
|
||||
&& fsm->slave_state != ec_fsm_error) return;
|
||||
if (fsm->slave_state != ec_fsm_slave_end
|
||||
&& fsm->slave_state != ec_fsm_slave_error) return;
|
||||
|
||||
ec_fsm_master_action_process_states(fsm);
|
||||
}
|
||||
|
|
@ -959,8 +726,7 @@ void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */)
|
|||
slave->ring_position);
|
||||
kfree(slave->new_eeprom_data);
|
||||
slave->new_eeprom_data = NULL;
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -999,8 +765,7 @@ void ec_fsm_master_sdodict(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
|
||||
|
||||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1034,8 +799,7 @@ void ec_fsm_master_sdo_request(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||
request->return_code = -1;
|
||||
master->sdo_seq_master++;
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
fsm->master_state(fsm); // execute immediately
|
||||
fsm->master_state = ec_fsm_master_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1049,6 +813,28 @@ void ec_fsm_master_sdo_request(ec_fsm_t *fsm /**< finite state machine */)
|
|||
fsm->master_state(fsm); // execute immediately
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
State: ERROR.
|
||||
*/
|
||||
|
||||
void ec_fsm_master_error(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
State: END.
|
||||
*/
|
||||
|
||||
void ec_fsm_master_end(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
fsm->master_state = ec_fsm_master_start;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* slave scan state machine
|
||||
*****************************************************************************/
|
||||
|
|
@ -1083,7 +869,7 @@ void ec_fsm_slavescan_address(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to write station address of slave %i.\n",
|
||||
fsm->slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1109,7 +895,7 @@ void ec_fsm_slavescan_state(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to read AL state of slave %i.\n",
|
||||
fsm->slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1141,7 +927,7 @@ void ec_fsm_slavescan_base(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to read base data of slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1178,7 +964,7 @@ void ec_fsm_slavescan_datalink(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to read DL status of slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1214,7 +1000,7 @@ void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to read EEPROM size of slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1242,7 +1028,7 @@ void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (!(slave->eeprom_data =
|
||||
(uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1271,7 +1057,7 @@ void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1359,13 +1145,13 @@ void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm /**< finite state machine */)
|
|||
cat_word += cat_size + 2;
|
||||
}
|
||||
|
||||
fsm->slave_state = ec_fsm_end;
|
||||
fsm->slave_state = ec_fsm_slave_end;
|
||||
return;
|
||||
|
||||
end:
|
||||
EC_ERR("Failed to analyze category data.\n");
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -1388,7 +1174,7 @@ void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_change_success(&fsm->fsm_change)) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1400,7 +1186,7 @@ void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
// slave is now in INIT
|
||||
if (slave->current_state == slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
fsm->slave_state = ec_fsm_slave_end; // successful
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished configuration of slave %i.\n",
|
||||
slave->ring_position);
|
||||
|
|
@ -1457,7 +1243,7 @@ void ec_fsm_slaveconf_init(ec_fsm_t *fsm /**< finite state machine */)
|
|||
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;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
ec_sync_config(sync, slave,
|
||||
|
|
@ -1483,7 +1269,7 @@ void ec_fsm_slaveconf_sync(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to set sync managers on slave %i.\n",
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1511,7 +1297,7 @@ void ec_fsm_slaveconf_preop(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_change_success(&fsm->fsm_change)) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1523,7 +1309,7 @@ void ec_fsm_slaveconf_preop(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
if (slave->current_state == slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
fsm->slave_state = ec_fsm_slave_end; // successful
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished configuration of slave %i.\n",
|
||||
slave->ring_position);
|
||||
|
|
@ -1574,7 +1360,7 @@ void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm /**< finite state machine */)
|
|||
if (datagram->state != EC_DATAGRAM_RECEIVED
|
||||
|| datagram->working_counter != 1) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
EC_ERR("Failed to set FMMUs on slave %i.\n",
|
||||
fsm->slave->ring_position);
|
||||
return;
|
||||
|
|
@ -1608,7 +1394,7 @@ void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1644,7 +1430,7 @@ void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_change_success(&fsm->fsm_change)) {
|
||||
fsm->slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1655,7 +1441,7 @@ void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
if (fsm->slave->current_state == fsm->slave->requested_state) {
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
fsm->slave_state = ec_fsm_slave_end; // successful
|
||||
if (master->debug_level) {
|
||||
EC_DBG("Finished configuration of slave %i.\n",
|
||||
slave->ring_position);
|
||||
|
|
@ -1684,7 +1470,7 @@ void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */)
|
|||
|
||||
if (!ec_fsm_change_success(&fsm->fsm_change)) {
|
||||
slave->error_flag = 1;
|
||||
fsm->slave_state = ec_fsm_error;
|
||||
fsm->slave_state = ec_fsm_slave_error;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1695,7 +1481,7 @@ void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */)
|
|||
EC_DBG("Finished configuration of slave %i.\n", slave->ring_position);
|
||||
}
|
||||
|
||||
fsm->slave_state = ec_fsm_end; // successful
|
||||
fsm->slave_state = ec_fsm_slave_end; // successful
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -1706,7 +1492,7 @@ void ec_fsm_slaveconf_op(ec_fsm_t *fsm /**< finite state machine */)
|
|||
State: ERROR.
|
||||
*/
|
||||
|
||||
void ec_fsm_error(ec_fsm_t *fsm /**< finite state machine */)
|
||||
void ec_fsm_slave_error(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1716,7 +1502,7 @@ void ec_fsm_error(ec_fsm_t *fsm /**< finite state machine */)
|
|||
State: END.
|
||||
*/
|
||||
|
||||
void ec_fsm_end(ec_fsm_t *fsm /**< finite state machine */)
|
||||
void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,14 +84,9 @@ struct ec_fsm
|
|||
|
||||
int ec_fsm_init(ec_fsm_t *, ec_master_t *);
|
||||
void ec_fsm_clear(ec_fsm_t *);
|
||||
void ec_fsm_reset(ec_fsm_t *);
|
||||
|
||||
int ec_fsm_exec(ec_fsm_t *);
|
||||
|
||||
void ec_fsm_startup(ec_fsm_t *);
|
||||
int ec_fsm_startup_success(ec_fsm_t *);
|
||||
|
||||
void ec_fsm_configuration(ec_fsm_t *);
|
||||
int ec_fsm_configuration_success(ec_fsm_t *);
|
||||
int ec_fsm_success(ec_fsm_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ void ec_fsm_coe_dict_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
if (mbox_prot != 0x03) { // CoE
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -549,7 +549,7 @@ void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *fsm
|
|||
}
|
||||
|
||||
if (mbox_prot != 0x03) { // CoE
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -722,7 +722,7 @@ void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *fsm
|
|||
}
|
||||
|
||||
if (mbox_prot != 0x03) { // CoE
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -970,7 +970,7 @@ void ec_fsm_coe_down_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
if (mbox_prot != 0x03) { // CoE
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1210,8 +1210,10 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
request->size = 0;
|
||||
|
||||
if (complete_size) {
|
||||
if (!(request->data = (uint8_t *) kmalloc(complete_size + 1, GFP_ATOMIC))) {
|
||||
EC_ERR("Failed to allocate %i bytes of SDO data!\n", complete_size);
|
||||
if (!(request->data = (uint8_t *)
|
||||
kmalloc(complete_size + 1, GFP_ATOMIC))) {
|
||||
EC_ERR("Failed to allocate %i bytes of SDO data!\n",
|
||||
complete_size);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1228,9 +1230,11 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
fsm->toggle = 0;
|
||||
|
||||
if (data_size < complete_size) {
|
||||
EC_WARN("SDO data incomplete (%i / %i).\n", data_size, complete_size);
|
||||
EC_WARN("SDO data incomplete (%i / %i).\n",
|
||||
data_size, complete_size);
|
||||
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {
|
||||
if (!(data = ec_slave_mbox_prepare_send(slave, datagram,
|
||||
0x03, 3))) {
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1354,7 +1358,7 @@ void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
}
|
||||
|
||||
if (mbox_prot != 0x03) { // CoE
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
359
master/master.c
359
master/master.c
|
|
@ -59,6 +59,7 @@ void ec_master_sync_io(ec_master_t *);
|
|||
void ec_master_idle_run(void *);
|
||||
void ec_master_eoe_run(unsigned long);
|
||||
void ec_master_check_sdo(unsigned long);
|
||||
int ec_master_measure_bus_time(ec_master_t *);
|
||||
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
|
||||
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
|
||||
const char *, size_t);
|
||||
|
|
@ -109,28 +110,55 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
EC_INFO("Initializing master %i.\n", index);
|
||||
|
||||
atomic_set(&master->available, 1);
|
||||
master->index = index;
|
||||
|
||||
master->device = NULL;
|
||||
init_MUTEX(&master->device_sem);
|
||||
atomic_set(&master->available, 1);
|
||||
|
||||
master->mode = EC_MASTER_MODE_ORPHANED;
|
||||
|
||||
INIT_LIST_HEAD(&master->slaves);
|
||||
master->slave_count = 0;
|
||||
|
||||
INIT_LIST_HEAD(&master->datagram_queue);
|
||||
master->datagram_index = 0;
|
||||
|
||||
INIT_LIST_HEAD(&master->domains);
|
||||
INIT_LIST_HEAD(&master->eoe_handlers);
|
||||
master->debug_level = 0;
|
||||
|
||||
master->stats.timeouts = 0;
|
||||
master->stats.corrupted = 0;
|
||||
master->stats.skipped = 0;
|
||||
master->stats.unmatched = 0;
|
||||
master->stats.output_jiffies = 0;
|
||||
|
||||
INIT_WORK(&master->idle_work, ec_master_idle_run, (void *) master);
|
||||
init_timer(&master->eoe_timer);
|
||||
master->eoe_timer.function = ec_master_eoe_run;
|
||||
master->eoe_timer.data = (unsigned long) master;
|
||||
master->internal_lock = SPIN_LOCK_UNLOCKED;
|
||||
master->eoe_running = 0;
|
||||
master->eoe_checked = 0;
|
||||
|
||||
for (i = 0; i < HZ; i++) {
|
||||
master->idle_cycle_times[i] = 0;
|
||||
master->eoe_cycle_times[i] = 0;
|
||||
}
|
||||
master->idle_cycle_time_pos = 0;
|
||||
master->eoe_cycle_time_pos = 0;
|
||||
master->debug_level = 0;
|
||||
|
||||
init_timer(&master->eoe_timer);
|
||||
master->eoe_timer.function = ec_master_eoe_run;
|
||||
master->eoe_timer.data = (unsigned long) master;
|
||||
master->eoe_running = 0;
|
||||
master->eoe_checked = 0;
|
||||
INIT_LIST_HEAD(&master->eoe_handlers);
|
||||
|
||||
master->internal_lock = SPIN_LOCK_UNLOCKED;
|
||||
master->request_cb = NULL;
|
||||
master->release_cb = NULL;
|
||||
master->cb_data = NULL;
|
||||
|
||||
master->eeprom_write_enable = 0;
|
||||
|
||||
master->sdo_request = NULL;
|
||||
master->sdo_seq_user = 0;
|
||||
master->sdo_seq_master = 0;
|
||||
init_MUTEX(&master->sdo_sem);
|
||||
init_timer(&master->sdo_timer);
|
||||
master->sdo_timer.function = ec_master_check_sdo;
|
||||
|
|
@ -175,7 +203,6 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
return -1;
|
||||
}
|
||||
|
||||
ec_master_reset(master);
|
||||
return 0;
|
||||
|
||||
out_clear_eoe:
|
||||
|
|
@ -203,10 +230,17 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
{
|
||||
ec_master_t *master = container_of(kobj, ec_master_t, kobj);
|
||||
ec_eoe_t *eoe, *next_eoe;
|
||||
ec_datagram_t *datagram, *next_c;
|
||||
|
||||
EC_INFO("Clearing master %i...\n", master->index);
|
||||
ec_master_clear_slaves(master);
|
||||
|
||||
// empty datagram queue
|
||||
list_for_each_entry_safe(datagram, next_c,
|
||||
&master->datagram_queue, queue) {
|
||||
datagram->state = EC_DATAGRAM_ERROR;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
|
||||
ec_master_reset(master);
|
||||
ec_fsm_clear(&master->fsm);
|
||||
destroy_workqueue(master->workqueue);
|
||||
ec_xmldev_clear(&master->xmldev);
|
||||
|
|
@ -218,11 +252,6 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
kfree(eoe);
|
||||
}
|
||||
|
||||
if (master->device) {
|
||||
ec_device_clear(master->device);
|
||||
kfree(master->device);
|
||||
}
|
||||
|
||||
EC_INFO("Master %i cleared.\n", master->index);
|
||||
|
||||
kfree(master);
|
||||
|
|
@ -230,57 +259,6 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Resets the master.
|
||||
Note: This function has to be called, everytime ec_master_release() is
|
||||
called, to free the slave list, domains etc.
|
||||
*/
|
||||
|
||||
void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_datagram_t *datagram, *next_c;
|
||||
ec_domain_t *domain, *next_d;
|
||||
|
||||
ec_master_eoe_stop(master);
|
||||
ec_master_idle_stop(master);
|
||||
ec_master_flush_sdo_requests(master);
|
||||
ec_master_clear_slaves(master);
|
||||
|
||||
// empty datagram queue
|
||||
list_for_each_entry_safe(datagram, next_c,
|
||||
&master->datagram_queue, queue) {
|
||||
datagram->state = EC_DATAGRAM_ERROR;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
|
||||
// clear domains
|
||||
list_for_each_entry_safe(domain, next_d, &master->domains, list) {
|
||||
list_del(&domain->list);
|
||||
kobject_del(&domain->kobj);
|
||||
kobject_put(&domain->kobj);
|
||||
}
|
||||
|
||||
master->datagram_index = 0;
|
||||
|
||||
master->stats.timeouts = 0;
|
||||
master->stats.corrupted = 0;
|
||||
master->stats.skipped = 0;
|
||||
master->stats.unmatched = 0;
|
||||
master->stats.output_jiffies = 0;
|
||||
|
||||
master->mode = EC_MASTER_MODE_ORPHANED;
|
||||
|
||||
master->request_cb = NULL;
|
||||
master->release_cb = NULL;
|
||||
master->cb_data = NULL;
|
||||
|
||||
master->eeprom_write_enable = 0;
|
||||
|
||||
ec_fsm_reset(&master->fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Clears all slaves.
|
||||
*/
|
||||
|
|
@ -294,6 +272,7 @@ void ec_master_clear_slaves(ec_master_t *master)
|
|||
kobject_del(&slave->kobj);
|
||||
kobject_put(&slave->kobj);
|
||||
}
|
||||
|
||||
master->slave_count = 0;
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +293,123 @@ void ec_master_flush_sdo_requests(ec_master_t *master)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
int ec_master_enter_idle_mode(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
master->mode = EC_MASTER_MODE_IDLE;
|
||||
queue_delayed_work(master->workqueue, &master->idle_work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
void ec_master_leave_idle_mode(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_master_eoe_stop(master);
|
||||
|
||||
master->mode = EC_MASTER_MODE_ORPHANED;
|
||||
if (!cancel_delayed_work(&master->idle_work)) {
|
||||
flush_workqueue(master->workqueue);
|
||||
}
|
||||
|
||||
ec_master_flush_sdo_requests(master);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
int ec_master_enter_operation_mode(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_slave_t *slave;
|
||||
ec_datagram_t *datagram = &master->fsm.datagram;
|
||||
|
||||
master->mode = EC_MASTER_MODE_OPERATION;
|
||||
if (!cancel_delayed_work(&master->idle_work)) {
|
||||
flush_workqueue(master->workqueue);
|
||||
}
|
||||
|
||||
// wait for FSM datagram
|
||||
if (datagram->state == EC_DATAGRAM_SENT) {;
|
||||
while (get_cycles() - datagram->cycles_sent
|
||||
< (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000)) {}
|
||||
ecrt_master_receive(master);
|
||||
}
|
||||
|
||||
// finish running FSM
|
||||
while (ec_fsm_exec(&master->fsm)) {
|
||||
ec_master_sync_io(master);
|
||||
}
|
||||
|
||||
if (!ec_fsm_success(&master->fsm)) {
|
||||
EC_ERR("Master state machine failure!\n");
|
||||
goto out_idle;
|
||||
}
|
||||
|
||||
if (master->debug_level) {
|
||||
if (ec_master_measure_bus_time(master)) {
|
||||
EC_ERR("Bus time measuring failed!\n");
|
||||
goto out_idle;
|
||||
}
|
||||
}
|
||||
|
||||
// set initial slave states
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
if (ec_slave_is_coupler(slave)) {
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
|
||||
}
|
||||
else {
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_idle:
|
||||
master->mode = EC_MASTER_MODE_IDLE;
|
||||
queue_delayed_work(master->workqueue, &master->idle_work, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
void ec_master_leave_operation_mode(ec_master_t *master
|
||||
/**< EtherCAT master */)
|
||||
{
|
||||
ec_slave_t *slave;
|
||||
ec_domain_t *domain, *next_d;
|
||||
|
||||
// clear domains
|
||||
list_for_each_entry_safe(domain, next_d, &master->domains, list) {
|
||||
ec_domain_dequeue_datagrams(domain);
|
||||
list_del(&domain->list);
|
||||
kobject_del(&domain->kobj);
|
||||
kobject_put(&domain->kobj);
|
||||
}
|
||||
|
||||
master->request_cb = NULL;
|
||||
master->release_cb = NULL;
|
||||
master->cb_data = NULL;
|
||||
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
ec_slave_reset(slave);
|
||||
}
|
||||
|
||||
master->mode = EC_MASTER_MODE_IDLE;
|
||||
queue_delayed_work(master->workqueue, &master->idle_work, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Places a datagram in the datagram queue.
|
||||
*/
|
||||
|
|
@ -544,32 +640,6 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Scans the EtherCAT bus for slaves.
|
||||
Creates a list of slave structures for further processing.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_fsm_t *fsm = &master->fsm;
|
||||
|
||||
ec_fsm_startup(fsm); // init startup state machine
|
||||
|
||||
while (ec_fsm_exec(fsm)) {
|
||||
ec_master_sync_io(master);
|
||||
}
|
||||
|
||||
if (!ec_fsm_startup_success(fsm)) {
|
||||
ec_master_clear_slaves(master);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Output statistics in cyclic mode.
|
||||
This function outputs statistical data on demand, but not more often than
|
||||
|
|
@ -606,52 +676,6 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Starts the Idle mode.
|
||||
*/
|
||||
|
||||
void ec_master_idle_start(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
if (master->mode == EC_MASTER_MODE_IDLE) return;
|
||||
|
||||
if (master->mode == EC_MASTER_MODE_OPERATION) {
|
||||
EC_ERR("ec_master_idle_start: Master already running!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
EC_INFO("Starting Idle mode.\n");
|
||||
|
||||
master->mode = EC_MASTER_MODE_IDLE;
|
||||
ec_fsm_reset(&master->fsm);
|
||||
queue_delayed_work(master->workqueue, &master->idle_work, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Stops the Idle mode.
|
||||
*/
|
||||
|
||||
void ec_master_idle_stop(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
if (master->mode != EC_MASTER_MODE_IDLE) return;
|
||||
|
||||
ec_master_eoe_stop(master);
|
||||
|
||||
EC_INFO("Stopping Idle mode.\n");
|
||||
master->mode = EC_MASTER_MODE_ORPHANED; // this is important for the
|
||||
// IDLE work function to not
|
||||
// queue itself again
|
||||
|
||||
if (!cancel_delayed_work(&master->idle_work)) {
|
||||
flush_workqueue(master->workqueue);
|
||||
}
|
||||
|
||||
ec_master_clear_slaves(master);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Idle mode function.
|
||||
*/
|
||||
|
|
@ -947,16 +971,16 @@ void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */)
|
|||
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;
|
||||
slave->error_flag = 0;
|
||||
if (eoe->opened)
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
|
||||
else
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
EC_WARN("No EoE handler for slave %i!\n", slave->ring_position);
|
||||
slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
slave->error_flag = 0;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -995,8 +1019,7 @@ void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */)
|
|||
// decouple all EoE handlers
|
||||
list_for_each_entry(eoe, &master->eoe_handlers, list) {
|
||||
if (eoe->slave) {
|
||||
eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
eoe->slave->error_flag = 0;
|
||||
ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_PREOP);
|
||||
eoe->slave = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1253,27 +1276,23 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
|||
domain_offset += domain->data_size;
|
||||
}
|
||||
|
||||
// determine initial states.
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
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
|
||||
|
||||
// execute master FSM until termination
|
||||
while (ec_fsm_exec(fsm)) {
|
||||
ec_master_sync_io(master);
|
||||
}
|
||||
|
||||
if (!ec_fsm_configuration_success(fsm)) {
|
||||
if (!ec_fsm_success(fsm)) {
|
||||
EC_ERR("Error in master state machine.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_fsm_reset(&master->fsm); // prepare for operation state machine
|
||||
// check, if all slaves have been configured
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
if (slave->error_flag || !slave->online) {
|
||||
EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1289,13 +1308,21 @@ void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */)
|
|||
{
|
||||
ec_fsm_t *fsm = &master->fsm;
|
||||
ec_slave_t *slave;
|
||||
ec_datagram_t *datagram = &master->fsm.datagram;
|
||||
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
// wait for FSM datagram
|
||||
if (datagram->state == EC_DATAGRAM_SENT) {
|
||||
while (get_cycles() - datagram->cycles_sent
|
||||
< (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000)) {}
|
||||
ecrt_master_receive(master);
|
||||
}
|
||||
|
||||
ec_fsm_configuration(fsm); // init configuration state machine
|
||||
// set states for all slaves
|
||||
list_for_each_entry(slave, &master->slaves, list) {
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
|
||||
}
|
||||
|
||||
// execute master FSM to deactivate slaves
|
||||
while (ec_fsm_exec(fsm)) {
|
||||
ec_master_sync_io(master);
|
||||
}
|
||||
|
|
@ -1416,7 +1443,7 @@ void ecrt_master_prepare(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
// queue datagrams of all domains
|
||||
list_for_each_entry(domain, &master->domains, list)
|
||||
ec_domain_queue(domain);
|
||||
ec_domain_queue_datagrams(domain);
|
||||
|
||||
ecrt_master_send(master);
|
||||
|
||||
|
|
@ -1443,7 +1470,7 @@ void ecrt_master_run(ec_master_t *master /**< EtherCAT master */)
|
|||
// output statistics
|
||||
ec_master_output_stats(master);
|
||||
|
||||
// execute master state machine
|
||||
// execute master state machine in a loop
|
||||
ec_fsm_exec(&master->fsm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,35 +148,31 @@ struct ec_master
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
// master creation and deletion
|
||||
// master creation
|
||||
int ec_master_init(ec_master_t *, unsigned int, unsigned int, dev_t);
|
||||
void ec_master_reset(ec_master_t *);
|
||||
|
||||
// free run
|
||||
void ec_master_idle_start(ec_master_t *);
|
||||
void ec_master_idle_stop(ec_master_t *);
|
||||
// mode transitions
|
||||
int ec_master_enter_idle_mode(ec_master_t *);
|
||||
void ec_master_leave_idle_mode(ec_master_t *);
|
||||
int ec_master_enter_operation_mode(ec_master_t *);
|
||||
void ec_master_leave_operation_mode(ec_master_t *);
|
||||
|
||||
// EoE
|
||||
void ec_master_eoe_start(ec_master_t *);
|
||||
void ec_master_eoe_stop(ec_master_t *);
|
||||
|
||||
// IO
|
||||
// datagram IO
|
||||
void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t);
|
||||
void ec_master_queue_datagram(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 *);
|
||||
int ec_master_measure_bus_time(ec_master_t *);
|
||||
void ec_master_calc_addressing(ec_master_t *);
|
||||
|
||||
// other methods
|
||||
// helper functions
|
||||
void ec_sync_config(const ec_sii_sync_t *, const ec_slave_t *, uint8_t *);
|
||||
void ec_fmmu_config(const ec_fmmu_t *, const ec_slave_t *, uint8_t *);
|
||||
void ec_master_calc_addressing(ec_master_t *);
|
||||
void ec_master_flush_sdo_requests(ec_master_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -384,7 +384,8 @@ int ecdev_start(unsigned int master_index /**< master index */)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ec_master_idle_start(master);
|
||||
ec_master_enter_idle_mode(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -402,8 +403,7 @@ void ecdev_stop(unsigned int master_index /**< master index */)
|
|||
ec_master_t *master;
|
||||
if (!(master = ec_find_master(master_index))) return;
|
||||
|
||||
ec_master_idle_stop(master);
|
||||
ec_master_flush_sdo_requests(master);
|
||||
ec_master_leave_idle_mode(master);
|
||||
|
||||
if (ec_device_close(master->device))
|
||||
EC_WARN("Failed to close device!\n");
|
||||
|
|
@ -459,31 +459,19 @@ ec_master_t *ecrt_request_master(unsigned int master_index
|
|||
goto out_module_put;
|
||||
}
|
||||
|
||||
ec_master_reset(master); // also stops idle mode
|
||||
master->mode = EC_MASTER_MODE_OPERATION;
|
||||
|
||||
if (ec_master_measure_bus_time(master)) {
|
||||
EC_ERR("Bus time measuring failed!\n");
|
||||
goto out_reset;
|
||||
}
|
||||
|
||||
if (ec_master_bus_scan(master)) {
|
||||
EC_ERR("Bus scan failed!\n");
|
||||
goto out_reset;
|
||||
if (ec_master_enter_operation_mode(master)) {
|
||||
EC_ERR("Failed to enter OPERATION mode!\n");
|
||||
goto out_module_put;
|
||||
}
|
||||
|
||||
EC_INFO("Successfully requested master %i.\n", master_index);
|
||||
return master;
|
||||
|
||||
out_reset:
|
||||
ec_master_reset(master);
|
||||
ec_master_idle_start(master);
|
||||
out_module_put:
|
||||
module_put(master->device->module);
|
||||
out_release:
|
||||
atomic_inc(&master->available);
|
||||
out_return:
|
||||
EC_ERR("Failed to request master %i.\n", master_index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -496,20 +484,12 @@ ec_master_t *ecrt_request_master(unsigned int master_index
|
|||
|
||||
void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
EC_INFO("Releasing master %i...\n", master->index);
|
||||
|
||||
if (atomic_read(&master->available)) {
|
||||
EC_ERR("Master %i was never requested!\n", master->index);
|
||||
return;
|
||||
}
|
||||
|
||||
ec_master_reset(master);
|
||||
ec_master_idle_start(master);
|
||||
ec_master_leave_operation_mode(master);
|
||||
|
||||
module_put(master->device->module);
|
||||
atomic_inc(&master->available);
|
||||
|
||||
EC_INFO("Successfully released master %i.\n", master->index);
|
||||
EC_INFO("Released master %i.\n", master->index);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
|
|||
slave->error_flag = 0;
|
||||
slave->online = 1;
|
||||
slave->fmmu_count = 0;
|
||||
slave->registered = 0;
|
||||
|
||||
slave->coupler_index = 0;
|
||||
slave->coupler_subindex = 0xFFFF;
|
||||
|
|
@ -243,7 +242,7 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
|
|||
kobject_put(&sdo->kobj);
|
||||
}
|
||||
|
||||
// free SDO kobject
|
||||
// free SDO kobject FIXME
|
||||
if (slave->sdo_dictionary_fetched) kobject_del(&slave->sdo_kobj);
|
||||
kobject_put(&slave->sdo_kobj);
|
||||
|
||||
|
|
@ -262,6 +261,30 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Reset slave from operation mode.
|
||||
*/
|
||||
|
||||
void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
slave->fmmu_count = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
void ec_slave_request_state(ec_slave_t *slave, /**< ETherCAT slave */
|
||||
ec_slave_state_t state /**< new state */
|
||||
)
|
||||
{
|
||||
slave->requested_state = state;
|
||||
slave->error_flag = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Fetches data from a STRING category.
|
||||
\return 0 in case of success, else < 0
|
||||
|
|
@ -514,7 +537,6 @@ int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */
|
|||
fmmu->logical_start_address = 0;
|
||||
|
||||
slave->fmmu_count++;
|
||||
slave->registered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -810,13 +832,13 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */
|
|||
if (attr == &attr_state) {
|
||||
char state[EC_STATE_STRING_SIZE];
|
||||
if (!strcmp(buffer, "INIT\n"))
|
||||
slave->requested_state = EC_SLAVE_STATE_INIT;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
|
||||
else if (!strcmp(buffer, "PREOP\n"))
|
||||
slave->requested_state = EC_SLAVE_STATE_PREOP;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
|
||||
else if (!strcmp(buffer, "SAVEOP\n"))
|
||||
slave->requested_state = EC_SLAVE_STATE_SAVEOP;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_SAVEOP);
|
||||
else if (!strcmp(buffer, "OP\n"))
|
||||
slave->requested_state = EC_SLAVE_STATE_OP;
|
||||
ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
|
||||
else {
|
||||
EC_ERR("Invalid slave state \"%s\"!\n", buffer);
|
||||
return -EINVAL;
|
||||
|
|
@ -825,7 +847,6 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */
|
|||
ec_state_string(slave->requested_state, state);
|
||||
EC_INFO("Accepted new state %s for slave %i.\n",
|
||||
state, slave->ring_position);
|
||||
slave->error_flag = 0;
|
||||
return size;
|
||||
}
|
||||
else if (attr == &attr_eeprom) {
|
||||
|
|
|
|||
|
|
@ -197,10 +197,9 @@ struct ec_slave
|
|||
|
||||
ec_slave_state_t requested_state; /**< requested slave state */
|
||||
ec_slave_state_t current_state; /**< current slave state */
|
||||
unsigned int configured; /**< the slave is configured by this master */
|
||||
unsigned int configured; /**< the slave was configured by this master */
|
||||
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 */
|
||||
|
|
@ -261,9 +260,13 @@ struct ec_slave
|
|||
// slave construction/destruction
|
||||
int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t);
|
||||
|
||||
void ec_slave_reset(ec_slave_t *);
|
||||
|
||||
int ec_slave_prepare_fmmu(ec_slave_t *, const ec_domain_t *,
|
||||
const ec_sii_sync_t *);
|
||||
|
||||
void ec_slave_request_state(ec_slave_t *, ec_slave_state_t);
|
||||
|
||||
// SII categories
|
||||
int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *);
|
||||
void ec_slave_fetch_general(ec_slave_t *, const uint8_t *);
|
||||
|
|
|
|||
Loading…
Reference in New Issue