原文地址:http://blog.csdn.net/huangxianxinalice/article/details/9919967
另外,这里有一个应用程序特别的检查(在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
- }