# HG changeset patch # User Florian Pose # Date 1248795720 0 # Node ID 88b608a1a7f32b5268f7532aacf4531aa4089ee7 # Parent a864688e7de5ebbbf7012ac60ec234bef615047d Improved bus information API. diff -r a864688e7de5 -r 88b608a1a7f3 NEWS --- a/NEWS Mon Jul 27 10:48:52 2009 +0000 +++ b/NEWS Tue Jul 28 15:42:00 2009 +0000 @@ -35,10 +35,15 @@ * 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. + the userspace library (thanks to Martin Troxler). +* Added bus information interface (methods ecrt_master(), + ecrt_master_get_slave(), ecrt_master_get_sync_manager(), + ecrt_master_get_pdo() and ecrt_master_get_pdo_entry()) to get information + about the currently connected slaves and the PDO entries provided (thanks to + Martin Troxler and Stefan Weiser). +* Added ecrt_master_sdo_download() and ecrt_master_sdo_upload() + methods to let an application transfer SDOs before activating the master + (thanks to Stefan Weiser). * Fixed SDO upload segment response (thanks to Christoph Peter). * SDO entry access rights are shown in 'ethercat sdos'. * Added 64-bit data access macros to application header. @@ -48,9 +53,6 @@ * Output device link state in 'ethercat master'. * Added 'ethercat graph' command which outputs the bus topology in DOT language. -* Added ecrt_slave_sdo_upload() and ecrt_slave_sdo_download() methods to let - an application transfer SDOs before activating the master. Thanks to Stefan - Weiser. * Changed EC_MAX_SII_SIZE to 4096. * 'ethercat xml' creates valid XML for more than one slave (thanks to E. Burgstaller). diff -r a864688e7de5 -r 88b608a1a7f3 include/ecrt.h --- a/include/ecrt.h Mon Jul 27 10:48:52 2009 +0000 +++ b/include/ecrt.h Tue Jul 28 15:42:00 2009 +0000 @@ -55,11 +55,12 @@ * ecrt_slave_config_sync_manager()). * - Added ecrt_open_master() and ecrt_master_reserve() separation for * userspace. - * - Added ecrt_master() userspace interface, to get information about a - * master. - * - Added ecrt_master_slave() to get information about a certain slave. - * - Added ecrt_slave_sdo_upload() and ecrt_slave_sdo_download() methods to - * let an application transfer SDOs before activating the master. + * - Added bus information interface (methods ecrt_master(), + * ecrt_master_get_slave(), ecrt_master_get_sync_manager(), + * ecrt_master_get_pdo() and ecrt_master_get_pdo_entry()) to get information + * about the currently connected slaves and the PDO entries provided. + * - Added ecrt_master_sdo_download() and ecrt_master_sdo_upload() + * methods to let an application transfer SDOs before activating the 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 @@ -220,9 +221,9 @@ /** Slave information. * - * This is used as an output parameter of ecrt_master_slave(). - * - * \see ecrt_master_slave(). + * This is used as an output parameter of ecrt_master_get_slave(). + * + * \see ecrt_master_get_slave(). */ typedef struct { uint16_t position; /**< Offset of the slave in the ring. */ @@ -557,13 +558,104 @@ * * \return 0 in case of success, else < 0 */ -int ecrt_master_slave( +int ecrt_master_get_slave( ec_master_t *master, /**< EtherCAT master */ - uint16_t position, /**< Slave position. */ + uint16_t slave_position, /**< Slave position. */ ec_slave_info_t *slave_info /**< Structure that will output the information */ ); +/** Returns the proposed configuration of a slave's sync manager. + * + * Fills a given ec_sync_info_t structure with the attributes of a sync + * manager. The \a pdos field of the return value is left empty. Use + * ecrt_master_get_pdo() to get the PDO information. + * + * \return zero on success, else non-zero + */ +int ecrt_master_get_sync_manager( + ec_master_t *master, /**< EtherCAT master. */ + uint16_t slave_position, /**< Slave position. */ + uint8_t sync_index, /**< Sync manager index. Must be less + than #EC_MAX_SYNC_MANAGERS. */ + ec_sync_info_t *sync /**< Pointer to output structure. */ + ); + +/** Returns information about a currently assigned PDO. + * + * Fills a given ec_pdo_info_t structure with the attributes of a currently + * assigned PDO of the given sync manager. The \a entries field of the return + * value is left empty. Use ecrt_master_get_pdo_entry() to get the PDO + * entry information. + * + * \retval zero on success, else non-zero + */ +int ecrt_master_get_pdo( + ec_master_t *master, /**< EtherCAT master. */ + uint16_t slave_position, /**< Slave position. */ + uint8_t sync_index, /**< Sync manager index. Must be less + than #EC_MAX_SYNC_MANAGERS. */ + uint16_t pos, /**< Zero-based PDO position. */ + ec_pdo_info_t *pdo /**< Pointer to output structure. */ + ); + +/** Returns information about a currently mapped PDO entry. + * + * Fills a given ec_pdo_entry_info_t structure with the attributes of a + * currently mapped PDO entry of the given PDO. + * + * \retval zero on success, else non-zero + */ +int ecrt_master_get_pdo_entry( + ec_master_t *master, /**< EtherCAT master. */ + uint16_t slave_position, /**< Slave position. */ + uint8_t sync_index, /**< Sync manager index. Must be less + than #EC_MAX_SYNC_MANAGERS. */ + uint16_t pdo_pos, /**< Zero-based PDO position. */ + uint16_t entry_pos, /**< Zero-based PDO entry position. */ + ec_pdo_entry_info_t *entry /**< Pointer to output structure. */ + ); + +/** Executes an SDO write request to download data. + * + * This function operates aside of the normal way to request SDOs. Before the + * activation of the master, these requests are processed by the master state + * machine itself. After activation the user has to ensure cyclic processing. + * + * \retval 0 Success. + * \retval -1 An error occured. + */ +int ecrt_master_sdo_download( + ec_master_t *master, /**< EtherCAT master. */ + uint16_t slave_position, /**< Slave position. */ + uint16_t index, /**< Index of the SDO. */ + uint8_t subindex, /**< Subindex of the SDO. */ + uint8_t *data, /**< Data buffer to download. */ + size_t data_size, /**< Size of the data buffer. */ + uint32_t *abort_code /**< Abort code of the SDO download. */ + ); + +/** Executes a SDO read request to upload data. + * + * This function operates aside of the normal way to request SDOs. Before the + * activation of the master, these requests are processed by the master state + * machine itself. After activation the user have to ensure cyclic + * processing. + * + * \retval 0 Success. + * \retval -1 Error occured. + */ +int ecrt_master_sdo_upload( + ec_master_t *master, /**< EtherCAT master. */ + uint16_t slave_position, /**< Slave position. */ + uint16_t index, /**< Index of the SDO. */ + uint8_t subindex, /**< Subindex of the SDO. */ + uint8_t *target, /**< Target buffer for the upload. */ + size_t target_size, /**< Size of the target buffer. */ + size_t *result_size, /**< Uploaded data size. */ + uint32_t *abort_code /**< Abort code of the SDO upload. */ + ); + #endif /* #ifndef __KERNEL__ */ /** Finishes the configuration phase and prepares for cyclic operation. @@ -666,50 +758,6 @@ ec_master_t *master /**< EtherCAT master. */ ); -#ifndef __KERNEL__ - -/** Executes an SDO write request to download data. - * - * This function operates aside of the normal way to request SDOs. Before the - * activation of the master, these requests are processed by the master state - * machine itself. After activation the user has to ensure cyclic processing. - * - * \retval 0 Success. - * \retval -1 An error occured. - */ -int ecrt_slave_sdo_download( - ec_master_t* master, /**< EtherCAT master. */ - uint16_t slave_position, /**< Slave position. */ - uint16_t index, /**< Index of the SDO. */ - uint8_t subindex, /**< Subindex of the SDO. */ - uint8_t *data, /**< Data buffer to download. */ - size_t data_size, /**< Size of the data buffer. */ - uint32_t *abort_code /**< Abort code of the SDO download. */ - ); - -/** Executes a SDO read request to upload data. - * - * This function operates aside of the normal way to request SDOs. Before the - * activation of the master, these requests are processed by the master state - * machine itself. After activation the user have to ensure cyclic - * processing. - * - * \retval 0 Success. - * \retval -1 Error occured. - */ -int ecrt_slave_sdo_upload( - ec_master_t* master, /**< EtherCAT master. */ - uint16_t slave_position, /**< Slave position. */ - uint16_t index, /**< Index of the SDO. */ - uint8_t subindex, /**< Subindex of the SDO. */ - uint8_t *target, /**< Target buffer for the upload. */ - size_t target_size, /**< Size of the target buffer. */ - size_t *result_size, /**< Uploaded data size. */ - uint32_t *abort_code /**< Abort code of the SDO upload. */ - ); - -#endif /* #ifndef __KERNEL__ */ - /****************************************************************************** * Slave configuration methods *****************************************************************************/ diff -r a864688e7de5 -r 88b608a1a7f3 lib/master.c --- a/lib/master.c Mon Jul 27 10:48:52 2009 +0000 +++ b/lib/master.c Tue Jul 28 15:42:00 2009 +0000 @@ -131,13 +131,13 @@ /*****************************************************************************/ -int ecrt_master_slave(ec_master_t *master, uint16_t position, +int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position, ec_slave_info_t *slave_info) { ec_ioctl_slave_t data; int index; - data.position = position; + data.position = slave_position; if (ioctl(master->fd, EC_IOCTL_SLAVE, &data) == -1) { fprintf(stderr, "Failed to get slave info: %s\n", strerror(errno)); @@ -161,6 +161,152 @@ /*****************************************************************************/ +int ecrt_master_get_sync_manager(ec_master_t *master, uint16_t slave_position, + uint8_t sync_index, ec_sync_info_t *sync) +{ + ec_ioctl_slave_sync_t data; + + if (sync_index >= EC_MAX_SYNC_MANAGERS) + return -ENOENT; + + memset(&data, 0x00, sizeof(ec_ioctl_slave_sync_t)); + data.slave_position = slave_position; + data.sync_index = sync_index; + + if (ioctl(master->fd, EC_IOCTL_SLAVE_SYNC, &data) == -1) { + fprintf(stderr, "Failed to get sync manager information: %s\n", + strerror(errno)); + return -1; // FIXME + } + + sync->index = sync_index; + sync->dir = EC_READ_BIT(&data.control_register, 2) ? + EC_DIR_OUTPUT : EC_DIR_INPUT; + sync->n_pdos = data.pdo_count; + sync->pdos = NULL; + sync->watchdog_mode = EC_READ_BIT(&data.control_register, 6) ? + EC_WD_ENABLE : EC_WD_DISABLE; + + return 0; +} + +/*****************************************************************************/ + +int ecrt_master_get_pdo(ec_master_t *master, uint16_t slave_position, + uint8_t sync_index, uint16_t pos, ec_pdo_info_t *pdo) +{ + ec_ioctl_slave_sync_pdo_t data; + + if (sync_index >= EC_MAX_SYNC_MANAGERS) + return -ENOENT; + + memset(&data, 0x00, sizeof(ec_ioctl_slave_sync_pdo_t)); + data.slave_position = slave_position; + data.sync_index = sync_index; + data.pdo_pos = pos; + + if (ioctl(master->fd, EC_IOCTL_SLAVE_SYNC_PDO, &data) == -1) { + fprintf(stderr, "Failed to get pdo information: %s\n", + strerror(errno)); + return -1; // FIXME + } + + pdo->index = data.index; + pdo->n_entries = data.entry_count; + pdo->entries = NULL; + + return 0; +} + +/*****************************************************************************/ + +int ecrt_master_get_pdo_entry(ec_master_t *master, uint16_t slave_position, + uint8_t sync_index, uint16_t pdo_pos, uint16_t entry_pos, + ec_pdo_entry_info_t *entry) +{ + ec_ioctl_slave_sync_pdo_entry_t data; + + if (sync_index >= EC_MAX_SYNC_MANAGERS) + return -ENOENT; + + memset(&data, 0x00, sizeof(ec_ioctl_slave_sync_pdo_entry_t)); + data.slave_position = slave_position; + data.sync_index = sync_index; + data.pdo_pos = pdo_pos; + data.entry_pos = entry_pos; + + if (ioctl(master->fd, EC_IOCTL_SLAVE_SYNC_PDO_ENTRY, &data) == -1) { + fprintf(stderr, "Failed to get pdo entry information: %s\n", + strerror(errno)); + return -1; // FIXME + } + + entry->index = data.index; + entry->subindex = data.subindex; + entry->bit_length = data.bit_length; + + return 0; +} + +/*****************************************************************************/ + +int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, + uint16_t index, uint8_t subindex, uint8_t *data, + size_t data_size, uint32_t *abort_code) +{ + ec_ioctl_slave_sdo_download_t download; + + download.slave_position = slave_position; + download.sdo_index = index; + download.sdo_entry_subindex = subindex; + download.data_size = data_size; + download.data = data; + + if (ioctl(master->fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, &download) == -1) { + if (errno == -EIO) { + if (abort_code) { + *abort_code = download.abort_code; + } + } + fprintf(stderr, "Failed to execute SDO download: %s\n", + strerror(errno)); + return -1; + } + + return 0; +} + +/*****************************************************************************/ + +int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, + uint16_t index, uint8_t subindex, uint8_t *target, + size_t target_size, size_t *result_size, uint32_t *abort_code) +{ + ec_ioctl_slave_sdo_upload_t upload; + + upload.slave_position = slave_position; + upload.sdo_index = index; + upload.sdo_entry_subindex = subindex; + upload.target_size = target_size; + upload.target = target; + + if (ioctl(master->fd, EC_IOCTL_SLAVE_SDO_UPLOAD, &upload) == -1) { + if (errno == -EIO) { + if (abort_code) { + *abort_code = upload.abort_code; + } + } + fprintf(stderr, "Failed to execute SDO upload: %s\n", + strerror(errno)); + return -1; + } + + *result_size = upload.data_size; + return 0; +} + +/*****************************************************************************/ + int ecrt_master_activate(ec_master_t *master) { if (ioctl(master->fd, EC_IOCTL_ACTIVATE, @@ -248,60 +394,3 @@ } /*****************************************************************************/ - -int ecrt_slave_sdo_download(ec_master_t* master, uint16_t slave_position, - uint16_t index, uint8_t subindex, uint8_t *data, - size_t data_size, uint32_t *abort_code) -{ - ec_ioctl_slave_sdo_download_t download; - - download.slave_position = slave_position; - download.sdo_index = index; - download.sdo_entry_subindex = subindex; - download.data_size = data_size; - download.data = data; - - if (ioctl(master->fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, &download) == -1) { - if (errno == -EIO) { - if (abort_code) { - *abort_code = download.abort_code; - } - } - fprintf(stderr, "Failed to execute SDO download: %s\n", - strerror(errno)); - return -1; - } - - return 0; -} - -/*****************************************************************************/ - -int ecrt_slave_sdo_upload(ec_master_t* master, uint16_t slave_position, - uint16_t index, uint8_t subindex, uint8_t *target, - size_t target_size, size_t *result_size, uint32_t *abort_code) -{ - ec_ioctl_slave_sdo_upload_t upload; - - upload.slave_position = slave_position; - upload.sdo_index = index; - upload.sdo_entry_subindex = subindex; - upload.target_size = target_size; - upload.target = target; - - if (ioctl(master->fd, EC_IOCTL_SLAVE_SDO_UPLOAD, &upload) == -1) { - if (errno == -EIO) { - if (abort_code) { - *abort_code = upload.abort_code; - } - } - fprintf(stderr, "Failed to execute SDO upload: %s\n", - strerror(errno)); - return -1; - } - - *result_size = upload.data_size; - return 0; -} - -/*****************************************************************************/