# HG changeset patch # User Florian Pose # Date 1223631426 0 # Node ID 5f9d1abbee717e2eab5397d49963ce212c700b3c # Parent 900f1124e8f8c5cb8d32acb8b60bd222934b69c2 Added state functions; writing of process data works. diff -r 900f1124e8f8 -r 5f9d1abbee71 examples/user/main.c --- a/examples/user/main.c Fri Oct 10 08:34:15 2008 +0000 +++ b/examples/user/main.c Fri Oct 10 09:37:06 2008 +0000 @@ -47,6 +47,7 @@ /****************************************************************************/ // Application parameters +#define FREQUENCY 100 #define PRIORITY 1 // Optional features @@ -56,10 +57,13 @@ // EtherCAT static ec_master_t *master = NULL; +static ec_master_state_t master_state = {}; static ec_domain_t *domain1 = NULL; +static ec_domain_state_t domain1_state = {}; static ec_slave_config_t *sc_ana_in = NULL; +static ec_slave_config_state_t sc_ana_in_state = {}; // Timer static unsigned int sig_alarms = 0; @@ -75,8 +79,9 @@ #define AnaInSlavePos 0, 2 #define DigOutSlavePos 0, 3 -#define Beckhoff_EK1100 0x00000002, 0x044C2C52 -#define Beckhoff_EL2004 0x00000002, 0x07D43052 +#define Beckhoff_EK1100 0x00000002, 0x044c2c52 +#define Beckhoff_EL2004 0x00000002, 0x07d43052 +#define Beckhoff_EL2032 0x00000002, 0x07f03052 #define Beckhoff_EL3152 0x00000002, 0x0c503052 #define Beckhoff_EL4102 0x00000002, 0x10063052 @@ -90,10 +95,13 @@ {AnaInSlavePos, Beckhoff_EL3152, 0x3101, 1, &off_ana_in_status}, {AnaInSlavePos, Beckhoff_EL3152, 0x3101, 2, &off_ana_in_value}, {AnaOutSlavePos, Beckhoff_EL4102, 0x3001, 1, &off_ana_out}, - {DigOutSlavePos, Beckhoff_EL2004, 0x3001, 1, &off_dig_out}, + {DigOutSlavePos, Beckhoff_EL2032, 0x3001, 1, &off_dig_out}, {} }; +static unsigned int counter = 0; +static unsigned int blink = 0; + /*****************************************************************************/ #if CONFIGURE_PDOS @@ -161,24 +169,100 @@ }; #endif +/*****************************************************************************/ + +void check_domain1_state(void) +{ + ec_domain_state_t ds; + + ecrt_domain_state(domain1, &ds); + + if (ds.working_counter != domain1_state.working_counter) + printf("Domain1: WC %u.\n", ds.working_counter); + if (ds.wc_state != domain1_state.wc_state) + printf("Domain1: State %u.\n", ds.wc_state); + + domain1_state = ds; +} + +/*****************************************************************************/ + +void check_master_state(void) +{ + ec_master_state_t ms; + + ecrt_master_state(master, &ms); + + if (ms.slaves_responding != master_state.slaves_responding) + printf("%u slave(s).\n", ms.slaves_responding); + if (ms.al_states != master_state.al_states) + printf("AL states: 0x%02X.\n", ms.al_states); + if (ms.link_up != master_state.link_up) + printf("Link is %s.\n", ms.link_up ? "up" : "down"); + + master_state = ms; +} + +/*****************************************************************************/ + +void check_slave_config_states(void) +{ + ec_slave_config_state_t s; + + ecrt_slave_config_state(sc_ana_in, &s); + + if (s.al_state != sc_ana_in_state.al_state) + printf("AnaIn: State 0x%02X.\n", s.al_state); + if (s.online != sc_ana_in_state.online) + printf("AnaIn: %s.\n", s.online ? "online" : "offline"); + if (s.operational != sc_ana_in_state.operational) + printf("AnaIn: %soperational.\n", + s.operational ? "" : "Not "); + + sc_ana_in_state = s; +} + /****************************************************************************/ void cyclic_task() { + int i; + + // receive process data ecrt_master_receive(master); ecrt_domain_process(domain1); + // check process data state (optional) + check_domain1_state(); + + if (counter) { + counter--; + } else { // do this at 1 Hz + counter = FREQUENCY; + + // calculate new process data + blink = !blink; + + // check for master state (optional) + check_master_state(); + + // check for islave configuration state(s) (optional) + check_slave_config_states(); + } + #if 0 -#if EL3152_ALT_PDOS - printf("AnaIn: value %u\n", - EC_READ_U16(domain1_pd + off_ana_in_value)); -#else + // read process data printf("AnaIn: state %u value %u\n", EC_READ_U8(domain1_pd + off_ana_in_status), EC_READ_U16(domain1_pd + off_ana_in_value)); #endif -#endif - + +#if 1 + // write process data + EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09); +#endif + + // send process data ecrt_domain_queue(domain1); ecrt_master_send(master); } @@ -234,7 +318,7 @@ } if (!(sc = ecrt_master_slave_config( - master, DigOutSlavePos, Beckhoff_EL2004))) { + master, DigOutSlavePos, Beckhoff_EL2032))) { fprintf(stderr, "Failed to get slave configuration.\n"); return -1; } @@ -280,7 +364,7 @@ printf("Starting timer...\n"); tv.it_interval.tv_sec = 0; - tv.it_interval.tv_usec = 10000; + tv.it_interval.tv_usec = 1000000 / FREQUENCY; tv.it_value.tv_sec = 0; tv.it_value.tv_usec = 1000; if (setitimer(ITIMER_REAL, &tv, NULL)) { diff -r 900f1124e8f8 -r 5f9d1abbee71 lib/domain.c --- a/lib/domain.c Fri Oct 10 08:34:15 2008 +0000 +++ b/lib/domain.c Fri Oct 10 09:37:06 2008 +0000 @@ -119,6 +119,15 @@ void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state) { + ec_ioctl_domain_state_t data; + + data.domain_index = domain->index; + data.state = state; + + if (ioctl(domain->master->fd, EC_IOCTL_DOMAIN_STATE, &data) == -1) { + fprintf(stderr, "Failed to get domain state: %s\n", + strerror(errno)); + } } /*****************************************************************************/ diff -r 900f1124e8f8 -r 5f9d1abbee71 lib/master.c --- a/lib/master.c Fri Oct 10 08:34:15 2008 +0000 +++ b/lib/master.c Fri Oct 10 09:37:06 2008 +0000 @@ -117,7 +117,7 @@ if (master->process_data_size) { master->process_data = mmap(0, master->process_data_size, - PROT_READ | PROT_WRITE, MAP_PRIVATE, master->fd, 0); + PROT_READ | PROT_WRITE, MAP_SHARED, master->fd, 0); if (master->process_data == MAP_FAILED) { fprintf(stderr, "Failed to map process data: %s", strerror(errno)); master->process_data = NULL; @@ -154,6 +154,9 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state) { + if (ioctl(master->fd, EC_IOCTL_MASTER_STATE, state) == -1) { + fprintf(stderr, "Failed to get master state: %s\n", strerror(errno)); + } } /*****************************************************************************/ diff -r 900f1124e8f8 -r 5f9d1abbee71 lib/slave_config.c --- a/lib/slave_config.c Fri Oct 10 08:34:15 2008 +0000 +++ b/lib/slave_config.c Fri Oct 10 09:37:06 2008 +0000 @@ -298,7 +298,7 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size) { - return 0; + return 0; // TODO } /*****************************************************************************/ @@ -306,7 +306,7 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc, size_t size) { - return 0; + return 0; // TODO } /*****************************************************************************/ @@ -314,6 +314,15 @@ void ecrt_slave_config_state(const ec_slave_config_t *sc, ec_slave_config_state_t *state) { -} - -/*****************************************************************************/ + ec_ioctl_sc_state_t data; + + data.config_index = sc->index; + data.state = state; + + if (ioctl(sc->master->fd, EC_IOCTL_SC_STATE, &data) == -1) { + fprintf(stderr, "Failed to get slave configuration state: %s\n", + strerror(errno)); + } +} + +/*****************************************************************************/ diff -r 900f1124e8f8 -r 5f9d1abbee71 master/cdev.c --- a/master/cdev.c Fri Oct 10 08:34:15 2008 +0000 +++ b/master/cdev.c Fri Oct 10 09:37:06 2008 +0000 @@ -1560,6 +1560,29 @@ /*****************************************************************************/ +/** Get the master state. + */ +int ec_cdev_ioctl_master_state( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_master_state_t data; + + if (unlikely(!priv->requested)) + return -EPERM; + + ecrt_master_state(master, &data); + + if (copy_to_user((void __user *) arg, &data, sizeof(data))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + /** Set the direction of a sync manager. */ int ec_cdev_ioctl_sc_sync( @@ -1839,6 +1862,45 @@ /*****************************************************************************/ +/** Get the slave configuration's state. + */ +int ec_cdev_ioctl_sc_state( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_state_t data; + const ec_slave_config_t *sc; + ec_slave_config_state_t state; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + return -EFAULT; + } + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config_const(master, data.config_index))) { + up(&master->master_sem); + return -ESRCH; + } + + ecrt_slave_config_state(sc, &state); + + up(&master->master_sem); + + if (copy_to_user((void __user *) data.state, &state, sizeof(state))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + /** Gets the domain's offset in the total process data. */ int ec_cdev_ioctl_domain_offset( @@ -1925,6 +1987,45 @@ return 0; } +/*****************************************************************************/ + +/** Get the domain state. + */ +int ec_cdev_ioctl_domain_state( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_domain_state_t data; + const ec_domain_t *domain; + ec_domain_state_t state; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + return -EFAULT; + } + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(domain = ec_master_find_domain_const(master, data.domain_index))) { + up(&master->master_sem); + return -ESRCH; + } + + ecrt_domain_state(domain, &state); + + up(&master->master_sem); + + if (copy_to_user((void __user *) data.state, &state, sizeof(state))) + return -EFAULT; + + return 0; +} + /****************************************************************************** * File operations *****************************************************************************/ @@ -2067,6 +2168,8 @@ if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_receive(master, arg, priv); + case EC_IOCTL_MASTER_STATE: + return ec_cdev_ioctl_master_state(master, arg, priv); case EC_IOCTL_SC_SYNC: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; @@ -2095,6 +2198,8 @@ if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_sc_sdo(master, arg, priv); + case EC_IOCTL_SC_STATE: + return ec_cdev_ioctl_sc_state(master, arg, priv); case EC_IOCTL_DOMAIN_OFFSET: return ec_cdev_ioctl_domain_offset(master, arg, priv); case EC_IOCTL_DOMAIN_PROCESS: @@ -2105,6 +2210,8 @@ if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_domain_queue(master, arg, priv); + case EC_IOCTL_DOMAIN_STATE: + return ec_cdev_ioctl_domain_state(master, arg, priv); default: return -ENOTTY; } diff -r 900f1124e8f8 -r 5f9d1abbee71 master/ioctl.h --- a/master/ioctl.h Fri Oct 10 08:34:15 2008 +0000 +++ b/master/ioctl.h Fri Oct 10 09:37:06 2008 +0000 @@ -56,6 +56,7 @@ #define EC_IOW(nr, type) _IOW(EC_IOCTL_TYPE, nr, type) #define EC_IOWR(nr, type) _IOWR(EC_IOCTL_TYPE, nr, type) +// Command-line tool #define EC_IOCTL_MASTER EC_IOR(0x00, ec_ioctl_master_t) #define EC_IOCTL_SLAVE EC_IOWR(0x01, ec_ioctl_slave_t) #define EC_IOCTL_SLAVE_SYNC EC_IOWR(0x02, ec_ioctl_slave_sync_t) @@ -79,22 +80,28 @@ #define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x14, ec_ioctl_config_pdo_entry_t) #define EC_IOCTL_CONFIG_SDO EC_IOWR(0x15, ec_ioctl_config_sdo_t) +// Application interface #define EC_IOCTL_REQUEST EC_IO(0x16) #define EC_IOCTL_CREATE_DOMAIN EC_IO(0x17) #define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x18, ec_ioctl_config_t) #define EC_IOCTL_ACTIVATE EC_IOR(0x19, size_t) #define EC_IOCTL_SEND EC_IO(0x1a) #define EC_IOCTL_RECEIVE EC_IO(0x1b) -#define EC_IOCTL_SC_SYNC EC_IOW(0x1c, ec_ioctl_config_t) -#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x1c, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x1d, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x1e, ec_ioctl_add_pdo_entry_t) -#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x1f, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x20, ec_ioctl_reg_pdo_entry_t) -#define EC_IOCTL_SC_SDO EC_IOW(0x21, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x22) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x23) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x24) +#define EC_IOCTL_MASTER_STATE EC_IOR(0x1c, ec_master_state_t) +#define EC_IOCTL_SC_SYNC EC_IOW(0x1d, ec_ioctl_config_t) +#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x1e, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x1f, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x20, ec_ioctl_add_pdo_entry_t) +#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x21, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x22, ec_ioctl_reg_pdo_entry_t) +#define EC_IOCTL_SC_SDO EC_IOW(0x23, ec_ioctl_sc_sdo_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x24, ec_ioctl_sc_state_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x25) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x26) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x27) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x28, ec_ioctl_domain_state_t) + +/*****************************************************************************/ #define EC_IOCTL_STRING_SIZE 64 @@ -413,6 +420,26 @@ /*****************************************************************************/ +typedef struct { + // inputs + uint32_t config_index; + + // outputs + ec_slave_config_state_t *state; +} ec_ioctl_sc_state_t; + +/*****************************************************************************/ + +typedef struct { + // inputs + uint32_t domain_index; + + // outputs + ec_domain_state_t *state; +} ec_ioctl_domain_state_t; + +/*****************************************************************************/ + /** \endcond */ #endif