Separated master requesting into open and reserve for userspace library.
(thanks to Martin Troxler).
--- a/NEWS Fri Jul 10 09:38:37 2009 +0000
+++ b/NEWS Fri Jul 10 10:07:48 2009 +0000
@@ -28,6 +28,10 @@
O. Zarges.
* Going to the Bootstrap state is now supported by the state machines and the
command-line tool.
+* Added ecrt_open_master() and ecrt_master_reserve() separation for
+ the userspace libary (thanks to Martin Troxler).
+* Added ecrt_master() userspace interface, to get information about a
+ master (thanks to Martin Troxler).
* Introduced ecrt_master_slave() to get information about a certain slave.
* SDO entry access rights are shown in 'ethercat sdos'.
* Added 64-bit data access macros to application header.
--- a/include/ecrt.h Fri Jul 10 09:38:37 2009 +0000
+++ b/include/ecrt.h Fri Jul 10 10:07:48 2009 +0000
@@ -47,6 +47,10 @@
* ecrt_master_sync_reference_clock() and ecrt_master_sync_slave_clocks()
* for offset and drift compensation. The EC_TIMEVAL2NANO() macro can be
* used for epoch time conversion.
+ * - Added ecrt_open_master() and ecrt_master_reserve() separation for
+ * userspace.
+ * - Added ecrt_master() userspace interface, to get information about a
+ * master.
* - Changed the meaning of the negative return values of
* ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*().
* - Imlemented the Vendor-specific over EtherCAT mailbox protocol. See
@@ -192,6 +196,22 @@
/*****************************************************************************/
+#ifndef __KERNEL__
+
+/** Master information.
+ *
+ * This is used as an output parameter of ecrt_master().
+ *
+ * \see ecrt_master().
+ */
+typedef struct {
+ unsigned int slave_count; /**< Number of slaves in the bus. */
+ unsigned int link_up : 1; /**< \a true, if the network link is up. */
+ uint64_t app_time; /**< Application time. */
+} ec_master_info_t;
+
+/*****************************************************************************/
+
/** Slave information.
*
* This is used as an output parameter of ecrt_master_slave().
@@ -213,6 +233,8 @@
char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */
} ec_slave_info_t;
+#endif // #ifndef __KERNEL__
+
/*****************************************************************************/
/** Domain working counter interpretation.
@@ -354,6 +376,9 @@
* Before an application can access an EtherCAT master, it has to reserve one
* for exclusive use.
*
+ * In userspace, this is a convenience function for ecrt_open_master() and
+ * ecrt_master_reserve().
+ *
* This function has to be the first function an application has to call to
* use EtherCAT. The function takes the index of the master as its argument.
* The first master has index 0, the n-th master has index n - 1. The number
@@ -365,6 +390,25 @@
unsigned int master_index /**< Index of the master to request. */
);
+#ifndef __KERNEL__
+
+/** Opens an EtherCAT master for userspace access.
+ *
+ * This function has to be the first function an application has to call to
+ * use EtherCAT. The function takes the index of the master as its argument.
+ * The first master has index 0, the n-th master has index n - 1. The number
+ * of masters has to be specified when loading the master module.
+ *
+ * For convenience, the function ecrt_request_master() can be used.
+ *
+ * \return Pointer to the opened master, otherwise \a NULL.
+ */
+ec_master_t *ecrt_open_master(
+ unsigned int master_index /**< Index of the master to request. */
+ );
+
+#endif // #ifndef __KERNEL__
+
/** Releases a requested EtherCAT master.
*
* After use, a master it has to be released to make it available for other
@@ -378,6 +422,22 @@
* Master methods
*****************************************************************************/
+#ifndef __KERNEL__
+
+/** Reserves an EtherCAT master for realtime operation.
+ *
+ * Before an application can use PDO/domain registration functions or SDO
+ * request functions on the master, it has to reserve one for exclusive use.
+ *
+ * \return 0 in case of success, else < 0
+ *
+ */
+int ecrt_master_reserve(
+ ec_master_t *master /**< EtherCAT master */
+ );
+
+#endif // #ifndef __KERNEL__
+
#ifdef __KERNEL__
/** Sets the locking callbacks.
@@ -451,6 +511,21 @@
#ifndef __KERNEL__
+/** Obtains master information.
+ *
+ * No memory is allocated on the heap in
+ * this function.
+ *
+ * \attention The pointer to this structure must point to a valid variable.
+ *
+ * \return 0 in case of success, else < 0
+ */
+int ecrt_master(
+ ec_master_t *master, /**< EtherCAT master */
+ ec_master_info_t *master_info /**< Structure that will output the
+ information */
+ );
+
/** Obtains slave information.
*
* Tries to find the slave with the given ring position. The obtained
@@ -468,7 +543,7 @@
information */
);
-#endif /* ifndef __KERNEL__ */
+#endif /* #ifndef __KERNEL__ */
/** Finishes the configuration phase and prepares for cyclic operation.
*
@@ -603,7 +678,7 @@
uint32_t *abort_code /**< Abort code of the SDO upload. */
);
-#endif /* ifndef __KERNEL__ */
+#endif /* #ifndef __KERNEL__ */
/******************************************************************************
* Slave configuration methods
--- a/lib/common.c Fri Jul 10 09:38:37 2009 +0000
+++ b/lib/common.c Fri Jul 10 10:07:48 2009 +0000
@@ -50,9 +50,25 @@
/*****************************************************************************/
+ec_master_t *ecrt_request_master(unsigned int master_index)
+{
+ ec_master_t *master = ecrt_open_master(master_index);
+ if (master) {
+ if (ecrt_master_reserve(master) < 0) {
+ close(master->fd);
+ free(master);
+ master = 0;
+ }
+ }
+
+ return master;
+}
+
+/*****************************************************************************/
+
#define MAX_PATH_LEN 64
-ec_master_t *ecrt_request_master(unsigned int master_index)
+ec_master_t *ecrt_open_master(unsigned int master_index)
{
char path[MAX_PATH_LEN];
ec_master_t *master;
@@ -75,14 +91,6 @@
return 0;
}
- if (ioctl(master->fd, EC_IOCTL_REQUEST, NULL) == -1) {
- fprintf(stderr, "Failed to request master %u: %s\n",
- master_index, strerror(errno));
- close(master->fd);
- free(master);
- return 0;
- }
-
return master;
}
--- a/lib/master.c Fri Jul 10 09:38:37 2009 +0000
+++ b/lib/master.c Fri Jul 10 10:07:48 2009 +0000
@@ -42,6 +42,17 @@
/*****************************************************************************/
+int ecrt_master_reserve(ec_master_t *master)
+{
+ if (ioctl(master->fd, EC_IOCTL_REQUEST, NULL) == -1) {
+ fprintf(stderr, "Failed to reserve master: %s\n",
+ strerror(errno));
+ return -1;
+ }
+}
+
+/*****************************************************************************/
+
ec_domain_t *ecrt_master_create_domain(ec_master_t *master)
{
ec_domain_t *domain;
@@ -103,6 +114,23 @@
/*****************************************************************************/
+int ecrt_master(ec_master_t* master, ec_master_info_t *master_info)
+{
+ ec_ioctl_master_t data;
+
+ if (ioctl(master->fd, EC_IOCTL_MASTER, &data) < 0) {
+ fprintf(stderr, "Failed to get master info: %s\n", strerror(errno));
+ return -1;
+ }
+
+ master_info->slave_count = data.slave_count;
+ master_info->link_up = data.devices[0].link_state;
+ master_info->app_time = data.app_time;
+ return 0;
+}
+
+/*****************************************************************************/
+
int ecrt_master_slave(ec_master_t *master, uint16_t position,
ec_slave_info_t *slave_info)
{
@@ -112,8 +140,7 @@
data.position = position;
if (ioctl(master->fd, EC_IOCTL_SLAVE, &data) == -1) {
- fprintf(stderr, "Failed to get slave info: %s\n",
- strerror(errno));
+ fprintf(stderr, "Failed to get slave info: %s\n", strerror(errno));
return -1;
}
@@ -129,7 +156,6 @@
slave_info->sync_count = data.sync_count;
slave_info->sdo_count = data.sdo_count;
strncpy(slave_info->name, data.name, EC_IOCTL_STRING_SIZE);
-
return 0;
}