<div dir="ltr"><div>Good morning, my name is Eduardo and I am a member of a work group from a university in Mexico and we are exploring ethercat technology, we use a NUC and an EPOS4 with the IgH library, we have many problems with Syncronia, we even managed to solve it in partly by using some codes within our project, we noticed the critical failures when we made movements with motors, having emergency exits and stopping the trajectory, it was when we explored the error and defined it by 2 parts by means of grep and by EPOS4 records, We return to the beginning of the development and we use the dc_user again and again we find the same error, if you could help us I would greatly appreciate it.<br></div><div><br></div><div><br></div><div>[ 2028.813557] EtherCAT ERROR 0-0: AL status message 0x001A: "Synchronization error".</div><div><br></div><div>The kernel and patch from Xenomai are <a href="https://source.denx.de/Xenomai/linux-dovetail">https://source.denx.de/Xenomai/linux-dovetail</a> //dovetail 5.10.76 patch</div><div><br></div><div>20.04编译Linux5.10.76+Xenomai-3.2.1<br></div><div><br></div><div>We used a generic ethernet port from NUC and we are planning to use a Dual Port Gigabit Ethernet card.</div><div><br></div><div>This is the IgH configuration that has been selected.</div><div><br></div>sudo ./configure --with-module-dir=/lib/modules/5.10.76-xenomai --enable-eoe=no --enable-generic=si --enable-8139too=no --enable-e1000e --enable-cycles --enable-hrtimer --with-xenomai-dir=/usr/xenomai --prefix=/opt/etherlab <br><div><br></div><div>Grep from the console before running the code.</div><div><br></div><div>rtlinux@rtlinux-NUC7i7BNH:~/xenomai/ethercat-e1000e-5.10$ dmesg | grep -i ether</div><div><br>[ 1335.760859] EtherCAT: Master driver 1.5.2 unknown<br>[ 1335.760921] EtherCAT: 1 master waiting for devices.<br>[ 1335.767208] ec_generic: EtherCAT master generic Ethernet device module 1.5.2 unknown<br>[ 1335.767214] EtherCAT: Accepting 94:C6:91:AD:1D:92 as main device for master 0.<br>[ 1335.786391] EtherCAT 0: Starting EtherCAT-IDLE thread.<br>[ 1335.786429] EtherCAT 0: Link state of ecm0 changed to UP.<br>[ 1335.790455] EtherCAT 0: 1 slave(s) responding on main device.<br>[ 1335.790456] EtherCAT 0: Slave states on main device: INIT.<br>[ 1335.791004] EtherCAT 0: Scanning bus.<br>[ 1335.971731] EtherCAT 0: Bus scanning completed in 180 ms.<br>[ 1335.971732] EtherCAT 0: Using slave 0 as DC reference clock.<br>[ 1335.975743] EtherCAT 0: Slave states on main device: PREOP.<br></div><div><br></div><div><div>Grep from the console after running the code.</div></div><div><div><br></div><div>rtlinux@rtlinux-NUC7i7BNH:~/xenomai/ethercat-e1000e-5.10$ dmesg | grep -i ether</div></div><div><br></div><div> 1335.767208] ec_generic: EtherCAT master generic Ethernet device module 1.5.2 unknown<br>[ 1335.767214] EtherCAT: Accepting 94:C6:91:AD:1D:92 as main device for master 0.<br>[ 1335.786391] EtherCAT 0: Starting EtherCAT-IDLE thread.<br>[ 1335.786429] EtherCAT 0: Link state of ecm0 changed to UP.<br>[ 1335.790455] EtherCAT 0: 1 slave(s) responding on main device.<br>[ 1335.790456] EtherCAT 0: Slave states on main device: INIT.<br>[ 1335.791004] EtherCAT 0: Scanning bus.<br>[ 1335.971731] EtherCAT 0: Bus scanning completed in 180 ms.<br>[ 1335.971732] EtherCAT 0: Using slave 0 as DC reference clock.<br>[ 1335.975743] EtherCAT 0: Slave states on main device: PREOP.<br>[ 2022.370620] EtherCAT: Requesting master 0...<br>[ 2022.370623] EtherCAT: Successfully requested master 0.<br>[ 2022.370645] EtherCAT 0: Domain0: Logical address 0x00000000, 2 byte, expected working counter 1.<br>[ 2022.370646] EtherCAT 0:   Datagram domain0-0-main: Logical offset 0x00000000, 2 byte, type LWR.<br>[ 2022.372689] EtherCAT 0: Master thread exited.<br>[ 2022.372691] EtherCAT 0: Starting EtherCAT-OP thread.<br>[ 2024.375379] EtherCAT WARNING 0: 4 datagrams UNMATCHED!<br>[ 2024.380714] EtherCAT WARNING: Datagram 00000000047a0a66 (domain0-0-main) was SKIPPED 2 times.<br>[ 2027.593324] EtherCAT WARNING 0-0: Slave did not sync after 5000 ms.<br>[ 2027.605534] EtherCAT 0: Domain 0: Working counter changed to 1/1<br>[ 2027.907634] EtherCAT 0: Slave states on main device: OP.<br>[ 2028.374763] EtherCAT WARNING 0: 12 datagrams UNMATCHED!<br>[ 2028.396512] EtherCAT WARNING: Datagram 00000000047a0a66 (domain0-0-main) was SKIPPED 6 times.<br>[ 2028.604830] EtherCAT 0: Releasing master...<br>[ 2028.608678] EtherCAT 0: Master thread exited.<br>[ 2028.608688] EtherCAT 0: Starting EtherCAT-IDLE thread.<br>[ 2028.608831] EtherCAT 0: Released.<br>[ 2028.608843] EtherCAT 0: 0 slave(s) responding on main device.<br>[ 2028.612972] EtherCAT 0: 1 slave(s) responding on main device.<br>[ 2028.612975] EtherCAT 0: Slave states on main device: SAFEOP + ERROR.<br>[ 2028.613588] EtherCAT 0: Scanning bus.<br>[ 2028.614191] EtherCAT WARNING 0-0: Slave has state error bit set (SAFEOP + ERROR)!<br>[ 2028.624296] EtherCAT WARNING: Datagram 00000000a2dc8bb0 (master-fsm) was SKIPPED 1 time.<br>[ 2028.805082] EtherCAT 0: Bus scanning completed in 192 ms.<br>[ 2028.805084] EtherCAT 0: Using slave 0 as DC reference clock.<br>[ 2028.813557] EtherCAT ERROR 0-0: AL status message 0x001A: "Synchronization error".<br>[ 2028.815031] EtherCAT 0-0: Acknowledged state SAFEOP.<br>[ 2028.826964] EtherCAT 0: Slave states on main device: PREOP.<br></div><div><br></div><div>Code dc_user.cpp</div><div><br></div><div>/*****************************************************************************<br> *<br> *  Copyright (C) 2007-2022  Florian Pose, Ingenieurgemeinschaft IgH<br> *<br> *  This file is part of the IgH EtherCAT Master.<br> *<br> *  The IgH EtherCAT Master is free software; you can redistribute it and/or<br> *  modify it under the terms of the GNU General Public License version 2, as<br> *  published by the Free Software Foundation.<br> *<br> *  The IgH EtherCAT Master is distributed in the hope that it will be useful,<br> *  but WITHOUT ANY WARRANTY; without even the implied warranty of<br> *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General<br> *  Public License for more details.<br> *<br> *  You should have received a copy of the GNU General Public License along<br> *  with the IgH EtherCAT Master; if not, write to the Free Software<br> *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA<br> *<br> *  ---<br> *<br> *  The license mentioned above concerns the source code only. Using the<br> *  EtherCAT technology and brand is only permitted in compliance with the<br> *  industrial property and similar rights of Beckhoff Automation GmbH.<br> *<br> ****************************************************************************/<br><br>#include <errno.h><br>#include <signal.h><br>#include <stdio.h><br>#include <string.h><br>#include <sys/resource.h><br>#include <sys/time.h><br>#include <sys/types.h><br>#include <unistd.h><br>#include <time.h><br>#include <sys/mman.h><br>#include <malloc.h><br>#include <sched.h> /* sched_setscheduler() */<br><br>/****************************************************************************/<br><br>#include "ecrt.h"<br><br>/****************************************************************************/<br><br>// Application parameters<br>#define FREQUENCY 1000<br>#define CLOCK_TO_USE CLOCK_MONOTONIC<br>#define MEASURE_TIMING<br>#define NUMBER_OF_SAMPLE 1000<br><br>/****************************************************************************/<br><br>#define NSEC_PER_SEC (1000000000L)<br>#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)<br>#define SHIFT0 (PERIOD_NS/2)<br><br>#define DIFF_NS(A, B) (((B).tv_sec - (A).tv_sec) * NSEC_PER_SEC + \<br>        (B).tv_nsec - (A).tv_nsec)<br><br>#define TIMESPEC2NS(T) ((uint64_t) (T).tv_sec * NSEC_PER_SEC + (T).tv_nsec)<br><br>/****************************************************************************/<br><br>// EtherCAT<br>static ec_master_t *master = NULL;<br>static ec_master_state_t master_state = {};<br><br>static ec_domain_t *domain1 = NULL;<br>static ec_domain_state_t domain1_state = {};<br><br>int slave_working = 0;<br><br>/****************************************************************************/<br><br>// process data<br>static uint8_t *domain1_pd = NULL;<br><br>#define BusCouplerPos    0, 0<br><br><br>#define EPOS4 0x000000fb , 0x61500000 <br><br><br>// offsets for PDO entries<br>static int controlworld;<br><br>static unsigned int counter = 0;<br>static unsigned int blink = 0;<br>static unsigned int sync_ref_counter = 0;<br>const struct timespec cycletime = {0, PERIOD_NS};<br><br>/****************************************************************************/<br><br>struct timespec timespec_add(struct timespec time1, struct timespec time2)<br>{<br>    struct timespec result;<br><br>    if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {<br>        result.tv_sec = time1.tv_sec + time2.tv_sec + 1;<br>        result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;<br>    } else {<br>        result.tv_sec = time1.tv_sec + time2.tv_sec;<br>        result.tv_nsec = time1.tv_nsec + time2.tv_nsec;<br>    }<br><br>    return result;<br>}<br><br>/****************************************************************************/<br><br>void check_domain1_state(void)<br>{<br>    ec_domain_state_t ds;<br><br>    ecrt_domain_state(domain1, &ds);<br><br>    if (ds.working_counter != domain1_state.working_counter)<br>        printf("Domain1: WC %u.\n", ds.working_counter);<br>    if (ds.wc_state != domain1_state.wc_state)<br>        printf("Domain1: State %u.\n", ds.wc_state);<br>        if (ds.wc_state == 2)<br>  {<br>    slave_working = 1;<br>  }<br>    domain1_state = ds;<br>}<br><br>/****************************************************************************/<br><br>void check_master_state(void)<br>{<br>    ec_master_state_t ms;<br><br>    ecrt_master_state(master, &ms);<br><br>    if (ms.slaves_responding != master_state.slaves_responding)<br>        printf("%u slave(s).\n", ms.slaves_responding);<br>    if (ms.al_states != master_state.al_states)<br>        printf("AL states: 0x%02X.\n", ms.al_states);<br>    if (ms.link_up != master_state.link_up)<br>        printf("Link is %s.\n", ms.link_up ? "up" : "down");<br><br>    master_state = ms;<br>}<br><br>/****************************************************************************/<br><br>void cyclic_task()<br>{<br>    struct timespec wakeupTime, time;<br>    uint32_t sample_no = 0;<br>#ifdef MEASURE_TIMING<br>    struct timespec startTime, endTime, lastStartTime = {};<br>    uint32_t period_ns = 0, exec_ns = 0, latency_ns = 0,<br>             latency_min_ns = 0, latency_max_ns = 0,<br>             period_min_ns = 0, period_max_ns = 0,<br>             exec_min_ns = 0, exec_max_ns = 0;<br>#endif<br><br>    // get current time<br>    clock_gettime(CLOCK_TO_USE, &wakeupTime);<br><br>  //  while(1) <br>      while(sample_no < NUMBER_OF_SAMPLE){<br>        wakeupTime = timespec_add(wakeupTime, cycletime);<br>        clock_nanosleep(CLOCK_TO_USE, TIMER_ABSTIME, &wakeupTime, NULL);<br><br>        // Write application time to master<br>        //<br>        // It is a good idea to use the target time (not the measured time) as<br>        // application time, because it is more stable.<br>        //<br>        ecrt_master_application_time(master, TIMESPEC2NS(wakeupTime));<br><br>#ifdef MEASURE_TIMING<br>        clock_gettime(CLOCK_TO_USE, &startTime);<br>        latency_ns = DIFF_NS(wakeupTime, startTime);<br>        period_ns = DIFF_NS(lastStartTime, startTime);<br>        exec_ns = DIFF_NS(lastStartTime, endTime);<br>        lastStartTime = startTime;<br><br>        if (latency_ns > latency_max_ns) {<br>            latency_max_ns = latency_ns;<br>        }<br>        if (latency_ns < latency_min_ns) {<br>            latency_min_ns = latency_ns;<br>        }<br>        if (period_ns > period_max_ns) {<br>            period_max_ns = period_ns;<br>        }<br>        if (period_ns < period_min_ns) {<br>            period_min_ns = period_ns;<br>        }<br>        if (exec_ns > exec_max_ns) {<br>            exec_max_ns = exec_ns;<br>        }<br>        if (exec_ns < exec_min_ns) {<br>            exec_min_ns = exec_ns;<br>        }<br>#endif<br><br>        // receive process data<br>        ecrt_master_receive(master);<br>        ecrt_domain_process(domain1);<br><br>        // check process data state (optional)<br>        check_domain1_state();<br>        <br>        <br>    if (slave_working)<br>    {<br>      // output timing stats<br>      sample_no++;<br>    }<br><br><br>        if (counter) {<br>            counter--;<br>        } else { // do this at 1 Hz<br>            counter = FREQUENCY;<br><br>            // check for master state (optional)<br>            check_master_state();<br><br>#ifdef MEASURE_TIMING<br>            // output timing stats<br>            printf("period     %10u ... %10u\n",<br>                    period_min_ns, period_max_ns);<br>            printf("exec       %10u ... %10u\n",<br>                    exec_min_ns, exec_max_ns);<br>            printf("latency    %10u ... %10u\n",<br>                    latency_min_ns, latency_max_ns);<br>            period_max_ns = 0;<br>            period_min_ns = 0xffffffff;<br>            exec_max_ns = 0;<br>            exec_min_ns = 0xffffffff;<br>            latency_max_ns = 0;<br>            latency_min_ns = 0xffffffff;<br>             printf("sample_no     %10u \n",<br>                    sample_no);<br>#endif<br><br>            // calculate new process data<br>            blink = !blink;<br>        }<br><br>        // write process data<br>        EC_WRITE_U8(domain1_pd + controlworld, blink ? 0x66 : 0x99);<br><br><br>        if (sync_ref_counter) {<br>            sync_ref_counter--;<br>        } else {<br>            sync_ref_counter = 1; // sync every cycle<br><br>            clock_gettime(CLOCK_TO_USE, &time);<br>            ecrt_master_sync_reference_clock_to(master, TIMESPEC2NS(time));<br>        }<br>        ecrt_master_sync_slave_clocks(master);<br><br>        // send process data<br>        ecrt_domain_queue(domain1);<br>        ecrt_master_send(master);<br><br>#ifdef MEASURE_TIMING<br>        clock_gettime(CLOCK_TO_USE, &endTime);<br>#endif<br>    }<br>}<br><br>/****************************************************************************/<br><br>int main(int argc, char **argv)<br>{<br>    ec_slave_config_t *sc;<br><br>    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {<br>        perror("mlockall failed");<br>        return -1;<br>    }<br><br>    master = ecrt_request_master(0);<br>    if (!master)<br>        return -1;<br><br>    domain1 = ecrt_master_create_domain(master);<br>    if (!domain1)<br>        return -1;<br><br>    // Create configuration for bus coupler<br>    sc = ecrt_master_slave_config(master, BusCouplerPos, EPOS4);<br>    if (!sc)<br>        return -1;<br><br>    <br>    controlworld = ecrt_slave_config_reg_pdo_entry(sc, 0x6040, 0x00, domain1, NULL);<br>    if (controlworld < 0)<br>        return -1;<br><br><br>    // configure SYNC signals for this slave<br>    ecrt_slave_config_dc(sc, 0x0300, PERIOD_NS, SHIFT0, 0, 0);<br><br>    printf("Activating master...\n");<br>    if (ecrt_master_activate(master))<br>        return -1;<br><br>    if (!(domain1_pd = ecrt_domain_data(domain1))) {<br>        return -1;<br>    }<br><br>    /* Set priority */<br><br>    struct sched_param param = {};<br>    param.sched_priority = sched_get_priority_max(SCHED_FIFO);<br><br>    printf("Using priority %i.", param.sched_priority);<br>    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {<br>        perror("sched_setscheduler failed");<br>    }<br><br>    printf("Starting cyclic function.\n");<br>    cyclic_task();<br>    ecrt_release_master(master);<br>    return 0;<br>}<br><br>/****************************************************************************/<br></div>-- <br><div dir="ltr" data-smartmail="gmail_signature"><div dir="ltr"><br><div>Dr. Eduardo Rodríguez Orozco</div></div></div></div>