Kaynağa Gözat

Redesign the EFEM module for thread safe issue.

sangwq 11 ay önce
ebeveyn
işleme
7a1faeac74

+ 1 - 0
Venus/Framework/Common/Routine/IRoutine.cs

@@ -50,6 +50,7 @@ namespace Aitex.Core.RT.Routine
 
         protected RoutineRunner Runner = new RoutineRunner();
 
+        protected readonly int _delay_5ms = 5;
         protected readonly int _delay_50ms = 50;
         protected readonly int _delay_1s = 1000;
         protected readonly int _delay_2s = 2000;

+ 5 - 2
Venus/Venus_RT/Devices/EFEM/JetEfem.cs

@@ -522,8 +522,11 @@ namespace Venus_RT.Devices.EFEM
 
         public override bool SetLamp(LightType light, LightStatus status)
         {
-            //if (!CheckEfemStatus())
-            //    return false;
+            if (Status == RState.Running)
+            {
+                LOG.Write(eEvent.ERR_EFEM_ROBOT, ModuleName.EFEM, "EFEM is busy, please wait a minute");
+                return false;
+            }
 
             _currentMsg = new EfemMessage
             {

+ 16 - 16
Venus/Venus_RT/Devices/EFEM/Loadport.cs

@@ -22,7 +22,7 @@ namespace Venus_RT.Devices.EFEM
 {
     sealed class Loadport : ILoadport
     {
-        private readonly EfemBase _controller;
+        private  EfemEntity _controller => Singleton<RouteManager>.Instance.EFEM;
 
         //---------------------------------Properties------------------------------------
         // 
@@ -101,7 +101,6 @@ namespace Venus_RT.Devices.EFEM
         {
             Module = mod;
             PortId = ((int)mod - (int)ModuleName.LP1 + 1).ToString();
-            _controller = efem;
 			
 			TimerNotifyJobDone = new Stopwatch();
 
@@ -151,7 +150,7 @@ namespace Venus_RT.Devices.EFEM
 
             SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
 
-            _controller.SetThickness(Module, _waferThicknessType);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.SetThickness, Module,  _waferThicknessType);
         }
 
         public void SetThin()
@@ -160,7 +159,7 @@ namespace Venus_RT.Devices.EFEM
 
             SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
 
-            _controller.SetThickness(Module, _waferThicknessType);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.SetThickness,  Module, _waferThicknessType);
         }
 
 
@@ -175,7 +174,7 @@ namespace Venus_RT.Devices.EFEM
 
             IsBusy = true;
 
-            _controller.Home(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.HomeLP, Module);
         }
 		
 		public void NoteJobStart()
@@ -233,7 +232,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.Load(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Load, Module);
         }
 
         public void LoadStart()
@@ -294,7 +293,7 @@ namespace Venus_RT.Devices.EFEM
 
             IsBusy = true;
 
-            _controller.Unload(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Unload, Module);
         }
 
         public void UnloadStart()
@@ -351,7 +350,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.Dock(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Dock, Module);
         }
 
         public void OnDocked()
@@ -386,7 +385,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.Undock(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Undock, Module);
         }
 
         public void OnUndocked()
@@ -421,7 +420,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.Clamp(Module, isUnloadClamp);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Clamp, Module, isUnloadClamp);
         }
 
         public void OnClamped(bool isUnloadClamp)
@@ -468,7 +467,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.Unclamp(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Unclamp, Module);
         }
 
 
@@ -495,7 +494,7 @@ namespace Venus_RT.Devices.EFEM
 
         public void Map()
         {
-            _controller.Map(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.Map, Module);
         }
 
 
@@ -516,9 +515,10 @@ namespace Venus_RT.Devices.EFEM
                 EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read carrier ID");
                 return;
             }
+
             IsBusy = true;
 
-            _controller.ReadCarrierId(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.ReadCarrierId, Module);
         }
 
         public void OnCarrierIDRead(string data)
@@ -577,7 +577,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.WriteCarrierId(Module, id);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.WriteCarrierID, Module, id);
         }
 
         public void OnCarrierIDWrite(string data)
@@ -750,7 +750,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.ReadTagData(Module);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.ReadTagData, Module);
         }
 
         public void OnTagDataRead(string data)
@@ -809,7 +809,7 @@ namespace Venus_RT.Devices.EFEM
             }
             IsBusy = true;
 
-            _controller.WriteTagData(Module, tagData);
+            _controller.SendEfemBackroundCommand(EfemEntity.MSG.WriteTagData, Module, tagData);
         }
 
         public void OnTagDataWrite(string data)

+ 1 - 1
Venus/Venus_RT/Devices/KeplerSignalTower.cs

@@ -97,7 +97,7 @@ namespace Venus_RT.Devices
 
             if (RtInstance.ConfigType ==  Venus_Core.ConfigType.Kepler2200 || RtInstance.ConfigType == Venus_Core.ConfigType.Kepler2300)
             {
-                Singleton<RouteManager>.Instance.EFEM?.InvokeSignalTower(venusType, venusSetpoint);
+                Singleton<RouteManager>.Instance.EFEM?.SendEfemBackroundCommand(EfemEntity.MSG.Light, venusType, venusSetpoint);
             }
                 
             return true;

+ 95 - 19
Venus/Venus_RT/Modules/EFEM/EfemEntity.cs

@@ -21,6 +21,7 @@ using Venus_RT.Devices.YASKAWA;
 using Venus_RT.Devices.EFEM;
 using Venus_RT.Modules.LPs;
 using Venus_RT.Modules.EFEM;
+using System.Collections.Concurrent;
 
 namespace Venus_RT.Modules
 {
@@ -77,7 +78,6 @@ namespace Venus_RT.Modules
             PMLiftPinDown,      // 19
             TurnOffBuzzer, 
             Abort,
-            Map,
 			ToInit,
 			Cool,
             Swap,
@@ -86,7 +86,23 @@ namespace Venus_RT.Modules
             Flip,
             LiftActionDone,
             Offline,
+
+            BackroundCmd = 100,
             Light,
+            SetThickness,
+            HomeLP,
+            Load,
+            Unload,
+            Dock,
+            Undock,
+            Clamp,
+            Unclamp,
+            Map,
+            ReadCarrierId,
+            WriteCarrierID,
+            ReadTagData,
+            WriteTagData,
+            MaxMsgValue,
         }
 
         public enum EfemType
@@ -142,7 +158,7 @@ namespace Venus_RT.Modules
         private readonly string Name;
         private readonly EfemBase _efem;
         private readonly LoadPortModule[] _lpms = new LoadPortModule[3];
-        private readonly EfemSignalTower _signalTower;
+        private readonly EfemBackroundMsgProcessor _signalTower;
 
         private readonly EfemType _efemType;
         public EfemBase EfemDevice => _efem;
@@ -178,7 +194,7 @@ namespace Venus_RT.Modules
             _efemType = (EfemType)SC.GetValue<int>($"EFEM.EfemType");
 
             _efem = new JetEfem();
-            _signalTower = new EfemSignalTower(_efem);
+            _signalTower = new EfemBackroundMsgProcessor(_efem);
 
             Name = ModuleName.EFEM.ToString();
 
@@ -275,7 +291,7 @@ namespace Venus_RT.Modules
             AnyStateTransition(MSG.Online,                  fnOnline,           FSM_STATE.SAME);
             AnyStateTransition(MSG.Abort,                   fnAbortRobot,       STATE.Idle);
             AnyStateTransition(MSG.ToInit,                  fnToInit,           STATE.Init);
-            AnyStateTransition(MSG.Light,                   fnSetLight,         FSM_STATE.SAME);
+            AnyStateTransition(MSG.BackroundCmd,            fnBackroundCommand, FSM_STATE.SAME);
 
 
             AnyStateTransition(MSG.CommReady,          fnCommReady,               STATE.Init);
@@ -468,12 +484,9 @@ namespace Venus_RT.Modules
             return true;
         }
 
-        private bool fnSetLight(object[] param)
+        private bool fnBackroundCommand(object[] param)
         {
-            LightType light = (LightType)param[0];
-            LightStatus st = (LightStatus)param[1];
-
-            _signalTower.SetLight(light, st);
+            _signalTower.SendBackroundCommand(param);
             return true;
         }
 
@@ -757,10 +770,10 @@ namespace Venus_RT.Modules
             return (int)FSM_MSG.NONE;
         }
 
-        public int InvokeSignalTower(LightType type, LightStatus status)
+        public int SendEfemBackroundCommand(params object[] args)
         {
-            if(CheckToPostMessage((int)MSG.Light, type, status))
-                return (int)MSG.Light;
+            if(CheckToPostMessage((int)MSG.BackroundCmd, args))
+                return (int)MSG.BackroundCmd;
 
             return (int)FSM_MSG.NONE;
         }
@@ -1001,11 +1014,11 @@ namespace Venus_RT.Modules
         }
     }
 
-    public class EfemSignalTower
+    public class EfemBackroundMsgProcessor
     {
         private EfemBase _efem;
-        private Queue<KeyValuePair<LightType, LightStatus>> _pendingCmds = new Queue<KeyValuePair<LightType, LightStatus>>();
-        public EfemSignalTower(EfemBase efem)
+        private ConcurrentQueue<object[]> _pendingCmds = new ConcurrentQueue<object[]>();
+        public EfemBackroundMsgProcessor(EfemBase efem)
         {
             _efem = efem;
         }
@@ -1014,14 +1027,77 @@ namespace Venus_RT.Modules
         {
             if(Singleton<RouteManager>.Instance.EFEM.RobotStatus != RState.Running && _pendingCmds.Count > 0)
             {
-                var lightCommand = _pendingCmds.Dequeue();
-                _efem.SetLamp(lightCommand.Key, lightCommand.Value);
+                if(_pendingCmds.TryDequeue(out object[] args))
+                {
+                    EfemEntity.MSG cmd = (EfemEntity.MSG)args[0];
+                    if ((int)cmd > (int)EfemEntity.MSG.BackroundCmd && (int)cmd < (int)EfemEntity.MSG.MaxMsgValue)
+                    {
+                        processBackroundCommand(cmd, args);
+                    }
+                    else
+                    {
+                        LOG.Write(eEvent.ERR_EFEM_ROBOT, ModuleName.EFEM, $"Invalid EFEM backround command {cmd}");
+                    }
+                }
             }
         }
 
-        public void SetLight(LightType type, LightStatus status)
+        public void SendBackroundCommand(object[] args)
         {
-            _pendingCmds.Enqueue(new KeyValuePair<LightType, LightStatus>(type, status));
+            _pendingCmds.Enqueue(args);
+        }
+
+
+        private void processBackroundCommand(EfemEntity.MSG cmd, object[] args)
+        {
+            switch(cmd)
+            {
+                case EfemEntity.MSG.Light:
+                    _efem.SetLamp((LightType)args[1], (LightStatus)args[2]);
+                    break;
+                case EfemEntity.MSG.SetThickness:
+                    _efem.SetThickness((ModuleName)args[1], (string)args[2]);
+                    break;
+                case EfemEntity.MSG.HomeLP:
+                    _efem.Home((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Load:
+                    _efem.Load((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Unload:
+                    _efem.Unload((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Dock:
+                    _efem.Dock((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Undock:
+                    _efem.Undock((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Clamp:
+                    _efem.Clamp((ModuleName)args[1], (bool)args[2]);
+                    break;
+                case EfemEntity.MSG.Unclamp:
+                    _efem.Unclamp((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.Map:
+                    _efem.Map((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.ReadCarrierId:
+                    _efem.ReadCarrierId((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.WriteCarrierID:
+                    _efem.WriteCarrierId((ModuleName)args[1], (string)args[2]);
+                    break;
+                case EfemEntity.MSG.ReadTagData:
+                    _efem.ReadCarrierId((ModuleName)args[1]);
+                    break;
+                case EfemEntity.MSG.WriteTagData:
+                    _efem.WriteCarrierId((ModuleName)args[1], (string)args[2]);
+                    break;
+                default:
+                    LOG.Write(eEvent.ERR_EFEM_ROBOT, ModuleName.EFEM, $"unprocessed Efem command {cmd}");
+                    break;
+            }
         }
     }
 }

+ 9 - 9
Venus/Venus_RT/Modules/EFEM/EfemSwapRoutine.cs

@@ -24,7 +24,7 @@ namespace Venus_RT.Modules.EFEM
             OpenSlitDoor,
             WaitEFEMIdle,
             MoveWafer,
-            WaitMaferMoved,
+            WaferMoved,
             CloseSlitDoor,
             NotifyDone,
         }
@@ -109,14 +109,14 @@ namespace Venus_RT.Modules.EFEM
 
         public RState Monitor()
         {
-            Runner.Wait(SwapStep.WaitModuleReady,  () => _llModule.IsIdle,     _delay_60s)
-                .Run(SwapStep.ModulePrepare,       ModulePrepare,              IsModulePrepareReady)
-                .Run(SwapStep.OpenSlitDoor,        OpenSlitDoor,               IsSlitDoorOpen)
-                .Wait(SwapStep.WaitEFEMIdle,       WaitRobotReady)
-                .LoopStart(SwapStep.MoveWafer,     loopName(),                 _actionCount,           MoveWafer)
-                .LoopEnd(SwapStep.WaitMaferMoved,  NullFun,                    WaitWaferMoved,         _moveTimeout + _delay_1s)
-                .Run(SwapStep.CloseSlitDoor,       CloseSlitDoor,              IsSlitDoorClosed)
-                .End(SwapStep.NotifyDone,          NotifyLLDone,               _delay_50ms);
+            Runner.Wait(SwapStep.WaitModuleReady,       () => _llModule.IsIdle,     _delay_60s)
+                .Run(SwapStep.ModulePrepare,            ModulePrepare,              IsModulePrepareReady)
+                .Run(SwapStep.OpenSlitDoor,             OpenSlitDoor,               IsSlitDoorOpen)
+                .LoopStart(SwapStep.WaitEFEMIdle,       loopName(),                 _actionCount,           NullFun,                    WaitRobotReady,     _delay_60s)
+                .LoopRun(SwapStep.MoveWafer,            MoveWafer,                  WaitWaferMoved,         _moveTimeout + _delay_1s)
+                .LoopEnd(SwapStep.WaferMoved,           NullFun,                    _delay_5ms)
+                .Run(SwapStep.CloseSlitDoor,            CloseSlitDoor,              IsSlitDoorClosed)
+                .End(SwapStep.NotifyDone,               NotifyLLDone,               _delay_50ms);
 
             return Runner.Status;
         }