Introduction to SECS/GEM
SEMI.org, an international organization of semiconductor manufacturers, is an organization body that governs the standards for semiconductor manufacturing equipments. Often the standard is referred to as 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 when compared to HSMS.
- SECS-II defines how the information is passed between the equipment and the host in the form of low level messages (in the bits and bytes interpretation).
- HSMS defines 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 the equipment while interfacing with the host.
As said earlier, SECS-II defines a low level message content between the equipment and the 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 there are a couple of third-party SECS/GEM drivers that provide a high level application programming interface (API) for use in your host application.
Introduction to SecsToTool.NET
Now you may wonder, what is SecsToTool.NET?
SecsToTool.NET is a connectivity solution for the semiconductor equipment that supports SECS/GEM communication interface. The SecsToTool.NET driver SDK is designed to provide high level method call/reply and event driven environment for your host application to communicate with the equipment. By using SecsToTool.NET, you can concentrate on developing a solid application rather than being 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 programming languages such as C#, VB, J#, C++, Pyton, etc. To interface with SECS/GEM capable equipment, we can focus our development effort on message handling in the well formatted data item and business logic with minimal code written.
The SDK comes with a Model Builder Editor that lets you quickly and easily model the equipment SECS/GEM capability that communicates with your host application. Rather than coding the formats, communication settings, other equipments modeling into your application, you can use SecsToTool Model Builder to configure it and generate the data in a single XML file.
Download a copy of SecsToTool.NET SDK from here. The SDK includes a full developer API reference and a user guide documentation for you to quickly get started on using SecsToTool.NET.
Interfacing with the equipment using SecsToTool.NET
The following code shows you how to perform initialization and establish communication with the equipment using SecsToTool.NET. All the APIs are .NET compliant and provide an event-driven environment:
using System;
using Insphere.SecsToTool.Application;
using Insphere.SecsToTool.Common;
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 can declare a proper EventArgs that is compliant to the .NET programming guidelines.
The following class demonstrates how to develop a Daisy-chain type of initialization approach. First, we declare an InitializationChainContext as a context information that is assigned to our hostController.Tag. The tag assigned will be reset for every transaction, which means it will not be carried forward to the next transaction unless we set it again. Every transaction that is involved in this daisy chain ring is assigned an InitializationChainContext variable:
[Editor comment: Line breaks used to avoid scrolling.]
public class InitializationExample {
private SECsHost hostController;
private const string InitializationChainContext =
"Establish Communication Chain";
public event DelInitializationExample MessageIn;
public InitializationExample() {
hostController = SECsFactory.CreateInstance();
hostController.SECsPrimaryIn += new Insphere.SecsToTool.
Application.SECsBase.SECsPrimaryInEventHandler(OnPrimaryIn);
hostController.SECsSecondaryIn += new Insphere.SecsToTool.
Application.SECsBase.SECsSecondaryInEventHandler(OnSecondaryIn);
hostController.SECsHostError += new Insphere.SecsToTool.
Application.SECsBase.SECsHostErrorHandler(OnErrorNotification);
}
In the constructor, we create an instance of SECsHost object that provides a library of methods for your host application to send messages to the equipment. The hostController subscribes to the following events:
SECsPrimaryIn - this is the event initiated by the equipment to host.
SECsSecondaryIn - this is the reply or acknowledgement from the equipment. When the host sends a message to the equipment, the equipment will send a reply or acknowledgement via the secondary event.
SECsHostError - this is the error generated by the SECsHost compiler. When the equipment sends an illegal message or invalid formats, the host will fire an error to notify the host application:
[Editor comment: Line breaks used to avoid scrolling.]
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();
}
This method is our sample application entry point to trigger a series of methods to be executed in a daisy-chain fashion. (Meaning it is executed in the form of RING, when the reply is OK, the execution continues). hostController triggers a Connect method to open the HSMS connection with the equipment.
private void OnPrimaryIn(object sender,
SECsPrimaryInEventArgs e) {
switch (e.EventId) {
case PrimaryEventType.Connected:
Logger("Equipment Connected");
hostController.Tag = InitializationChainContext;
Logger("Step 3: Initiate Establish " +
"Communication via S1F13 to equipment");
hostController.EstablishCommunication();
break;
case PrimaryEventType.EventReport:
Logger("Received event: " +
e.Inputs.DataItem["Ln"]["CEID"].Value);
break;
}
}
When equipment accepts the connection, it sends the connected event to our PrimaryIn.
The rest of the following code, shows how to handle the reply or acknowledgement from the equipment and continue the daisy chain execution until it hits the final line:
private void OnSecondaryIn(object sender,
SECsSecondaryInEventArgs e) {
switch (e.EventId) {
case SecondaryEventType.EstablishCommunicationReply:
if (e.Outputs.DataItem["Ln"]["COMMACK"].Value.ToString() == "0")
{ Logger("Establish Communication accepted");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["TIACK"].Value.ToString() == "0")
{ Logger("DateTimeSet acknowledged OK");
if (e.Tag.Equals(InitializationChainContext)) {
hostController.Tag = InitializationChainContext;
Logger("Step 5: Disable all the alarm " +
"activation status at Equipment");
hostController.EnableAlarm(false);
}
}
break;
case SecondaryEventType.DisableAlarmReportReply:
if (e.Outputs.DataItem["ACKC5"].Value.ToString() == "0")
{
Logger("Disable all Alarms accepted by equipment");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["ACKC5"].Value.ToString() == "0") {
Logger("Enable all Alarms accepted by equipment");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["DRACK"].Value.ToString() == "0")
{
Logger("Delete all report accepted");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["DRACK"].Value.ToString() == "0")
{
Logger("Define all report accepted");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["LRACK"].Value.ToString() == "0")
{
Logger("Unlink event report is accepted");
if (e.Tag.Equals(InitializationChainContext)) {
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:
if (e.Outputs.DataItem["LRACK"].Value.ToString() == "0")
{
Logger("Unlink event report is accepted");
Logger("Daisy Chain Demo completed.");
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 the 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 message 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 represents 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]