--- a/master/master.c Mon Jun 26 16:07:07 2006 +0000
+++ b/master/master.c Wed Aug 02 12:25:25 2006 +0000
@@ -50,12 +50,12 @@
#include "slave.h"
#include "types.h"
#include "device.h"
-#include "command.h"
+#include "datagram.h"
#include "ethernet.h"
/*****************************************************************************/
-void ec_master_freerun(void *);
+void ec_master_idle_run(void *);
void ec_master_eoe_run(unsigned long);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
@@ -68,11 +68,13 @@
EC_SYSFS_READ_ATTR(slave_count);
EC_SYSFS_READ_ATTR(mode);
EC_SYSFS_READ_WRITE_ATTR(eeprom_write_enable);
+EC_SYSFS_READ_WRITE_ATTR(debug_level);
static struct attribute *ec_def_attrs[] = {
&attr_slave_count,
&attr_mode,
&attr_eeprom_write_enable,
+ &attr_debug_level,
NULL,
};
@@ -98,7 +100,7 @@
int ec_master_init(ec_master_t *master, /**< EtherCAT master */
unsigned int index, /**< master index */
- unsigned int eoe_devices /**< number of EoE devices */
+ unsigned int eoeif_count /**< number of EoE interfaces */
)
{
ec_eoe_t *eoe, *next_eoe;
@@ -110,11 +112,11 @@
master->device = NULL;
master->reserved = 0;
INIT_LIST_HEAD(&master->slaves);
- INIT_LIST_HEAD(&master->command_queue);
+ INIT_LIST_HEAD(&master->datagram_queue);
INIT_LIST_HEAD(&master->domains);
INIT_LIST_HEAD(&master->eoe_handlers);
- ec_command_init(&master->simple_command);
- INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master);
+ ec_datagram_init(&master->simple_datagram);
+ 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;
@@ -128,7 +130,7 @@
}
// create EoE handlers
- for (i = 0; i < eoe_devices; i++) {
+ for (i = 0; i < eoeif_count; i++) {
if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate EoE-Object.\n");
goto out_clear_eoe;
@@ -171,7 +173,7 @@
/**
Master destructor.
- Removes all pending commands, clears the slave list, clears all domains
+ Removes all pending datagrams, clears the slave list, clears all domains
and frees the device.
*/
@@ -184,7 +186,7 @@
ec_master_reset(master);
ec_fsm_clear(&master->fsm);
- ec_command_clear(&master->simple_command);
+ ec_datagram_clear(&master->simple_datagram);
destroy_workqueue(master->workqueue);
// clear EoE objects
@@ -212,17 +214,18 @@
void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
{
- ec_command_t *command, *next_c;
+ ec_datagram_t *datagram, *next_c;
ec_domain_t *domain, *next_d;
ec_master_eoe_stop(master);
- ec_master_freerun_stop(master);
+ ec_master_idle_stop(master);
ec_master_clear_slaves(master);
- // empty command queue
- list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
- list_del_init(&command->queue);
- command->state = EC_CMD_ERROR;
+ // empty datagram queue
+ list_for_each_entry_safe(datagram, next_c,
+ &master->datagram_queue, queue) {
+ list_del_init(&datagram->queue);
+ datagram->state = EC_CMD_ERROR;
}
// clear domains
@@ -232,7 +235,7 @@
kobject_put(&domain->kobj);
}
- master->command_index = 0;
+ master->datagram_index = 0;
master->debug_level = 0;
master->timeout = 500; // 500us
@@ -242,7 +245,7 @@
master->stats.unmatched = 0;
master->stats.t_last = 0;
- master->mode = EC_MASTER_MODE_IDLE;
+ master->mode = EC_MASTER_MODE_ORPHANED;
master->request_cb = NULL;
master->release_cb = NULL;
@@ -274,101 +277,101 @@
/*****************************************************************************/
/**
- Places a command in the command queue.
-*/
-
-void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */
- ec_command_t *command /**< command */
- )
-{
- ec_command_t *queued_command;
-
- // check, if the command is already queued
- list_for_each_entry(queued_command, &master->command_queue, queue) {
- if (queued_command == command) {
- command->state = EC_CMD_QUEUED;
+ Places a datagram in the datagram queue.
+*/
+
+void ec_master_queue_datagram(ec_master_t *master, /**< EtherCAT master */
+ ec_datagram_t *datagram /**< datagram */
+ )
+{
+ ec_datagram_t *queued_datagram;
+
+ // check, if the datagram is already queued
+ list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
+ if (queued_datagram == datagram) {
+ datagram->state = EC_CMD_QUEUED;
if (unlikely(master->debug_level))
- EC_WARN("command already queued.\n");
+ EC_WARN("datagram already queued.\n");
return;
}
}
- list_add_tail(&command->queue, &master->command_queue);
- command->state = EC_CMD_QUEUED;
-}
-
-/*****************************************************************************/
-
-/**
- Sends the commands in the queue.
+ list_add_tail(&datagram->queue, &master->datagram_queue);
+ datagram->state = EC_CMD_QUEUED;
+}
+
+/*****************************************************************************/
+
+/**
+ Sends the datagrams in the queue.
\return 0 in case of success, else < 0
*/
-void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
-{
- ec_command_t *command;
- size_t command_size;
+void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram;
+ size_t datagram_size;
uint8_t *frame_data, *cur_data;
void *follows_word;
cycles_t t_start, t_end;
- unsigned int frame_count, more_commands_waiting;
+ unsigned int frame_count, more_datagrams_waiting;
frame_count = 0;
t_start = get_cycles();
- if (unlikely(master->debug_level > 0))
- EC_DBG("ec_master_send_commands\n");
+ if (unlikely(master->debug_level > 1))
+ EC_DBG("ec_master_send_datagrams\n");
do {
// fetch pointer to transmit socket buffer
frame_data = ec_device_tx_data(master->device);
cur_data = frame_data + EC_FRAME_HEADER_SIZE;
follows_word = NULL;
- more_commands_waiting = 0;
-
- // fill current frame with commands
- list_for_each_entry(command, &master->command_queue, queue) {
- if (command->state != EC_CMD_QUEUED) continue;
-
- // does the current command fit in the frame?
- command_size = EC_COMMAND_HEADER_SIZE + command->data_size
- + EC_COMMAND_FOOTER_SIZE;
- if (cur_data - frame_data + command_size > ETH_DATA_LEN) {
- more_commands_waiting = 1;
+ more_datagrams_waiting = 0;
+
+ // fill current frame with datagrams
+ list_for_each_entry(datagram, &master->datagram_queue, queue) {
+ if (datagram->state != EC_CMD_QUEUED) continue;
+
+ // does the current datagram fit in the frame?
+ datagram_size = EC_DATAGRAM_HEADER_SIZE + datagram->data_size
+ + EC_DATAGRAM_FOOTER_SIZE;
+ if (cur_data - frame_data + datagram_size > ETH_DATA_LEN) {
+ more_datagrams_waiting = 1;
break;
}
- command->state = EC_CMD_SENT;
- command->t_sent = t_start;
- command->index = master->command_index++;
-
- if (unlikely(master->debug_level > 0))
- EC_DBG("adding command 0x%02X\n", command->index);
-
- // set "command following" flag in previous frame
+ datagram->state = EC_CMD_SENT;
+ datagram->t_sent = t_start;
+ datagram->index = master->datagram_index++;
+
+ if (unlikely(master->debug_level > 1))
+ EC_DBG("adding datagram 0x%02X\n", datagram->index);
+
+ // set "datagram following" flag in previous frame
if (follows_word)
EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000);
- // EtherCAT command header
- EC_WRITE_U8 (cur_data, command->type);
- EC_WRITE_U8 (cur_data + 1, command->index);
- EC_WRITE_U32(cur_data + 2, command->address.logical);
- EC_WRITE_U16(cur_data + 6, command->data_size & 0x7FF);
+ // EtherCAT datagram header
+ EC_WRITE_U8 (cur_data, datagram->type);
+ EC_WRITE_U8 (cur_data + 1, datagram->index);
+ EC_WRITE_U32(cur_data + 2, datagram->address.logical);
+ EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF);
EC_WRITE_U16(cur_data + 8, 0x0000);
follows_word = cur_data + 6;
- cur_data += EC_COMMAND_HEADER_SIZE;
-
- // EtherCAT command data
- memcpy(cur_data, command->data, command->data_size);
- cur_data += command->data_size;
-
- // EtherCAT command footer
+ cur_data += EC_DATAGRAM_HEADER_SIZE;
+
+ // EtherCAT datagram data
+ memcpy(cur_data, datagram->data, datagram->data_size);
+ cur_data += datagram->data_size;
+
+ // EtherCAT datagram footer
EC_WRITE_U16(cur_data, 0x0000); // reset working counter
- cur_data += EC_COMMAND_FOOTER_SIZE;
+ cur_data += EC_DATAGRAM_FOOTER_SIZE;
}
if (cur_data - frame_data == EC_FRAME_HEADER_SIZE) {
- if (unlikely(master->debug_level > 0))
+ if (unlikely(master->debug_level > 1))
EC_DBG("nothing to send.\n");
break;
}
@@ -381,19 +384,19 @@
while (cur_data - frame_data < ETH_ZLEN - ETH_HLEN)
EC_WRITE_U8(cur_data++, 0x00);
- if (unlikely(master->debug_level > 0))
+ if (unlikely(master->debug_level > 1))
EC_DBG("frame size: %i\n", cur_data - frame_data);
// send frame
ec_device_send(master->device, cur_data - frame_data);
frame_count++;
}
- while (more_commands_waiting);
-
- if (unlikely(master->debug_level > 0)) {
+ while (more_datagrams_waiting);
+
+ if (unlikely(master->debug_level > 1)) {
t_end = get_cycles();
- EC_DBG("ec_master_send_commands sent %i frames in %ius.\n",
- frame_count, (u32) (t_end - t_start) * 1000 / cpu_khz);
+ EC_DBG("ec_master_send_datagrams sent %i frames in %ius.\n",
+ frame_count, (unsigned int) (t_end - t_start) * 1000 / cpu_khz);
}
}
@@ -411,10 +414,10 @@
)
{
size_t frame_size, data_size;
- uint8_t command_type, command_index;
+ uint8_t datagram_type, datagram_index;
unsigned int cmd_follows, matched;
const uint8_t *cur_data;
- ec_command_t *command;
+ ec_datagram_t *datagram;
if (unlikely(size < EC_FRAME_HEADER_SIZE)) {
master->stats.corrupted++;
@@ -436,64 +439,64 @@
cmd_follows = 1;
while (cmd_follows) {
- // process command header
- command_type = EC_READ_U8 (cur_data);
- command_index = EC_READ_U8 (cur_data + 1);
- data_size = EC_READ_U16(cur_data + 6) & 0x07FF;
- cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000;
- cur_data += EC_COMMAND_HEADER_SIZE;
+ // process datagram header
+ datagram_type = EC_READ_U8 (cur_data);
+ datagram_index = EC_READ_U8 (cur_data + 1);
+ data_size = EC_READ_U16(cur_data + 6) & 0x07FF;
+ cmd_follows = EC_READ_U16(cur_data + 6) & 0x8000;
+ cur_data += EC_DATAGRAM_HEADER_SIZE;
if (unlikely(cur_data - frame_data
- + data_size + EC_COMMAND_FOOTER_SIZE > size)) {
+ + data_size + EC_DATAGRAM_FOOTER_SIZE > size)) {
master->stats.corrupted++;
ec_master_output_stats(master);
return;
}
- // search for matching command in the queue
+ // search for matching datagram in the queue
matched = 0;
- list_for_each_entry(command, &master->command_queue, queue) {
- if (command->state == EC_CMD_SENT
- && command->type == command_type
- && command->index == command_index
- && command->data_size == data_size) {
+ list_for_each_entry(datagram, &master->datagram_queue, queue) {
+ if (datagram->state == EC_CMD_SENT
+ && datagram->type == datagram_type
+ && datagram->index == datagram_index
+ && datagram->data_size == data_size) {
matched = 1;
break;
}
}
- // no matching command was found
+ // no matching datagram was found
if (!matched) {
master->stats.unmatched++;
ec_master_output_stats(master);
- cur_data += data_size + EC_COMMAND_FOOTER_SIZE;
+ cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE;
continue;
}
- // copy received data in the command memory
- memcpy(command->data, cur_data, data_size);
+ // copy received data in the datagram memory
+ memcpy(datagram->data, cur_data, data_size);
cur_data += data_size;
- // set the command's working counter
- command->working_counter = EC_READ_U16(cur_data);
- cur_data += EC_COMMAND_FOOTER_SIZE;
-
- // dequeue the received command
- command->state = EC_CMD_RECEIVED;
- list_del_init(&command->queue);
- }
-}
-
-/*****************************************************************************/
-
-/**
- Sends a single command and waits for its reception.
- If the slave doesn't respond, the command is sent again.
+ // set the datagram's working counter
+ datagram->working_counter = EC_READ_U16(cur_data);
+ cur_data += EC_DATAGRAM_FOOTER_SIZE;
+
+ // dequeue the received datagram
+ datagram->state = EC_CMD_RECEIVED;
+ list_del_init(&datagram->queue);
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ Sends a single datagram and waits for its reception.
+ If the slave doesn't respond, the datagram is sent again.
\return 0 in case of success, else < 0
*/
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */
- ec_command_t *command /**< command */
+ ec_datagram_t *datagram /**< datagram */
)
{
unsigned int response_tries_left;
@@ -502,19 +505,19 @@
while (1)
{
- ec_master_queue_command(master, command);
+ ec_master_queue_datagram(master, datagram);
ecrt_master_sync_io(master);
- if (command->state == EC_CMD_RECEIVED) {
- if (likely(command->working_counter))
+ if (datagram->state == EC_CMD_RECEIVED) {
+ if (likely(datagram->working_counter))
return 0;
}
- else if (command->state == EC_CMD_TIMEOUT) {
+ else if (datagram->state == EC_CMD_TIMEOUT) {
EC_ERR("Simple-IO TIMEOUT!\n");
return -1;
}
- else if (command->state == EC_CMD_ERROR) {
- EC_ERR("Simple-IO command error!\n");
+ else if (datagram->state == EC_CMD_ERROR) {
+ EC_ERR("Simple-IO datagram error!\n");
return -1;
}
@@ -540,7 +543,7 @@
{
ec_slave_t *slave;
ec_slave_ident_t *ident;
- ec_command_t *command;
+ ec_datagram_t *datagram;
unsigned int i;
uint16_t coupler_index, coupler_subindex;
uint16_t reverse_coupler_index, current_coupler_index;
@@ -550,12 +553,12 @@
return -1;
}
- command = &master->simple_command;
+ datagram = &master->simple_datagram;
// determine number of slaves on bus
- if (ec_command_brd(command, 0x0000, 4)) return -1;
- if (unlikely(ec_master_simple_io(master, command))) return -1;
- master->slave_count = command->working_counter;
+ if (ec_datagram_brd(datagram, 0x0000, 4)) return -1;
+ if (unlikely(ec_master_simple_io(master, datagram))) return -1;
+ master->slave_count = datagram->working_counter;
EC_INFO("Found %i slaves on bus.\n", master->slave_count);
if (!master->slave_count) return 0;
@@ -588,10 +591,10 @@
list_for_each_entry(slave, &master->slaves, list) {
// write station address
- if (ec_command_apwr(command, slave->ring_position, 0x0010,
+ if (ec_datagram_apwr(datagram, slave->ring_position, 0x0010,
sizeof(uint16_t))) goto out_free;
- EC_WRITE_U16(command->data, slave->station_address);
- if (unlikely(ec_master_simple_io(master, command))) {
+ EC_WRITE_U16(datagram->data, slave->station_address);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Writing station address failed on slave %i!\n",
slave->ring_position);
goto out_free;
@@ -650,7 +653,7 @@
if (unlikely((u32) (t_now - master->stats.t_last) / cpu_khz > 1000)) {
if (master->stats.timeouts) {
- EC_WARN("%i commands TIMED OUT!\n", master->stats.timeouts);
+ EC_WARN("%i datagrams TIMED OUT!\n", master->stats.timeouts);
master->stats.timeouts = 0;
}
if (master->stats.delayed) {
@@ -662,7 +665,7 @@
master->stats.corrupted = 0;
}
if (master->stats.unmatched) {
- EC_WARN("%i command(s) UNMATCHED!\n", master->stats.unmatched);
+ EC_WARN("%i datagram(s) UNMATCHED!\n", master->stats.unmatched);
master->stats.unmatched = 0;
}
master->stats.t_last = t_now;
@@ -672,41 +675,43 @@
/*****************************************************************************/
/**
- Starts the Free-Run mode.
-*/
-
-void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
-{
- if (master->mode == EC_MASTER_MODE_FREERUN) return;
+ 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_RUNNING) {
- EC_ERR("ec_master_freerun_start: Master already running!\n");
+ EC_ERR("ec_master_idle_start: Master already running!\n");
return;
}
- EC_INFO("Starting Free-Run mode.\n");
-
- master->mode = EC_MASTER_MODE_FREERUN;
+ EC_INFO("Starting Idle mode.\n");
+
+ master->mode = EC_MASTER_MODE_IDLE;
ec_fsm_reset(&master->fsm);
- queue_delayed_work(master->workqueue, &master->freerun_work, 1);
-}
-
-/*****************************************************************************/
-
-/**
- Stops the Free-Run mode.
-*/
-
-void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
-{
- if (master->mode != EC_MASTER_MODE_FREERUN) return;
+ 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 Free-Run mode.\n");
- master->mode = EC_MASTER_MODE_IDLE;
-
- if (!cancel_delayed_work(&master->freerun_work)) {
+ 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);
}
@@ -716,10 +721,10 @@
/*****************************************************************************/
/**
- Free-Run mode function.
-*/
-
-void ec_master_freerun(void *data /**< master pointer */)
+ Idle mode function.
+*/
+
+void ec_master_idle_run(void *data /**< master pointer */)
{
ec_master_t *master = (ec_master_t *) data;
@@ -736,8 +741,8 @@
// release master lock
spin_unlock_bh(&master->internal_lock);
- if (master->mode == EC_MASTER_MODE_FREERUN)
- queue_delayed_work(master->workqueue, &master->freerun_work, 1);
+ if (master->mode == EC_MASTER_MODE_IDLE)
+ queue_delayed_work(master->workqueue, &master->idle_work, 1);
}
/*****************************************************************************/
@@ -771,11 +776,24 @@
*/
void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */
+ const ec_slave_t *slave, /**< EtherCAT slave */
uint8_t *data /**> configuration memory */
)
{
+ size_t sync_size;
+
+ sync_size = ec_slave_calc_eeprom_sync_size(slave, sync);
+
+ if (slave->master->debug_level) {
+ EC_INFO("Slave %i, sync manager %i:\n", slave->ring_position,
+ sync->index);
+ EC_INFO(" Address: 0x%04X\n", sync->physical_start_address);
+ EC_INFO(" Size: %i\n", sync_size);
+ EC_INFO(" Control: 0x%02X\n", sync->control_register);
+ }
+
EC_WRITE_U16(data, sync->physical_start_address);
- EC_WRITE_U16(data + 2, sync->length);
+ EC_WRITE_U16(data + 2, sync_size);
EC_WRITE_U8 (data + 4, sync->control_register);
EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
EC_WRITE_U16(data + 6, sync->enable ? 0x0001 : 0x0000); // enable
@@ -827,14 +845,20 @@
}
else if (attr == &attr_mode) {
switch (master->mode) {
+ case EC_MASTER_MODE_ORPHANED:
+ return sprintf(buffer, "ORPHANED\n");
case EC_MASTER_MODE_IDLE:
return sprintf(buffer, "IDLE\n");
- case EC_MASTER_MODE_FREERUN:
- return sprintf(buffer, "FREERUN\n");
case EC_MASTER_MODE_RUNNING:
return sprintf(buffer, "RUNNING\n");
}
}
+ else if (attr == &attr_debug_level) {
+ return sprintf(buffer, "%i\n", master->debug_level);
+ }
+ else if (attr == &attr_eeprom_write_enable) {
+ return sprintf(buffer, "%i\n", master->eeprom_write_enable);
+ }
return 0;
}
@@ -873,6 +897,24 @@
EC_INFO("Slave EEPROM writing disabled.\n");
}
}
+ else if (attr == &attr_debug_level) {
+ if (!strcmp(buffer, "0\n")) {
+ master->debug_level = 0;
+ }
+ else if (!strcmp(buffer, "1\n")) {
+ master->debug_level = 1;
+ }
+ else if (!strcmp(buffer, "2\n")) {
+ master->debug_level = 2;
+ }
+ else {
+ EC_ERR("Invalid debug level value!\n");
+ return -EINVAL;
+ }
+
+ EC_INFO("Master debug level set to %i.\n", master->debug_level);
+ return size;
+ }
return -EINVAL;
}
@@ -914,14 +956,14 @@
else {
slave->requested_state = EC_SLAVE_STATE_INIT;
}
- slave->state_error = 0;
+ slave->error_flag = 0;
break;
}
if (!found) {
EC_WARN("No EoE handler for slave %i!\n", slave->ring_position);
slave->requested_state = EC_SLAVE_STATE_INIT;
- slave->state_error = 0;
+ slave->error_flag = 0;
}
}
@@ -959,7 +1001,7 @@
list_for_each_entry(eoe, &master->eoe_handlers, list) {
if (eoe->slave) {
eoe->slave->requested_state = EC_SLAVE_STATE_INIT;
- eoe->slave->state_error = 0;
+ eoe->slave->error_flag = 0;
eoe->slave = NULL;
}
}
@@ -989,7 +1031,7 @@
if (master->request_cb(master->cb_data))
goto queue_timer;
}
- else if (master->mode == EC_MASTER_MODE_FREERUN) {
+ else if (master->mode == EC_MASTER_MODE_IDLE) {
spin_lock(&master->internal_lock);
}
else
@@ -1006,7 +1048,7 @@
if (master->mode == EC_MASTER_MODE_RUNNING) {
master->release_cb(master->cb_data);
}
- else if (master->mode == EC_MASTER_MODE_FREERUN) {
+ else if (master->mode == EC_MASTER_MODE_IDLE) {
spin_unlock(&master->internal_lock);
}
@@ -1075,7 +1117,7 @@
{
unsigned int j;
ec_slave_t *slave;
- ec_command_t *command;
+ ec_datagram_t *datagram;
const ec_sync_t *sync;
const ec_slave_type_t *type;
const ec_fmmu_t *fmmu;
@@ -1083,7 +1125,7 @@
ec_domain_t *domain;
ec_eeprom_sync_t *eeprom_sync, mbox_sync;
- command = &master->simple_command;
+ datagram = &master->simple_datagram;
// allocate all domains
domain_offset = 0;
@@ -1112,11 +1154,12 @@
// reset FMMUs
if (slave->base_fmmu_count) {
- if (ec_command_npwr(command, slave->station_address, 0x0600,
- EC_FMMU_SIZE * slave->base_fmmu_count))
+ if (ec_datagram_npwr(datagram, slave->station_address, 0x0600,
+ EC_FMMU_SIZE * slave->base_fmmu_count))
return -1;
- memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
- if (unlikely(ec_master_simple_io(master, command))) {
+ memset(datagram->data, 0x00,
+ EC_FMMU_SIZE * slave->base_fmmu_count);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Resetting FMMUs failed on slave %i!\n",
slave->ring_position);
return -1;
@@ -1125,11 +1168,12 @@
// reset sync managers
if (slave->base_sync_count) {
- if (ec_command_npwr(command, slave->station_address, 0x0800,
+ if (ec_datagram_npwr(datagram, slave->station_address, 0x0800,
EC_SYNC_SIZE * slave->base_sync_count))
return -1;
- memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
- if (unlikely(ec_master_simple_io(master, command))) {
+ memset(datagram->data, 0x00,
+ EC_SYNC_SIZE * slave->base_sync_count);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Resetting sync managers failed on slave %i!\n",
slave->ring_position);
return -1;
@@ -1137,68 +1181,67 @@
}
// configure sync managers
- if (type) { // known slave type, take type's SM information
+
+ // does the slave provide sync manager information?
+ if (!list_empty(&slave->eeprom_syncs)) {
+ list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
+ if (ec_datagram_npwr(datagram, slave->station_address,
+ 0x800 + eeprom_sync->index *
+ EC_SYNC_SIZE,
+ EC_SYNC_SIZE)) return -1;
+ ec_eeprom_sync_config(eeprom_sync, slave, datagram->data);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
+ EC_ERR("Setting sync manager %i failed on slave %i!\n",
+ eeprom_sync->index, slave->ring_position);
+ return -1;
+ }
+ }
+ }
+
+ else if (type) { // known slave type, take type's SM information
for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
sync = type->sync_managers[j];
- if (ec_command_npwr(command, slave->station_address,
- 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
+ if (ec_datagram_npwr(datagram, slave->station_address,
+ 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
return -1;
- ec_sync_config(sync, slave, command->data);
- if (unlikely(ec_master_simple_io(master, command))) {
+ ec_sync_config(sync, slave, datagram->data);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Setting sync manager %i failed on slave %i!\n",
j, slave->ring_position);
return -1;
}
}
}
- else if (slave->sii_mailbox_protocols) { // unknown type, but mailbox
- // does the device supply SM configurations in its EEPROM?
- if (!list_empty(&slave->eeprom_syncs)) {
- list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
- EC_INFO("Sync manager %i...\n", eeprom_sync->index);
- if (ec_command_npwr(command, slave->station_address,
- 0x800 + eeprom_sync->index *
- EC_SYNC_SIZE,
- EC_SYNC_SIZE)) return -1;
- ec_eeprom_sync_config(eeprom_sync, command->data);
- if (unlikely(ec_master_simple_io(master, command))) {
- EC_ERR("Setting sync manager %i failed on slave %i!\n",
- eeprom_sync->index, slave->ring_position);
- return -1;
- }
- }
+
+ // no sync manager information; guess mailbox settings
+ else if (slave->sii_mailbox_protocols) {
+ mbox_sync.physical_start_address =
+ slave->sii_rx_mailbox_offset;
+ mbox_sync.length = slave->sii_rx_mailbox_size;
+ mbox_sync.control_register = 0x26;
+ mbox_sync.enable = 1;
+ if (ec_datagram_npwr(datagram, slave->station_address,
+ 0x800,EC_SYNC_SIZE)) return -1;
+ ec_eeprom_sync_config(&mbox_sync, slave, datagram->data);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
+ EC_ERR("Setting sync manager 0 failed on slave %i!\n",
+ slave->ring_position);
+ return -1;
}
- else { // no sync manager information; guess mailbox settings
- mbox_sync.physical_start_address =
- slave->sii_rx_mailbox_offset;
- mbox_sync.length = slave->sii_rx_mailbox_size;
- mbox_sync.control_register = 0x26;
- mbox_sync.enable = 1;
- if (ec_command_npwr(command, slave->station_address,
- 0x800,EC_SYNC_SIZE)) return -1;
- ec_eeprom_sync_config(&mbox_sync, command->data);
- if (unlikely(ec_master_simple_io(master, command))) {
- EC_ERR("Setting sync manager 0 failed on slave %i!\n",
- slave->ring_position);
- return -1;
- }
-
- mbox_sync.physical_start_address =
- slave->sii_tx_mailbox_offset;
- mbox_sync.length = slave->sii_tx_mailbox_size;
- mbox_sync.control_register = 0x22;
- mbox_sync.enable = 1;
- if (ec_command_npwr(command, slave->station_address,
- 0x808, EC_SYNC_SIZE)) return -1;
- ec_eeprom_sync_config(&mbox_sync, command->data);
- if (unlikely(ec_master_simple_io(master, command))) {
+
+ mbox_sync.physical_start_address =
+ slave->sii_tx_mailbox_offset;
+ mbox_sync.length = slave->sii_tx_mailbox_size;
+ mbox_sync.control_register = 0x22;
+ mbox_sync.enable = 1;
+ if (ec_datagram_npwr(datagram, slave->station_address,
+ 0x808, EC_SYNC_SIZE)) return -1;
+ ec_eeprom_sync_config(&mbox_sync, slave, datagram->data);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Setting sync manager 1 failed on slave %i!\n",
slave->ring_position);
return -1;
- }
- }
- EC_INFO("Mailbox configured for unknown slave %i\n",
- slave->ring_position);
+ }
}
// change state to PREOP
@@ -1218,11 +1261,11 @@
// configure FMMUs
for (j = 0; j < slave->fmmu_count; j++) {
fmmu = &slave->fmmus[j];
- if (ec_command_npwr(command, slave->station_address,
- 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
+ if (ec_datagram_npwr(datagram, slave->station_address,
+ 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
return -1;
- ec_fmmu_config(fmmu, slave, command->data);
- if (unlikely(ec_master_simple_io(master, command))) {
+ ec_fmmu_config(fmmu, slave, datagram->data);
+ if (unlikely(ec_master_simple_io(master, datagram))) {
EC_ERR("Setting FMMU %i failed on slave %i!\n",
j, slave->ring_position);
return -1;
@@ -1288,17 +1331,17 @@
/*****************************************************************************/
/**
- Sends queued commands and waits for their reception.
+ Sends queued datagrams and waits for their reception.
\ingroup RealtimeInterface
*/
void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
{
- ec_command_t *command, *n;
- unsigned int commands_sent;
+ ec_datagram_t *datagram, *n;
+ unsigned int datagrams_sent;
cycles_t t_start, t_end, t_timeout;
- // send commands
+ // send datagrams
ecrt_master_async_send(master);
t_start = get_cycles(); // measure io time
@@ -1310,23 +1353,23 @@
t_end = get_cycles(); // take current time
if (t_end - t_start >= t_timeout) break; // timeout!
- commands_sent = 0;
- list_for_each_entry_safe(command, n, &master->command_queue, queue) {
- if (command->state == EC_CMD_RECEIVED)
- list_del_init(&command->queue);
- else if (command->state == EC_CMD_SENT)
- commands_sent++;
- }
-
- if (!commands_sent) break;
- }
-
- // timeout; dequeue all commands
- list_for_each_entry_safe(command, n, &master->command_queue, queue) {
- switch (command->state) {
+ datagrams_sent = 0;
+ list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
+ if (datagram->state == EC_CMD_RECEIVED)
+ list_del_init(&datagram->queue);
+ else if (datagram->state == EC_CMD_SENT)
+ datagrams_sent++;
+ }
+
+ if (!datagrams_sent) break;
+ }
+
+ // timeout; dequeue all datagrams
+ list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
+ switch (datagram->state) {
case EC_CMD_SENT:
case EC_CMD_QUEUED:
- command->state = EC_CMD_TIMEOUT;
+ datagram->state = EC_CMD_TIMEOUT;
master->stats.timeouts++;
ec_master_output_stats(master);
break;
@@ -1337,26 +1380,26 @@
default:
break;
}
- list_del_init(&command->queue);
- }
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous sending of commands.
+ list_del_init(&datagram->queue);
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous sending of datagrams.
\ingroup RealtimeInterface
*/
void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */)
{
- ec_command_t *command, *n;
+ ec_datagram_t *datagram, *n;
if (unlikely(!master->device->link_state)) {
- // link is down, no command can be sent
- list_for_each_entry_safe(command, n, &master->command_queue, queue) {
- command->state = EC_CMD_ERROR;
- list_del_init(&command->queue);
+ // link is down, no datagram can be sent
+ list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
+ datagram->state = EC_CMD_ERROR;
+ list_del_init(&datagram->queue);
}
// query link state
@@ -1365,19 +1408,19 @@
}
// send frames
- ec_master_send_commands(master);
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous receiving of commands.
+ ec_master_send_datagrams(master);
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous receiving of datagrams.
\ingroup RealtimeInterface
*/
void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
{
- ec_command_t *command, *next;
+ ec_datagram_t *datagram, *next;
cycles_t t_received, t_timeout;
ec_device_call_isr(master->device);
@@ -1385,18 +1428,19 @@
t_received = get_cycles();
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
- // dequeue all received commands
- list_for_each_entry_safe(command, next, &master->command_queue, queue)
- if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue);
-
- // dequeue all commands that timed out
- list_for_each_entry_safe(command, next, &master->command_queue, queue) {
- switch (command->state) {
+ // dequeue all received datagrams
+ list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue)
+ if (datagram->state == EC_CMD_RECEIVED)
+ list_del_init(&datagram->queue);
+
+ // dequeue all datagrams that timed out
+ list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
+ switch (datagram->state) {
case EC_CMD_SENT:
case EC_CMD_QUEUED:
- if (t_received - command->t_sent > t_timeout) {
- list_del_init(&command->queue);
- command->state = EC_CMD_TIMEOUT;
+ if (t_received - datagram->t_sent > t_timeout) {
+ list_del_init(&datagram->queue);
+ datagram->state = EC_CMD_TIMEOUT;
master->stats.timeouts++;
ec_master_output_stats(master);
}
@@ -1411,7 +1455,7 @@
/**
Prepares synchronous IO.
- Queues all domain commands and sends them. Then waits a certain time, so
+ Queues all domain datagrams and sends them. Then waits a certain time, so
that ecrt_master_sasync_receive() can be called securely.
\ingroup RealtimeInterface
*/
@@ -1421,7 +1465,7 @@
ec_domain_t *domain;
cycles_t t_start, t_end, t_timeout;
- // queue commands of all domains
+ // queue datagrams of all domains
list_for_each_entry(domain, &master->domains, list)
ecrt_domain_queue(domain);