Reading of Pdo mapping via CoE during scan.
This commit is contained in:
parent
5e22bcec73
commit
397b5bf0cc
3
NEWS
3
NEWS
|
|
@ -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
6
TODO
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
Loading…
Reference in New Issue