bool ProcessChamber::do_Process(const string &rcpID, bool shutterIn)
{
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: begin do_Process("+rcpID+").");
try
{
if ((m_isCancelRecipe != NULL) && (m_isCancelRecipe->getValueAsDescriptor() == "Yes"))
{
m_isCancelRecipe->setValue("No");
}
if (m_isCleaning->getValueAsDescriptor() == "Yes")
{
m_aboutToClean->setValue("No"); // <> yangy 20170129: reset
}
m_monitor->stop(); // <> make sure the monitor is stop
// <> reset m_nbaProcess
//
if (m_nbaProcess->isPosted())
{
m_nbaProcess->executeRecovery((unsigned int)0); // clear the posted one
}
m_nbaProcess->setDescription(""); // clear description
m_isHighPressureCyclePurgeRcp = false;
try //<><>2021-03-10 fuml add RC_CyclePurge for mark 'highpress cyclepurge'
{
string cyclepurge = getRcpAttribute(rcpID,RC_CyclePurge);
m_isHighPressureCyclePurgeRcp = (cyclepurge == "Yes");
}
catch(const string &err)
{
//if this attribute not exist, skip..
}
// <><> ensure door is closed, added for Auto-Clean function <><>
//
//if (m_isCleaning && !m_closeDoor4Cleaning)
if (m_isCleaning->getValueAsDescriptor() != "No")
{
//resetContextInfo(); // reset context info, <> yangy 20160624: avoid report cleaning data to EAP
// compare to resetContextInfo, information about m_transEnv,m_transMode,m_transSlot are left.
// to avoid AbortException when closeDoorFor in do_Complete() because of m_transEnv is set to Unknown.
// a Complete will occur when a Clean inside of a Swap(between pick and PrepSwap) finished.
m_lotID->setValue("");
m_matID->setValue(-1);
m_matName->setValue("");
m_matNameID->setValue("");
m_matSrcPort->setValue(-1);
m_matSrcSlot->setValue(-1);
map<TransEnv::Type, PhySlotValve*>::iterator it = m_doors.begin();
for (; it != m_doors.end(); ++it)
{
if (it->second == NULL)
{
#ifdef MEC_LANG_CH
throw string("清洁腔室失败,因为'"+Converter::convertToString(it->first)+"' 侧没有配置隔离阀.");
#else
throw string("Clean failed for NO door configured on '"+Converter::convertToString(it->first)+"' side.");
#endif
}
if (it->second->isOpen() && !waitfor(closeDoorFor(it->first), 6000))
{
#ifdef MEC_LANG_CH
throw string("关闭隔离阀门超时.");
#else
throw string("Close slot valve time out for 6000 ms.");
#endif
}
}
//<><><>yangy?<><><>EventLogger::logInfo(getSelfName(), ACTOR::SLOTVLV, ACTION::FINISH_CLOSE, "");
}
m_monitor->disableAllMonitorItems();
// <> prepare recipe
//
prepareRecipe(rcpID); // throw string
// <><>2021-02-17 fuml add for ALC
checkLidTempB4Proc(rcpID);
checkPedTempB4Proc(rcpID); // <> throw AbortException
checkChillerTempB4Proc(rcpID);
checkIdleRecipeStopStepB4Proc(rcpID);
checkTempControlZone();
//prepareCompensation(rcpID);
if (m_compensEnabled)
{
string procType = getRcpAttribute(rcpID, RC_ProcType); //throw string
string setupName = getSelfName() + "Param";
map<int, string>::iterator it;
for (it = m_procTypes.begin(); it != m_procTypes.end(); ++it)
{
if (procType == it->second) //1,Ti 2,TiN
{
// cout << "recipe typeNum-----" << it->first << endl;
// cout << "recipe type -------" << it->second << endl;
loadSetupOption(setupName, it->first);
}
}
}
// <> check process with 'Shutter' or normal 'Material', avoid damage pedestal
int transSlot = m_transSlot->getValue();
//if (m_needPasting) // <><><> need? all process must do the followings
{
// get comment and check whether use shutter or not
//
string useShutter = getRcpAttribute(rcpID, RC_Shutter); //throw string
if (useShutter == "Yes")
{
// reset material information to avoid log shutter process data to material.
//
m_lotID->setValue("");
m_matID->setValue(-1);
m_matName->setValue("");
m_matNameID->setValue("");
m_matSrcPort->setValue(-1);
m_matSrcSlot->setValue(-1);
if (m_chuck == NULL)
{
#ifdef MEC_LANG_CH
throw string("没有配置Shutter.");
#else
throw string("No shutter configured.");
#endif
}
if (transSlot == -1)
{
transSlot = 1; // <> if no valid 'm_transSlot' value, use '1' as default
m_transSlotForShutter = 1;
}
m_transSlot->setValue(transSlot); // <> keep shuttered slot 1 as trans
if (isSlotFree(transSlot))
{
// use shutter without material
//
EventLogger::logInfo(getSelfName(), ACTOR::CHUCK, ACTION::BEGIN_MOVETO, "ReleasePosition");
m_chuck->call_ReleasePosition();
EventLogger::logInfo(getSelfName(), ACTOR::CHUCK, ACTION::FINISH_MOVETO, "ReleasePosition");
EventLogger::logInfo(getSelfName(), ACTOR::CHUCK, ACTION::BEGIN_IN, "");
m_chuck->call_Shutter(); // if no shutter config, AbortException will be thrown <>
EventLogger::logInfo(getSelfName(), ACTOR::CHUCK, ACTION::FINISH_IN, "");
changeSlotState(transSlot, Module::Shuttered); // update slot data to 'Shuttered'
}
else if (isSlotShuttered(transSlot) && m_chuck->isShuttered())
{
// <><> shuttered and sensor check ok, continue
}
else // else NOT ok <>
{
#ifdef MEC_LANG_CH
throw string("槽位 '"+Converter::convertToString(transSlot)+"' 有物料, 移动挡板失败!");
#else
throw string("Move shutter in failed for slot '"+Converter::convertToString(transSlot)+"' is NOT free.");
#endif
}
if (m_enableCycWaferCountWithoutWafer && (m_matIncrement != NULL))
{
if (!Converter::stringToDouble(m_increment,getRcpAttribute(rcpID,RC_Increment)))//for cycwafer counter step increment;
{
#ifdef MEC_LANG_CH
throw string("转换配方的增量属性不成功.");
#else
throw string("Failed to convert recipe 'Increment' attribution.");
#endif
}
m_matIncrement->setValue(m_increment);
}
}
else if (useShutter == "YesOut") //noshutter and nomaterial,change "NoMat" to "YesOut" in accord with Alpad
{
//<><> Pc Chamber do pasting Recipe
if (transSlot == -1)
{
transSlot = 1; // <> if no valid 'm_transSlot' value, use '1' as default
}
if (!isSlotFree(transSlot)) // do not need material in
{
#ifdef MEC_LANG_CH
throw string("槽位 '"+Converter::convertToString(transSlot)+"' 上有物料!");
#else
throw string("slot '"+Converter::convertToString(transSlot)+"' is NOT free.");
#endif
}
if (m_enableCycWaferCountWithoutWafer && (m_matIncrement != NULL))
{
if (!Converter::stringToDouble(m_increment,getRcpAttribute(rcpID,RC_Increment)))//for cycwafer counter step increment;
{
#ifdef MEC_LANG_CH
throw string("转换配方的增量属性不成功.");
#else
throw string("Failed to convert recipe 'Increment' attribution.");
#endif
}
m_matIncrement->setValue(m_increment);
}
}
else if (!isMaterialPresent(transSlot) && !processWithoutMat(transSlot)) // shutter is out but no material in "useShutter==NO"
{
#ifdef MEC_LANG_CH
throw string("槽位 '"+Converter::convertToString(transSlot)+"' 上没有物料!");
#else
throw string("No material present in slot '"+Converter::convertToString(transSlot)+"'.");
#endif
}
else if (isMaterialPresent(transSlot))
{
m_curProcType->setValue(getRcpAttribute(rcpID, RC_ProcType)); // set current process type
//recordProcType(m_curProcType->getValueAsString()); // <> record cur process type into setup file
m_curRoute->setValue(m_nextRoute->getValue());
m_cleanContextInfoSetup->doSave(); // save Data value to Setup, assert successfully! <>
if (!m_cleanContextInfoSetup->commitChange()) // <> keep SysTime and all IdleTimeCounter into XML file
{
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()+"]::do_Process("+rcpID+"): record clean context info failed.");
}
if (m_matIncrement != NULL)
{
if (!Converter::stringToDouble(m_increment,getRcpAttribute(rcpID,RC_Increment)))//for cycwafer counter step increment;
{
#ifdef MEC_LANG_CH
throw string("转换配方的增量属性不成功.");
#else
throw string("Failed to convert recipe 'Increment' attribution.");
#endif
}
m_matIncrement->setValue(m_increment);
}
}
}
if (m_epdCalFlag) //<><>2021-12-18 wangjing added for epd calibration before executing recipe.
{
try
{
string rpsClean = getRcpAttribute(rcpID,RC_RPSClean);
m_isRPSCleanRcp = (rpsClean == "Yes" || rpsClean == "Y" || rpsClean == "True" || rpsClean == "YES" || rpsClean == "TRUE");
}
catch(const string &err)
{
m_isRPSCleanRcp = false;
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()+"]::no comment 'RC_RPSClean' configured in recipe("+rcpID+")");
}
}
prepareProcess(); // call_Service...
// check process start pressure , must after chuck arrived at process position to prevent corrugated pipe leak.
//
checkProcStartPressure(rcpID); // <> support retry, throw AbortException
if (m_gaugeValve != NULL)
{
if (!waitfor(m_gaugeValve->call_Close(), 3000))
{
#ifdef MEC_LANG_CH
throw string("关闭规保护阀门超时.");
#else
throw string("Close protected gauge valve time out in 3000 ms.");
#endif
}
}
// for turn off ion gauge in process.
if (m_turnOffIonGaugeInProcess && (m_cfgTriggerIonGauge->getValueAsDescriptor() == "Yes"))
{
// disable PG valve if it exists before off IG.
if (m_pgValve != NULL)
{
m_pgValve->disableAutoCtrl();
}
if (!waitfor(m_ionGauge->call_Off(),6000))
{
throw string("wait for Ion gauge turning off timeout within 6000 ms.");
}
}
}
catch (const string &err)
{
// reset m_transSlot to -1 if it is set by shutter in.
resetTransSlotForShutter();
completeProcess(false);
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()+"]: do_Process() failed! "+err);
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 准备工艺 '"+rcpID+"' 失败!\\"+err);
#else
throw IAP::AbortException("Prepare Process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+err);
#endif
}
catch (const IAP::InterruptException &ex)
{
// reset m_transSlot to -1 if it is set by shutter in.
resetTransSlotForShutter();
completeProcess(false);
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: do_Process() is interrupted!");
#ifdef MEC_LANG_CH
throw IAP::InterruptException("'"+getSelfName()+"' 准备工艺 '"+rcpID+"' 失败!\\"+(m_interrupted ? m_interruptInfo : "流程被中断."));
#else
throw IAP::InterruptException("Prepare process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+(m_interrupted ? m_interruptInfo : "The procedure is interrupted."));
#endif
}
catch (const IAP::Exception &ex)
{
// reset m_transSlot to -1 if it is set by shutter in.
resetTransSlotForShutter();
completeProcess(false);
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()+"]: do_Process() is aborting!");
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 准备工艺 '"+rcpID+"' 失败!\\"+string(ex.what()));
#else
throw IAP::AbortException("Prepare process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+string(ex.what()));
#endif
}
try
{
//wxj 20240701:fix bug:idletimer stop counting after interrupted
stopIdleTimer(); // <><> stop idle timer
waitforIdleTimerLastNotify(500); // ms // <><><> from CuBS/HM idle bake, ensure lamp off<><><>
executeProcess(rcpID); // <> InterruptException, AbortException
}
catch (const string &err)
{
stopInnerLoop(); // <><> liuxq 20190925 : necessary ?
EventLogger::logInfo(getSelfName(), ACTOR::PM, ACTION::FINISH_PROC, m_recipeName->getValue(), "Abnormal: "+err); // <><><>yangy: log err?<><><>
completeProcess(false); // NOT a normal end
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()+"]: do_Process() failed! "+err);
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 执行工艺 '"+rcpID+"' 失败!\\"+err);
#else
throw IAP::AbortException("Execute process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+err);
#endif
}
catch (const IAP::InterruptException &ex)
{
stopInnerLoop(); // <><> liuxq 20220820: necessary concern, the same as in catch(const string&err).
EventLogger::logInfo(getSelfName(), ACTOR::PM, ACTION::FINISH_PROC, m_recipeName->getValue(), "Abnormal: Process is interrupted.");
completeProcess(false); // liuxq :it is NOT OK if spacing compensation enabled.
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::FATAL, "ProcessChamber["+getName()
+"]::do_Process("+rcpID+"): Recipe is interrupted at step '"+m_rcpStepCounter->getValueAsString()+"',"+ex.what());
throw;
}
catch (const IAP::Exception &ex)
{
stopInnerLoop(); // <><> liuxq 20220820: necessary concern, the same as in catch(const string&err).
EventLogger::logInfo(getSelfName(), ACTOR::PM, ACTION::FINISH_PROC, m_recipeName->getValue(), "Abnormal: Process is aborted.");
completeProcess(false);
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::ERROR, "ProcessChamber["+getName()
+"]::do_Process("+rcpID+"): Recipe is aborted at step '"+m_rcpStepCounter->getValueAsString()+"',"+ex.what());
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 执行工艺 '"+rcpID+"' 失败!\\"+ex.what());
#else
throw IAP::AbortException("Execute Process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+ex.what());
#endif
}
// complete
//
try
{
completeProcess(true); // Normal end, good! call_Service ...
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: finished do_Process("+rcpID+").");
return true;
}
catch (const string &err)
{
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: do_Process() is failed."+err);
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 执行完成工艺 '"+rcpID+"' 流程时失败!\\"+err);
#else
throw IAP::AbortException("Complete process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+err);
#endif
}
catch (const IAP::InterruptException &ex)
{
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: do_Process() is interrupted!");
#ifdef MEC_LANG_CH
throw IAP::InterruptException("'"+getSelfName()+"' 执行完成工艺 '"+rcpID+"' 流程时失败!\\"+(m_interrupted ? m_interruptInfo : "流程被中断."));
#else
throw IAP::InterruptException("Complete process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+(m_interrupted ? m_interruptInfo : "The procedure is interrupted."));
#endif
}
catch (const IAP::Exception &ex)
{
resetTransSlotForShutter();
startIdleTimer();
SysLogger::getInstance()->logMsg(LOGBRANCH::APP, LEVEL::EVENT, "ProcessChamber["+getName()+"]: do_Process() is aborting!");
#ifdef MEC_LANG_CH
throw IAP::AbortException("'"+getSelfName()+"' 执行完成工艺 '"+rcpID+"' 流程时失败!\\"+string(ex.what()));
#else
throw IAP::AbortException("Complete process '"+rcpID+"' in '"+getSelfName()+"' failed!\\"+string(ex.what()));
#endif
}
}
分析这段代码,梳理出主要的流程
最新发布