PMProcessRoutine.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. using System;
  2. using System.Collections.Generic;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Common;
  6. using Aitex.Core.RT.RecipeCenter;
  7. using Venus_RT.Devices;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.SubstrateTrackings;
  10. using Venus_Core;
  11. using System.Diagnostics;
  12. using MECF.Framework.Common.DBCore;
  13. using System.Threading.Tasks;
  14. using Aitex.Core.RT.Event;
  15. using Aitex.Core.RT.Log;
  16. using Aitex.Core.RT.DataCenter;
  17. using Aitex.Core.Common.DeviceData;
  18. using Aitex.Core.Util;
  19. namespace Venus_RT.Modules.PMs
  20. {
  21. class PMProcessRoutine : PMRoutineBase, IRoutine
  22. {
  23. private enum ProcessStep
  24. {
  25. PreparePVHe2,
  26. ClosePVHe2,
  27. WaitPressure,
  28. PreparePressure,
  29. PrepareTemperature,
  30. RunChuckRecipe,
  31. RunProcessRecipe,
  32. RunDechuckRecipe,
  33. RunCleanRecipe,
  34. End,
  35. }
  36. public string CurrentRunningRecipe { get; set; }
  37. public string ProcessRecipeName { get; set; }
  38. public string ChuckRecipeName { get; set; }
  39. public string DechuckRecipeName { get; set; }
  40. public string CleanRecipeName { get; set; }
  41. public RecipeHead ProcessRecipeHead { get; set; }
  42. public DateTime RecipeStartTime { get; private set; }
  43. public DateTime RecipeEndTime { get; private set; }
  44. public string WaferId { get; set; }
  45. public string SlotID { get; set; }
  46. public string LotID { get; set; }
  47. public string RecipeId { get; set; }
  48. //public bool CurrentRecipeType { get; set; }
  49. //int Timeall;
  50. private Stopwatch Recipetime = new Stopwatch();
  51. private readonly PumpDownRoutine _pumpDownRoutine;
  52. private readonly ProcessHelper _processHelper;
  53. private bool _withWafer = true;
  54. //private bool _needPumpDown = false;
  55. public Recipe _currentRecipe = null;
  56. private int _currentStep = 0;
  57. private List<Recipe> Recipelist = new List<Recipe>();
  58. //private double _tolerance;
  59. //private double _OffsetTemp = 0.0f;
  60. private bool _bLoopMode = false;
  61. private int _loopStartStep = 0;
  62. private int _loopCounter = 0;
  63. private int _recipeRunningMode = 0;
  64. private Stopwatch _stepTime = new Stopwatch();
  65. public RecipeResult currentRecipeResult;
  66. public bool isMaualEndStep;
  67. private RecipeFACallback _faCallback;
  68. private JetChamber _jetChamber;
  69. private RecipeType _recipeType;
  70. private Recipe ProcessRecipe;
  71. private Recipe ChuckRecipe;
  72. private Recipe DechuckRecipe;
  73. private Recipe CleanRecipe;
  74. private bool needprocess;
  75. private bool needdechuck;
  76. private bool needchuck;
  77. private bool needclean;
  78. private bool IsVenus;
  79. //private double ProcessPressureOffset = 10;
  80. //private Fdc _fdc;
  81. private string Eap_StartRecipeTime="Null";
  82. private string Eap_EndRecipeTime="Null";
  83. private int Eap_RecipeRFOnTime;
  84. private Stopwatch Eap_RFStopWatch = new Stopwatch();
  85. private double BaseTemperature
  86. {
  87. get
  88. {
  89. if (ProcessRecipeHead != null)
  90. {
  91. if (!string.IsNullOrEmpty(ProcessRecipeHead.Temperature))
  92. {
  93. double setpoint = Convert.ToDouble(ProcessRecipeHead.Temperature);
  94. if (setpoint > 0 && setpoint < 600)
  95. return setpoint;
  96. }
  97. }
  98. return 0;
  99. }
  100. }
  101. private double BasePressure
  102. {
  103. get
  104. {
  105. if (ProcessRecipeHead != null)
  106. {
  107. if (!string.IsNullOrEmpty(ProcessRecipeHead.BasePressure))
  108. {
  109. double setpoint = Convert.ToDouble(ProcessRecipeHead.BasePressure);
  110. if (setpoint > 0 && setpoint < 750000)
  111. return setpoint;
  112. }
  113. }
  114. return SC.GetValue<int>($"{Module}.Pump.PumpBasePressure");
  115. }
  116. }
  117. public double EstimatedTotalLeftTime
  118. {
  119. get;
  120. private set;
  121. }
  122. public PMProcessRoutine(JetPMBase chamber, PumpDownRoutine pdRoutine) : base(chamber)
  123. {
  124. Name = "Process";
  125. _pumpDownRoutine = pdRoutine;
  126. _processHelper = new ProcessHelper(chamber);
  127. _faCallback = new RecipeFACallback();
  128. _jetChamber = (JetChamber)SC.GetValue<int>($"{chamber.Module}.ChamberType");
  129. if (_jetChamber == JetChamber.VenusSE || _jetChamber == JetChamber.VenusDE)
  130. IsVenus = true;
  131. else
  132. IsVenus = false;
  133. DATA.Subscribe($"{chamber.Module}.RecipeStartTime", ()=>Eap_StartRecipeTime);
  134. DATA.Subscribe($"{chamber.Module}.RecipeEndTime", ()=> Eap_EndRecipeTime);
  135. DATA.Subscribe($"{chamber.Module}.StepTime", ()=> _processHelper.EAP_StepTime);
  136. DATA.Subscribe($"{chamber.Module}.RecipeRfOntime", () => Eap_RecipeRFOnTime);
  137. DATA.Subscribe($"{chamber.Module}.StepNo", () => _currentRecipe?.Steps[_currentStep].StepNo);
  138. }
  139. private bool AssignFuns(Recipe recipe)
  140. {
  141. foreach (var step in recipe.Steps)
  142. {
  143. if (_processHelper.LoadStepFuns(step) == false)
  144. return false;
  145. foreach (ProcessUnitBase unit in step.LstUnit)
  146. {
  147. if (_processHelper.LoadMethods(unit) == false)
  148. {
  149. Stop($"Cannot find the process routine for unit:{unit.GetType()}");
  150. return false;
  151. }
  152. }
  153. }
  154. return true;
  155. }
  156. public RState Start(params object[] objs)
  157. {
  158. needprocess = false;
  159. needchuck = false;
  160. needclean = false;
  161. needdechuck = false;
  162. Recipelist.Clear();
  163. string recipeName = (string)objs[0];
  164. if (objs.Length >= 2)
  165. {
  166. _recipeType = (RecipeType)Enum.Parse(typeof(RecipeType), objs[2].ToString());
  167. if (_recipeType == RecipeType.Clean)
  168. {
  169. _withWafer = false;
  170. }
  171. else
  172. {
  173. _withWafer = true;
  174. }
  175. }
  176. if (objs.Length >= 4)
  177. {
  178. LotID = objs[3].ToString();
  179. }
  180. else
  181. {
  182. LotID = "";
  183. }
  184. if (_withWafer && WaferManager.Instance.CheckNoWafer(Module, 0))
  185. {
  186. Stop($"can not run process, no wafer at {Module}");
  187. EV.PostAlarmLog(Module.ToString(), eEvent.ERR_PM_PROCESSNOWAFER, $"can not run process, no wafer at {Module}");
  188. return RState.Failed;
  189. }
  190. else if (!_withWafer && WaferManager.Instance.CheckHasWafer(Module, 0))
  191. {
  192. Stop($"can not run clean recipe{recipeName}, a wafer at {Module}");
  193. EV.PostAlarmLog(Module.ToString(), eEvent.ERR_PM_CLEANWITHWAFER, $"can not run clean recipe, a wafer at {Module}");
  194. return RState.Failed;
  195. }
  196. if (!_chamber.IsRFGInterlockOn)
  197. {
  198. Stop("射频电源 Interlock条件不满足");
  199. EV.PostAlarmLog(Module.ToString(), eEvent.ERR_RF_RFGInterlock, "射频电源 Interlock条件不满足");
  200. return RState.Failed;
  201. }
  202. if (!CheckSlitDoor() || !CheckDryPump() || !CheckTurboPump())
  203. {
  204. return RState.Failed;
  205. }
  206. currentRecipeResult = new RecipeResult();
  207. currentRecipeResult.RecipeName = recipeName;
  208. string recipeContent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipeName, false, objs[2].ToString());
  209. Recipe recipe = Recipe.Load(recipeContent);
  210. if (recipeName != recipe.Header.Name)
  211. {
  212. Stop($"Recipe内部名{recipe.Header.Name}与外部名{recipeName}不一致,请确认Recipe来源");
  213. return RState.Failed;
  214. }
  215. if (_jetChamber != recipe.Header.ChamberType)
  216. {
  217. Stop($"不可以在{_jetChamber}腔体跑{recipe.Header.ChamberType}类型的Recipe,请确认Recipe来源");
  218. return RState.Failed;
  219. }
  220. currentRecipeResult.RecipeStepCount = recipe.Steps.Count;
  221. if (recipe == null)
  222. {
  223. Stop($"Load Recipe:{recipeName} failed");
  224. EV.PostAlarmLog(Module.ToString(), $"Load Recipe:{recipeName} failed");
  225. return RState.Failed;
  226. }
  227. _recipeRunningMode = SC.GetValue<int>($"{Module}.RecipeRunningMode");
  228. _processHelper.m_RecipeHead = recipe.Header;
  229. switch (recipe.Header.Type)
  230. {
  231. case RecipeType.Process:
  232. if (_recipeRunningMode == 1 && recipe.Header.ChuckRecipe != null && !string.IsNullOrEmpty(recipe.Header.ChuckRecipe))
  233. {
  234. string chuckcontent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipe.Header.ChuckRecipe, false, RecipeType.Chuck.ToString());
  235. ChuckRecipe = Recipe.Load(chuckcontent);
  236. if (ChuckRecipe != null)
  237. {
  238. ChuckRecipeName = recipe.Header.ChuckRecipe;
  239. needchuck = true;
  240. Recipelist.Add(ChuckRecipe);
  241. }
  242. }
  243. needprocess = true;
  244. ProcessRecipeHead = recipe.Header;
  245. ProcessRecipe = recipe;
  246. ProcessRecipeName = recipeName;
  247. Recipelist.Add(recipe);
  248. if (_recipeRunningMode == 1 && recipe.Header.DechuckRecipe != null && !string.IsNullOrEmpty(recipe.Header.DechuckRecipe))
  249. {
  250. string dechuckcontent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipe.Header.DechuckRecipe, false, RecipeType.DeChuck.ToString());
  251. DechuckRecipe = Recipe.Load(dechuckcontent);
  252. if (DechuckRecipe != null)
  253. {
  254. DechuckRecipeName = recipe.Header.DechuckRecipe;
  255. needdechuck = true;
  256. Recipelist.Add(DechuckRecipe);
  257. }
  258. }
  259. break;
  260. case RecipeType.Chuck:
  261. ChuckRecipeName = recipeName;
  262. ChuckRecipe = recipe;
  263. Recipelist.Add(ChuckRecipe);
  264. needchuck = true;
  265. break;
  266. case RecipeType.DeChuck:
  267. DechuckRecipeName = recipeName;
  268. Recipelist.Add(DechuckRecipe);
  269. DechuckRecipe = recipe;
  270. needdechuck = true;
  271. break;
  272. case RecipeType.Clean:
  273. CleanRecipe = recipe;
  274. CleanRecipeName = recipeName;
  275. Recipelist.Add(CleanRecipe);
  276. needclean = true;
  277. break;
  278. }
  279. foreach (Recipe rcp in Recipelist)
  280. {
  281. if (AssignFuns(rcp) == false)
  282. {
  283. Stop($"Associate process alogrithm with recipe:{rcp.Header.Name} failed");
  284. EV.PostAlarmLog(Module.ToString(), $"Associate process alogrithm with recipe:{rcp.Header.Name} failed");
  285. return RState.Failed;
  286. }
  287. }
  288. _bLoopMode = false;
  289. _loopStartStep = 0;
  290. _loopCounter = 0;
  291. _processHelper.isLoop = false;
  292. _processHelper.loopsteps = 0;
  293. _processHelper.currentStepIndex = 0;
  294. if (needprocess)
  295. {
  296. switch (_jetChamber)
  297. {
  298. case JetChamber.VenusSE:
  299. if (Convert.ToDouble(ProcessRecipe.Header.Temperature) != SC.GetValue<double>($"{_chamber.Module}.Chiller.LastTemp"))
  300. {
  301. LOG.Write(eEvent.ERR_PROCESS, _chamber.Module, $"Chiller Temp setpoint not {ProcessRecipe.Header.Temperature}");
  302. return RState.Failed;
  303. }
  304. else
  305. {
  306. SC.SetItemValue($"{_chamber.Module}.Chiller.EnableToleranceAlarm", true);
  307. }
  308. if (Convert.ToDouble(ProcessRecipe.Header.WallTemperature) != ((AITHeaterData)DATA.Poll($"{_chamber.Module}.WallHeater.DeviceData")).SetPoint)
  309. {
  310. LOG.Write(eEvent.ERR_PROCESS, _chamber.Module, $"WallChiller Temp setpoint not {ProcessRecipe.Header.WallTemperature}");
  311. return RState.Failed;
  312. }
  313. else
  314. {
  315. SC.SetItemValue($"{_chamber.Module}.WallChiller.EnableToleranceAlarm", true);
  316. }
  317. break;
  318. case JetChamber.VenusDE:
  319. if (Convert.ToDouble(ProcessRecipe.Header.Temperature) != SC.GetValue<double>($"{_chamber.Module}.Chiller.LastTemp"))
  320. {
  321. LOG.Write(eEvent.ERR_PROCESS, _chamber.Module, $"Chiller Temp setpoint not {ProcessRecipe.Header.Temperature}");
  322. return RState.Failed;
  323. }
  324. else
  325. {
  326. SC.SetItemValue($"{_chamber.Module}.Chiller.EnableToleranceAlarm", true);
  327. }
  328. if (Convert.ToDouble(ProcessRecipe.Header.WallTemperature) != SC.GetValue<double>($"{_chamber.Module}.WallChiller.LastTemp"))
  329. {
  330. LOG.Write(eEvent.ERR_PROCESS, _chamber.Module, $"WallChiller Temp setpoint not {ProcessRecipe.Header.WallTemperature}");
  331. return RState.Failed;
  332. }
  333. else
  334. {
  335. SC.SetItemValue($"{_chamber.Module}.WallChiller.EnableToleranceAlarm", true);
  336. }
  337. break;
  338. }
  339. }
  340. //ProcessPressureOffset = SC.GetValue<double>($"{_chamber.Module}.ProcessPressureOffset");
  341. _faCallback.RecipeStart(_chamber.Module.ToString(), recipeName);
  342. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.InProcess);
  343. Eap_StartRecipeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
  344. Eap_EndRecipeTime = "";
  345. return Runner.Start(Module, Name);
  346. }
  347. public RState Monitor()
  348. {
  349. if (IsVenus)
  350. {
  351. Runner.Run(ProcessStep.PreparePVHe2, PrepareHe2, _delay_5s)
  352. .Run(ProcessStep.ClosePVHe2, CloseHe2, _delay_1s)
  353. .Wait(ProcessStep.WaitPressure, CheckBasePressure, _delay_30s)
  354. .RunIf(ProcessStep.RunChuckRecipe, needchuck, StartChuckRecipe, CheckRecipeDone, 5 * 60 * 60 * 1000)
  355. .RunIf(ProcessStep.RunProcessRecipe, needprocess, StartProcessRecipe, CheckRecipeDone, 5 * 60 * 60 * 1000)
  356. .RunIf(ProcessStep.RunDechuckRecipe, needdechuck, StartDechuckRecipe, CheckRecipeDone, 5 * 60 * 60 * 1000)
  357. .RunIf(ProcessStep.RunCleanRecipe, needclean, StartCleanRecipe, CheckRecipeDone, 5 * 60 * 60 * 1000)
  358. .End(ProcessStep.End, ProcessDone, _delay_1s);
  359. }
  360. else
  361. {
  362. if ((DATA.Poll($"{_chamber.Module}.Rf.DeviceData") as AITRfData).IsRfOn)
  363. {
  364. Eap_RFStopWatch.Start();
  365. }
  366. else
  367. {
  368. Eap_RFStopWatch.Stop();
  369. }
  370. Runner.Run(ProcessStep.PreparePressure, PreparePressure, IsPressureReady)
  371. .Run(ProcessStep.PrepareTemperature, PrepareTemp, IsTempReady)
  372. .RunIf(ProcessStep.RunChuckRecipe, needchuck, StartChuckRecipe, CheckRecipeDone, 500 * 60 * 60 * 1000)
  373. .RunIf(ProcessStep.RunProcessRecipe, needprocess, StartProcessRecipe, CheckRecipeDone, 500 * 60 * 60 * 1000)
  374. .RunIf(ProcessStep.RunDechuckRecipe, needdechuck, StartDechuckRecipe, CheckRecipeDone, 500 * 60 * 60 * 1000)
  375. .RunIf(ProcessStep.RunCleanRecipe, needclean, StartCleanRecipe, CheckRecipeDone, 500 * 60 * 60 * 1000)
  376. .End(ProcessStep.End, ProcessDone, _delay_1s);
  377. }
  378. return Runner.Status;
  379. }
  380. private bool CheckBasePressure()
  381. {
  382. if (needprocess)
  383. return _chamber.ProcessPressure <= Convert.ToDouble(ProcessRecipe.Header.BasePressure);
  384. else
  385. return true;
  386. }
  387. private bool CloseHe2()
  388. {
  389. _chamber.OpenValve(ValveType.PVHe2, false);
  390. return true;
  391. }
  392. private bool PrepareHe2()
  393. {
  394. _chamber.OpenValve(ValveType.PVHe2, true);
  395. return true;
  396. }
  397. private bool PreparePressure()
  398. {
  399. //if (_chamber.ProcessPressure < BasePressure && RtInstance.ConfigType==ConfigType.Kepler2200)
  400. //{
  401. // _needPumpDown = false;
  402. // return true;
  403. //}
  404. //_needPumpDown = true;
  405. return _pumpDownRoutine.Start(BasePressure) == RState.Running;
  406. }
  407. private bool IsPressureReady()
  408. {
  409. //if (_needPumpDown == false && RtInstance.ConfigType == ConfigType.Kepler2200)
  410. //{
  411. // return true;
  412. //}
  413. var status = _pumpDownRoutine.Monitor();
  414. if (status == RState.End)
  415. {
  416. return true;
  417. }
  418. else if (status == RState.Failed || status == RState.Timeout)
  419. {
  420. Runner.Stop($"Pump down to {BasePressure} failed.");
  421. EV.PostAlarmLog(Module.ToString(), $"Pump down to {BasePressure} failed.");
  422. return true;
  423. }
  424. return false;
  425. }
  426. private bool PrepareTemp()
  427. {
  428. //if (_jetChamber == JetChamber.Venus)
  429. //{
  430. // return SetCoolantTemp(BaseTemperature, _OffsetTemp);
  431. //}
  432. //else
  433. //{
  434. // return true;
  435. //}
  436. return true;
  437. }
  438. private bool IsTempReady()
  439. {
  440. //if (_jetChamber == JetChamber.Venus)
  441. //{
  442. // return CheckCoolantTemp(BaseTemperature, _tolerance);
  443. //}
  444. //else
  445. //{
  446. // return true;
  447. //}
  448. return true;
  449. }
  450. public RState StartNewStep()
  451. {
  452. ProcessDataRecorder.StepStart(RecipeId, _currentRecipe.Steps[_currentStep].StepNo, $"{Module}:{_currentRecipe.Header.Name}:{_currentRecipe.Steps[_currentStep].Description}", _currentRecipe.Steps[_currentStep].Time);
  453. _stepTime.Restart();
  454. var state = _currentRecipe.Steps[_currentStep].Start();
  455. LOG.Write(eEvent.INFO_PROCESS, Module, $"Recipe:{CurrentRunningRecipe} Step{_currentStep + 1} Start");
  456. _faCallback.RecipeStepStart(Module.ToString(), CurrentRunningRecipe, _currentStep);
  457. if (state != RState.Running)
  458. {
  459. Runner.Stop($"Start Step {_currentStep + 1} failed.");
  460. return state;
  461. }
  462. //if (_bLoopMode == true)
  463. //{
  464. //}
  465. if (_currentRecipe.Steps[_currentStep].CycleStart)
  466. {
  467. if (!_bLoopMode)
  468. {
  469. _bLoopMode = true;
  470. _loopStartStep = _currentStep;
  471. _loopCounter = _currentRecipe.Steps[_currentStep].CycleNumber - 1;
  472. currentRecipeResult.RecipeAllCounters = _currentRecipe.Steps[_currentStep].CycleNumber;
  473. currentRecipeResult.RecipeCurrentCounter = _loopCounter == 0 ? 0 : 1;
  474. _processHelper.isLoop = true;
  475. _processHelper.loopsteps = _currentRecipe.Steps[_currentStep].CycleNumber;
  476. }
  477. else
  478. {
  479. _processHelper.currentStepIndex += 1;
  480. }
  481. }
  482. return RState.Running;
  483. }
  484. private bool startRecipe(Recipe _recipe)
  485. {
  486. _currentRecipe = _recipe;
  487. if (_currentRecipe != null)
  488. {
  489. _currentStep = 0;
  490. CurrentRunningRecipe = _currentRecipe.Header.Name;
  491. RecipeId = Guid.NewGuid().ToString();
  492. RecipeStartTime = DateTime.Now;
  493. Recipetime.Restart();
  494. Notify($"Recipe:{CurrentRunningRecipe} start");
  495. _chamber.EPDRecipeStart(CurrentRunningRecipe);
  496. return StartNewStep() == RState.Running;
  497. }
  498. else { return false; }
  499. }
  500. private bool StartProcessRecipe()
  501. {
  502. return startRecipe(ProcessRecipe);
  503. }
  504. private bool StartChuckRecipe()
  505. {
  506. return startRecipe(ChuckRecipe);
  507. }
  508. private bool StartDechuckRecipe()
  509. {
  510. return startRecipe(DechuckRecipe);
  511. }
  512. private bool StartCleanRecipe()
  513. {
  514. return startRecipe(CleanRecipe);
  515. }
  516. private bool CheckRecipeDone()
  517. {
  518. var step = _currentRecipe.Steps[_currentStep];
  519. currentRecipeResult.RecipeStepCount = _currentRecipe.Steps.Count;
  520. currentRecipeResult.RecipeName = _currentRecipe.Header.Name;
  521. currentRecipeResult.RecipeType = _currentRecipe.Header.Type.ToString();
  522. currentRecipeResult.RecipeStepNumber = (_currentStep + 1);
  523. currentRecipeResult.RecipeStepType = step.Type.ToString();
  524. currentRecipeResult.RecipeStepDescription = string.IsNullOrEmpty(step.Description) ? "" : step.Description;
  525. switch (step.Type)
  526. {
  527. case StepType.Time:
  528. currentRecipeResult.RecipeStepSetTime = step.Time;
  529. break;
  530. case StepType.OverEtch:
  531. currentRecipeResult.RecipeStepSetTime = (int)_processHelper.lastEPDStepTime / 1000;
  532. break;
  533. default:
  534. currentRecipeResult.RecipeStepSetTime = null;
  535. break;
  536. }
  537. //currentRecipeResult.RecipeStepSetTime = step.Type==StepType.OverEtch? (int)_processHelper.lastEPDStepTime/1000: step.Time;
  538. currentRecipeResult.RecipeType = _currentRecipe.Header.Type.ToString();
  539. currentRecipeResult.RecipeStepDuringTime = (int)_stepTime.ElapsedMilliseconds / 1000;
  540. var result = step.Run();
  541. if (result == RState.Failed)
  542. {
  543. RecipeDone("Fail");
  544. UpdateWaferStatus(false);
  545. Runner.Stop($"Recipe:{CurrentRunningRecipe}, Step:{_currentStep + 1} Failed in {_stepTime.ElapsedMilliseconds / 1000}s");
  546. EV.PostAlarmLog(Module.ToString(), $"Recipe:{CurrentRunningRecipe}, Step:{_currentStep + 1} Failed");
  547. _faCallback.RecipeFailed(Module.ToString(), CurrentRunningRecipe);
  548. return true;
  549. }
  550. else if (result == RState.End || isMaualEndStep == true)
  551. {
  552. if (_currentRecipe.Steps.Count > _currentStep + 1)
  553. {
  554. _currentRecipe.Steps[_currentStep].End();
  555. }
  556. if (_currentRecipe.Steps[_currentStep].CycleEnd)
  557. {
  558. if (_loopCounter > 0)
  559. {
  560. _loopCounter--;
  561. currentRecipeResult.RecipeCurrentCounter += 1;
  562. _currentStep = _loopStartStep;
  563. return StartNewStep() != RState.Running;
  564. }
  565. else
  566. {
  567. _bLoopMode = false;
  568. _loopStartStep = 0;
  569. //_processHelper.loopStep(false, 0, 0);
  570. _processHelper.isLoop = false;
  571. _processHelper.loopsteps = 0;
  572. _processHelper.currentStepIndex = 0;
  573. }
  574. }
  575. if (_currentStep < _currentRecipe.Steps.Count - 1 || isMaualEndStep == true)
  576. {
  577. result = RState.End;
  578. isMaualEndStep = false;
  579. _currentStep++;
  580. LOG.Write(eEvent.INFO_PROCESS, Module, $"Recipe:{CurrentRunningRecipe} Step{_currentStep} End");
  581. //ProcessDataRecorder.StepEnd(RecipeId, _currentRecipe.Steps[_currentStep].StepNo, $"{Module}:{_currentRecipe.Header.Name}:{_currentRecipe.Steps[_currentStep].Description}", _currentRecipe.Steps[_currentStep].Time);
  582. _faCallback.RecipeStepEnd(Module.ToString(), CurrentRunningRecipe, _currentStep);
  583. return StartNewStep() != RState.Running;
  584. }
  585. else
  586. {
  587. LOG.Write(eEvent.INFO_PROCESS, Module, $"Recipe:{CurrentRunningRecipe} Step{_currentStep + 1} End");
  588. Notify($"Recipe:{CurrentRunningRecipe} finished");
  589. //FaEvent.FaPostInfo(Module.ToString(), $"Recipe:{CurrentRunningRecipe} finished");
  590. UpdateWaferStatus();
  591. //if (_currentRecipe.Header.Type == RecipeType.Process)
  592. //{
  593. // processRecipe = (Recipe)SerializeHelper.Instance.Clone(_currentRecipe);
  594. //}
  595. _chamber.EPDRecipeStop();
  596. RecipeDone("Success");
  597. return true;
  598. }
  599. }
  600. return false;
  601. }
  602. public void RecipeDone(string result)
  603. {
  604. Eap_EndRecipeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
  605. Eap_RecipeRFOnTime = Convert.ToInt32(Eap_RFStopWatch.ElapsedMilliseconds / 1000);
  606. Eap_RFStopWatch.Reset();
  607. Recipetime.Stop();
  608. string carrierId = "";
  609. WaferInfo waferInfo = WaferManager.Instance.GetWafer(ModuleHelper.Converter(Module.ToString()), 0);
  610. if (!waferInfo.IsEmpty)
  611. {
  612. WaferId =string.IsNullOrEmpty(waferInfo.EAPWaferID) ? waferInfo.InnerId.ToString(): waferInfo.EAPWaferID;
  613. SlotID = waferInfo.OriginSlot.ToString();
  614. LotID = waferInfo.ProcessJob == null || string.IsNullOrEmpty(waferInfo.ProcessJob.LotName) ? "" : waferInfo.ProcessJob.LotName;
  615. if (RtInstance.ConfigType == ConfigType.Kepler2200 && waferInfo.ProcessJob!=null)
  616. {
  617. string lp = waferInfo.ProcessJob.SlotWafers[0].Item1.ToString();
  618. carrierId = Singleton<RouteManager>.Instance.EFEM.LPCarrierId(ModuleHelper.Converter(lp));
  619. }
  620. }
  621. RecipeEndTime = RecipeStartTime + Recipetime.Elapsed;
  622. switch (_currentRecipe.Header.Type)
  623. {
  624. case RecipeType.Clean:
  625. ProcessDataRecorder.RecordPrecess(RecipeId, RecipeStartTime, RecipeEndTime, _currentRecipe.Header.Name, result, "", _chamber.Name, "", "", _currentRecipe.Header.Type.ToString(),"","");
  626. break;
  627. case RecipeType.Chuck:
  628. case RecipeType.DeChuck:
  629. case RecipeType.Process:
  630. ProcessDataRecorder.RecordPrecess(RecipeId, RecipeStartTime, RecipeEndTime, _currentRecipe.Header.Name, result, WaferId, _chamber.Name, LotID, SlotID, _currentRecipe.Header.Type.ToString(), carrierId, waferInfo.LotType) ;
  631. break;
  632. }
  633. }
  634. private bool ProcessDone()
  635. {
  636. _currentRecipe.Steps[_currentStep].End();
  637. _faCallback.RecipeComplete(Module.ToString(), CurrentRunningRecipe);
  638. RecipeFileManager.Instance.SaveRecipe(Module.ToString(), _currentRecipe.Header.Type.ToString(), _currentRecipe.Header.Name, RecipeUnity.RecipeToString(_currentRecipe), false, false);
  639. _stepTime.Stop();
  640. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Idle);
  641. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Completed);
  642. CloseAllValves();
  643. _chamber.GeneratorSetpower(0);
  644. _chamber.GeneratorBiasSetpower(0);
  645. _chamber.GeneratorBiasPowerOn(false);
  646. _chamber.GeneratorPowerOn(false);
  647. _chamber.OpenValve(ValveType.TurboPumpPumping, true);
  648. _chamber.OpenValve(ValveType.TurboPumpPurge, true);
  649. _chamber.OpenValve(ValveType.Guage, true);
  650. _chamber.SetPVPostion(1000);
  651. switch (_chamber.ChamberType)
  652. {
  653. case JetChamber.VenusSE:
  654. SC.SetItemValue($"{_chamber.Module}.Chiller.EnableToleranceAlarm", false);
  655. if (_chamber.IsHVOn)
  656. {
  657. _chamber.OnOffSetESCHV(false);
  658. }
  659. break;
  660. case JetChamber.VenusDE:
  661. SC.SetItemValue($"{_chamber.Module}.Chiller.EnableToleranceAlarm", false);
  662. SC.SetItemValue($"{_chamber.Module}.WallChiller.EnableToleranceAlarm", false);
  663. if (_chamber.IsHVOn)
  664. {
  665. _chamber.OnOffSetESCHV(false);
  666. }
  667. break;
  668. }
  669. return true;
  670. }
  671. private void UpdateWaferStatus(bool bDone = true)
  672. {
  673. if (bDone == false)
  674. {
  675. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Failed);
  676. if (_currentRecipe.Header.Type == RecipeType.Chuck)
  677. {
  678. // set wafer chucked flag even if the chuck recipe failed.
  679. WaferManager.Instance.UpdateWaferChuckStatus(Module, 0, EnumWaferChuckStatus.Chucked);
  680. }
  681. }
  682. switch (_currentRecipe.Header.Type)
  683. {
  684. case RecipeType.Process:
  685. break;
  686. case RecipeType.Chuck:
  687. WaferManager.Instance.UpdateWaferChuckStatus(Module, 0, EnumWaferChuckStatus.Chucked);
  688. break;
  689. case RecipeType.DeChuck:
  690. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Completed);
  691. WaferManager.Instance.UpdateWaferChuckStatus(Module, 0, EnumWaferChuckStatus.Dechucked);
  692. break;
  693. }
  694. }
  695. public async void Abort()
  696. {
  697. if (_currentRecipe != null)
  698. {
  699. RecipeDone("Abort");
  700. }
  701. WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Failed);
  702. _chamber.GeneratorBiasPowerOn(false);
  703. _chamber.GeneratorPowerOn(false);
  704. CloseAllValves();
  705. _chamber.OpenValve(ValveType.TurboPumpPumping, true);
  706. _chamber.OpenValve(ValveType.TurboPumpPurge, true);
  707. if (_chamber.ChamberType == JetChamber.VenusSE || _chamber.ChamberType == JetChamber.VenusDE)
  708. {
  709. _chamber.SetBacksideHeThreshold(0, 0);
  710. _chamber.SetBacksideOutHeThreshold(0, 0);
  711. _chamber.MagnetSetpower(0);
  712. await Task.Delay(2000);
  713. _chamber.OnOffSetESCHV(false);
  714. }
  715. }
  716. }
  717. }