4.4   WTX Tcl API

This section introduces the WTX Tcl API and gives a series of interactive examples for using Tcl to communicate with a target server. These examples not only explain the WTX Tcl API, but also demonstrate how the WTX Protocol works. For this reason, users who plan to work primarily with the WTX C API (see 4.5 WTX C API) may benefit from working through these Tcl examples.

4.4.1   Description

The WTX Tcl API provides a binding of the WTX protocol to the Tcl language. This allows you to write Tcl scripts that interact with the WTX environment. Every WTX protocol request is available to the Tcl interface. Tornado provides a standalone Tcl interpreter, as well as an object library that allows the WTX-Tcl binding to be included in other applications. The WTX Tcl API is based on Tcl version 8.0, and on UNIX hosts includes the Extended Tcl 8.0 package.

For each WTX protocol request (for example, WTX_MEM_READ), there is a corresponding Tcl command (wtxMemRead). The names of all WTX Tcl API commands are derived from the protocol request names according to A. Tcl Coding Conventions; in other words, underscores are removed and all words but the first are capitalized.

Each WTX Tcl command has an online reference entry in HTML format under Tornado API Guide>WTX Tcl Library. For information on the online reference material, see the Tornado User's Guide: Documentation Guide and Tornado Getting Started. Most WTX Tcl API commands also return a brief syntax message if they are invoked without arguments.

4.4.2   Starting a wtxtcl Session

One of the interactive tools in Tornado is called wtxtcl, a standalone Tcl interpreter for the WTX extensions. All Tornado tools also include their own Tcl interpreter, because Tcl is the language of much of the Tornado implementation. All the interpreters have access to the WTX extensions. However, wtxtcl is an ideal environment for experimenting with and testing the WTX interface because it contains only the WTX extensions.

When you call wtxtcl, Tornado responds with the wtxtcl prompt; you may begin typing Tcl commands immediately. Invoking wtxtcl with an argument identifies a file of Tcl commands to execute.

4.4.3   Attaching to a Target Server

Before the majority of wtxtcl commands can be used, you must attach to an active target server. The Tornado registry maintains a list of available target servers for a site or workgroup. Use wtxInfoQ to determine what servers are active by querying the contents of the Tornado registry.

wtxtcl> wtxInfoQ 
{vxsim7@aven tgtsvr rpc/aven/147.11.80.6/570425345/1/tcp/42781} 
{mv147@aven tgtsvr rpc/aven/147.11.80.6/570425347/1/tcp/44830} 
{jim@dnestr tgtsvr rpc/dnestr/147.11.80.4/570425345/1/tcp/52411} 
{wtxregd@aven registry rpc/aven/147.11.80.6/570425344/1/tcp/52157}

The routine returns a series of three-element lists, each of the form {name type key}. The Tornado registry includes information about itself (note the fourth line of the output). To limit the returned information, you can use regular expressions on the wtxInfoQ command to qualify each of the three fields. For example, to see only target servers running on host aven, type:

wtxtcl> wtxInfoQ @aven$ tgtsvr .* 
{vxsim7@aven tgtsvr rpc/aven/147.11.80.6/570425345/1/tcp/42781} 
{mv147@aven tgtsvr rpc/aven/147.11.80.6/570425347/1/tcp/44830} 

Each of the three arguments is a regular expression that qualifies the corresponding field in the output, and an entry is returned only if it matches all regular expressions provided.

After learning the name of a target server, you must attach to it in order to carry out further WTX transactions:

wtxtcl> wtxToolAttach t80-202@aven myTool 
t80-202@aven

The string myTool is a name you choose to represent your Tcl session. The target server records it and reports this name to any tool that requests a list of attached tools. You can see myTool in the list of attached tools on the Tornado launcher (UNIX) or the Manage Target Servers dialog box (Windows) if your target server is selected.

The value returned by this command, t80-202@aven, is called the WTX Tcl handle, and can be used to refer to this connection when multiple connections are made in a single wtxtcl session.

Once a target server is attached, you may use any WTX Tcl command. The examples in the remainder of this section assume that a target server is attached.

4.4.4   Obtaining Target Server Information

You can learn about the architecture and about other tools connected to the target server with wtxTsInfoGet:

wtxtcl> wtxTsInfoGet 
{WDB Agent RPC} {255 0} {5 1 0 8192 1234}  {1 5.4} {Motorola MVME162} / 
aven:/installDir/target/config/mv162/vxWorks {0 4194304} {0x96c60 223546}  
chrisc {Fri Jan  8 17:59:38 1999} {Fri Jan  8 17:59:38 1999} unreserved 0  
myTool 2.0
{0x1a5278 wtxtcl {} {} myself@aven}

For a detailed explanation of the fields in this structure, see the online reference material underTornado API Guide>WTX Protocol.

4.4.5   Working with Memory

To read a block of memory from the target, use wtxMemRead, specifying the base address and the size of the block:

wtxtcl> wtxMemRead 0x2000 256 
mblk0

The command returns a memory block handle. This short string is used by a variety of Tcl commands that work with memory. These commands are provided to avoid the overhead of converting target memory to a string representation, and to make manipulating memory easier. It is often convenient to save memory block handles in variables:

wtxtcl> set mb [wtxMemRead 0x2000 256] 
mblk1

To print the memory block, you can use memBlockGet with the handle as a parameter:

wtxtcl> memBlockGet $mb 
0x03 0x00 0x00 0x39 0x82 0x10 0x60...

The target server manages a block of memory on the target. You can allocate such a block from the host using wtxMemAlloc. You can write to allocated memory, and read it back to verify that the write took place:

wtxtcl> set mem [wtxMemAlloc 256]
0x5897d0 wtxtcl> wtxMemWrite $mb $mem 0 wtxtcl> set ver [wtxMemRead $mem 256] mblk2 wtxtcl> memBlockGet $ver 0x03 0x00 0x00 0x39 0x82 0x10 0x60...

You can also work with parts of memory blocks, free blocks, write memory blocks to binary files or pipes, fill and checksum blocks of memory, and so on. For more information, see the online reference material under Tornado API Guide>WTX Protocol and WTX Tcl Library.

4.4.6   Disassembling Memory

To disassemble a block of memory from the target, use wtxMemDisassemble, specifying the base address and the number of instructions (default 10). The following example is from a PowerPC target:

wtxtcl> wtxSymListGet -name "^printf$" 
{printf 0x13e7bc 0x5 0 1 vxWorks} 
wtxtcl> wtxMemDisassemble -opcodes 0x13e7bc 
{printf} 4 {} {9421ff80} {stwu        r1, 0xff80(r1)} 
{} 4 {} {7c0802a6} {mfspr       r0, LR} 
{} 4 {} {90010084} {stw         r0, 0x84(r1)} 
{} 4 {} {90610008} {stw         r3, 0x8(r1)} 
{} 4 {} {9081000c} {stw         r4, 0xc(r1)} 
{} 4 {} {90a10010} {stw         r5, 0x10(r1)} 
{} 4 {} {90c10014} {stw         r6, 0x14(r1)} 
{} 4 {} {90e10018} {stw         r7, 0x18(r1)} 
{} 4 {} {9101001c} {stw         r8, 0x1c(r1)} 
{} 4 {} {91210020} {stw         r9, 0x20(r1)}

4.4.7   Working with the Symbol Table

The target server symbol table can be queried and modified from wtxtcl. The reason for doing this is to learn the address of a routine to call, the entry point for a task, or the address of a variable in order to read its value. Symbols can be looked up by name or value:

wtxtcl> wtxSymFind -name taskDelay 
_taskDelay 0x22ed4 0x5 0 0 "" 
wtxtcl> wtxSymFind -value 0x226b4 
_taskSuspend 0x226b4 0x5 0 0 ""

For convenience, you can define a procedure that returns the value member of the symbol list for a given symbol name. Further examples assume the presence of this procedure (symbol). In order to use it, define it by typing it as shown:

wtxtcl> proc symbol {name} \ 
{return [lindex [wtxSymFind -name $name] 1]} 
wtxtcl> symbol taskDelay 
0x22ed4

To query a list of symbols using a regular expression, use wtxSymListGet:

wtxtcl> wtxSymListGet -name ^taskD.* 
{taskDeleteHookAdd 0x14b624 0x5 0 1 vxWorks} 
{taskDeleteTable 0x1a2368 0x9 0 1 vxWorks} 
{taskDeleteHookDelete 0x14b6b4 0x5 0 1 vxWorks} 
{taskDeleteForce 0x15ff48 0x5 0 1 vxWorks} 
{taskDelete 0x15ff1c 0x5 0 1 vxWorks} 
{taskDelay 0x1617cc 0x5 0 1 vxWorks} 
{taskDestroy 0x15ffa0 0x5 0 1 vxWorks}...

You can also use wtxSymListGet to obtain a list of the symbols found near a given value:

wtxtcl> wtxSymListGet -value 0x68000 
{_ip_output 0x67ae0 0x5 0 0 vxWorks} 
{_ip_insertoptions 0x681ac 0x5 0 0 vxWorks} 
{_ip_optcopy 0x68320 0x5 0 0 vxWorks} 
...

4.4.8   Working with Object Modules

The WTX Tcl API provides complete access to the target server's dynamic loading capabilities. The fundamental command is wtxObjModuleLoad, which works like the ld( ) command in the Tornado shell. It takes a path to an object module and downloads the module to the target. This command returns a module ID, followed by the addresses of the sections of the relocated module. You can load a module and save the ID in a variable:

wtxtcl> set modId [lindex [wtxObjModuleLoad /work/dir/mod.o] 0]

If the module contains unresolvable symbols, a list of them is returned with the module ID:

wtxtcl> wtxObjModuleLoad /work/dir/umod.o 
0x624ef8 0x36c540 0x36d5a8 0x36d5d8 
_missingVar 
_missingFunc

There are also routines for obtaining information about object modules. wtxObjModuleList returns a list of loaded object modules. This list can be directed to input for wtxObjModuleInfo, which takes the list as an argument and returns information about all listed modules.

wtxtcl> foreach mod [wtxObjModuleList] { 
puts stdout [wtxObjModuleInfo $mod] 
} 
0x71db0 vxWorks a.out 0 0x64 {0 0x2000 0x957e8}  {0 0x977e8 0x10f50}  {0 0xa8738 0x87b0} 
0x1324b0 mod.o a.out 0x1 0x4 {0 0x39e9e8 0x1048}  {0 0x39fa30 0x30}  {0 0x39fa60 0xa8} 
0x132760 umod.o a.out 0x2 0x4 {0 0x39d530 0x1068}  {0 0x39e598 0x30}  {0 0x39e5c8 0xa8}

4.4.9   Working with Tasks

If the target server is connected to a target running VxWorks, you can create and manipulate VxWorks tasks interactively with Tcl commands. Creating a task interactively from wtxtcl is less efficient than using the Tornado shell. The Tornado shell uses Tcl procedures to automate many tasks, including task creation. This chapter treats only those features available directly from wtxtcl.

The first step is to spawn a task named uMyTask at priority 100 with VxWorks options 0x3 (VX_UNBREAKABLE | VX_SUPERVISOR_MODE). The entry point is the taskDelay( )routine, whose address comes from symbol, which you created in 4.4.7 Working with the Symbol Table. The argument 10000 causes the task to delay for 10,000 ticks before exiting. (For more information on command parameters, see the online reference material under Tornado API Guide>WTX Tcl Library.)

wtxtcl> wtxContextCreate 1 uMyTask 100 0x3 0 5000 \ 
[symbol taskDelay] 0 0 10000  
0x3b6870

The output, 0x3b6780, is the ID of the new task. If you are running a Tornado shell, you can use i( ) to check that it has been created. The task has not begun running yet; it is created in the suspended state, and must be resumed before it executes:

wtxtcl> wtxContextResume CONTEXT_TASK 0x3b6870 
0

Now the task runs, and vanishes after the task delay has expired. To find out what other commands operate on contexts, see the online reference material under Tornado API Guide>WTX Tcl Library. To see a list of these commands, type:

wtxtcl> info commands wtxContext* 
wtxContextResume wtxContextKill wtxContextStep wtxContextSuspend  
wtxContextCreate wtxContextCont

4.4.10   Working with Events

The target server receives event strings from the target and from attached tools and directs them to appropriate queues. For a discussion of the WTX event facility, see 4.3.10 Event Management. By default, when tools first attach, they receive no event strings. It is up to each tool to register for the events it is interested in and to check its queue periodically.

Registering for Events

Your wtxtcl session is not yet registered for any events. In order to receive event strings, you must call wtxRegisterForEvent. The argument to this command is a regular expression that serves as the target server filter for assigning events to your tool queue. The following example registers for all events:

wtxtcl> wtxRegisterForEvent .* 
0

The return value 0 indicates that you have successfully registered for all events.

Unregistering for Events

Your wtxtcl session is registered for all events. If you don't want to receive some types of events, you must call wtxUnregisterForEvent. The argument to this command is a regular expression that serves the target server as a filter for assigning events to your tool queue. The following example unregisters for tool- related events (TOOL_ATTACH and TOOL_DETACH):

wtxtcl> wtxUnregisterForEvent TOOL.* 
0

The return value 0 indicates that you have successfully unregistered for tool related events.

Checking the Event Queue

One way to confirm that your wtxtcl session is registered for all events is to call wtxEventGet to query the target server for events. It returns an event string if any events are queued. The first word in the string is the event type, and the rest are event-specific parameters. Table 4-1 contains a detailed list of the events and their parameters. The reference entry for wtxEventGet details their Tcl representation. If the queue is empty, wtxEventGet returns the empty string.

Some environments generate many events. In other cases, you may have to query the queue many times before an event is returned. Within the Tornado shell Tcl interpreter, a routine wtxEventPoll is available to check the queue regularly. You can use the same building blocks in wtxtcl to create a polling routine. The WTX primitive wtxEventGet, which asks for one event if it is available, can be combined with the Tcl procedure msleep, which puts the invoking process to sleep for a specified number of milliseconds. The following Tcl procedure polls for events with the specified delay. Define this procedure (eventPoll) to the interpreter as follows:

wtxtcl> proc eventPoll {intvl} { 
while {[set event [wtxEventGet]] == ""} { 
msleep $intvl 
} 
return $event 
}

Generating and Retrieving Events

The example in this section stimulates two events on the target and captures them. The first step is to create a task with entry point tickGet( ). Then set two eventpoints on tickGet( ) and resume the task. When the task hits the first eventpoint it generates an event, which you can retrieve from the queue. When it completes, it generates a second event.

To create the task, use the technique from 4.4.9 Working with Tasks, without setting the VX_UNBREAKABLE bit in the task options:

wtxtcl> set ctxId [wtxContextCreate CONTEXT_TASK tick 100 0x1 \ 
0 2000 [symbol tickGet] 0 0] 
0x4aeec90

You can use the shell to verify that the task has appeared. The task is in the suspended state, and its ID has been saved in the variable ctxId.

To add an eventpoint to tickGet( ), use wtxEventpointAdd. The eventpoint stops the task, which generates an event when it resumes. The parameters of wtxEventpointAdd include three WTX enumerated constant types: EVENT_TYPE, CONTEXT_TYPE, and ACTION_TYPE. (For information on specifying these arguments in numeric form, see the online reference material under Tornado API Guide>WTX Protocol). In Tcl you can specify the parameters symbolically. Use wtxEnumList to obtain a list of constant types. Then give wtxEnumInfo any of these constants as a parameter to obtain a list of all events of a given type which can be passed to a Tcl command, as in the following example:

wtxtcl> wtxEnumList  
ACTION_TYPE CONTEXT_TYPE EVENT_TYPE REG_SET_TYPE LOAD_FLAG VIO_CTL_REQUEST AGENT_MODE TASK_OPTION OBJ_KILL_REQUEST OPEN_FLAG CONTEXT_STATUS 
wtxtcl> wtxEnumInfo EVENT_TYPE 
WTX_EVENT_NONE 0x0 
WTX_EVENT_CTX_START 0x1 
WTX_EVENT_CTX_EXIT 0x2 
WTX_EVENT_TEXT_ACCESS 0x3 
WTX_EVENT_DATA_ACCESS 0x4 
WTX_EVENT_EXCEPTION 0x5 
WTX_EVENT_VIO_WRITE 0x6 
WTX_EVENT_HW_BP 0x7 
WTX_EVENT_CALL_RETURN 0x8

Since it is difficult to type these long names at the keyboard, you can query for abbreviations by giving the -abbrev flag to wtxEnumInfo along with the constant:

wtxtcl> wtxEnumInfo -abbrev EVENT_TYPE 
WTX_EVENT_NONE WTX_EVENT_NONE NONE none 0x0 
WTX_EVENT_CTX_START WTX_EVENT_CTX_START CTX_START cstart 0x1 
WTX_EVENT_CTX_EXIT WTX_EVENT_CTX_EXIT CTX_EXIT cexit 0x2 
WTX_EVENT_TEXT_ACCESS WTX_EVENT_TEXT_ACCESS TEXT_ACCESS tacc 0x3 
WTX_EVENT_DATA_ACCESS WTX_EVENT_DATA_ACCESS DATA_ACCESS dacc 0x4 
WTX_EVENT_EXCEPTION WTX_EVENT_EXCEPTION EXCEPTION exc 0x5 
WTX_EVENT_VIO_WRITE WTX_EVENT_VIO_WRITE VIO_WRITE viow 0x6 
WTX_EVENT_HW_BP WTX_EVENT_HW_BP HW_BP hwbp 0x7 
WTX_EVENT_CALL_RETURN WTX_EVENT_CALL_RETURN CALL_RETURN cret 0x8


*

CAUTION: The abbreviations are handy for typing but, if you are writing scripts, it is better practice to use the complete name.

WTX_EVENT_TEXT_ACCESS is an appropriate event type for a traditional code breakpoint. In the list of event type abbreviations, WTX_EVENT_TEXT_ACCESS can be abbreviated tacc. WTX_EVENT_CTX_EXIT generates an event when the task exits, and can be abbreviated cexit.

Calling wtxEnumInfo with the -abbrev flag for CONTEXT_TYPE and ACTION_TYPE shows that you can use task and notify to abbreviate CONTEXT_TASK and ACTION_NOTIFY.

Now you have all the information you need to add two eventpoints to the tickGet( ) routine, as shown in the following example:

wtxtcl> wtxEventpointAdd tacc [symbol tickGet] task $ctxId \ 
notify|stop 0 0 0 
0x1 
wtxtcl> wtxEventpointAdd cexit [symbol tickGet] task $ctxId \ 
notify 0 0 0 
0x2

Before resuming the task, register to receive all events and flush the event queue. The following example creates a procedure, listEvents, which flushes the queue and writes all events:

wtxtcl> wtxRegisterForEvent .* 
0 
wtxtcl> proc listEvents {} {while {[set event [wtxEventGet]] != ""}\  
{puts $event}} 
wtxtcl> listEvents 
TOOL_DETACH windsh 0x44ce50 
TOOL_ATTACH windsh 0x44ff90 
CALL_RETURN 0x4ae2720 0x4 0xd0003 
...

Now start the task and check for events:

wtxtcl> wtxContextResume task $ctxId 
0 
wtxtcl> listEvents 
CALL_RETURN 0x4ae2720 0x5 0xd0003 
TOOL_ATTACH browser 0x450f90 
... 
TEXT_ACCESS 0x4aeec90 0x3 0x426d5c 0x4aeec4c 0x4aeec20

When you see the TEXT_ACCESS line of output, the breakpoint event has arrived. The following message appears in WindSh:

->  
Break at 0x00426d5c: _tickGet                Task: 0x4aeec90 (tick)

The task remains stopped at the breakpoint until you continue it:

wtxtcl> wtxContextCont task $ctxId 
0

The task now completes, generating another event, which you can retrieve:

wtxtcl> listEvents 
... 
CTX_EXIT 0x3 0x4aeec90 0x3ce474 0xd0003

4.4.11   Working with Virtual I/O

Virtual input and output is comprised of strings that are placed into memory blocks by wtxtcl. WTX provides commands for manipulating the memory blocks. WTX uses an event to notify the tool that virtual output is available.

Virtual Output

This example assumes a Tornado shell for configuring the virtual I/O and a target whose configuration includes virtual I/O (as is the case with the target images supplied with Tornado). For more information on configuring Tornado and the target, see the Tornado User's Guide.

Be sure to launch the target server without any target redirection option (for more details, see Tornado User's Guide: Target Server), otherwise the example may not work properly.

First, open a virtual I/O channel and redirect the target's standard input, output, and error streams to this channel. To start WindSh on the target server, click the WindSh button in the Tornado window or start the shell from the Windows command prompt or a UNIX shell prompt:

% windsh vxsim7@aven 
...

In WindSh, unset the SH_GET_TASK_IO configuration parameter to avoid any conflict with the WindSh local redirection (see Tornado User's Guide: Shell for more details), Open a virtual I/O device and reroute standard input, output, and error to it. Then, using the shell, print a string to standard output. The string is sent to the attached tools in the form of an event which you can examine in wtxtcl. The commands and output are shown in the following example:

-> ?shConfig SH_GET_TASK_IO off 
-> vioFd = open ("/vio/1", 2) 
new symbol "vioFd" added to symbol table. 
vioFd = 0x39d1a0: value = 7 = 0x7 
-> ioGlobalStdSet (0, vioFd) 
value = 0 = 0x0 
-> ioGlobalStdSet (1, vioFd) 
value = 1 = 0x1 
-> ioGlobalStdSet (2, vioFd) 
value = 2 = 0x2 
-> printf "hello\n" 
value = 6 = 0x6

The string prints in the virtual console if it is enabled. It also goes to vioFd. Now you can return to your wtxtcl session and call the procedure listEvents (or repeatedly run wtxEventGet) to see what events have arrived:

wtxtcl> listEvents 
SYM_ADDED vioFd 0x490efec 
CALL_RETURN 0x4ae2720 0x4 0xd0003 
CALL_RETURN 0x4ae2720 0x4 0xd0003 
CALL_RETURN 0x4ae2720 0x4 0xd0003 
VIO_WRITE 0 mblk0

Depending on your exact environment, you may see additional events. You should see at least the five events shown above, indicating that the symbol vioFd has been added to the symbol table, that the three calls to ioGlobalStdSet have returned, and that virtual I/O is available. The event of interest is the one that indicates that virtual I/O has been received and stored in the memory block mblk0. The easiest way to see the data is to use the memBlockGetString command:

wtxtcl> memBlockGetString mblk0 
hello

Another useful command for dealing with memory blocks that contain VIO data is memBlockWriteFile, which can be used to dump the contents of a block to stdout directly:

wtxtcl> memBlockWriteFile mblk0 - 
hello

The - character indicates that the block should be written to stdout. Before continuing, free the memory block holding the VIO data:

wtxtcl> memBlockDelete mblk0

Virtual Input

For an example of virtual input, return to the shell and run a task that reads input. Create a new variable and initialize it to 0, then run a scanf( ) task that blocks waiting for input. Since you redirected standard input to the virtual I/O channel, a virtual I/O write will satisfy the scanf( ) call.

First, be sure that IO redirection is still turned off, or turn it off. Then create the variable and issue the scanf( ) in WindSh:

-> ?shConfig 
SH_GET_TASK_IO = off 
... 
-> myVioData = 0 
new symbol "myVioData" added to symbol table. 
myVioData = 0x39d188: value = 0 = 0x0 
-> scanf ("%d", &myVioData) 

At this point the shell prompt does not return, because scanf( ) is waiting for input. To send the data for scanf( ) to convert, return to wtxtcl and issue this command:

wtxtcl> wtxVioWrite 1 -string "99\n" 
0x3

In the shell, you should see the routine return, and you can inspect the value of the variable that scanf( ) filled in:

value = 1 = 0x1 
-> myVioData 
myVioData = 0x39d188: value = 99 = 0x63 = 'c' 


*

NOTE: The target server can perform redirections like the one described in this example. For more information on this feature, see tgtsvr in the online reference material under Tornado Reference>Tornado Tools and Tornado User's Guide: Target Server.


*

NOTE: WindSh can also redirect the I/O of all the spawned tasks in its own window. For more informations on this feature, please see Tornado User's Guide: Shell.

4.4.12   Calling Target Routines

Calling target routines is easier than spawning tasks from scratch, because the target server and agent provide support to simplify the process. The central command is wtxFuncCall, which spawns a task on the target and arranges for an event containing the return value to be generated when the task completes. For example, use sysClkRateGet( )to report the system clock rate:

wtxtcl> wtxFuncCall -int [symbol sysClkRateGet] 
0x358908

The call returns a call ID, the ID of the task that is spawned to call the routine. In addition, the agent posts an event to the target server which can be viewed using wtxEventGet, listEvents (see Generating and Retrieving Events), or eventPoll (see Checking the Event Queue), as shown in the following example:

wtxtcl> wtxEventGet 
CALL_RETURN 0x358908 0x3c

The event string includes both the call ID and the integer return value (0x3c = 60).

The next example calls taskDelay( ) with a delay of 10 seconds (assuming the system clock rate is 60Hz) and then polls at the rate of 1 Hz (every 1000 milliseconds) waiting for the result.

wtxtcl> wtxFuncCall -int [symbol taskDelay] 600 
wtxtcl> eventPoll 1000 
CALL_RETURN 0x358908 0 0 

4.4.13   Working With Multiple Connections

It is possible to maintain more than one target server connection at once with wtxtcl. To make two connections, issue the wtxToolAttach command twice, each time saving the Tcl handle in a variable for convenience.

wtxtcl> set h1 [wtxToolAttach vxsim7] 
wtxtcl> set h2 [wtxToolAttach mv147] 
wtxtcl> set h1 
vxsim7@aven 
wtxtcl> set h2 
mv147@aven

The WTX Tcl API maintains a stack of handles. The most recently opened connection is at the top of the stack, so any WTX commands issued after entering the list of commands in the previous example go to mv147. To examine and manipulate the handle stack, use the wtxHandle procedure. With no arguments, it displays the stack (top item first). With an argument, it places the named handle at the top of the stack. Notice that the second command in the following example places vxsim7 at the top of the stack; further WTX commands are directed there.

wtxtcl> wtxHandle 
mv147@aven vxsim7@aven 
wtxtcl> wtxHandle $h1 
vxsim7@aven mv147@aven

You can also direct any WTX Tcl command to any connected handle without manipulating the stack. The generic -hwtx option, which takes a handle name argument, directs the WTX command to the named connection. For example, the following example shows a script which prints the BSP name of each connected target. Executing wtxHandle without arguments provides the list of connected targets, and running wtxTsInfoGet with the -hwtx option queries the correct target. Output is directed to stdout.

wtxtcl> foreach handle [wtxHandle] { 
set info [wtxTsInfoGet -hwtx $handle] 
puts stdout [lindex $info 4] 
} 
SunOS 5.5.1 [sun4u] 
Motorola MVME2600 - MPC 603p

4.4.14   Timeout Handling

Three methods are available for adjusting timeout values. They are listed from the most general to the most specific.

wtxTimeout

This command affects all subsequent WTX requests. The specified value serves as the default for all commands that do not have a different value assigned.

To get the current timeout setting, issue the following command:

wtxtcl> wtxTimeout 
30

To set a new timeout value, issue the following command:

wtxtcl> wtxTimeout 120 
120

wtxCmdTimeout

This array allows you to set a timeout for any WTX commands you choose. If the entry corresponding to a particular command is not set, the default timeout applies, unless the -timeout option is used when the command is issued.

To set up a timeout for all wtxObjModuleLoad commands, issue:

wtxtcl> set wtxCmdTimeout(wtxObjModuleLoad) 2400 
240

All subsequent object module loads will use a timeout value of 240 seconds.

-timeout

All WTX Tcl commands that involve communicating with the target server can take a -timeout option. This option affects only the timeout setting for the specific command.

wtxtcl> wtxSymFind -timeout 1 -name errno 
errno 0x96b3c 0x9 0 0 ""

4.4.15   Error Handling

WTX Tcl has an error handling facility that is designed to take advantage of Tcl's own exception handling features. When a wtxtcl request results in a WTX protocol error, the request generates a Tcl error. Tcl errors initiate a process called unwinding. The procedure that invoked the offending wtxtcl command stops executing, and immediately returns to its parent with the error code returned by the target server. If the parent was called by another procedure, it returns the error code to its parent, and so on. This process can continue indefinitely until the entire stack of procedure invocations is removed or the error is caught by an error handling routine. At each step, a descriptive message is appended to the global variable errorInfo. Printing this variable displays a backtrace showing the circumstances leading to the error.

The next example shows an error occurring in a nested context. A wtxMemRead call specifying an invalid address is embedded in a foreach and a while loop. When the error is returned, errorInfo prints the value of the error messages.

wtxtcl> foreach x {1 2 3} { 
while 1 { 
wtxMemRead 0xeeeeeeee 0x100 
} 
} 
Error: WTX Error 0x100ca (AGENT_MEM_ACCES_ERROR) 
wtxtcl> set errorInfo 
WTX Error 0x100ca (AGENT_MEM_ACCES_ERROR) 
while executing 
"wtxMemRead 0xeeeeeeee 0x100" 
("while" body line 2) 
invoked from within 
"while 1 { 
wtxMemRead 0xeeeeeeee 0x100 
}" 
("foreach" body line 2) 
invoked from within 
"foreach x {1 2 3} { 
while 1 { 
wtxMemRead 0xeeeeeeee 0x100 
} 
}"

Tcl's standard exception handling command, catch, can be used with WTX calls. Using catch interrupts the unwinding process, preventing errors from escaping to higher levels and allowing errors to be inspected and acted on.

While it is sometimes appropriate to examine each error individually, it is also common to take a specific action in response to a particular protocol error regardless of what command caused the error. In addition to the Tcl catch command, wtxtcl provides a means to establish an error handling procedure.

An error handler is a special Tcl procedure that is invoked when a protocol error occurs. An error handler procedure is invoked with four arguments. These are: the handle name, the command provoking the error, the error message itself, and a tag that can be supplied when the error handler is attached. (For more information see the online reference material underTornado API Guide>WTX Tcl Library.) An error handler procedure must accept these four arguments. Here is a simple error handler that prints its arguments and then resubmits the error to the Tcl interpreter. Except for the printing it has no effect on the application.

wtxtcl> proc myErrorHandler {handle cmd err tag} { 
puts stdout "handle $handle\ncmd $cmd\nerr $err\ntag $tag" 
error $err 
}

Error handler procedures are associated with communication handles, so different connections may have different error handlers in one wtxtcl session. To attach the error handler myErrorHandler to the WTX handle at the top of the handle stack, use the following command:

wtxtcl> wtxErrorHandler [lindex [wtxHandle] 0] myErrorHandler

You can test the process by defining this procedure to the interpreter and entering a faulty memory read request as in the following example:

wtxtcl> wtxMemRead 0xeeeeeeee 0x1000 
handle vxsim7@aven 
cmd wtxMemRead 0xeeeeeeee 0x1000 
err WTX Error 0x100ca (AGENT_MEM_ACCES_ERROR) 
tag  
Error: WTX Error 0x100ca (AGENT_MEM_ACCES_ERROR)

The first four lines of output were printed by the handler. The fifth was printed by the wtxtcl main loop in response to the error it received. This is because the error handler resubmits the errors it receives.

There are several guidelines to observe when writing error handlers: