Introduction to new SECS/GEM driver using SecsToTool.Net


Introduction to SECS/GEM

SEMI.org, an international organization of semiconductor manufacturer, is an organization body that govern the standards for semiconductor manufacturing equipment. Often the the standard referred to SECS/GEM standard, which includes the SECS-I, SECS-II, HSMS and GEM standards.

  • SECS-I defines a point to point communication protocol for RS-232 serial communications. This is a much slower media as compared to HSMS
  • SECS-II defines how information is passed between equipment and host in the form of low level messages (in the bits and bytes interpretation)
  • HSMS define a point to point communication protocol for TCP/IP ethernet communication
  • GEM defines how to use the core SECS-II messages to perform particular tasks, such as event report, data collection and recipe management. It also defines the behavior of equipment when interfacing with the host.

As said previously, the SECS-II defines a low level message contents between equipment and host. For example, the following message is sent from device 66 telling the host that the temperature at point T1 has exceeded a preset process limit



 

10000000     R=1 (to the host)
00101110     Device Code=66
00000101     Stream 5, W=0
00000001     Function 1
10000000     E=1
00000001     Block 1
00000000
00000000     System bytes=0
00000000
00000000
00000001     List
00000011     3 Elements
00100001     Binary Item next byte length
00000001     1 byte long
00000100     Alarm set, category 4
01100101     Item, 1-byte integer, next byte length
00000001     1 byte long
00010001     Alarm 17
01000001     Item, ASCII, next byte length
00000111     7 characters
01010100     ASCII T
00110001     ASCII 1
00100000     ASCII space
01001000     ASCII H
01001001     ASCII I
01000111     ASCII G
01001000     ASCII H

This is a very tedious job if you want to interpret the raw binary messages so that your application can process it. Today they are a couple of third-party SECS/GEM drivers that provides a high level application programming interface (API) for used in your host application.

Introduction to SecsToTool.Net

Before you begin reading this further, please download a copy of the SDK at http://www.insphere.com.sg

Now you may wonder, what is SecsToTool.Net?

SecsToTool.Net is a connectivity solution for the semiconductor equipment that support SECS/GEM communication interface. The SecsToTool.Net driver SDK is designed to provide a high level method call/reply and event driven environment for your host application to communicate with equipment. By using SecsToTool.Net, you can concentrate on developing a solid application rather than sidetracked by the lower level SECS/GEM message protocols and formats which are very tedious.

The Host SECS Library features a fully CLS (Common Language Runtime) compliant API and can be used from any of the .NET support programming language such as C#, VB, J#, C++, Pyton, etc. To interface with SECS/GEM capable equipment, the development effort can be focus on the message handling in the well formatted data item and business logic with a minimal code written

The SDK is also come with a Model Builder Editor that let you quickly and easily model the equipment SECS/GEM capability that will be communicating with your host application. Rather than coding the formats, communication settings, other equipment modeling into your application, you use SecsToTool Model Builder to configure it and generate the data into a single xml file.

Download a copy of SecsToTool.Net SDK at http://www.insphere.com.sg/download.htm. The SDK includes a full developer API reference and a user guide documentation for you to quickly get started of using SecsToTool.Net

Interfacing with Equipment using SecsToTool.Net

The following code shows you how to perform initialization and establish communication with equipment using SecsToTool.Net. All the API are .Net compliant and event-driven environment.

using System;

// Import the SecsToTool Driver namespace

using Insphere.SecsToTool.Application;

// Import the SecsDataItem namespance

using Insphere.SecsToTool.Common;

// Declare a simple delegate to broadcast our message to subscriber.

public delegate void DelInitializationExample(string message);

We also declare a simple delegate to broadcast our message to a higher layer handler. E.g: Equipment Manager.

You could declare a proper EventArgs which compliant to the .Net programming guidelines.

The following class demonstrate how to develop a Daisy-chain type of initialization approach. First, we will declare a InitializationChainContext as a context information that will be assigned to our hostController.Tag. The tag assigned will be reset for every transaction, meaning it will not be carried forward for the next transaction unless we set it again. You will notice for every transaction that are involved in this daisy chain ring is assigned with the InitializationChainContext variable

// This class provides the example for Host to perform Initialization to Equipment upon
Establish Communication through S1F13.

// This example provides user a guide of how to perform initialization using the
Asynchronous Daisy Chain approach

public class InitializationExample

{

 

      // Declare the SECsHost object

      private SECsHost hostController;

 

      // Declare a Daisy chain context

      private const string InitializationChainContext = "Establish Communication Chain";

 

   

      // Declare a simple event to broadcast our activity

      public event DelInitializationExample MessageIn;

 

      // Constructor instance

      public InitializationExample()

      {

            // create an instance of SECsHost object

            hostController = SECsFactory.CreateInstance();

 

            // hook up event sent by the equipment.

            hostController.SECsPrimaryIn +=
new Insphere.SecsToTool.Application.SECsBase.
SECsPrimaryInEventHandler(OnPrimaryIn);

 

            // hook up reply/acknowledgement sent by the equipment

            hostController.SECsSecondaryIn +=
new Insphere.SecsToTool.Application.SECsBase.
SECsSecondaryInEventHandler(OnSecondaryIn);

 

            // hook up the error messages from the library

            hostController.SECsHostError +=
new Insphere.SecsToTool.Application.SECsBase.
SECsHostErrorHandler(OnErrorNotification);

      } 

In the constructor we create an instance of SECsHost object that provides the library of methods for your host application to send messages to equipment. The hostController subscribe to events:

  • SECsPrimaryIn - this is events initiated by equipment to host.
  • SECsSecondaryIn - this is a reply or acknowledgement from equipment. When host send a message to equipment, equipment will send the reply or ack via the secondary event.
  • SECsHostError - these are all the error generated by the SECsHost compiler. When equipment send illegal messages or invalid formats, host will fire an error to notify the host application.

// Start Initialization to the equipment

public void StartInitialization()

  {

     Logger("Step 1: Initialize the Tool Model");

     hostController.Initialize(AppDomain.CurrentDomain.BaseDirectory + "\\ToolModel1.xml");

     Logger("Step 2: Open HSMS connection port");

     hostController.Connect();

     // Now we will wait for the Equipment to acknowledge and notify at the Primary Event

  } 

This method is our sample application entry point to trigger a series of methods to be executed in daisy-chain fashion. (Meaning it is executed in the form of RING, when reply is OK, the execution continues). hostController triggers a Connect method to open the HSMS connection with equipment.

      // Primary event handler

      private void OnPrimaryIn(object sender, SECsPrimaryInEventArgs e)

      {

            switch (e.EventId)

            {

                  case PrimaryEventType.Connected:   

// this signal that we have successfully connected to the equipment

                        Logger("Equipment Connected");

                        // Use Tag to set the context for our Daisy Chain method

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 3: Initiate Establish Communication via
S1F13 to equipment");

                        // Trigger the S1F13 message to equipment.

// Now note that our establish communication carry a
InitializationChain Context

                        hostController.EstablishCommunication();

 

                        // Wait for the reply from Equipment in Secondary Event

                        break;

                  case PrimaryEventType.EventReport:

                        Logger("Received event: " + e.Inputs.DataItem["Ln"]["CEID"].Value);

                        break;

 

            }

      }

When equipment accept the connection, it will send the connected event to our PrimaryIn.

The rest of the following code, shows how to handle the reply or acknowledgement from equipment and continue the daisy chain execution until it hits the final line.

// Secondary Event Handler

    private void OnSecondaryIn(object sender, SECsSecondaryInEventArgs e) {

        switch (e.EventId) {

            case SecondaryEventType.EstablishCommunicationReply:
// S1F14. Replies from S1F13 message

                // Check if equipment accept our S1F13 request

                if (e.Outputs.DataItem["Ln"]["COMMACK"].Value.ToString()  == "0")  {
// 0 means OK

                    Logger("Establish Communication accepted");

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 4: Synchronous Host current date
and time with Equipment");

                        hostController.DateTimeSetRequest();

                    }

                }

                else

                    Logger("Establish Communication not accepted.
Initialization terminated!");

                   

                break;

 

            case SecondaryEventType.DateTimeSetReply:
// S2F32. Acknowledgement from our DateTimeSetRequest()

                if (e.Outputs.DataItem["TIACK"].Value.ToString() == "0") { // 0 Means OK

                    Logger("DateTimeSet acknowledged OK");

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 5: Disable all the alarm activation
status at Equipment");

                        hostController.EnableAlarm(false);

                    }

                }

                break;

 

            case SecondaryEventType.DisableAlarmReportReply:

// S5F4. Acknowledgement from our EnableAlarm(false) - Disable all alarm

                if (e.Outputs.DataItem["ACKC5"].Value.ToString() == "0") {

                    Logger("Disable all Alarms accepted by equipment");

 

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 6: Enable all the alarm as
defined in our ToolModel1.xml");

                        hostController.EnableAlarm(true);

                    }

                }

                else

                    Logger("Disable all Alarms not accepted by equipment.
Initialization terminated!");

 

                break;

 

            case SecondaryEventType.EnableAlarmReportReply:
// S5F4. Enable Alarm acknowledgement

                if (e.Outputs.DataItem["ACKC5"].Value.ToString() == "0") {

                    Logger("Enable all Alarms accepted by equipment");

               

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 7: Delete equipment existing report definition");

                        hostController.DefineReports(DefineReportType.DeleteReports);

 

                    }

                }

                else

                    Logger("Enable Alarms not accepted by equipment.
Initialization terminated!");

 

                break;

 

            case SecondaryEventType.DeleteAllReportsReply:
// S2F34. Delete all reports acknowledgement

                if (e.Outputs.DataItem["DRACK"].Value.ToString() == "0") {

                    Logger("Delete all report accepted");

 

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 8: Define all reports and its associated
variables as defined in out ToolModel1.xml");

                        hostController.DefineReports(DefineReportType.DefineReports);

 

                    }

                }

                else

                    Logger("Delete all report not accepted. Initialization terminated!");

 

                break;

 

            case SecondaryEventType.DefineReportsReply:
// S2F34. Define reports acknowledgement

                if (e.Outputs.DataItem["DRACK"].Value.ToString() == "0") {

                    Logger("Define all report accepted");

 

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 9: Unlink equipment event report definition");

                        hostController.LinkEventReport(LinkEventReportType.UnlinkEventReports);

 

                    }

                }

                else

                    Logger("Define all report not accepted. Initialization terminated!");

 

                break;

 

            case SecondaryEventType.UnlinkEventReportsReply:
// S2F36 Unlink event report acknowledgement

                if (e.Outputs.DataItem["LRACK"].Value.ToString() == "0") {

                    Logger("Unlink event report is accepted");

 

                    // Check if it is a Initialization Chain Context

                    if (e.Tag.Equals(InitializationChainContext)) {

                        // Continue our initialization

 

                        // Keep setting the Daisy Chain context

                        hostController.Tag = InitializationChainContext;

 

                        Logger("Step 10: Link event report definition to equipment as
defined in our ToolModel1.xml");

                        hostController.LinkEventReport(LinkEventReportType.LinkEventReports);

 

                    }

                }

                else

                    Logger("Unlink event report is not accepted.
Initialization terminated!");

 

                break;

 

            case SecondaryEventType.LinkEventReportsReply:
// S2F36 Link event report acknowledgement

                if (e.Outputs.DataItem["LRACK"].Value.ToString() == "0") {

                    Logger("Unlink event report is accepted");

 

                    Logger("Daisy Chain Demo completed.");

               

                    // This will disconnect our connection to equipment

                    hostController.Disconnect();

                    Logger("Communication disconnected");

                }

                else

                    Logger("Unlink event report is not accepted.
Initialization terminated!");

 

                break;

 

        }

    }

 

    private void Logger(string message) {

        if (MessageIn != null)

            MessageIn(message);

    }

 

    private void OnErrorNotification(object sender, SECsHostErrorEventArgs e) {

        Logger("Error source: " + e.Source + ", Message: " + e.Message);

    }

Sample High Level Log contents

The message transacted between the semiconductor equipment and host can be represented in the semiconductor markup language (SML) which is pretty much similar to the XML structure.

Sending @12/21/2005 10:52:53 PM
S2F33 [00000008] W
 <L[2]
  <U4[3] 100>
  <L[0]
  >
 >
.
Received @12/21/2005 10:52:54 PM
S2F34 [00000008]
 <B[1] 00
 >
.
Sending @12/21/2005 10:52:54 PM
S2F33 [00000009] W
 <L[2]
  <U4[3] 101>
  <L[3]
   <L[2]
    <U4[3] 100>
    <L[5]
     <U4[3] 200>
     <U4[3] 201>
     <U4[3] 202>
     <U4[3] 203>
     <U4[3] 204>
    >
   >
   <L[2]
    <U4[3] 101>
    <L[2]
     <U4[3] 205>
     <U4[3] 207>
    >
   >
   <L[2]
    <U4[3] 102>
    <L[0]
    >
   >
  >
 >
.
Received @12/21/2005 10:52:54 PM
S2F34 [00000009]
 <B[1] 00>
.
Sending @12/21/2005 10:52:54 PM
S2F35 [00000010] W
 <L[2]
  <U4[3] 102>
  <L[3]
   <L[2]
    <U4[4] 2000>
    <L[0]
    >
   >
   <L[2]
    <U4[4] 2001>
    <L[0]
    >
   >
   <L[2]
    <U4[4] 2002>
    <L[0]
    >
   >
  >
 >
.
Received @12/21/2005 10:52:54 PM
S2F36 [00000010]
 <B[1] 00>

Sample Low Level SECS messages log contents

This is the original messages sent and received in the SecsToTool.Net compiler level. All this complexity will be transparent to the host application level. SecsToTool.Net does the interpretation and parsing of the raw messages and represent it in a human readable structure.

--> 12/22/2005 12:55:17 AM Length [00 00 00 0A]
--> 12/22/2005 12:55:17 AM SelectReq[FC FC 00 00 00 01 00 00 00 01]
<-- 12/22/2005 12:55:17 AM Length [00 00 00 0A]
<-- 12/22/2005 12:55:17 AM SelectRsp[FC FC 00 00 00 02 00 00 00 01]
--> 12/22/2005 12:55:17 AM Length [00 00 00 0A]
--> 12/22/2005 12:55:17 AM LinktestReq[FC FC 00 00 00 05 00 00 00 02]
<-- 12/22/2005 12:55:18 AM Length [00 00 00 0A]
<-- 12/22/2005 12:55:18 AM LinktestRsp[FF FF 00 00 00 06 00 00 00 02]
--> 12/22/2005 12:55:18 AM Length [00 00 00 0C]
--> 12/22/2005 12:55:18 AM Header [00 03 81 0D 00 00 00 00 00 04]
--> 12/22/2005 12:55:18 AM Data   [01 00]
<-- 12/22/2005 12:55:22 AM Length [00 00 00 24]
<-- 12/22/2005 12:55:22 AM Header [00 03 01 0E 00 00 00 00 00 04]
<-- 12/22/2005 12:55:22 AM Data   [01 02 21 01 00 01 02 41 07 66 73 64 61 66 61 66 41 08 66 64 61 66 73 61 66 64]
--> 12/22/2005 12:55:22 AM Length [00 00 00 1C]
--> 12/22/2005 12:55:22 AM Header [00 03 82 1F 00 00 00 00 00 05]
--> 12/22/2005 12:55:22 AM Data   [41 10 32 30 30 35 31 32 32 32 30 30 35 35 32 32 30 30]
<-- 12/22/2005 12:55:23 AM Length [00 00 00 0D]
<-- 12/22/2005 12:55:23 AM Header [00 03 02 20 00 00 00 00 00 05]
<-- 12/22/2005 12:55:23 AM Data   [21 01 00]