SOEM 源码解析 ecx_readeepromAP

发布于:2024-08-10 ⋅ 阅读:(167) ⋅ 点赞:(0)
/* Read EEPROM from slave bypassing cache. APRD method.
 * 从站绕过缓存读取 EEPROM。APRD方法
 * @param[in] context     = context struct
 *                          上下文结构体
 * @param[in] aiadr       = auto increment address of slave
 *                          从站自增地址
 * @param[in] eeproma     = (WORD) Address in the EEPROM
 *                          (WORD单位)EEPROM 中的地址
 * @param[in] timeout     = Timeout in us.
 *                          超时时间[单位:us(微秒)]
 * @return EEPROM data 64bit or 32bit
 *                64bit EEPROM数据 或 32bit EEPROM数据
 */
uint64 ecx_readeepromAP(ecx_contextt *context, uint16 aiadr, uint16 eeproma, int timeout)
{
   uint16 estat;/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
   uint32 edat32;/* 32bit EEPROM数据 */
   uint64 edat64;/* 64bit EEPROM数据 */
   ec_eepromt ed;/* EtherCAT EEPROM 通信记录 */
   int wkc,/* 工作计数器 */
       cnt, /* 试行次数:最大三回 */
       nackcnt = 0;/* EEprom 状态机错误应答试行次数:最大三回 */

   edat64 = 0;/* 64bit EEPROM数据 */
   edat32 = 0;/* 32bit EEPROM数据 */
   /* 在超时时间内、设置EEprom 状态机忙位busy→idle */
   if (ecx_eeprom_waitnotbusyAP(
       context, /* 上下文结构体 */
       aiadr,/* 从站自增地址 */
       &estat,/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
       timeout))/* 超时时间[单位:us(微秒)] */
   {
       /*
        0x0502:0x0503.11
        Checksum Error at in ESC Configuration Area: ESC配置区校验
        0: Checksum ok :校验和正确
        1: Checksum error :校验和错误

        0x0502:0x0503.12
        EEPROM loading status: 器件信息校验
        0: EEPROM loaded, device information ok : 器件信息正确
        1: EEPROM not loaded, device information not available : 从EEPROM装载器件信息错误
        (EEPROM loading in progress or finished with a failure)

        0x0502:0x0503.13
        Error Acknowledge/Command: 命令应答
        0: No error :无错误
        1: Missing EEPROM acknowledge or invalid command EEPROM emulation only:
        PDI writes 1 if a temporary failure has occurred. :EEPROM无应答,或命令无效

        0x0502:0x0503.14
        Error Write Enable: 写使能错误
        0: No error:无错误
        1: Write Command without Write enable:请求写命令时无写使能
        */
      if (estat /* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
          & EC_ESTAT_EMASK/* EEprom 状态机错误标志掩码 Reg0x0502.11~14 EEPROM Control/Status  */
          ) /* error bits are set *//* 错误位已设置 */
      {
         estat/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
             = htoes(/* 大小端转换操作宏 uint16 */
             EC_ECMD_NOP); /* clear error bits */
         wkc = /* 工作计数器 */
             ecx_APWR(// 自增式物理写(APWR) Auto increment physical write 
                 context->port, /* 端口(port) */
                 aiadr,/* 从站自增地址 */
                 ECT_REG_EEPCTL,// EEPROM Control/Status EEP控制/EEP状态 EEPROM控制和状态寄存器[0x0502:0x0503]
                 sizeof(estat),/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
                 &estat,/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
                 EC_TIMEOUTRET3);/* 安全数据传输的超时时间值,最大重试次数为三次 */
      }

      do
      {
         ed.comm/* Ethercat EEprom 命令类型 */
             = htoes(/* 大小端转换操作宏 uint16 */
             EC_ECMD_READ);/* 读 */
         ed.addr/* EEPROM 地址 */
             = htoes(/* 大小端转换操作宏 uint16 */
             eeproma);/* (WORD单位)EEPROM 中的地址 */
         ed.d2   = 0x0000;/* 第二个EEPROM地址设为0 */
         cnt = 0;/* 试行次数:最大三回 */
         do
         {
            wkc = /* 工作计数器 */
                ecx_APWR(// 自增式物理写(APWR) Auto increment physical write 
                    context->port,/* 端口(port) */
                    aiadr, /* 从站自增地址 */
                    ECT_REG_EEPCTL,// EEPROM Control/Status EEP控制/EEP状态 EEPROM控制和状态寄存器[0x0502:0x0503]
                    sizeof(ed), /* EtherCAT EEPROM 通信记录大小=6 */
                    &ed, /* EtherCAT EEPROM 通信记录 */
                    EC_TIMEOUTRET);/* 发送帧(tx frame)返回到接收(rx)的超时时间[单位:us(微秒)]=2000 */
         }
         while ((wkc/* 工作计数器 */ <= 0) 
             && (cnt++/* 试行次数:最大三回 */
                 < EC_DEFAULTRETRIES));/* 默认重试次数,如果 WKC <= 0 */
         if (wkc/* 工作计数器 */)
         {
             /* 睡眠函数,休眠到要求的时间(指定的延迟时间[单位:usec]) */
            osal_usleep(
                EC_LOCALDELAY/* eeprom准备循环的延迟时间[单位:us(微秒)] */);
            estat = 0x0000;/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
            /* 在超时时间内、设置EEprom 状态机忙位busy→idle */
            if (ecx_eeprom_waitnotbusyAP(
                context,/* 上下文结构体 */
                aiadr, /* 从站自增地址 */
                &estat, /* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
                timeout))/* 超时时间[单位:us(微秒)] */
            {

               if (estat/* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
                   & EC_ESTAT_NACK)/* EEprom 状态机错误应答 */
               {
                  nackcnt++;/* EEprom 状态机错误应答试行次数:最大三回 */
                  /* 睡眠函数,休眠到要求的时间(指定的延迟时间[单位:usec]) */
                  osal_usleep(
                      EC_LOCALDELAY/* eeprom准备循环的延迟时间[单位:us(微秒)] */ * 5);
               }
               else/* EEprom 状态机错误应答位为0,跳出循环 */
               {
                  nackcnt = 0;/* EEprom 状态机错误应答试行次数:最大三回 */
                  if (estat & /* Reg0x0502:0x0503 EEPROM Control/Status EEP控制/EEP状态 */
                      EC_ESTAT_R64)/* EEprom 状态机读取大小:支持读字节数[0: 4 Bytes:4个字节;1: 8 Bytes:8个字节] */
                  {
                     cnt = 0;/* 试行次数:最大三回 */
                     do
                     {
                        wkc = /* 工作计数器 */
                            ecx_APRD(// 自增式物理读(APRD) Auto increment physical read 
                                context->port,/* 端口(port) */
                                aiadr, /* 从站自增地址 */
                                ECT_REG_EEPDAT,// EEPROM Data:EEPROM数据=0x0508
                                sizeof(edat64),/* 64bit EEPROM数据 */
                                &edat64, /* 8 Bytes:8个字节 */
                                EC_TIMEOUTRET);/* 发送帧(tx frame)返回到接收(rx)的超时时间[单位:us(微秒)]=2000 */
                     }
                     while ((wkc/* 工作计数器 */ <= 0) 
                         && (cnt++ /* 试行次数:最大三回 */ 
                             < EC_DEFAULTRETRIES/* 默认重试次数,如果 WKC <= 0 */));
                  }
                  else
                  {
                     cnt = 0;/* 试行次数:最大三回 */
                     do
                     {
                        wkc = /* 工作计数器 */
                            ecx_APRD(// 自增式物理读(APRD) Auto increment physical read 
                                context->port,/* 端口(port) */
                                aiadr, /* 从站自增地址 */
                                ECT_REG_EEPDAT,// EEPROM Data:EEPROM数据=0x0508
                                sizeof(edat32),/* 32bit EEPROM数据 */ 
                                &edat32,/* 32bit EEPROM数据 */
                                EC_TIMEOUTRET);/* 发送帧(tx frame)返回到接收(rx)的超时时间[单位:us(微秒)]=2000 */
                     }
                     while ((wkc/* 工作计数器 */ <= 0) 
                         && (cnt++/* 试行次数:最大三回 */ 
                             < EC_DEFAULTRETRIES/* 默认重试次数,如果 WKC <= 0 */));
                     edat64/* 64bit EEPROM数据 */
                         =(uint64)edat32;/* 32bit EEPROM数据 */
                  }
               }
            }
         }
      }
      while ((nackcnt > 0) && (nackcnt < 3));/* EEprom 状态机错误应答试行次数:最大三回 */
   }

   return edat64;/* 64bit EEPROM数据 */
}


网站公告

今日签到

点亮在社区的每一天
去签到