另外,这里有一个应用程序特别的检查(在ecatappl.c里面),如果状态转换从INIT到BOOT应该被完成,如果结果是NOERROR_INWORK,从站应该停留在INIT状态直到超时或者转换应该在AL_ControlRes里面完成
/
/**
\brief 应用程序控制响应
\brief 这个函数被周期性调用,如果状态转换暂停(bEcatWaitForAlControlRes == TRUE)
\brief 如果ESM超时,状态转换将被拒绝。否则,应用程序特殊的状态转换函数将会被调用
\brief 如果暂停状态转换被应用程序触发,状态转换将被应用程序(ECAT_StateChange)中完成
*
void AL_ControlRes(void)
{
if(bEcatWaitForAlControlRes)
{
UINT16 result = 0;
UINT8 Status = 0;
UINT16 StatusCode = 0;
if(EsmTimeoutCounter == 0)
{
Status = (UINT8)(nEcatStateTrans >> 4);
/* ESM 超时*/
switch(nEcatStateTrans)
{
case INIT_2_PREOP:
case INIT_2_BOOT:
#if MAILBOX_SUPPORTED
if(!bApplEsmPending)
APPL_StopMailboxHandler();
MBX_StopMailboxHandler();
#endif
if(bLocalErrorFlag)
{
/*设置应用程序特殊的错误*/
StatusCode = u16LocalErrorCode;
}
else
{
/*设置非特殊的错误*/
StatusCode = ALSTATUSCODE_UNSPECIFIEDERROR;
}
break;
case PREOP_2_SAFEOP:
if(!bApplEsmPending)
APPL_StopInputHandler();
StopInputHandler();
if(bLocalErrorFlag)
{
/*设置应用程序的特殊错误*/
StatusCode = u16LocalErrorCode;
}
else
{
/*设置非特殊错误*/
StatusCode = ALSTATUSCODE_UNSPECIFIEDERROR;
}
break;
case SAFEOP_2_OP:
#if DC_SUPPORTED
if(bDcSyncActive)
{
/*SafeOP to OP 超时溢出检查,当应用状态码需要被写入*/
if(!bDcRunning)
{
/*没有Sync0信号被接受*/
StatusCode = ALSTATUSCODE_NOSYNCERROR;
}
else if(!bEcatFirstOutputsReceived)
{
/*没有过程数据被接受*/
StatusCode = ALSTATUSCODE_SMWATCHDOG;
}
else
{
/*Pll 没有使能*/
StatusCode = ALSTATUSCODE_DCPLLSYNCERROR;
}
}
else
#endif
{
#if !OP_PD_REQUIRED
/*设置有效的状态转换即使超时产生*/
Status = STATE_OP;
StatusCode = 0;
/* 从站是在可运行状态 */
bEcatOutputUpdateRunning = TRUE;
#else
StatusCode = ALSTATUSCODE_SMWATCHDOG;
#endif
}
/*停止操作在一个错误的转换*/
if(StatusCode != 0)
{
if(!bApplEsmPending)
APPL_StopOutputHandler();
StopOutputHandler();
}
break;
}
} //ESM timeout
else
{
/*调用应用程序特殊的转换函数和如果完成转换的话,函数将返回0*/
switch(nEcatStateTrans)
{
case INIT_2_PREOP:
case INIT_2_BOOT:
if(bApplEsmPending)
{
bApplEsmPending = FALSE;
#if MAILBOX_SUPPORTED
/*APPL_StartMailboxHandler()需要被调用 */
result = APPL_StartMailboxHandler();
if(result == 0)
{
/*应用程序特殊的转换成功,设置激活的邮箱操作*/
bMbxRunning = TRUE;
Status = (UINT8)(nEcatStateTrans & STATE_MASK);
}
else
{
/*应用程序特殊的转换失败。(在pending中,应用程序需要完成它的转换)
*/
if(result != NOERROR_INWORK)
{
APPL_StopMailboxHandler();
MBX_StopMailboxHandler();
}
}
#endif
}
break;
case PREOP_2_SAFEOP:
if(bApplEsmPending)
{
bApplEsmPending = FALSE;
result = APPL_StartInputHandler(&u16ALEventMask);
if(result == 0)
{
bEcatInputUpdateRunning = TRUE;
Status = STATE_SAFEOP;
}
else
{
/*The application specific transition failed.
(In pending case the application need to complete the transition)*/
if(result != NOERROR_INWORK)
{
APPL_StopInputHandler();
StopInputHandler();
}
}
}
break;
case SAFEOP_2_OP:
if(bApplEsmPending)
{
#if DC_SUPPORTED
if(bDcSyncActive)
{
if(i16WaitForPllRunningTimeout > 0 && i16WaitForPllRunningTimeout <= i16WaitForPllRunningCnt)
{
/*PLL队列的有效时间是200ms(由APPL_StartOutputHandler()函数设置)
默认状态转换到OP状态 */
i16WaitForPllRunningTimeout = 0;
i16WaitForPllRunningCnt = 0;
result = APPL_StartOutputHandler();
if(result == 0)
{
/* 从站是在OPERATIONAL的状态 */
bEcatOutputUpdateRunning = TRUE;
Status = STATE_OP;
}
else
{
if(result != NOERROR_INWORK)
{
APPL_StopOutputHandler();
StopOutputHandler();
}
}
}
}
else
#endif
{
#if OP_PD_REQUIRED
if(nPdOutputSize == 0 || bEcatFirstOutputsReceived)
#endif
{
result = APPL_StartOutputHandler();
if(result == 0)
{
/* Slave is OPERATIONAL */
bEcatOutputUpdateRunning = TRUE;
Status = STATE_OP;
}
else
{
if(result != NOERROR_INWORK)
{
APPL_StopOutputHandler();
StopOutputHandler();
}
}
}
}
}
break;
}//Switch - transition
}
if(Status != 0)
{
/*暂停状态转换停止=>写入AL的状态和状态码*/
bEcatWaitForAlControlRes = FALSE;
if(StatusCode != 0)
Status |= STATE_CHANGE;
SetALStatus(Status,StatusCode);
}
}// Pending state transition (bEcatWaitForAlControlRes == true)
}
/
/**
\param alStatus 新的AL状态(写到寄存器0x130)
\param alStatusCode 新的AL状态码(写到寄存器0x134)
\brief 这个函数改变EtherCAT ASIC芯片的状态到所求的状态
*
void SetALStatus(UINT8 alStatus, UINT16 alStatusCode)
{
UINT16 Value = alStatusCode;
/*更新所需要的全局状态变量*/
if(nAlStatus != alStatus)
{
nAlStatus = alStatus;
}
nAlStatus &= ~STATE_DEVID;
if (alStatusCode != 0xFFFF)
{
Value = SWAPWORD(Value);
HW_EscWriteWord(Value,ESC_AL_STATUS_CODE_OFFSET);
}
Value = nAlStatus;
Value = SWAPWORD(Value);
HW_EscWriteWord(Value,ESC_AL_STATUS_OFFSET);
#if LEDS_SUPPORTED || ESC_SUPPORT_ECAT_LED
/*The Run LED state is set in Set LED Indication, only the Error LED blink code is set here*/
/*set Error blink code*/
if(alStatusCode == 0x00 || !(alStatus & STATE_CHANGE))
{
u8EcatErrorLed = LED_OFF;
}
else if((alStatusCode == ALSTATUSCODE_NOSYNCERROR) ||
(alStatusCode == ALSTATUSCODE_DCPLLSYNCERROR))
{
u8EcatErrorLed = LED_SINGLEFLASH;
}
else if((alStatusCode == ALSTATUSCODE_SMWATCHDOG))
{
/* ECATCHANGE_START(V5.01) HW3*/
u8EcatErrorLed = LED_DOUBLEFLASH;
/* ECATCHANGE_END(V5.01) HW3*/
}
else
{
u8EcatErrorLed = LED_BLINKING;
}
#if ESC_SUPPORT_ECAT_LED
u8EcatErrorLed |= LED_OVERRIDE;
#if ESC_32BIT_ACCESS || ESC_16BIT_ACCESS
/*The Run LED registers are also written in 16 or 32 Bit access => calculate value*/
switch((alStatus & STATE_CHANGE))
{
case STATE_INIT:
u8EcatRunLed = LED_OFF;
break;
case STATE_PREOP:
u8EcatRunLed = LED_BLINKING;
break;
case STATE_SAFEOP:
u8EcatRunLed = LED_SINGLEFLASH;
break;
case STATE_OP:
u8EcatRunLed = LED_ON;
break;
case STATE_BOOT:
u8EcatRunLed = LED_FLICKERING;
break;
}
u8EcatRunLed |= LED_OVERRIDE;
#if ESC_32BIT_ACCESS
{
UINT32 TmpVar = 0;
TmpVar = SWAPDWORD((((UINT32)u8EcatRunLed) | (((UINT32)u8EcatErrorLed)>>8)));
HW_EscWriteDWord(TmpVar,ESC_RUN_LED_OVERRIDE);
}
#else
{
UINT16 TmpVar = 0;
TmpVar = SWAPWORD((((UINT16)u8EcatRunLed) | (((UINT16)u8EcatErrorLed)>>8)));
HW_EscWriteWord(TmpVar,ESC_RUN_LED_OVERRIDE);
}
#endif
#else
HW_EscWriteByte(u8EcatErrorLed,ESC_ERROR_LED_OVERRIDE);
#endif //#if ESC_32BIT_ACCESS || ESC_16BIT_ACCESS
#endif // #if ESC_SUPPORT_ECAT_LED
#endif //#if LEDS_SUPPORTED || ESC_SUPPORT_ECAT_LED
}