Commands are hyper-linked into the reference text.
::dmh::secsport portname ?tty_device? ?baudrate?
This document describes the secsport and hsms commands which are used for Semiconductor Equipment Communication Standard (SECS) protocol communication from within a Tcl/Tk application. See the GEM Equipment Interface Applications document for information on the configurable Tcl/Tk host and equipment applications that use these commands.
The secsport command is used for SECS-I and SECS-II communication using RS-232 ports. There are three varieties of RS-232 ports supported by the secsport command. First, there are the usual /dev/tty or COM ports supported directly by your operating system. Second, the secsport command supports RS-232 ports where the hardware or terminal server vendor has provided software drivers that make the ports appear to be supported by the operating system. An example would be using a Xyplex terminal server and their csportd driver software. Third, the secsport command can establish a TCP/IP connection and exchange the same SECS-I/SECS-II data streams that are usually exchanged with an RS-232 port. This option is typically used to directly communicate with a terminal server over a local area network. The terminal server relays the data streams through its RS-232 port.
The hsms command is used for SECS-II communication using HSMS-SS TCP/IP connections. Both the 1993 draft standard and the 1995 SEMI standard are supported.
Multiple ports of any connection type can be used simultaneously from a single Tcl program. Each port connection needs to be configured with its own serial SECS-I port, or its own TCP/IP socket number.
A port connection is created using the secsport or the hsms command; for example
set spname [secsport mach1 /dev/ttya 9600] puts "secsport $spname has been created"
The port connection is given a name when it is first created. The name, mach1, in this example, becomes both a Tcl command, and the name of a global data array.
When first created, the port connection does not respond to the port hardware or connection attempts. You use the online command to begin communication. Before using the online subcommand, specify how received messages are to be handled. Also, you may want to change some of the port settings from their default values. For example:
global mach1 set mach1(DEVID) 3 set mach1(EQUIP) 0 set mach1(TRACE) 0x440e mach1 whenmsg S1F1 { mach1 put S1F2 L ; mach1 whenmsg again } mach1 tracewin # Now begin communications mach1 online
Most of the time during development, you will want to have a window that displays communication activity with the port. The command portname tracewin as seen in the above example, is used to create a trace window. It has menu items that allow you to dynamically adjust the level of detail being displayed. Also, it has a menu item that brings up a Replay Window. The Replay Window allows you to send or receive any message that has been previously sent or received. It also allows you to save and load Replay session files. The re-receive feature is especially useful for you to debug and develop your interface software without needing to communicate with the actual equipment; the re-receive action simulates reception of the selected messages. The Tcl source code for the tracewin subcommand and for the Replay Window is provided. You may wish to customize it or write your own version(s). For example, you may wish to add menu items that cause custom messages to be sent, or add menu items to display application status. A new option, Logging... under the Tracing menu provides for configuring unattended saving of trace data to files.
The handling of received messages is specified using the whenmsg or whenever subcommands. You register Tcl code to be executed when messages of a specified stream and function are received. The software environment is completely dynamic; messages, and whenmsg handling code can be constructed, modified, and deleted while the application executes.
The put, putl and fileput subcommands are used to send messages. You specify callback code to detect failures such as the lack of a response. You do not need to manage your own reply timers. You can optionally specify Tcl code to handle a reply message when sending a message as an alternative to the whenmsg subcommand.
SECS Messages are specified using Tcl SECS Notation (TSN). TSN is similar to the representations of SECS-II messages found in the SEMI Standards, except that it incorporates the list formatting conventions of Tcl. See the manpage TSN for a description.
To parse received data items from TSN, you typically use the rset, vset, lindex, or scan Tcl commands. Also, the lrange and split commands may be useful.
To construct TSN messages for sending, you typically use the list and lappend commands in combination with the usual substitution of variables inside of double quotes. You also use the substitution of command evaluations by enclosing them in square brackets. The append, concat, format, join, lrange, lset and string commands are also used.
You use the close subcommand to terminate a communication connection.
mach1 closeWhen the application terminates normally, any existing port connections are automatically closed.
The first variation, the secsport command, creates a SECS-I serial port interface using a tty device on your Unix system, or a COM port on your Windows NT system. The optional tty_dev port specification defaults to COM1 on NT, /dev/tty0 on AIX, /dev/ser1 on QNX, otherwise /dev/tty01. The optional baudrate parameter, baud, defaults to 9600. If you are using a terminal server tty device such as the Xyplex csportd(l), the baudrate parameter has no effect.
Another means of creating a SECS-I interface, is to specify a terminalServerPort. With this variation, SECS-I/SECS-II data exchanges are made through a TCP/IP connection. This variation is usually used to directly attach to a terminal server where an RS-232 port is connected to a remote device. The terminalServerPort is of the form hostnameOrIP_addr:socketNum. Optionally, the terminalServerPort ends with ,S to indicate a server connection. The latter is used in testing, but not to connect to real terminal servers. The software assumes a binary passthrough IP socket connection to the terminal server. Usually, you need to separately configure the terminal server so the port does not perform telnet control character mappings or other canonical processing. For example:
secsport bonder6 xyplex6:2100
If a terminal server connection is lost, the default configuration of the software tries to reconnect periodically. Refer to the active_reconnect and T5 configuration options below.
The passive variation of the hsms command is used to establish an HSMS Single-Session Mode passive service. This is typically used by equipment at startup, to offer a listening socket for the host connection. The socketNum argument, an integer, is the socket number. Typical values are greater than 5000, and are chosen after reviewing /etc/services to avoid conflicts with existing TCP/IP applications. For example, the values 6000 and 7500 should not be used since they are commonly used by X-Windows font servers. The operating system command, netstat -a is used to display which sockets are in use on your system.
The active switch is used with the hsms command to create an HSMS active client. The hostnameOrIP specifies the hostname or IP address of the HSMS passive server that the client should connect to. It defaults to your own workstation which is convenient for testing. You may use the Unix ping command to determine if a hostname or IP address is valid and the server machine is participating in the TCP/IP network. The socketNum argument specifies the port number that the server is listening at.
The global array of the name portname is used to store configuration parameters for the port connection and related data. Do not try to use the same name in your application as a global scalar variable. You may add your own data elements to the array, if you avoid naming conflicts with this software. Also, do not use the variable name secsport. This name is used dynamically to indicate which port has received the current message.
With the addition of Stream 21 to the SEMI E5 Standard, Hume has recognized the need for a general mechanism to deal with overly large messages such that the software user does not need a toolset update if new large message types are added to the Standards. The fileput subcommand supports sending overly large messages and the newly added file_receive subcommand supports receiving overly large messages. Along with the low-level support in the HSMS command implementation, Hume has added Tcl application code for deploying Stream 21 in the gem2/lib/filesend.tcl file which can be used from the Tcl/Tk host and equipment applications, or used by compiled language applications. The Tcl code also provides a worked example of how to deploy custom or newly-added overly large message types.
When a message is received in file receiving mode, the procedure ::dmh::hsms_ppbody_tmpfile is executed to obtain the pathname of a file for the binary message data. A substitute TSN message of the form {L:3 {A pathname} {B:1 rc} {A errtext}} is created and passed to the whenmsg handling logic. The return code value, rc will be 0x00 and the errtext will be empty for the usual successful saving of message data to the file. In the event of file system error, the rc value will be non-zero, and there will be a non-empty errtext message. An application typically renames the saved file before the next file-based reception as seen in the example code of gem2/lib/filesend.tcl.
The receiving length limit configuration option, recv_max does not apply to file mode receiving. During file mode receiving the software uses blocking IO which means that it becomes non-responsive to other connections or application events. System architects and developers should avoid using file mode transfers if possible. Stream 13 is better suited for responsive applications and deploying multiple connections in the same process. If file mode receiving is used heavily each connection should run in its own application process.
set MHEAD "B [$mach lastheader]" $mach put S9F5 $MHEAD
For an HSMS active client, the online subcommand causes an attempt to establish a TCP/IP connection and subsequently a "selected" HSMS connection to the HSMS server. If the attempt to connect fails, or the "Select.req" fails, the online command will return an error. If you want to periodically retry connecting after delays of T5, call the Tcl procedure hsms_wait_online portname. The procedure can also be called by an HSMS server. In this case, it will wait indefinitely for a client to establish a selected connection before returning. Once a successful connection is established, if the connection is lost, the default behavior of an active HSMS client is to periodically attempt to reconnect. See the description of the active_reconnect configuration option to change this.
When you send even numbered functions, it is known that you are replying to a primary message, and the reply header is setup for you. The port software saves the latest reply header data for unanswered primary messages. The saved reply headers are indexed by their stream and function. Therefore, your application should reply to a given message before receiving a new message of the same stream and function, or the reply data will be overwritten.
The data of the SECS-II message, TSN, is specified using Tcl SECS Notation (TSN). See the manpage TSN.
If you are expecting a reply, you may use the optional arguments -whenreply tcl_code to register Tcl code to be executed when the reply is received. You can also use the whenmsg subcommand described below. The -whenreply tcl_code will only be executed for the specific message that is received as a reply to your outbound message; the secsport software will match the identification bytes in the message header. This is different behavior than the whenmsg subcommand where the stream and function are matched, but not the identification bytes. The -whenreply tcl_code approach can safely handle the situation of simultaneously expecting more than one reply of a specific stream and function and needing to handle the replies differently. If you are handling all replies of a specific stream and function with the same code, you may find it easiest to use the whenmsg subcommand. When the reply message is received, the tcl_code is executed as described below with the whenmsg subcommand. If the message is not sent successfully, or the reply is not received successfully within the T3 interval, the -whenreply tcl_code is automatically cancelled.
A reply message that is sent with the function value set to 0, is known as an abort message. The -whenreply tcl_code is executed for abort replies since the received reply message does have matching identification bytes in the message header. An abort reply is also seen by the optional send callback logic, described below. When you are using both the send callback and the -whenreply options, you will usually handle all the failure cases from your callback code, and handle the successful replies in your -whenreply tcl_code. So you will typically test for and ignore an abort message that is received by your -whenreply tcl_code. If you have been using the whenmsg subcommand for receiving replies, it is easy to forget about the possibility of receiving abort replies with your -whenreply callback since you typically register whenmsg tclcode for only the usual, successful reply function.
With SECS-I communication the put command returns immediately and the message is queued for sending in the background as events are processed. Configuration options are discussed below. If you have left the MULT option false, so that multiple open transactions are not allowed, the new message is not sent until earlier transactions have been completed either by replies having been received, or by timing out. If the MULT option is set true, the message is sent irrespective of any open conversations. This may cause the remote entity to owe more than one reply; a situation that some software cannot properly handle.
The optional callback argument to the put subcommand is used to setup Tcl code to be executed on any of the following conditions: (i) sending the message failed, (ii) the message was sent successfully, and, if the message was sent with a reply expected, (iii) notification that a reply has not been received within the time interval T3, or (iv) a Stream 9 error message or Function 0 message has been received in place of a successful reply. You do not need to set up reply timers, the software does it for you. In the case of a normal reply message not being received, the callback gets evaluated twice; once at the successful completion of sending, and again when the T3 timer expires, or the other error replies are received.
For SECS-I, in accordance with the standard, the actual timeout criteria of condition (iii) is that the initial block of the reply has not been received in the interval T3, or that any subsequent block has not been received within interval T4 of the previous block.
The optional callback argument is executed as follows. It is treated as a list, concatenated with four more arguments, and then evaluated at a global level by the interpreter. The evaluation method allows you to code multiple Tcl statements in your callback, or to set up additional arguments that preceed the appended ones for your custom procedures. This feature is commonly used. An example would be to pass the name of a global array that holds context information.
The four appended callback arguments are (1) the portname, (2) the SsFf?R? argument, (3) condition, and (4) description. The condition argument will be the literal text send_failure, send_complete, or receive_failure. The description argument provides a text description or diagnostic message of the condition.
Here is an example of using a callback:
proc s1f1_callback {portname sfr reason desc} { global debug $portname if { $debug } { puts "put_callback: [list $portname $sfr $reason $desc]" } if { $reason == "send_complete" } return # here on failure # disarm a potentially late reply: $portname whenmsg S1F2 # notify upperlevel software event_report $portname HEARTBEAT FAILURE }proc do_heartbeat {mach} { $mach whenmsg S1F2 "event_report $mach HEARTBEAT OK" $mach put S1F1R "" s1f1_callback }
The T3 configuration option specifies the timeout interval for reply messages. A reply may arrive late even though the callback is executed for the condition receive_failure. If you used the -whenreply tcl_code, your whenreply logic is cancelled at the timeout and is not executed. The secsport software will then see if you have a matching whenmsg established for this stream and function, and it will be executed. If you wish to disarm the whenmsg logic, you may do so in the callback as demonstrated in the example above.
With HSMS communication, the message is sent before the put subcommand returns. Unlike with SECS-I, it is known synchronously whether the message was sent successfully. For compatibility with SECS-I, the optional callback is used exactly as described above to return the send_failure, send_complete, and receive_failure results asynchronously. In addition, the return value of the HSMS put subcommand is a two element list giving the reason and description arguments that are used with callbacks. For example, typical replies are "send_complete success", and "send_failure {port is not connected}". If you may ever use SECS-I instead of HSMS, code your driver using the callback feature for compatibility. If you will always use HSMS, you can take advantage of the simpler synchronous result.
The global variable portname( lastsmsg ) is set to the TSN after the message is successfully sent. Similarly, the latest received message is copied to portname( lastrmsg ). This may be useful for debugging. Also, you can use trace to capture every message sent or received on the port.
The software handles SECS-I line contention in the standard way; the host will defer to an equipment message, it will dispatch the receiving logic for the equipment message, and then it will resume attempting to send the message.
At the time the tclcode argument is evaluated, the global variable secsport is set to the value portname, the global variable portname( lastrSFR ) is set to the received SsFf, and the global variable portname( lastrmsg ) is set to the TSN representation of the received SECS-II message. The portname( lastrSFR ) array item ends with an R when the sender expects a reply.
The recommended technique is to call a procedure with the data items that you wish to use as arguments so that the Tcl interpreter makes a copy of their values. Otherwise, the reception of another message may overwrite the current values. Usually in your whenmsg code, you represent the port connection with a variable. It may be a little confusing if you are new to Tcl to write code where the variable name is substituted immediately, but the portname( lastrSFR ) is substituted when the tclcode is evaluated. Use of the escape character \ is described on manpage Tcl. Here are two examples. The whenmsg code is evaluated at a global level so the global variables do not need to be declared global.
# get the $mach substituted now, but have the data # substituted when the message arrives: $mach whenmsg S12F7 \ "process_map \$${mach}(lastrmsg) ; $mach whenmsg again"# echo a binary string $sp whenever S2F25 "$sp put S2F26 \[set ${sp}(lastrmsg)\]"
As you can see, the tclcode may be more than one programming statement separated by semicolons or newlines. There are other examples on the TSN manpage.
The whenmsg tclcode is discarded after it is used once on the next message of the specified stream and function. The whenmsg again subcommand is used to re-register the same tclcode for use on the next message of the specified stream and function. The whenever tclcode is not discarded after use. The same tclcode is applied to every received message of the specified stream and function until it is cancelled. In other words, the whenever subcommand combines the functionality of the whenmsg tclcode and whenmsg again subcommands into one command.
This software also enables you to establish default whenmsg Tcl code for any stream and function that you have not specifically configured using the whenmsg SsFf command. Just use S0F1 as the SsFf argument to specify default handling for any primary message (odd function) and use S0F2 to specify the default tcl_code for any reply message (even function). Unlike the use of whenmsg for specific streams and functions, the S0F2 and S0F1 specifications are not discarded after use, and you do not need to use whenmsg again to re-register them.
# catch all unexpected primaries: $mach whenmsg S0F1 \ "async_inbound \$${mach}(lastrSFR) \$${mach}(lastrmsg)"proc async_inbound {SFR msg} { switch -exact $SFR { S1F1R { ... } S5F1 { ... } ....
The whenmsg tcl_code is saved in the global array portname using SsFf as the subscript. The inspect application may be used to view this data. However, do not update or delete these elements directly - always use the whenmsg command interface.
There are predefined whenmsg handlers registered for some message types when the connection is created. See the table later in this document.
If you have an error in your tcl_code it interrupts the execution at the point of error. If you execute whenmsg again before the error occurs, the processing of subsequent messages will be insured. However, if the whenmsg again statement occurs after the error, the specific tcl_code is not re-registered. Typically, when developing, you want your logic to stop on the first error so you can diagnose and fix it. However, in production, you want the messages to be processed even if there is an error is some part of the code. Therefore, you make an informed decision where to execute the whenmsg again statement. The whenever subcommand is equivalent to executing the whenmsg again statement at the beginning of your tcl_code.
When you create a port connection object, portname, a global array is created with the name portname. Many of the elements of this array are actually configuration parameters, that you may inspect or modify. We suggest using the inspect application during development for this purpose.
The software is designed to react and utilize your updated configuration values immediately. For example, if you change the BAUD parameter, the RS-232 hardware is reconfigured on the fly, even if you are in the middle of passing a message.
The remainder of this section is a description of the available configuraton options in alphabetical order.
Your application logic can determine how many callbacks are simultaneously active by reading the array element callback_depth. The value of this element is 0 when no callbacks are executing.
In summary, if you are developing an application that dispatches events within whenmsg callbacks, you may wish to consider setting the hsms_reentrant option to 0 to avoid possible issues with nested callback execution. Typically, this issue is only relevant to more complex applications that use synchronous style communication with multiple SECS or DMH entities.
If the transfer and saving succeed, the ackc7 value is 0 and the pathName value specifies a file. The application will usually rename the file to a name which is based on the PPID message value. The pathName value is computed by executing the procedure ::dmh::hsms_ppbody_tmpfile. The default logic is to name the file ppbodyReceive.bin. If there is a connection array element named recipe_dir, the value is used as a directory for the temporary file.
There can be errors that prevent success such as disk errors or the SECS message data being improper. If the transfer fails, the ackc7 value is set to non-zero and the errtext value is set with an explanation message. The application can use the ackc7 value as a suitable reply value for S7F4 which is not sent by the receiving logic.
Setting the ppbodyFileMode to 1 also provides a convenient means to send S7F3R or S7F6 using the usual put subcommand instead
of having to use the ppbody_put command. If the option is true, and S7F3[R] or S7F6 are being sent, and the structure of
the message being sent matches
L:2 {A ppid } {L {A pathName } {A bodyType:bodySize } [more list elements are optional ]}
then the HSMS sending logic will cause the standard L:2 PPID PPBODY message to be sent by directly reading the
process program data from the file specified by pathName . This avoids needing to handle the entire message in memory
as an ordinary message.
Setting the PROTOCOL array element to the value "1993" provides the behavior specified in the document "High-Speed SECS Message Services (HSMS) Working Draft Proposal For Single-Connection Reference Implementation" dated February 15, 1993 with the following exception. The exception was found necessary to insure operational compatibility with GW Associates implementations. According to the draft, HSMS Control Messages should be sent with the R-bit set as for SECS-II messages. However, GW Associates drivers that we have tested do not accept a ConnectionTestAcknowledge message (stype = 6) from an Equipment entity with the R-bit set. Therefore, control messages are always sent with the R-bit clear.
Setting the PROTOCOL array element to the value "1994" provides for a non-standard protocol which uses two length bytes and no control messages.
global gemhost set gemhost(recv_max) 1536000 ;# 1.5 meg proc recv_max_handler {spname size} { global $spname set fid [open "recv_max.txt" a] puts $fid "[localtime 9] allocation of $size refused for ${spname}." close $fid } set gemhost(recv_max_cmd) recv_max_handler
General Tracing: Output to portname(trace)
Bit Output Description
0x0001 Read and write calls 0x0002 algorithm state changes
Receive Tracing: Output to portname(rtrace)
Bit Description for Received Messages
0x0100 Header binary dump 0x0200 Header interpretation 0x0400 Stream and Function description 0x0800 Message data binary dump 0x0004 The Message as TSN
Send Tracing: Output to portname(strace)
Bit Description for Sent Messages
0x1000 Header binary dump 0x2000 Header interpretation 0x4000 Stream and Function description 0x8000 Message data binary dump 0x0008 The Message as TSN
Replay Tracing: Used for input to Replay Window
Bit Description
0x0040 Reception data traced to portname(last_recv) 0x0080 Send data traced to portname(last_send)
Logging: Control over output file(s)
0x10000 Save traced data to log file(s). 0x20000 Compress log file when closing.
Even without TRACE being set, the secsport and hsms software keep the state array element updated to the current low-level communication state. One application technique is to use the trace variable command to monitor this array element. The value of this element becomes OFFLINE or LISTENING if the communication connection is lost, or if a SECS-II message cannot be sent.
Saving of trace data to output files is indicated by setting the 0x10000 bit. The saving logic writes each day's output to a distinct file, in the directory named by the traceDir array element. The traceMax array element controls how many day files are saved per year. The traceMax array element value can be configured between 1 and 366. When file saving is initiated, the output filename is set to traceNNN.txt where the NNN value is the current day of the year, 0 to 365, modulo the traceMax value. If this file already exists and has been written to earlier in the same day, then the output is appended to it, otherwise the file is created as a new file. Note that if the traceMax value is set to 1, each day's output is saved to the same filename, trace000.txt. If the traceDir and traceMax array elements do not exist when trace data for file logging is first captured, the saving logic creates default values for them. The default values provide for saving the data from each connection in a separate subdirectory. When trace data is being written, the 0x20000 bit controls whether the logic attempts to compress the output file when it is closed at the end of the day (midnight). For compression to occur, the traceMax value must be greater than 1 and a non-blank compression command must exist as the array element traceZipCmd. The default assignment of traceZipCmd is similar to zip -m tracetxt.zip. This command causes the data file from the previous day to be moved into the tracetxt.zip archive.
The hsms and secsport software is written to conform to:
SEMI E4 - SEMI Equipment Communication Standard 1 - Message Transport (SECS-I)
SEMI E5 - SEMI Equipment Communication Standard 2 - Message Content (SECS-II)
SEMI E37 HIGH-SPEED SECS MESSAGE SERVICES (HSMS) GENERIC SERVICES
SEMI E37.1 HIGH-SPEED SECS MESSAGE SERVICES SINGLE-SESSION MODE (HSMS-SS)
The following statements are made with respect to standard documentation requirements:
Protocol parameters are set as array elements as discussed above.
Timeout parameters are specified with a resolution of 1 millisecond. Performance characteristics limit the actual resolution obtained. All normal parameter ranges are supported; the software will attempt to use any values specified.
There is no fixed maximum size of a message that can be received imposed by this software except as described above with the recv_max feature. Our test suites do not exercise SECS-I messages in excess of 50K or HSMS messages larger than 2 megabytes. To avoid performance degradation from extensive memory usage, users should avoid message sizes greater than 1 megabyte, and the ppBodyFileMode option described above should always be used for the transfer of process programs that may be larger than 1 megabyte. Stream 13 transfers can be used for larger datasets.
If a single process is acting as both the Active and Passive sides of an HSMS connection, and a message is sent that is large relative to the size of the TCP/IP buffers, there is some risk that the process will deadlock. This is not usually a concern, and there should be no problem with connections to other processes.
A passive HSMS server accepts multiple TCP connections, but only allows an HSMS-SS selected connection to the first active client. Subsequent clients are given the "Communication Already Active" response code to their select requests. This behavior is exactly the preferred option of SEMI E37 Rejection of Additional Connection Requests by a Passive Mode Entity.
You should document the maximum expected size of messages sent by your application, in order to comply with standard documention requirements.
There is no fixed limit to the number of concurrent open transactions. However, as noted above, the reply header information is indexed by stream and function. If more than one transaction of the same stream and function are open on a single port, the application is not able to reply to the earlier transaction. The application is able to overcome this limit by explicitly saving and restoring the header information through the addition of custom Tcl code. The SECS/GEM libraries provided by Hume Integration that manage a Tcl SECS server process for other language environments explicitly manage the message header transaction ID and do not have this limitation.
HSMS reject.req behavior is fully supported.