OpenEtherCATsociety / SOEM

Simple Open Source EtherCAT Master
Other
1.31k stars 669 forks source link

Invalid input mapping at cold-start #530

Closed balazs1123 closed 3 years ago

balazs1123 commented 3 years ago

Hello,

I'd like to ask your help on a PDO mapping issue of Ingenia EVE-XCR servo-drives (since I'm not an expert of EtherCAT). When I do a power cycle (so having a cold-start) on the drives and then run my SOEM wrapper program, I get the following error almost everytime (rarely, approx. 1 out of 10, I have a successful configuration): Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping Servo Drive 2 State= 12 StatusCode= 52 : Unknown

However, if I restart the my program, while the drives are still powered, then everything works fine. Or if I run TwinCAT this issue never happens, but that's irrelevant for me, since we use will not use TwinCAT as a Master stack. I tried to do the PDO mapping with and without Complete Access, it did not change anything.

Slave info after cold-start with failed PDO mapping:

SOEM (Simple Open EtherCAT Master)
Slaveinfo
Starting slaveinfo
ec_init on ens37 succeeded.
2 slaves found and configured.
Calculated workcounter 6
Not all slaves reached safe operational state.
Slave 1 State=12 StatusCode=  24 : Invalid input mapping

Slave:1
 Name:Servo Drives
 Output size: 96bits
 Input size: 224bits
 State: 18
 Delay: 0[ns]
 Has DC: 1
 Serialno.: 0
 DCParentport:0
 Activeports:0.1.0.0
 Configured address: 1001
 Man: 0000029c ID: 02c30001 Rev: 0005000b
 SM0 A:1000 L: 128 F:00010026 Type:1
 SM1 A:1400 L: 128 F:00010022 Type:2
 SM2 A:1800 L:  12 F:00010064 Type:3
 SM3 A:1c00 L:  28 F:00010020 Type:4
 FMMU0 Ls:00000000 Ll:  12 Lsb:0 Leb:7 Ps:1800 Psb:0 Ty:02 Act:01
 FMMU1 Ls:00000018 Ll:  28 Lsb:0 Leb:7 Ps:1c00 Psb:0 Ty:01 Act:01
 FMMUfunc 0:1 1:2 2:3 3:0
 MBX length wr: 128 rd: 128 MBX protocols : 0e
 CoE details: 2f FoE details: 01 EoE details: 01 SoE details: 00
 Ebus current: 0[mA]
 only LRD/LWR:0
PDO mapping according to CoE :
  SM2 outputs
     addr b   index: sub bitl data_type    name
  [0x0000.0] 0x2010:0x00 0x10 UNSIGNED16   Control word
  [0x0002.0] 0x2014:0x00 0x10 UNSIGNED16   Operation mode
  [0x0004.0] 0x2021:0x00 0x20 REAL32       Velocity set-point
  [0x0008.0] 0x201A:0x00 0x20 REAL32       Current quadrature set-point
  SM3 inputs
     addr b   index: sub bitl data_type    name
  [0x0018.0] 0x2011:0x00 0x10 UNSIGNED16   Status word
  [0x001A.0] 0x2015:0x00 0x10 UNSIGNED16   Operation mode display
  [0x001C.0] 0x2031:0x00 0x20 REAL32       Actual velocity
  [0x0020.0] 0x203B:0x00 0x20 REAL32       Current quadrature value
  [0x0024.0] 0x204A:0x00 0x20 INTEGER32    BiSS-C slave 1 / Primary SSI - Position
  [0x0028.0] 0x200F:0x00 0x20 INTEGER32    Last error
  [0x002C.0] 0x2061:0x00 0x20 REAL32       Primary temperature value
  [0x0030.0] 0x2060:0x00 0x20 REAL32       Bus voltage value

Slave:2
 Name:Servo Drives
 Output size: 96bits
 Input size: 224bits
 State: 4
 Delay: 1082[ns]
 Has DC: 1
 Serialno.: 0
 DCParentport:1
 Activeports:1.1.0.0
 Configured address: 1002
 Man: 0000029c ID: 02c30001 Rev: 0005000b
 SM0 A:1000 L: 128 F:00010026 Type:1
 SM1 A:1400 L: 128 F:00010022 Type:2
 SM2 A:1800 L:  12 F:00010064 Type:3
 SM3 A:1c00 L:  28 F:00010020 Type:4
 FMMU0 Ls:0000000c Ll:  12 Lsb:0 Leb:7 Ps:1800 Psb:0 Ty:02 Act:01
 FMMU1 Ls:00000034 Ll:  28 Lsb:0 Leb:7 Ps:1c00 Psb:0 Ty:01 Act:01
 FMMUfunc 0:1 1:2 2:3 3:0
 MBX length wr: 128 rd: 128 MBX protocols : 0e
 CoE details: 2f FoE details: 01 EoE details: 01 SoE details: 00
 Ebus current: 0[mA]
 only LRD/LWR:0
PDO mapping according to CoE :
  SM2 outputs
     addr b   index: sub bitl data_type    name
  [0x000C.0] 0x2010:0x00 0x10 UNSIGNED16   Control word
  [0x000E.0] 0x2014:0x00 0x10 UNSIGNED16   Operation mode
  [0x0010.0] 0x2021:0x00 0x20 REAL32       Velocity set-point
  [0x0014.0] 0x201A:0x00 0x20 REAL32       Current quadrature set-point
  SM3 inputs
     addr b   index: sub bitl data_type    name
  [0x0034.0] 0x2011:0x00 0x10 UNSIGNED16   Status word
  [0x0036.0] 0x2015:0x00 0x10 UNSIGNED16   Operation mode display
  [0x0038.0] 0x2031:0x00 0x20 REAL32       Actual velocity
  [0x003C.0] 0x203B:0x00 0x20 REAL32       Current quadrature value
  [0x0040.0] 0x204A:0x00 0x20 INTEGER32    BiSS-C slave 1 / Primary SSI - Position
  [0x0044.0] 0x200F:0x00 0x20 INTEGER32    Last error
  [0x0048.0] 0x2061:0x00 0x20 REAL32       Primary temperature value
  [0x004C.0] 0x2060:0x00 0x20 REAL32       Bus voltage value
End slaveinfo, close socket
End program

Slave info after the restarted program, with successful PDO mapping:

SOEM (Simple Open EtherCAT Master)
Slaveinfo
Starting slaveinfo
ec_init on ens37 succeeded.
2 slaves found and configured.
Calculated workcounter 6

Slave:1
 Name:Servo Drives
 Output size: 96bits
 Input size: 224bits
 State: 4
 Delay: 0[ns]
 Has DC: 1
 Serialno.: 0
 DCParentport:0
 Activeports:0.1.0.0
 Configured address: 1001
 Man: 0000029c ID: 02c30001 Rev: 0005000b
 SM0 A:1000 L: 128 F:00010026 Type:1
 SM1 A:1400 L: 128 F:00010022 Type:2
 SM2 A:1800 L:  12 F:00010064 Type:3
 SM3 A:1c00 L:  28 F:00010020 Type:4
 FMMU0 Ls:00000000 Ll:  12 Lsb:0 Leb:7 Ps:1800 Psb:0 Ty:02 Act:01
 FMMU1 Ls:00000018 Ll:  28 Lsb:0 Leb:7 Ps:1c00 Psb:0 Ty:01 Act:01
 FMMUfunc 0:1 1:2 2:3 3:0
 MBX length wr: 128 rd: 128 MBX protocols : 0e
 CoE details: 2f FoE details: 01 EoE details: 01 SoE details: 00
 Ebus current: 0[mA]
 only LRD/LWR:0
PDO mapping according to CoE :
  SM2 outputs
     addr b   index: sub bitl data_type    name
  [0x0000.0] 0x2010:0x00 0x10 UNSIGNED16   Control word
  [0x0002.0] 0x2014:0x00 0x10 UNSIGNED16   Operation mode
  [0x0004.0] 0x2021:0x00 0x20 REAL32       Velocity set-point
  [0x0008.0] 0x201A:0x00 0x20 REAL32       Current quadrature set-point
  SM3 inputs
     addr b   index: sub bitl data_type    name
  [0x0018.0] 0x2011:0x00 0x10 UNSIGNED16   Status word
  [0x001A.0] 0x2015:0x00 0x10 UNSIGNED16   Operation mode display
  [0x001C.0] 0x2031:0x00 0x20 REAL32       Actual velocity
  [0x0020.0] 0x203B:0x00 0x20 REAL32       Current quadrature value
  [0x0024.0] 0x204A:0x00 0x20 INTEGER32    BiSS-C slave 1 / Primary SSI - Position
  [0x0028.0] 0x200F:0x00 0x20 INTEGER32    Last error
  [0x002C.0] 0x2061:0x00 0x20 REAL32       Primary temperature value
  [0x0030.0] 0x2060:0x00 0x20 REAL32       Bus voltage value

Slave:2
 Name:Servo Drives
 Output size: 96bits
 Input size: 224bits
 State: 4
 Delay: 1082[ns]
 Has DC: 1
 Serialno.: 0
 DCParentport:1
 Activeports:1.1.0.0
 Configured address: 1002
 Man: 0000029c ID: 02c30001 Rev: 0005000b
 SM0 A:1000 L: 128 F:00010026 Type:1
 SM1 A:1400 L: 128 F:00010022 Type:2
 SM2 A:1800 L:  12 F:00010064 Type:3
 SM3 A:1c00 L:  28 F:00010020 Type:4
 FMMU0 Ls:0000000c Ll:  12 Lsb:0 Leb:7 Ps:1800 Psb:0 Ty:02 Act:01
 FMMU1 Ls:00000034 Ll:  28 Lsb:0 Leb:7 Ps:1c00 Psb:0 Ty:01 Act:01
 FMMUfunc 0:1 1:2 2:3 3:0
 MBX length wr: 128 rd: 128 MBX protocols : 0e
 CoE details: 2f FoE details: 01 EoE details: 01 SoE details: 00
 Ebus current: 0[mA]
 only LRD/LWR:0
PDO mapping according to CoE :
  SM2 outputs
     addr b   index: sub bitl data_type    name
  [0x000C.0] 0x2010:0x00 0x10 UNSIGNED16   Control word
  [0x000E.0] 0x2014:0x00 0x10 UNSIGNED16   Operation mode
  [0x0010.0] 0x2021:0x00 0x20 REAL32       Velocity set-point
  [0x0014.0] 0x201A:0x00 0x20 REAL32       Current quadrature set-point
  SM3 inputs
     addr b   index: sub bitl data_type    name
  [0x0034.0] 0x2011:0x00 0x10 UNSIGNED16   Status word
  [0x0036.0] 0x2015:0x00 0x10 UNSIGNED16   Operation mode display
  [0x0038.0] 0x2031:0x00 0x20 REAL32       Actual velocity
  [0x003C.0] 0x203B:0x00 0x20 REAL32       Current quadrature value
  [0x0040.0] 0x204A:0x00 0x20 INTEGER32    BiSS-C slave 1 / Primary SSI - Position
  [0x0044.0] 0x200F:0x00 0x20 INTEGER32    Last error
  [0x0048.0] 0x2061:0x00 0x20 REAL32       Primary temperature value
  [0x004C.0] 0x2060:0x00 0x20 REAL32       Bus voltage value
End slaveinfo, close socket
End program

However, I did not find any difference except for the error message at the beginning and the state of slave 1.

I captured the network traffic during the failed PDO mapping on cold start and afterwards when I restarted my program with a successful PDO mapping. Please see the .pcapng files below.

wireshark.zip

Please let me know, if you need further details and thank you for your help in advance.

ArthurKetels commented 3 years ago

There is one issue in your slave configuration. You start with SDO download of object 0x1600. But according to the standard you should first write object 0x1c12 and 0x1c13. Could you add that to your startup routine?

The effect from your restart is that now 0x1c12 is configured from the attempt before. So this would explain the behaviour.

balazs1123 commented 3 years ago

Thank you for your really quick response. However, I'd like to ask some further questions.

  1. Probably I overlooked something, but even after your answer I double checked, but I did not find it in the documentation. Could you please point me to the section in the documentation, where I could find the mentioned specific order? (ETG1000_5_V1i0i4_S_R_EcatALServices, ETG1000_6_V1i0i4_S_R_EcatALProtocols, ETG1020_V1i2i0_S_R_ProtocolEnhancements or ETG6010_V1i1i0_D_R_CiA402_ImplDirective)
  2. Based on your answer I changed the order, but I unfortunately I had the same behaviour as mentioned before. My pseudo code before you response:
    
    ...
    retval += ec_SDOwrite(
            slave,
            0x1600,
            0x00,
            TRUE,
            sizeof(map_1600_),
            &map_1600_,
            EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1a00, 0x00, TRUE, sizeof(map1a00), &map1a00, EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1c12, SUBINDEX, TRUE, sizeof(map1c12), &map1c12, EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1c13, 0x00, TRUE, sizeof(map1c13), &map1c13, EC_TIMEOUTRXM); ...

Example for the arrays to be mapped:

uint16_t map1600[9]{ 0x0004, 0x0010, 0x2010, 0x0010, 0x2014, 0x0020, 0x2021, 0x0020, 0x201a };

uint16_t map1c12[2]{0x0001, 0x1600};

So should I change it for the following?

retval += ec_SDOwrite( slave, 0x1c12, SUBINDEX, TRUE, sizeof(map1c12), &map1c12, EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1c13, 0x00, TRUE, sizeof(map1c13), &map1c13, EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1600, 0x00, TRUE, sizeof(map1600), &map1600, EC_TIMEOUTRXM);

retval += ec_SDOwrite( slave, 0x1a00, 0x00, TRUE, sizeof(map1a00), &map1a00, EC_TIMEOUTRXM);


As mentioned before I tried this version, but I've got the same issue (even if I tried to do it in a "sandwich". So map 1c12,1c13, then 1600,1a00, then 1c12,1c13 again).

3. Before my question I read through the forum, if someone had the same issue, but without luck. However, I found the following answer to another problem:
"And the order is also important, first the mapping object (0x1a01) then the SM assign (0x1c13)." 
in https://github.com/OpenEtherCATsociety/SOEM/issues/419
According to this answer I did it correctly in my original version, or did I misunderstand something here?
ArthurKetels commented 3 years ago

Ehh, reading back my comment it was perhaps not too clear.

The order for mapping:

  1. Write SDO 0x1c12:00 = 0
  2. Write SDO 0x1600 (CA) = mapping list
  3. Write SDO 0x1212 (CA) = assign list CA = Complete Access So in short : clear assign, map , assign.

In most slaves it does not matter what order you use because they only check assignment and mapping at pre-OP -> safe-OP transition. But there are implementations that are a bit too strict.

balazs1123 commented 3 years ago

Thank you for your quick response, especially on Friday evening. I appreciate your support.

I tried your last proposal, so "clear assign, map, assign". Unfortunately, the cold-start configuration produces the same behaviour. Without knowing the exact ESC type, and its datasheet, it's "tapping in the dark", at least for me. Anyway, please see my latest pdo mapping code:

uint8_t reset = 0x00;

retval += ec_SDOwrite(
            slave,
            0x1c12,
            0x00,
            FALSE,
            sizeof(reset),
            &reset,
            EC_TIMEOUTRXM);

retval += ec_SDOwrite(
            slave,
            0x1c13,
            0x00,
            FALSE,
            sizeof(reset),
            &reset,
            EC_TIMEOUTRXM);

// CA from this point
retval += ec_SDOwrite(
            slave,
            0x1600,
            0x00,
            TRUE,
            sizeof(map_1600_),
            &map_1600_,
            EC_TIMEOUTRXM);

retval += ec_SDOwrite(
            slave,
            0x1a00,
            0x00,
            TRUE,
            sizeof(map_1a00_),
            &map_1a00_,
            EC_TIMEOUTRXM);

retval += ec_SDOwrite(
            slave,
            0x1c12,
            0x00,
            TRUE,
            sizeof(map_1c12_),
            &map_1c12_,
            EC_TIMEOUTRXM);

retval += ec_SDOwrite(
            slave,
            0x1c13,
            0x00,
            TRUE,
            sizeof(map_1c13_),
            &map_1c13_,
            EC_TIMEOUTRXM);

Mapping arrays remained the same as mentioned above.

Please see the wireshark files below.

wireshark_2.zip

ArthurKetels commented 3 years ago

In above mapping code could you insert following after each SDOwrite()?

            ec_readstate();
            for(i = 1; i<=ec_slavecount ; i++)
            {
               if(ec_slave[i].state != EC_STATE_SAFE_OP)
               {
                  printf("Slave %d State=%2x StatusCode=%4x : %s\n",
                     i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
               }
            }

Of course it is best to make a function of this. This has two effects, first to see if there can be an error during the mapping process and not after all is done, and second to have some delay between mapping configuration steps. It is possible SOEM is a bit too fast for the slave and it first needs to do some internal bookkeeping before a transition to safe-OP is possible. The ESM (EtherCAT state machine) protocol should handle this, but you never know.

An other thing to try is to insert a delay of 1sec before doing the slave mapping.

What is also strange is that slave 1 and slave 2 output different AL status codes. Code 0x0052 is even not defined in the EtherCAT standard. Statuscode 0x0024 "Invalid input mapping" indicates that the mapping list is incorrect and not that the SM is programmed the wrong way.

As a last resort, could you wireshark a TwinCat sequence at cold boot? Perhaps there is some tiny detail we are overlooking.

ArthurKetels commented 3 years ago

When looking at: https://doc.ingeniamc.com/summit/manuals/summit-reference-manual/tricks-and-tips/ethercat-pdo-mapping

I noticed that the order of mapping inputs and outputs are reversed from what you are doing. Perhaps nothing, perhaps important. So first the inputs and then the outputs.

balazs1123 commented 3 years ago

Thank you for the tips, I appreciate it. I'll try them one by one and see, if any of them helps, then let you know about the results.

balazs1123 commented 3 years ago
  1. I tried to change the sequence of the mapping as you suggested, so first TxPDO then RxPDO. However, it produced the same behaviour.
  2. I tried to "slow down" the execution by insterting ec_read_state() after every SDO_write function. The behaviour is the same:
    
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error
    Servo Drive 1 State= 2 StatusCode= 0 : No error
    Servo Drive 2 State= 2 StatusCode= 0 : No error

Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping Servo Drive 2 State= 12 StatusCode= 52 : Unknow


3. I captured the network traffic of TwinCAT. The difference, at least in the mapping, that I saw, it mapped all the input and output registers (so 0x1a01, 0x1a02, 0x1601, 0x1602), but assigned only one-one(0x1600 and 0x1a00) to SM2/SM3. Could it be relevant, or am I mistaken here? (PDO mapping in the TwinCAT file from line 1117 to line 1345 - I'll give it a try probably tomorrow)

Please see the attached wireshark files of the executions in point 2 and 3, below:
[Wireshark_3.zip](https://github.com/OpenEtherCATsociety/SOEM/files/6802157/Wireshark_3.zip)
ArthurKetels commented 3 years ago

I also noticed a small difference. The SDOwrite of 0x1c12 and 0x1c13 in TwinCAT is in "expedited" form instead of "normal". This should not matter but we never know for sure. I do have to change the SOEM source a bit to mimic TwinCAT. Have a bit of patience.

balazs1123 commented 3 years ago

Thank you, I appreciate your help on this.

balazs1123 commented 3 years ago

I tried to do the PDO mapping for 0x1a01, 0x1a02, 0x1601 and 0x1602 as well, but it produced the same behaviour at cold-start, unfortunately.

Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown
ArthurKetels commented 3 years ago

I made some changes to allow CA to use expedited when objects <= 4 bytes are send via SDOwrite(). Please pull from branch coe_ca I hope this helps.

balazs1123 commented 3 years ago

Thank you again for your support. I cloned the branch, and I rebuilt my repo, but unfortunately, it did not solve the problem. I have the same behaviour at cold-start:

Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown

Please see the captured files as well: wireshark_4.zip

I'll also contact Ingenia, maybe they had this behaviour before.

ArthurKetels commented 3 years ago

Did you ever test with only one slave? Or reverse the slave order? I find it strange that the StatusCode is different for the two slaves.

Contacting the vendor is a good idea. They can debug this 100x faster than you and me. Do provide them with a good way to reproduce the issue. Send them the exact software you use for testing.

balazs1123 commented 3 years ago

Please, see my answers below:

Did you ever test with only one slave? Not yet, I'll give it a try tomorrow, with a modified simpletest. Or reverse the slave order? I tried now, and I had the same error messages:

Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown

Ofc, the physical position is reversed now. So Servo Drive 1 is always the last slave on the network (from Master point of view).

balazs1123 commented 3 years ago

Hello,

I contacted the vendor and I`m still waiting for their answer. However in the meantime I noticed something in the library, which might be relevant: If I did the power cycle while the program was running, the ecatcheck function (same as in redtest.c) could map successfully the slaves and bring them back to operational state (10/10 test-cases). Please see the attached wireshark files, where I captured the failed cold-start (with the intial configuration) and the cold-start by ecatcheck funtion with already configured and running master stack.

On the otherhand I had to add the following lines to the ethercatconfig.c after #L1599:

if (context->slavelist[slave].PO2SOconfigx) /* only if registered */
 {
     context->slavelist[slave].PO2SOconfigx(context, slave);
 }

I use the ecx_ functions in my wrapper code and I noticed that ` ecx_reconfig_slave(ecx_contextt context, uint16 slave, int timeout)does not call thePO2SOconfigx(context, slave)` function pointer. (Before the added code above the ecatcheck function could not bring them back to OP_STATE, only after this modification.)

Could this be relevant for you as well?

PDO_mapping.zip

balazs1123 commented 3 years ago

After my comment above, I tried to call ecx_configdc(&context) after the slaves reached SAFEOP and not after the ecx_config_overlap_map_group function call. However this order can only be seen in red_test.c example. Not in simple test or ec_master.c. Apperently this modification solved the cold-start configuration issue, decribed above. Could you please give some explanation on the reason behind this? (As stated before I`m not an expert in ECAT.)

ArthurKetels commented 3 years ago

The code below should have been in the configuration section.

if (context->slavelist[slave].PO2SOconfigx) /* only if registered */
 {
     context->slavelist[slave].PO2SOconfigx(context, slave);
 }

This is clearly a bug. Thanks for catching this!

ArthurKetels commented 3 years ago

ecx_configdc() does a lot of things. But most of them are invisible for the slaves. So I am really head scratching why this would make the slave behave. There are only two possible effects:

  1. It sets the slave clock offset and delay so the slave clock is roughly synchronized with the wall clock (absolute EtherCAT time starts at 1-1-2000 00:00). It uses the local PC time for this. The slave can read the clock, but I am stumped why it would need the current time. Still, it is a possibility.
  2. The function takes time. So it could just be the effect of a delay between SAFE-OP and mapping. You could test this by measuring the delay of this function and then replacing ecx_configdc() by a simple osal_usleep() of the same delay.

The more important function of ecx_configdc() is to measure the latency between each slave. It uses the unsynchronized local slave clocks and the timestamps of a packet entering and leaving each port of the slave. It solves a set of linear equations to figure out the time each packet travels between the slave ports. It then corrects the local slave clock to a course EtherCAT absolute time. The measured delay between a packet reaching the reference slave and the current slave is then programmed in the delay register. This delay value is needed to later synchronize all slaves to the reference slave clock.

After the slave clock set-up the slaves can be synchronized to each other. This is done automatically by the PDO transfer function. It attaches a clock read-multiple-write instruction to the PDO transfer. This reads the current clock value from the reference slave (the first slave in the chain that has DC clock function), and then writes it to the following slave clocks. The slave that gets the clock write will not actually write the clock value to its own local clock but use the value to compare it with its local clock. Taking into account the propagation delay between the reference slave and the current slave. A PLL will then skew the local clock until it is phase synchronous with the reference clock.

So when the master orders slaves to fire a clock event (SYNC0) then all slaves fire at the same absolute time (or at least within +/-20ns or so). No matter how much propagation delay there is between slaves. This is a mayor capability of EtherCAT.

balazs1123 commented 3 years ago

Hello, Thank you very much for your detailed answer and your support. I do appreciate it. I think we can close this issue. Regarding the bug (described above) should I create a seperate issue for it?

ArthurKetels commented 3 years ago

You are welcome. No need for a separate issue, I will make a patch for the PO2SOconfigx hook.