252 lines
7.7 KiB
C#
252 lines
7.7 KiB
C#
using System;
|
|
using Aitex.Core.Common;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Device.Devices;
|
|
using Aitex.Core.RT.Event;
|
|
using Aitex.Core.RT.RecipeCenter;
|
|
using Aitex.Core.RT.Routine;
|
|
using Aitex.Core.RT.SCCore;
|
|
using MECF.Framework.Common.Equipment;
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
|
|
|
|
namespace SicModules.PMs.Routines
|
|
{
|
|
public class PMProcessRoutine : ModuleRoutine, IRoutine
|
|
{
|
|
enum RoutineStep
|
|
{
|
|
Process,
|
|
NoteInProcess,
|
|
WaitProcess,
|
|
NoteProcessComplete,
|
|
NoteProcessFailed,
|
|
}
|
|
|
|
private int _timeout;
|
|
|
|
private PM _pm;
|
|
private IoInterLock _pmIoInterLock;
|
|
|
|
private string _paramRecipeName;
|
|
private bool _paramIsCleanRecipe;
|
|
private bool _paramWithWafer;
|
|
private string _recipeContent;
|
|
|
|
// private Guid _guidProcess;
|
|
|
|
public PMProcessRoutine(ModuleName module ) : base(module.ToString())
|
|
{
|
|
Name = "Process";
|
|
|
|
_pm = DEVICE.GetDevice<PM>(Module);
|
|
_pmIoInterLock = DEVICE.GetDevice<IoInterLock>($"{Module}.PMInterLock");
|
|
}
|
|
|
|
public Result Init(string recipeName, bool isClean, bool withWafer)
|
|
{
|
|
_paramRecipeName = recipeName;
|
|
_paramIsCleanRecipe = isClean;
|
|
_paramWithWafer = withWafer;
|
|
|
|
return Result.DONE;
|
|
}
|
|
|
|
|
|
protected override Result StartBody(params object[] objs)
|
|
{
|
|
if (_paramWithWafer && !WaferManager.Instance.CheckHasWafer(_pm.Module, 0))
|
|
{
|
|
EV.PostWarningLog(Module, $"can not run process, No wafer at {Module}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if (!_paramWithWafer && WaferManager.Instance.CheckHasWafer(_pm.Module, 0))
|
|
{
|
|
EV.PostWarningLog(Module, $"can not run waferless process, Has wafer at {Module}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_paramRecipeName))
|
|
{
|
|
EV.PostWarningLog(Module, $"can not run process, recipe name is empty");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
_recipeContent = RecipeFileManager.Instance.LoadRecipe(Module, _paramRecipeName, false);
|
|
if (string.IsNullOrEmpty(_recipeContent))
|
|
{
|
|
EV.PostWarningLog(Module, $"can not run process, load recipe {_paramRecipeName} failed");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
//_guidProcess = Guid.NewGuid();
|
|
|
|
if (!_pmIoInterLock.SetPMProcessRunning(true, out string reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not Purge,{reason}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
|
|
_timeout = SC.GetValue<int>("PM.ProcessTimeout");
|
|
Notify("Start");
|
|
return Result.RUN;
|
|
}
|
|
|
|
|
|
protected override void MonitorBody()
|
|
{
|
|
Process((int)RoutineStep.Process, _pm, _paramRecipeName, _recipeContent, _timeout);
|
|
NoteInProcess((int)RoutineStep.NoteInProcess, _pm.Module, 0);
|
|
WaitProcess((int)RoutineStep.WaitProcess, _pm, _timeout);
|
|
NoteProcessComplete((int)RoutineStep.NoteProcessComplete, _pm.Module, 0);
|
|
SetRoutineRuningDo();
|
|
}
|
|
|
|
public override void Abort()
|
|
{
|
|
SetRoutineRuningDo();
|
|
}
|
|
|
|
private void SetRoutineRuningDo()
|
|
{
|
|
_pmIoInterLock.DoProcessRunning = false;
|
|
}
|
|
|
|
|
|
protected void NoteInProcess(int id, string module, int slot)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
Notify($"Update process information, process in {module} start");
|
|
|
|
ModuleName mod = ModuleHelper.Converter(module);
|
|
|
|
WaferManager.Instance.UpdateWaferProcessStatus(mod, slot, EnumWaferProcessStatus.InProcess);
|
|
WaferManager.Instance.GetWafer(mod, slot).TrayProcessCount--;
|
|
|
|
// _pm.OnProcessStart(_guidProcess.ToString(), _paramRecipeName);
|
|
|
|
return true;
|
|
});
|
|
|
|
if (ret.Item1)
|
|
{
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
protected void NoteProcessFailed(int id, string module, int slot)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
Notify($"Update process information, process in {module} failed");
|
|
|
|
ModuleName mod = ModuleHelper.Converter(module);
|
|
|
|
WaferManager.Instance.UpdateWaferProcessStatus(mod, slot, EnumWaferProcessStatus.Failed);
|
|
|
|
// _pm.OnProcessEnd(_guidProcess.ToString(), "Failed");
|
|
|
|
return true;
|
|
});
|
|
|
|
//if (ret.Item1)
|
|
//{
|
|
// throw (new RoutineBreakException());
|
|
//}
|
|
}
|
|
|
|
protected void NoteProcessComplete(int id, string module, int slot)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
Notify($"Update process information, process in {module} completed");
|
|
|
|
ModuleName mod = ModuleHelper.Converter(module);
|
|
|
|
WaferManager.Instance.UpdateWaferProcessStatus(mod, slot, EnumWaferProcessStatus.Completed);
|
|
|
|
//_pm.OnProcessEnd(_guidProcess.ToString(), "Completed");
|
|
|
|
return true;
|
|
});
|
|
|
|
if (ret.Item1)
|
|
{
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
public void Process(int id, PM pm , string recipeName, string recipeContent, int timeout)
|
|
{
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
{
|
|
Notify($"Run {pm.Name} recipe {recipeName}");
|
|
|
|
pm.StartProcess(recipeName, recipeContent, _paramIsCleanRecipe);
|
|
|
|
return true;
|
|
}, () => {
|
|
if (pm.IsError)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return true;
|
|
|
|
}, timeout * 1000);
|
|
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
Stop($"{pm.Name} error");
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
|
{
|
|
Stop($"{pm.Name} run process timeout, over {timeout} seconds");
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
public void WaitProcess(int id, PM pm, int timeout)
|
|
{
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
{
|
|
return true;
|
|
}, () =>
|
|
{
|
|
if (pm.IsError)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return pm.IsIdle;
|
|
|
|
}, timeout * 1000);
|
|
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
Stop($"{pm.Name} error");
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
|
{
|
|
Stop($"{pm.Name} run process timeout, over {timeout} seconds");
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|