Reading of Pdo mapping via CoE during scan.

This commit is contained in:
Florian Pose 2008-02-26 16:58:20 +00:00
parent 5e22bcec73
commit 397b5bf0cc
13 changed files with 233 additions and 262 deletions

3
NEWS
View File

@ -41,7 +41,10 @@ Changes in version 1.4.0:
be reached by specifying an explicit Pdo mapping and registering those
Pdo entries.
* Pdo configuration is now supported.
* Current Pdo mapping/configuration is now read during bus scan, without
using the Sdo dictionary.
* Added 8139too driver for kernel 2.6.22, thanks to Erwin Burgstaller.
* Added 8139too driver for kernel 2.6.23, thanks to Richard Hacker.
* Added e1000 driver for kernel 2.6.22.
* Added support for slaves that do not support the LRW datagram type. Separate
domains have to be used for inputs and output.

6
TODO
View File

@ -8,7 +8,6 @@ $Id$
Version 1.4.0:
* Read PDO mapping via CoE during bus scan.
* Realtime interface changes:
- SDO access.
* Mailbox handler
@ -18,9 +17,8 @@ Version 1.4.0:
* Remove ecdb.h and let lsec output PDO information 'cut-and-pastable' for
applications.
* SDO write access in sysfs.
* Update documentation.
* Distributed clocks.
* Safety-over-EtherCAT
* Update documentation.
Future issues:
@ -29,6 +27,8 @@ Future issues:
to replace lsec.
- Step 2: Move kernel threads to user space daemon with a TCP interface
replacing the cdev.
* Mailbox gateway.
* Slave-to-slave communication.
* Redundancy with 2 network adapters.
* Interface/buffers for asynchronous domain IO.

View File

@ -26,16 +26,16 @@ digraph master {
action_configure -> configure_slave
action_process_states -> action_configure
action_process_states -> action_process_sdo
action_process_states -> sdodict
action_process_states -> action_process_eeprom
action_process_states -> end
action_next_slave_state -> read_states
action_next_slave_state -> validate_vendor
action_next_slave_state -> action_process_states
action_process_states -> action_configure
action_process_states -> action_process_sdo
action_process_states -> action_process_eeprom
action_process_states -> sdodict
action_process_states -> end
//read_states -> error
read_states -> action_next_slave_state
read_states -> acknowledge
@ -50,8 +50,8 @@ digraph master {
action_addresses -> rewrite_addresses
//validate_product -> error
validate_product -> validate_vendor
validate_product -> action_addresses
validate_product -> validate_vendor
//rewrite_addresses -> error
rewrite_addresses -> end
@ -67,6 +67,7 @@ digraph master {
configure_slave -> end
//write_eeprom -> error
write_eeprom -> action_process_eeprom
write_eeprom -> end
//sdodict -> error

View File

@ -416,7 +416,8 @@ ssize_t ec_sdo_entry_read_value(ec_sdo_entry_t *entry, /**< Sdo entry */
off_t off = 0;
ec_sdo_request_t request;
ec_sdo_request_init_read(&request, entry);
ec_sdo_request_init_read(&request, entry->sdo->slave,
entry->sdo->index, entry->subindex);
// schedule request.
down(&master->sdo_sem);
@ -479,11 +480,16 @@ ssize_t ec_show_sdo_entry_attribute(struct kobject *kobj, /**< kobject */
Sdo request constructor.
*/
void ec_sdo_request_init_read(ec_sdo_request_t *req, /**< Sdo request */
ec_sdo_entry_t *entry /**< Sdo entry */
)
void ec_sdo_request_init_read(
ec_sdo_request_t *req, /**< Sdo request */
ec_slave_t *slave, /**< Slave owning the Sdo. */
uint16_t index, /**< Sdo index. */
uint8_t subindex /**< Sdo subindex. */
)
{
req->entry = entry;
req->slave = slave;
req->index = index;
req->subindex = subindex;
req->data = NULL;
req->size = 0;
req->state = EC_REQUEST_QUEUED;

View File

@ -49,12 +49,9 @@
/*****************************************************************************/
/**
CANopen Sdo.
*/
struct ec_sdo
{
/** CANopen Sdo.
*/
struct ec_sdo {
struct kobject kobj; /**< kobject */
struct list_head list; /**< list item */
ec_slave_t *slave; /**< parent slave */
@ -67,12 +64,9 @@ struct ec_sdo
/*****************************************************************************/
/**
CANopen Sdo entry.
*/
typedef struct
{
/** CANopen Sdo entry.
*/
typedef struct {
struct kobject kobj; /**< kobject */
struct list_head list; /**< list item */
ec_sdo_t *sdo; /**< parent Sdo */
@ -80,17 +74,13 @@ typedef struct
uint16_t data_type; /**< entry data type */
uint16_t bit_length; /**< entry length in bit */
char *description; /**< entry description */
}
ec_sdo_entry_t;
} ec_sdo_entry_t;
/*****************************************************************************/
/**
CANopen Sdo configuration data.
*/
typedef struct
{
/** CANopen Sdo configuration data.
*/
typedef struct {
struct list_head list; /**< list item */
uint16_t index; /**< Sdo index */
uint8_t subindex; /**< Sdo subindex */
@ -105,15 +95,15 @@ ec_sdo_data_t;
CANopen Sdo request.
*/
typedef struct
{
typedef struct {
struct list_head list; /**< list item */
ec_sdo_entry_t *entry; /**< Sdo entry */
ec_slave_t *slave; /**< Slave owning the Sdo. */
uint16_t index; /**< Sdo index. */
uint8_t subindex; /**< Sdo subindex. */
uint8_t *data; /**< pointer to Sdo data */
size_t size; /**< size of Sdo data */
ec_request_state_t state; /**< Sdo request state */
}
ec_sdo_request_t;
} ec_sdo_request_t;
/*****************************************************************************/
@ -124,7 +114,8 @@ ec_sdo_entry_t *ec_sdo_get_entry(ec_sdo_t *, uint8_t);
int ec_sdo_entry_init(ec_sdo_entry_t *, uint8_t, ec_sdo_t *);
void ec_sdo_entry_destroy(ec_sdo_entry_t *);
void ec_sdo_request_init_read(ec_sdo_request_t *, ec_sdo_entry_t *);
void ec_sdo_request_init_read(ec_sdo_request_t *, ec_slave_t *, uint16_t,
uint8_t);
void ec_sdo_request_clear(ec_sdo_request_t *);
/*****************************************************************************/

View File

@ -1175,12 +1175,11 @@ void ec_fsm_coe_up_start(ec_fsm_coe_t *fsm /**< finite state machine */)
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
ec_sdo_request_t *request = fsm->request;
ec_sdo_entry_t *entry = request->entry;
uint8_t *data;
if (master->debug_level)
EC_DBG("Uploading Sdo 0x%04X:%i from slave %i.\n",
entry->sdo->index, entry->subindex, slave->ring_position);
request->index, request->subindex, slave->ring_position);
if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
@ -1195,8 +1194,8 @@ void ec_fsm_coe_up_start(ec_fsm_coe_t *fsm /**< finite state machine */)
EC_WRITE_U16(data, 0x2 << 12); // Sdo request
EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
EC_WRITE_U16(data + 3, entry->sdo->index);
EC_WRITE_U8 (data + 5, entry->subindex);
EC_WRITE_U16(data + 3, request->index);
EC_WRITE_U8 (data + 5, request->subindex);
memset(data + 6, 0x00, 4);
if (master->debug_level) {
@ -1311,7 +1310,6 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
uint8_t *data, mbox_prot;
size_t rec_size, data_size;
ec_sdo_request_t *request = fsm->request;
ec_sdo_entry_t *entry = request->entry;
uint32_t complete_size;
unsigned int expedited, size_specified;
@ -1361,7 +1359,7 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
EC_ERR("Sdo upload 0x%04X:%X aborted on slave %i.\n",
entry->sdo->index, entry->subindex, slave->ring_position);
request->index, request->subindex, slave->ring_position);
if (rec_size >= 10)
ec_canopen_abort_msg(EC_READ_U32(data + 6));
else
@ -1390,9 +1388,10 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
EC_READ_U16(data + 3) != entry->sdo->index || // index
EC_READ_U8 (data + 5) != entry->subindex) { // subindex
EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
EC_READ_U16(data + 3) != request->index || // index
EC_READ_U8 (data + 5) != request->subindex) { // subindex
EC_ERR("Sdo upload 0x%04X:%X failed:\n",
request->index, request->subindex);
EC_ERR("Invalid Sdo upload response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);
@ -1438,9 +1437,10 @@ void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm /**< finite state machine */)
if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
EC_READ_U16(data + 3) != entry->sdo->index || // index
EC_READ_U8 (data + 5) != entry->subindex) { // subindex
EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
EC_READ_U16(data + 3) != request->index || // index
EC_READ_U8 (data + 5) != request->subindex) { // subindex
EC_ERR("Sdo upload 0x%04X:%X failed:\n",
request->index, request->subindex);
EC_ERR("Invalid Sdo upload response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);
@ -1602,7 +1602,6 @@ void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
uint8_t *data, mbox_prot;
size_t rec_size, data_size;
ec_sdo_request_t *request = fsm->request;
ec_sdo_entry_t *entry = request->entry;
uint32_t seg_size;
unsigned int last_segment;
@ -1652,7 +1651,7 @@ void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
EC_ERR("Sdo upload 0x%04X:%X aborted on slave %i.\n",
entry->sdo->index, entry->subindex, slave->ring_position);
request->index, request->subindex, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
fsm->state = ec_fsm_coe_error;
return;
@ -1660,7 +1659,7 @@ void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
EC_READ_U8 (data + 2) >> 5 != 0x0) { // upload segment response
EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
EC_ERR("Sdo upload 0x%04X:%X failed:\n", request->index, request->subindex);
EC_ERR("Invalid Sdo upload segment response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);

View File

@ -55,7 +55,7 @@ void ec_fsm_coe_map_state_pdo_entry(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_action_next_dir(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *);
void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *);
@ -140,49 +140,56 @@ void ec_fsm_coe_map_state_start(
ec_fsm_coe_map_t *fsm /**< finite state machine */
)
{
// read mapping of first sync manager
fsm->sync_index = 0;
ec_fsm_coe_map_action_next_sync(fsm);
// read mapping for first direction
fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
ec_fsm_coe_map_action_next_dir(fsm);
}
/*****************************************************************************/
/**
* Read mapping of next sync manager.
* Read mapping of next direction manager.
*/
void ec_fsm_coe_map_action_next_sync(
void ec_fsm_coe_map_action_next_dir(
ec_fsm_coe_map_t *fsm /**< finite state machine */
)
{
ec_slave_t *slave = fsm->slave;
ec_sdo_entry_t *entry;
for (; fsm->sync_index < slave->sii_sync_count; fsm->sync_index++) {
if (!(fsm->sync_sdo = ec_slave_get_sdo(slave, 0x1C10 + fsm->sync_index)))
fsm->dir++;
if (slave->master->debug_level)
EC_DBG("Processing dir %u of slave %u.\n",
fsm->dir, slave->ring_position);
for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
if (!(fsm->sync = ec_slave_get_pdo_sync(slave, fsm->dir))) {
if (slave->master->debug_level)
EC_DBG("No sync manager for direction %u!\n", fsm->dir);
continue;
}
fsm->sync_sdo_index = 0x1C10 + fsm->sync->index;
if (slave->master->debug_level)
EC_DBG("Reading Pdo mapping of sync manager %u of slave %u.\n",
fsm->sync_index, slave->ring_position);
fsm->sync->index, slave->ring_position);
ec_pdo_mapping_clear_pdos(&fsm->mapping);
if (!(entry = ec_sdo_get_entry(fsm->sync_sdo, 0))) {
EC_ERR("Sdo 0x%04X has no subindex 0 on slave %u.\n",
fsm->sync_sdo->index,
fsm->slave->ring_position);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
ec_sdo_request_init_read(&fsm->request, entry);
ec_sdo_request_init_read(&fsm->request, slave, fsm->sync_sdo_index, 0);
fsm->state = ec_fsm_coe_map_state_pdo_count;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
return;
}
if (slave->master->debug_level)
EC_DBG("Reading of Pdo mapping finished for slave %u.\n",
slave->ring_position);
fsm->state = ec_fsm_coe_map_state_end;
}
@ -225,41 +232,27 @@ void ec_fsm_coe_map_action_next_pdo(
ec_fsm_coe_map_t *fsm /**< finite state machine */
)
{
ec_sdo_entry_t *entry;
if (fsm->sync_subindex <= fsm->sync_subindices) {
if (!(entry = ec_sdo_get_entry(fsm->sync_sdo,
fsm->sync_subindex))) {
EC_ERR("Sdo 0x%04X has no subindex %u on slave %u.\n",
fsm->sync_sdo->index,
fsm->sync_subindex,
fsm->slave->ring_position);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
ec_sdo_request_init_read(&fsm->request, entry);
ec_sdo_request_init_read(&fsm->request, fsm->slave,
fsm->sync_sdo_index, fsm->sync_subindex);
fsm->state = ec_fsm_coe_map_state_pdo;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
return;
}
{
ec_sync_t *sync = fsm->slave->sii_syncs + fsm->sync_index;
if (ec_pdo_mapping_copy(&sync->mapping, &fsm->mapping)) {
fsm->state = ec_fsm_coe_map_state_error;
return;
}
sync->mapping_source = EC_SYNC_MAPPING_COE;
ec_pdo_mapping_clear_pdos(&fsm->mapping);
// next sync manager
fsm->sync_index++;
ec_fsm_coe_map_action_next_sync(fsm);
// finished reading Pdo mapping/configuration
if (ec_pdo_mapping_copy(&fsm->sync->mapping, &fsm->mapping)) {
fsm->state = ec_fsm_coe_map_state_error;
return;
}
fsm->sync->mapping_source = EC_SYNC_MAPPING_COE;
ec_pdo_mapping_clear_pdos(&fsm->mapping);
// next direction
ec_fsm_coe_map_action_next_dir(fsm);
}
/*****************************************************************************/
@ -281,58 +274,26 @@ void ec_fsm_coe_map_state_pdo(
return;
}
{
ec_sdo_entry_t *entry;
if (!(fsm->pdo = (ec_pdo_t *)
kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate Pdo.\n");
fsm->state = ec_fsm_coe_map_state_error;
return;
}
ec_pdo_init(fsm->pdo);
fsm->pdo->index = EC_READ_U16(fsm->request.data);
fsm->pdo->dir =
ec_sync_direction(fsm->slave->sii_syncs + fsm->sync_index);
if (fsm->slave->master->debug_level)
EC_DBG(" Pdo 0x%04X.\n", fsm->pdo->index);
if (!(fsm->pdo_sdo = ec_slave_get_sdo(fsm->slave, fsm->pdo->index))) {
EC_ERR("Slave %u has no Sdo 0x%04X.\n",
fsm->slave->ring_position, fsm->pdo->index);
ec_pdo_clear(fsm->pdo);
kfree(fsm->pdo);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
if (ec_pdo_set_name(fsm->pdo, fsm->pdo_sdo->name)) {
ec_pdo_clear(fsm->pdo);
kfree(fsm->pdo);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
if (!(entry = ec_sdo_get_entry(fsm->pdo_sdo, 0))) {
EC_ERR("Sdo 0x%04X has no subindex 0 on slave %u.\n",
fsm->pdo_sdo->index,
fsm->slave->ring_position);
ec_pdo_clear(fsm->pdo);
kfree(fsm->pdo);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
ec_sdo_request_init_read(&fsm->request, entry);
fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
if (!(fsm->pdo = (ec_pdo_t *)
kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate Pdo.\n");
fsm->state = ec_fsm_coe_map_state_error;
return;
}
ec_pdo_init(fsm->pdo);
fsm->pdo->index = EC_READ_U16(fsm->request.data);
fsm->pdo->dir = ec_sync_direction(fsm->sync);
if (fsm->slave->master->debug_level)
EC_DBG(" Pdo 0x%04X.\n", fsm->pdo->index);
list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
ec_sdo_request_init_read(&fsm->request, fsm->slave, fsm->pdo->index, 0);
fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
}
/*****************************************************************************/
@ -374,19 +335,9 @@ void ec_fsm_coe_map_action_next_pdo_entry(
ec_fsm_coe_map_t *fsm /**< finite state machine */
)
{
ec_sdo_entry_t *entry;
if (fsm->pdo_subindex <= fsm->pdo_subindices) {
if (!(entry = ec_sdo_get_entry(fsm->pdo_sdo,
fsm->pdo_subindex))) {
EC_ERR("Sdo 0x%04X has no subindex %u on slave %u.\n",
fsm->pdo_sdo->index, fsm->pdo_subindex,
fsm->slave->ring_position);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
ec_sdo_request_init_read(&fsm->request, entry);
ec_sdo_request_init_read(&fsm->request, fsm->slave,
fsm->pdo->index, fsm->pdo_subindex);
fsm->state = ec_fsm_coe_map_state_pdo_entry;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
@ -419,8 +370,6 @@ void ec_fsm_coe_map_state_pdo_entry(
{
uint32_t pdo_entry_info;
ec_sdo_t *sdo;
ec_sdo_entry_t *entry;
ec_pdo_entry_t *pdo_entry;
pdo_entry_info = EC_READ_U32(fsm->request.data);
@ -438,49 +387,12 @@ void ec_fsm_coe_map_state_pdo_entry(
pdo_entry->bit_length = pdo_entry_info & 0xFF;
if (!pdo_entry->index && !pdo_entry->subindex) {
// we have a gap in the Pdo, next Pdo entry
if (fsm->slave->master->debug_level) {
EC_DBG(" Pdo entry gap: %u bit.\n",
pdo_entry->bit_length);
}
if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
ec_pdo_entry_clear(pdo_entry);
kfree(pdo_entry);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
fsm->pdo_subindex++;
ec_fsm_coe_map_action_next_pdo_entry(fsm);
return;
}
if (!(sdo = ec_slave_get_sdo(fsm->slave, pdo_entry->index))) {
EC_ERR("Slave %u has no Sdo 0x%04X.\n",
fsm->slave->ring_position, pdo_entry->index);
ec_pdo_entry_clear(pdo_entry);
kfree(pdo_entry);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
if (!(entry = ec_sdo_get_entry(sdo, pdo_entry->subindex))) {
EC_ERR("Slave %u has no Sdo entry 0x%04X:%u.\n",
fsm->slave->ring_position, pdo_entry->index,
pdo_entry->subindex);
ec_pdo_entry_clear(pdo_entry);
kfree(pdo_entry);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
if (ec_pdo_entry_set_name(pdo_entry, entry->description)) {
ec_pdo_entry_clear(pdo_entry);
kfree(pdo_entry);
fsm->state = ec_fsm_coe_map_state_error;
return;
}
if (fsm->slave->master->debug_level) {
@ -489,9 +401,8 @@ void ec_fsm_coe_map_state_pdo_entry(
pdo_entry->bit_length);
}
list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
// next Pdo entry
list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
fsm->pdo_subindex++;
ec_fsm_coe_map_action_next_pdo_entry(fsm);
}

View File

@ -61,8 +61,9 @@ struct ec_fsm_coe_map
ec_slave_t *slave; /**< EtherCAT slave */
ec_sdo_request_t request; /**< Sdo request */
unsigned int sync_index; /**< index of the current sync manager */
ec_sdo_t *sync_sdo; /**< pointer to the sync managers mapping Sdo */
ec_direction_t dir; /**< index of the current sync manager */
ec_sync_t *sync; /**< Pdo sync manager. */
uint16_t sync_sdo_index; /**< Index of the mapping Sdo. */
uint8_t sync_subindices; /**< number of mapped Pdos */
uint16_t sync_subindex; /**< current subindex in mapping Sdo */

View File

@ -60,7 +60,6 @@ void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *);
void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *);
void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *);
void ec_fsm_master_state_sdodict(ec_fsm_master_t *);
void ec_fsm_master_state_pdomap(ec_fsm_master_t *);
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *);
void ec_fsm_master_state_end(ec_fsm_master_t *);
void ec_fsm_master_state_error(ec_fsm_master_t *);
@ -88,7 +87,8 @@ void ec_fsm_master_init(ec_fsm_master_t *fsm, /**< master state machine */
// init sub-state-machines
ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram);
ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram);
ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram,
&fsm->fsm_slave_config, &fsm->fsm_coe_map);
ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
@ -387,7 +387,7 @@ int ec_fsm_master_action_process_sdo(
request->state = EC_REQUEST_IN_PROGRESS;
up(&master->sdo_sem);
slave = request->entry->sdo->slave;
slave = request->slave;
if (slave->current_state == EC_SLAVE_STATE_INIT ||
slave->online_state == EC_SLAVE_OFFLINE ||
slave->error_flag) {
@ -526,29 +526,6 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm
return;
}
// check, if slaves have their Pdo mapping to be read.
list_for_each_entry(slave, &master->slaves, list) {
if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)
|| slave->pdo_mapping_fetched
|| !slave->sdo_dictionary_fetched
|| slave->current_state == EC_SLAVE_STATE_INIT
|| slave->online_state == EC_SLAVE_OFFLINE) continue;
if (master->debug_level) {
EC_DBG("Fetching Pdo mapping from slave %i via CoE.\n",
slave->ring_position);
}
slave->pdo_mapping_fetched = 1;
// start fetching Pdo mapping
fsm->idle = 0;
fsm->state = ec_fsm_master_state_pdomap;
ec_fsm_coe_map_start(&fsm->fsm_coe_map, slave);
ec_fsm_coe_map_exec(&fsm->fsm_coe_map); // execute immediately
return;
}
// check for pending EEPROM write operations.
if (ec_fsm_master_action_process_eeprom(fsm))
return; // EEPROM write request found
@ -1039,28 +1016,7 @@ void ec_fsm_master_state_sdodict(ec_fsm_master_t *fsm /**< master state machine
/*****************************************************************************/
/**
* Scan the Pdo mapping of a slave.
*/
void ec_fsm_master_state_pdomap(
ec_fsm_master_t *fsm /**< master state machine */
)
{
if (ec_fsm_coe_map_exec(&fsm->fsm_coe_map)) return;
if (!ec_fsm_coe_map_success(&fsm->fsm_coe_map)) {
fsm->state = ec_fsm_master_state_error;
return;
}
// fetching of Pdo mapping finished
fsm->state = ec_fsm_master_state_end;
}
/*****************************************************************************/
/**
Master state: Sdo REQUEST.
Master state: SDO REQUEST.
*/
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *fsm /**< master state machine */)

View File

@ -54,19 +54,31 @@ void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
/*****************************************************************************/
/** Constructor.
*/
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, /**< slave state machine */
ec_datagram_t *datagram /**< datagram structure to use */
void ec_fsm_slave_scan_init(
ec_fsm_slave_scan_t *fsm, /**< Slave scanning state machine. */
ec_datagram_t *datagram, /**< Datagram to use. */
ec_fsm_slave_config_t *fsm_slave_config, /**< Slave configuration
state machine to use. */
ec_fsm_coe_map_t *fsm_coe_map /**< Pdo mapping state machine to use.
*/
)
{
fsm->datagram = datagram;
fsm->fsm_slave_config = fsm_slave_config;
fsm->fsm_coe_map = fsm_coe_map;
// init sub state machines
ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
@ -556,7 +568,11 @@ void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave sta
}
}
fsm->state = ec_fsm_slave_scan_state_end;
if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
ec_fsm_slave_scan_enter_preop(fsm);
} else {
fsm->state = ec_fsm_slave_scan_state_end;
}
return;
end:
@ -565,6 +581,82 @@ end:
fsm->state = ec_fsm_slave_scan_state_error;
}
/*****************************************************************************/
void ec_fsm_slave_scan_enter_preop(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
ec_slave_t *slave = fsm->slave;
if ((slave->current_state & EC_SLAVE_STATE_MASK) < EC_SLAVE_STATE_PREOP) {
if (slave->master->debug_level)
EC_DBG("Slave %u is not in the state to do mailbox com, setting"
" to PREOP.\n", slave->ring_position);
fsm->state = ec_fsm_slave_scan_state_preop;
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
ec_fsm_slave_config_start(fsm->fsm_slave_config, slave);
ec_fsm_slave_config_exec(fsm->fsm_slave_config);
} else {
ec_fsm_slave_scan_enter_pdos(fsm);
}
}
/*****************************************************************************/
/** Slave scan state: PREOP.
*/
void ec_fsm_slave_scan_state_preop(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
if (ec_fsm_slave_config_exec(fsm->fsm_slave_config))
return;
if (!ec_fsm_slave_config_success(fsm->fsm_slave_config)) {
fsm->state = ec_fsm_slave_scan_state_error;
return;
}
ec_fsm_slave_scan_enter_pdos(fsm);
}
/*****************************************************************************/
void ec_fsm_slave_scan_enter_pdos(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
ec_slave_t *slave = fsm->slave;
if (slave->master->debug_level)
EC_DBG("Scanning Pdo mapping/configuration of slave %u.\n",
slave->ring_position);
fsm->state = ec_fsm_slave_scan_state_pdos;
ec_fsm_coe_map_start(fsm->fsm_coe_map, slave);
ec_fsm_coe_map_exec(fsm->fsm_coe_map); // execute immediately
}
/*****************************************************************************/
/** Slave scan state: PDOS.
*/
void ec_fsm_slave_scan_state_pdos(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
if (ec_fsm_coe_map_exec(fsm->fsm_coe_map))
return;
if (!ec_fsm_coe_map_success(fsm->fsm_coe_map)) {
fsm->state = ec_fsm_slave_scan_state_error;
return;
}
// fetching of Pdo mapping finished
fsm->state = ec_fsm_slave_scan_state_end;
}
/******************************************************************************
* Common state functions
*****************************************************************************/

View File

@ -49,6 +49,7 @@
#include "fsm_sii.h"
#include "fsm_change.h"
#include "fsm_coe.h"
#include "fsm_coe_map.h"
#include "fsm_pdo_mapping.h"
#include "fsm_pdo_config.h"
@ -63,6 +64,9 @@ struct ec_fsm_slave_scan
{
ec_slave_t *slave; /**< Slave the FSM runs on. */
ec_datagram_t *datagram; /**< Datagram used in the state machine. */
ec_fsm_slave_config_t *fsm_slave_config; /**< Slave configuration state
machine to use. */
ec_fsm_coe_map_t *fsm_coe_map; /**< Pdo mapping state machine to use. */
unsigned int retries; /**< Retries on datagram timeout. */
void (*state)(ec_fsm_slave_scan_t *); /**< State function. */
@ -73,7 +77,8 @@ struct ec_fsm_slave_scan
/*****************************************************************************/
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *);
void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *,
ec_fsm_slave_config_t *, ec_fsm_coe_map_t *);
void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *, ec_slave_t *);

View File

@ -154,7 +154,6 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
INIT_LIST_HEAD(&slave->sdo_dictionary);
slave->sdo_dictionary_fetched = 0;
slave->pdo_mapping_fetched = 0;
slave->jiffies_preop = 0;
for (i = 0; i < 4; i++) {

View File

@ -53,6 +53,15 @@
/*****************************************************************************/
/** Slave state mask.
*
* Apply this mask to a slave state byte to get the slave state without
* the error flag.
*/
#define EC_SLAVE_STATE_MASK 0x0F
/*****************************************************************************/
/** State of an EtherCAT slave.
*/
typedef enum {
@ -156,8 +165,6 @@ struct ec_slave
struct list_head sdo_dictionary; /**< Sdo dictionary list */
uint8_t sdo_dictionary_fetched; /**< dictionary has been fetched */
unsigned long jiffies_preop; /**< time, the slave went to PREOP */
uint8_t pdo_mapping_fetched; /**< Pdo mapping has been fetched */
};
/*****************************************************************************/