OpenEtherCATsociety / SOEM

Simple Open Source EtherCAT Master
Other
1.24k stars 653 forks source link

A question about ecx_send_processdata #779

Open Edphoenixmax opened 6 months ago

Edphoenixmax commented 6 months ago

Long time no see . I wish all of you are good. I have a question about this function. There is cyclic cmd in ENI file , so that codesys put the cyclic cmd like check localDCtime in this section. So when we use ecx_send_processdata, it will also start set the referenceclocktime to all the slaves. Is this right? Thanks for your reply .

ArthurKetels commented 5 months ago

The DC clock distribution is automatic in ecx_send_processdata. look at the code.

         /* segment transfer if needed */
         do
         {
            sublength = (uint16)context->grouplist[group].IOsegment[currentsegment++];
            /* get new index */
            idx = ecx_getindex(context->port);
            w1 = LO_WORD(LogAdr);
            w2 = HI_WORD(LogAdr);
            DCO = 0;
            ecx_setupdatagram(context->port, &(context->port->txbuf[idx]), EC_CMD_LRW, idx, w1, w2, sublength, data);
            if(first)
            {
               /* FPRMW in second datagram */
               DCO = ecx_adddatagram(context->port, &(context->port->txbuf[idx]), EC_CMD_FRMW, idx, FALSE,
                                        context->slavelist[context->grouplist[group].DCnext].configadr,
                                        ECT_REG_DCSYSTIME, sizeof(int64), context->DCtime);
               first = FALSE;
            }
            /* send frame */
            ecx_outframe_red(context->port, idx);
            /* push index and data pointer on stack.
             * the iomapinputoffset compensate for where the inputs are stored 
             * in the IOmap if we use an overlapping IOmap. If a regular IOmap
             * is used it should always be 0.
             */
            ecx_pushindex(context, idx, (data + iomapinputoffset), sublength, DCO);      
            length -= sublength;
            LogAdr += sublength;
            data += sublength;
         } while (length && (currentsegment < context->grouplist[group].nsegments));

This is part of the default condition where slaves can be accessed by LRW. Other parts of the function handle slaves that need separate LRD and LWR datagrams.

It generates 1 or more packets (depending on IO size) where in the first packet a FRMW datagram is added on register DCSYSTIME. This is exactly what you asked, the local clock of the reference slave is read and written to all other slaves. This distributes the cock to all slaves so they synchronize. And at the end of the loop the packet is received by SOEM and the datagram has the local clock value of the reference slave. This is used to synchronize the master application to the slave clock.