--- a/master/master.c Thu Mar 08 18:15:25 2007 +0000
+++ b/master/master.c Fri Mar 09 10:24:50 2007 +0000
@@ -1384,215 +1384,24 @@
}
}
-/******************************************************************************
- * Realtime interface
- *****************************************************************************/
-
-/**
- Creates a domain.
- \return pointer to new domain on success, else NULL
- \ingroup RealtimeInterface
-*/
-
-ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
-{
- ec_domain_t *domain, *last_domain;
- unsigned int index;
-
- if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
- EC_ERR("Error allocating domain memory!\n");
- return NULL;
- }
-
- if (list_empty(&master->domains)) index = 0;
- else {
- last_domain = list_entry(master->domains.prev, ec_domain_t, list);
- index = last_domain->index + 1;
- }
-
- if (ec_domain_init(domain, master, index)) {
- EC_ERR("Failed to init domain.\n");
- return NULL;
- }
-
- list_add_tail(&domain->list, &master->domains);
-
- return domain;
-}
-
-/*****************************************************************************/
-
-/**
- Configures all slaves and leads them to the OP state.
- Does the complete configuration and activation for all slaves. Sets sync
- managers and FMMUs, and does the appropriate transitions, until the slave
- is operational.
- \return 0 in case of success, else < 0
- \ingroup RealtimeInterface
-*/
-
-int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
-{
- uint32_t domain_offset;
- ec_domain_t *domain;
- ec_fsm_slave_t fsm_slave;
- ec_slave_t *slave;
-
- // allocate all domains
- domain_offset = 0;
- list_for_each_entry(domain, &master->domains, list) {
- if (ec_domain_alloc(domain, domain_offset)) {
- EC_ERR("Failed to allocate domain %X!\n", (u32) domain);
- return -1;
- }
- domain_offset += domain->data_size;
- }
-
- ec_fsm_slave_init(&fsm_slave, &master->fsm_datagram);
-
- // configure all slaves
- list_for_each_entry(slave, &master->slaves, list) {
- ec_fsm_slave_start_conf(&fsm_slave, slave);
- while (ec_fsm_slave_exec(&fsm_slave)) {
- ec_master_queue_datagram(master, &master->fsm_datagram);
- ec_master_sync_io(master);
- }
-
- if (!ec_fsm_slave_success(&fsm_slave)) {
- ec_fsm_slave_clear(&fsm_slave);
- EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
- return -1;
- }
- }
-
- ec_fsm_slave_clear(&fsm_slave);
- ec_master_prepare(master); // prepare asynchronous IO
-
- if (master->debug_level)
- EC_DBG("FSM datagram is %x.\n", (unsigned int) &master->fsm_datagram);
-
- if (ec_master_thread_start(master)) {
- EC_ERR("Failed to start master thread!\n");
- return -1;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
- Sends queued datagrams and waits for their reception.
-*/
-
-void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram;
- unsigned int datagrams_sent;
-
- // send all datagrams
- ecrt_master_send(master);
-
- while (1) { // active waiting
- schedule(); // schedule other processes while waiting.
- ecrt_master_receive(master); // receive and dequeue datagrams
-
- // count number of datagrams still waiting for response
- datagrams_sent = 0;
- list_for_each_entry(datagram, &master->datagram_queue, queue) {
- // there may be another process that queued commands
- // in the meantime.
- if (datagram->state == EC_DATAGRAM_QUEUED) continue;
- datagrams_sent++;
- }
-
- // abort loop if there are no more datagrams marked as sent.
- if (!datagrams_sent) break;
- }
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous sending of datagrams.
- \ingroup RealtimeInterface
-*/
-
-void ecrt_master_send(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram, *n;
-
- if (master->injection_seq_rt != master->injection_seq_fsm) {
- // inject datagram produced by master FSM
- ec_master_queue_datagram(master, &master->fsm_datagram);
- master->injection_seq_rt = master->injection_seq_fsm;
- }
-
- if (unlikely(!master->main_device.link_state)) {
- // link is down, no datagram can be sent
- list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
- datagram->state = EC_DATAGRAM_ERROR;
- list_del_init(&datagram->queue);
- }
-
- // query link state
- ec_device_poll(&master->main_device);
- return;
- }
-
- // send frames
- ec_master_send_datagrams(master);
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous receiving of datagrams.
- \ingroup RealtimeInterface
-*/
-
-void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram, *next;
- cycles_t cycles_timeout;
-
- // receive datagrams
- ec_device_poll(&master->main_device);
-
- cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
-
- // dequeue all datagrams that timed out
- list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
- if (datagram->state != EC_DATAGRAM_SENT) continue;
-
- if (master->main_device.cycles_poll - datagram->cycles_sent
- > cycles_timeout) {
- list_del_init(&datagram->queue);
- datagram->state = EC_DATAGRAM_TIMED_OUT;
- master->stats.timeouts++;
- ec_master_output_stats(master);
- }
- }
-}
-
-/*****************************************************************************/
-
-/**
- Translates an ASCII coded bus-address to a slave pointer.
- These are the valid addressing schemes:
- - \a "X" = the X. slave on the bus,
- - \a "X:Y" = the Y. slave after the X. branch (bus coupler),
- - \a "#X" = the slave with alias X,
- - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X.
- X and Y are zero-based indices and may be provided in hexadecimal or octal
- notation (with respective prefix).
- \return pointer to the slave on success, else NULL
- \ingroup RealtimeInterface
-*/
-
-ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
- const char *address /**< address string */
- )
+/*****************************************************************************/
+
+/**
+ * Translates an ASCII coded bus-address to a slave pointer.
+ * These are the valid addressing schemes:
+ * - \a "X" = the X. slave on the bus (ring position),
+ * - \a "X:Y" = the Y. slave after the X. branch (bus coupler),
+ * - \a "#X" = the slave with alias X,
+ * - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X.
+ * X and Y are zero-based indices and may be provided in hexadecimal or octal
+ * notation (with respective prefix).
+ * \return pointer to the slave on success, else NULL
+ */
+
+ec_slave_t *ec_master_parse_slave_address(
+ const ec_master_t *master, /**< EtherCAT master */
+ const char *address /**< address string */
+ )
{
unsigned long first, second;
char *remainder, *remainder2;
@@ -1685,6 +1494,224 @@
return NULL;
}
+
+/******************************************************************************
+ * Realtime interface
+ *****************************************************************************/
+
+/**
+ Creates a domain.
+ \return pointer to new domain on success, else NULL
+ \ingroup RealtimeInterface
+*/
+
+ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
+{
+ ec_domain_t *domain, *last_domain;
+ unsigned int index;
+
+ if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
+ EC_ERR("Error allocating domain memory!\n");
+ return NULL;
+ }
+
+ if (list_empty(&master->domains)) index = 0;
+ else {
+ last_domain = list_entry(master->domains.prev, ec_domain_t, list);
+ index = last_domain->index + 1;
+ }
+
+ if (ec_domain_init(domain, master, index)) {
+ EC_ERR("Failed to init domain.\n");
+ return NULL;
+ }
+
+ list_add_tail(&domain->list, &master->domains);
+
+ return domain;
+}
+
+/*****************************************************************************/
+
+/**
+ Configures all slaves and leads them to the OP state.
+ Does the complete configuration and activation for all slaves. Sets sync
+ managers and FMMUs, and does the appropriate transitions, until the slave
+ is operational.
+ \return 0 in case of success, else < 0
+ \ingroup RealtimeInterface
+*/
+
+int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
+{
+ uint32_t domain_offset;
+ ec_domain_t *domain;
+ ec_fsm_slave_t fsm_slave;
+ ec_slave_t *slave;
+
+ // allocate all domains
+ domain_offset = 0;
+ list_for_each_entry(domain, &master->domains, list) {
+ if (ec_domain_alloc(domain, domain_offset)) {
+ EC_ERR("Failed to allocate domain %X!\n", (u32) domain);
+ return -1;
+ }
+ domain_offset += domain->data_size;
+ }
+
+ ec_fsm_slave_init(&fsm_slave, &master->fsm_datagram);
+
+ // configure all slaves
+ list_for_each_entry(slave, &master->slaves, list) {
+ ec_fsm_slave_start_conf(&fsm_slave, slave);
+ while (ec_fsm_slave_exec(&fsm_slave)) {
+ ec_master_queue_datagram(master, &master->fsm_datagram);
+ ec_master_sync_io(master);
+ }
+
+ if (!ec_fsm_slave_success(&fsm_slave)) {
+ ec_fsm_slave_clear(&fsm_slave);
+ EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
+ return -1;
+ }
+ }
+
+ ec_fsm_slave_clear(&fsm_slave);
+ ec_master_prepare(master); // prepare asynchronous IO
+
+ if (master->debug_level)
+ EC_DBG("FSM datagram is %x.\n", (unsigned int) &master->fsm_datagram);
+
+ if (ec_master_thread_start(master)) {
+ EC_ERR("Failed to start master thread!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+/**
+ Sends queued datagrams and waits for their reception.
+*/
+
+void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram;
+ unsigned int datagrams_sent;
+
+ // send all datagrams
+ ecrt_master_send(master);
+
+ while (1) { // active waiting
+ schedule(); // schedule other processes while waiting.
+ ecrt_master_receive(master); // receive and dequeue datagrams
+
+ // count number of datagrams still waiting for response
+ datagrams_sent = 0;
+ list_for_each_entry(datagram, &master->datagram_queue, queue) {
+ // there may be another process that queued commands
+ // in the meantime.
+ if (datagram->state == EC_DATAGRAM_QUEUED) continue;
+ datagrams_sent++;
+ }
+
+ // abort loop if there are no more datagrams marked as sent.
+ if (!datagrams_sent) break;
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous sending of datagrams.
+ \ingroup RealtimeInterface
+*/
+
+void ecrt_master_send(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram, *n;
+
+ if (master->injection_seq_rt != master->injection_seq_fsm) {
+ // inject datagram produced by master FSM
+ ec_master_queue_datagram(master, &master->fsm_datagram);
+ master->injection_seq_rt = master->injection_seq_fsm;
+ }
+
+ if (unlikely(!master->main_device.link_state)) {
+ // link is down, no datagram can be sent
+ list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
+ datagram->state = EC_DATAGRAM_ERROR;
+ list_del_init(&datagram->queue);
+ }
+
+ // query link state
+ ec_device_poll(&master->main_device);
+ return;
+ }
+
+ // send frames
+ ec_master_send_datagrams(master);
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous receiving of datagrams.
+ \ingroup RealtimeInterface
+*/
+
+void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram, *next;
+ cycles_t cycles_timeout;
+
+ // receive datagrams
+ ec_device_poll(&master->main_device);
+
+ cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
+
+ // dequeue all datagrams that timed out
+ list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
+ if (datagram->state != EC_DATAGRAM_SENT) continue;
+
+ if (master->main_device.cycles_poll - datagram->cycles_sent
+ > cycles_timeout) {
+ list_del_init(&datagram->queue);
+ datagram->state = EC_DATAGRAM_TIMED_OUT;
+ master->stats.timeouts++;
+ ec_master_output_stats(master);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ * Obtains a slave pointer by its bus address.
+ * A valid slave pointer is only returned, if vendor ID and product code are
+ * matching.
+ * \return pointer to the slave on success, else NULL
+ * \ingroup RealtimeInterface
+ */
+
+ec_slave_t *ecrt_master_get_slave(
+ const ec_master_t *master, /**< EtherCAT master */
+ const char *address, /**< address string
+ \see ec_master_parse_slave_address() */
+ uint32_t vendor_id, /**< vendor ID */
+ uint32_t product_code /**< product code */
+ )
+{
+ ec_slave_t *slave = ec_master_parse_slave_address(master, address);
+
+ if (!slave)
+ return NULL;
+
+ return ec_slave_validate(slave, vendor_id, product_code) ? NULL : slave;
+}
+
/*****************************************************************************/
/**