# HG changeset patch # User Florian Pose # Date 1247220468 0 # Node ID c9308eb34c0ea35fae49848be24a6e985be6fb91 # Parent f98f89d0d7782c73209928085d70e8f3ee2576f1 Separated master requesting into open and reserve for userspace library. (thanks to Martin Troxler). diff -r f98f89d0d778 -r c9308eb34c0e NEWS --- 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. diff -r f98f89d0d778 -r c9308eb34c0e include/ecrt.h --- 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 diff -r f98f89d0d778 -r c9308eb34c0e lib/common.c --- 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; } diff -r f98f89d0d778 -r c9308eb34c0e lib/master.c --- 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; }