# HG changeset patch # User Florian Pose # Date 1465473142 -7200 # Node ID 14a18eae7e3b0677239e661e5072d5855a185c08 # Parent 0f4b7d799c4453b10940f7f974fcf9c38f436ebf Migrated user-space example to use clock_nanosleep(). diff -r 0f4b7d799c44 -r 14a18eae7e3b examples/user/Makefile.am --- a/examples/user/Makefile.am Fri May 13 17:43:00 2016 +0200 +++ b/examples/user/Makefile.am Thu Jun 09 13:52:22 2016 +0200 @@ -31,6 +31,6 @@ ec_user_example_SOURCES = main.c ec_user_example_CFLAGS = -I$(top_srcdir)/include -Wall -ec_user_example_LDFLAGS = -L$(top_builddir)/lib/.libs -lethercat +ec_user_example_LDFLAGS = -L$(top_builddir)/lib/.libs -lethercat -lrt #------------------------------------------------------------------------------ diff -r 0f4b7d799c44 -r 14a18eae7e3b examples/user/main.c --- a/examples/user/main.c Fri May 13 17:43:00 2016 +0200 +++ b/examples/user/main.c Thu Jun 09 13:52:22 2016 +0200 @@ -35,6 +35,8 @@ #include #include #include +#include /* clock_gettime() */ +#include /* mlockall() */ /****************************************************************************/ @@ -42,13 +44,18 @@ /****************************************************************************/ -// Application parameters -#define FREQUENCY 100 -#define PRIORITY 1 - -// Optional features -#define CONFIGURE_PDOS 1 -#define SDO_ACCESS 0 +/** Task period in ns. */ +#define PERIOD_NS (1000000) + +#define MAX_SAFE_STACK (8 * 1024) /* The maximum stack size which is + guranteed safe to access without + faulting */ + +/****************************************************************************/ + +/* Constants */ +#define NSEC_PER_SEC (1000000000) +#define FREQUENCY (NSEC_PER_SEC / PERIOD_NS) /****************************************************************************/ @@ -62,10 +69,6 @@ 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; -static unsigned int user_alarms = 0; - /****************************************************************************/ // process data @@ -102,8 +105,6 @@ /*****************************************************************************/ -#if CONFIGURE_PDOS - // Analog in -------------------------- static ec_pdo_entry_info_t el3102_pdo_entries[] = { @@ -165,13 +166,6 @@ {1, EC_DIR_INPUT}, {0xff} }; -#endif - -/*****************************************************************************/ - -#if SDO_ACCESS -static ec_sdo_request_t *sdo; -#endif /*****************************************************************************/ @@ -181,10 +175,12 @@ ecrt_domain_state(domain1, &ds); - if (ds.working_counter != domain1_state.working_counter) + if (ds.working_counter != domain1_state.working_counter) { printf("Domain1: WC %u.\n", ds.working_counter); - if (ds.wc_state != domain1_state.wc_state) + } + if (ds.wc_state != domain1_state.wc_state) { printf("Domain1: State %u.\n", ds.wc_state); + } domain1_state = ds; } @@ -197,12 +193,15 @@ ecrt_master_state(master, &ms); - if (ms.slaves_responding != master_state.slaves_responding) + if (ms.slaves_responding != master_state.slaves_responding) { printf("%u slave(s).\n", ms.slaves_responding); - if (ms.al_states != master_state.al_states) + } + 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) + } + if (ms.link_up != master_state.link_up) { printf("Link is %s.\n", ms.link_up ? "up" : "down"); + } master_state = ms; } @@ -215,51 +214,28 @@ ecrt_slave_config_state(sc_ana_in, &s); - if (s.al_state != sc_ana_in_state.al_state) + 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) + } + 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 "); + } + if (s.operational != sc_ana_in_state.operational) { + printf("AnaIn: %soperational.\n", s.operational ? "" : "Not "); + } sc_ana_in_state = s; } /*****************************************************************************/ -#if SDO_ACCESS -void read_sdo(void) -{ - switch (ecrt_sdo_request_state(sdo)) { - case EC_REQUEST_UNUSED: // request was not used yet - ecrt_sdo_request_read(sdo); // trigger first read - break; - case EC_REQUEST_BUSY: - fprintf(stderr, "Still busy...\n"); - break; - case EC_REQUEST_SUCCESS: - fprintf(stderr, "SDO value: 0x%04X\n", - EC_READ_U16(ecrt_sdo_request_data(sdo))); - ecrt_sdo_request_read(sdo); // trigger next read - break; - case EC_REQUEST_ERROR: - fprintf(stderr, "Failed to read SDO!\n"); - ecrt_sdo_request_read(sdo); // retry reading - break; - } -} -#endif - -/****************************************************************************/ - void cyclic_task() { // receive process data ecrt_master_receive(master); ecrt_domain_process(domain1); - // check process data state (optional) + // check process data state check_domain1_state(); if (counter) { @@ -273,14 +249,8 @@ // check for master state (optional) check_master_state(); - // check for islave configuration state(s) (optional) + // check for slave configuration state(s) (optional) check_slave_config_states(); - -#if SDO_ACCESS - // read process data SDO - read_sdo(); -#endif - } #if 0 @@ -302,12 +272,11 @@ /****************************************************************************/ -void signal_handler(int signum) { - switch (signum) { - case SIGALRM: - sig_alarms++; - break; - } +void stack_prefault(void) +{ + unsigned char dummy[MAX_SAFE_STACK]; + + memset(dummy, 0, MAX_SAFE_STACK); } /****************************************************************************/ @@ -315,16 +284,18 @@ int main(int argc, char **argv) { ec_slave_config_t *sc; - struct sigaction sa; - struct itimerval tv; + struct timespec wakeup_time; + int ret = 0; master = ecrt_request_master(0); - if (!master) - return -1; + if (!master) { + return -1; + } domain1 = ecrt_master_create_domain(master); - if (!domain1) - return -1; + if (!domain1) { + return -1; + } if (!(sc_ana_in = ecrt_master_slave_config( master, AnaInSlavePos, Beckhoff_EL3102))) { @@ -332,16 +303,6 @@ return -1; } -#if SDO_ACCESS - fprintf(stderr, "Creating SDO requests...\n"); - if (!(sdo = ecrt_slave_config_create_sdo_request(sc_ana_in, 0x3102, 2, 2))) { - fprintf(stderr, "Failed to create SDO request.\n"); - return -1; - } - ecrt_sdo_request_timeout(sdo, 500); // ms -#endif - -#if CONFIGURE_PDOS printf("Configuring PDOs...\n"); if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3102_syncs)) { fprintf(stderr, "Failed to configure PDOs.\n"); @@ -369,12 +330,12 @@ fprintf(stderr, "Failed to configure PDOs.\n"); return -1; } -#endif // Create configuration for bus coupler sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100); - if (!sc) - return -1; + if (!sc) { + return -1; + } if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) { fprintf(stderr, "PDO entry registration failed!\n"); @@ -382,55 +343,55 @@ } printf("Activating master...\n"); - if (ecrt_master_activate(master)) - return -1; + if (ecrt_master_activate(master)) { + return -1; + } if (!(domain1_pd = ecrt_domain_data(domain1))) { return -1; } -#if PRIORITY + /* Set priority */ + pid_t pid = getpid(); - if (setpriority(PRIO_PROCESS, pid, -19)) + if (setpriority(PRIO_PROCESS, pid, -19)) { fprintf(stderr, "Warning: Failed to set priority: %s\n", strerror(errno)); -#endif - - sa.sa_handler = signal_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGALRM, &sa, 0)) { - fprintf(stderr, "Failed to install signal handler!\n"); - return -1; - } - - printf("Starting timer...\n"); - tv.it_interval.tv_sec = 0; - 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)) { - fprintf(stderr, "Failed to start timer: %s\n", strerror(errno)); - return 1; - } - - printf("Started.\n"); + } + + /* Lock memory */ + + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + fprintf(stderr, "Warning: Failed to lock memory: %s\n", + strerror(errno)); + } + + stack_prefault(); + + printf("Starting RT task with dt=%u ns.\n", PERIOD_NS); + + clock_gettime(CLOCK_MONOTONIC, &wakeup_time); + wakeup_time.tv_sec += 1; /* start in future */ + wakeup_time.tv_nsec = 0; + while (1) { - pause(); - -#if 0 - struct timeval t; - gettimeofday(&t, NULL); - printf("%u.%06u\n", t.tv_sec, t.tv_usec); -#endif - - while (sig_alarms != user_alarms) { - cyclic_task(); - user_alarms++; + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, + &wakeup_time, NULL); + if (ret) { + fprintf(stderr, "clock_nanosleep(): %s\n", strerror(ret)); + break; } - } - - return 0; -} - -/****************************************************************************/ + + cyclic_task(); + + wakeup_time.tv_nsec += PERIOD_NS; + while (wakeup_time.tv_nsec >= NSEC_PER_SEC) { + wakeup_time.tv_nsec -= NSEC_PER_SEC; + wakeup_time.tv_sec++; + } + } + + return ret; +} + +/****************************************************************************/