--- a/master/master.c Thu Apr 20 14:34:58 2006 +0000
+++ b/master/master.c Fri Apr 21 12:35:17 2006 +0000
@@ -6,6 +6,23 @@
*
* $Id$
*
+ * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT Master.
+ *
+ * The IgH EtherCAT Master is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the License.
+ *
+ * The IgH EtherCAT Master is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the IgH EtherCAT Master; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
*****************************************************************************/
#include <linux/module.h>
@@ -56,6 +73,7 @@
/**
Master constructor.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
int ec_master_init(ec_master_t *master, /**< EtherCAT master */
@@ -101,6 +119,7 @@
Master destructor.
Removes all pending commands, clears the slave list, clears all domains
and frees the device.
+ \ingroup Master
*/
void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
@@ -130,6 +149,7 @@
Resets the master.
Note: This function has to be called, everytime ec_master_release() is
called, to free the slave list, domains etc.
+ \ingroup Master
*/
void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
@@ -190,6 +210,7 @@
/**
Places a command in the command queue.
+ \ingroup Master
*/
void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */
@@ -217,6 +238,7 @@
/**
Sends the commands in the queue.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
@@ -318,6 +340,7 @@
Processes a received frame.
This function is called by the network driver for every received frame.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
void ec_master_receive(ec_master_t *master, /**< EtherCAT master */
@@ -405,6 +428,7 @@
Sends a single command and waits for its reception.
If the slave doesn't respond, the command is sent again.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */
@@ -449,6 +473,7 @@
Scans the EtherCAT bus for slaves.
Creates a list of slave structures for further processing.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
@@ -572,6 +597,7 @@
Output statistics in cyclic mode.
This function outputs statistical data on demand, but not more often than
necessary. The output happens at most once a second.
+ \ingroup Master
*/
void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
@@ -607,6 +633,7 @@
/**
Starts the Free-Run mode.
+ \ingroup Master
*/
void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
@@ -639,6 +666,7 @@
/**
Stops the Free-Run mode.
+ \ingroup Master
*/
void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
@@ -655,6 +683,7 @@
/**
Free-Run mode function.
+ \ingroup Master
*/
void ec_master_freerun(unsigned long data /**< private timer data = master */)
@@ -678,115 +707,9 @@
/*****************************************************************************/
/**
- 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
-*/
-
-ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
- const char *address /**< address string */
- )
-{
- unsigned long first, second;
- char *remainder, *remainder2;
- unsigned int alias_requested, alias_found;
- ec_slave_t *alias_slave = NULL, *slave;
-
- if (!address || address[0] == 0) return NULL;
-
- alias_requested = 0;
- if (address[0] == '#') {
- alias_requested = 1;
- address++;
- }
-
- first = simple_strtoul(address, &remainder, 0);
- if (remainder == address) {
- EC_ERR("Slave address \"%s\" - First number empty!\n", address);
- return NULL;
- }
-
- if (alias_requested) {
- alias_found = 0;
- list_for_each_entry(alias_slave, &master->slaves, list) {
- if (alias_slave->sii_alias == first) {
- alias_found = 1;
- break;
- }
- }
- if (!alias_found) {
- EC_ERR("Slave address \"%s\" - Alias not found!\n", address);
- return NULL;
- }
- }
-
- if (!remainder[0]) { // absolute position
- if (alias_requested) {
- return alias_slave;
- }
- else {
- list_for_each_entry(slave, &master->slaves, list) {
- if (slave->ring_position == first) return slave;
- }
- EC_ERR("Slave address \"%s\" - Absolute position invalid!\n",
- address);
- }
- }
- else if (remainder[0] == ':') { // field position
- remainder++;
- second = simple_strtoul(remainder, &remainder2, 0);
-
- if (remainder2 == remainder) {
- EC_ERR("Slave address \"%s\" - Second number empty!\n", address);
- return NULL;
- }
-
- if (remainder2[0]) {
- EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address);
- return NULL;
- }
-
- if (alias_requested) {
- if (!alias_slave->type ||
- alias_slave->type->special != EC_TYPE_BUS_COUPLER) {
- EC_ERR("Slave address \"%s\": Alias slave must be bus coupler"
- " in colon mode.\n", address);
- return NULL;
- }
- list_for_each_entry(slave, &master->slaves, list) {
- if (slave->coupler_index == alias_slave->coupler_index
- && slave->coupler_subindex == second)
- return slave;
- }
- EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave"
- " following!\n", address, alias_slave->ring_position,
- second);
- return NULL;
- }
- else {
- list_for_each_entry(slave, &master->slaves, list) {
- if (slave->coupler_index == first
- && slave->coupler_subindex == second) return slave;
- }
- }
- }
- else
- EC_ERR("Slave address \"%s\" - Invalid format!\n", address);
-
- return NULL;
-}
-
-/*****************************************************************************/
-
-/**
Initializes a sync manager configuration page.
The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes.
+ \ingroup Master
*/
void ec_sync_config(const ec_sync_t *sync, /**< sync manager */
@@ -805,6 +728,7 @@
/**
Initializes a sync manager configuration page with EEPROM data.
The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes.
+ \ingroup Master
*/
void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */
@@ -823,6 +747,7 @@
/**
Initializes an FMMU configuration page.
The referenced memory (\a data) must be at least EC_FMMU_SIZE bytes.
+ \ingroup Master
*/
void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< FMMU */
@@ -845,6 +770,7 @@
/**
Formats attribute data for SysFS read access.
\return number of bytes to read
+ \ingroup Master
*/
ssize_t ec_show_master_attribute(struct kobject *kobj, /**< kobject */
@@ -875,6 +801,7 @@
/**
Processes the watchdog command.
+ \ingroup Master
*/
void ec_master_process_watch_command(ec_master_t *master
@@ -918,6 +845,22 @@
}
}
+/*****************************************************************************/
+
+/**
+ Does the Ethernet-over-EtherCAT processing.
+ \ingroup Master
+*/
+
+void ec_master_run_eoe(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_eoe_t *eoe;
+
+ list_for_each_entry(eoe, &master->eoe_slaves, list) {
+ ec_eoe_run(eoe);
+ }
+}
+
/******************************************************************************
* Realtime interface
*****************************************************************************/
@@ -925,6 +868,7 @@
/**
Creates a domain.
\return pointer to new domain on success, else NULL
+ \ingroup Master
*/
ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
@@ -970,6 +914,7 @@
managers and FMMUs, and does the appropriate transitions, until the slave
is operational.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
@@ -1156,6 +1101,7 @@
/**
Resets all slaves to INIT state.
+ \ingroup Master
*/
void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */)
@@ -1175,6 +1121,7 @@
Fetches the SDO dictionaries of all slaves.
Slaves that do not support the CoE protocol are left out.
\return 0 in case of success, else < 0
+ \ingroup Master
*/
int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT master */)
@@ -1198,6 +1145,7 @@
/**
Sends queued commands and waits for their reception.
+ \ingroup Master
*/
void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
@@ -1253,6 +1201,7 @@
/**
Asynchronous sending of commands.
+ \ingroup Master
*/
void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */)
@@ -1279,6 +1228,7 @@
/**
Asynchronous receiving of commands.
+ \ingroup Master
*/
void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
@@ -1313,6 +1263,7 @@
Prepares synchronous IO.
Queues all domain commands and sends them. Then waits a certain time, so
that ecrt_master_sasync_receive() can be called securely.
+ \ingroup Master
*/
void ecrt_master_prepare_async_io(ec_master_t *master /**< EtherCAT master */)
@@ -1340,6 +1291,7 @@
/**
Does all cyclic master work.
+ \ingroup Master
*/
void ecrt_master_run(ec_master_t *master /**< EtherCAT master */)
@@ -1358,10 +1310,119 @@
/*****************************************************************************/
/**
+ 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 Master
+*/
+
+ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
+ const char *address /**< address string */
+ )
+{
+ unsigned long first, second;
+ char *remainder, *remainder2;
+ unsigned int alias_requested, alias_found;
+ ec_slave_t *alias_slave = NULL, *slave;
+
+ if (!address || address[0] == 0) return NULL;
+
+ alias_requested = 0;
+ if (address[0] == '#') {
+ alias_requested = 1;
+ address++;
+ }
+
+ first = simple_strtoul(address, &remainder, 0);
+ if (remainder == address) {
+ EC_ERR("Slave address \"%s\" - First number empty!\n", address);
+ return NULL;
+ }
+
+ if (alias_requested) {
+ alias_found = 0;
+ list_for_each_entry(alias_slave, &master->slaves, list) {
+ if (alias_slave->sii_alias == first) {
+ alias_found = 1;
+ break;
+ }
+ }
+ if (!alias_found) {
+ EC_ERR("Slave address \"%s\" - Alias not found!\n", address);
+ return NULL;
+ }
+ }
+
+ if (!remainder[0]) { // absolute position
+ if (alias_requested) {
+ return alias_slave;
+ }
+ else {
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (slave->ring_position == first) return slave;
+ }
+ EC_ERR("Slave address \"%s\" - Absolute position invalid!\n",
+ address);
+ }
+ }
+ else if (remainder[0] == ':') { // field position
+ remainder++;
+ second = simple_strtoul(remainder, &remainder2, 0);
+
+ if (remainder2 == remainder) {
+ EC_ERR("Slave address \"%s\" - Second number empty!\n", address);
+ return NULL;
+ }
+
+ if (remainder2[0]) {
+ EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address);
+ return NULL;
+ }
+
+ if (alias_requested) {
+ if (!alias_slave->type ||
+ alias_slave->type->special != EC_TYPE_BUS_COUPLER) {
+ EC_ERR("Slave address \"%s\": Alias slave must be bus coupler"
+ " in colon mode.\n", address);
+ return NULL;
+ }
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (slave->coupler_index == alias_slave->coupler_index
+ && slave->coupler_subindex == second)
+ return slave;
+ }
+ EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave"
+ " following!\n", address, alias_slave->ring_position,
+ second);
+ return NULL;
+ }
+ else {
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (slave->coupler_index == first
+ && slave->coupler_subindex == second) return slave;
+ }
+ }
+ }
+ else
+ EC_ERR("Slave address \"%s\" - Invalid format!\n", address);
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+/**
Sets the debug level of the master.
The following levels are valid:
- 1: only output positions marks and basic data
- 2: additional frame data output
+ \ingroup Master
*/
void ecrt_master_debug(ec_master_t *master, /**< EtherCAT master */
@@ -1382,6 +1443,7 @@
- 0: Only slave types and positions
- 1: with EEPROM contents
- >1: with SDO dictionaries
+ \ingroup Master
*/
void ecrt_master_print(const ec_master_t *master, /**< EtherCAT master */
@@ -1408,21 +1470,6 @@
/*****************************************************************************/
-/**
- Does the Ethernet-over-EtherCAT processing.
-*/
-
-void ec_master_run_eoe(ec_master_t *master /**< EtherCAT master */)
-{
- ec_eoe_t *eoe;
-
- list_for_each_entry(eoe, &master->eoe_slaves, list) {
- ec_eoe_run(eoe);
- }
-}
-
-/*****************************************************************************/
-
EXPORT_SYMBOL(ecrt_master_create_domain);
EXPORT_SYMBOL(ecrt_master_activate);
EXPORT_SYMBOL(ecrt_master_deactivate);