Tsctl: Difference between revisions

From embeddedTS Manuals
No edit summary
Line 150: Line 150:
The format of each command when reading from standard input or a file is identical to that of the command line.  Every command always is of the form:
The format of each command when reading from standard input or a file is identical to that of the command line.  Every command always is of the form:
  @host class command arguments...
  @host class command arguments...
where '''@host''' is optional.  
where '''@host''' is optional.


{{note|
Advanced Topic: The Command Stack
Advanced Topic: The Command Stack
Sometimes you may want to issue several commands, and the first part of each command will be the same.  As a simple example, consider reading the example of reading the red and green LEDs given above.  If read from a file, these commands would look like this:
Sometimes you may want to issue several commands, and the first part of each command will be the same.  As a simple example, consider reading the example of reading the red and green LEDs given above.  If read from a file, these commands would look like this:
Line 173: Line 174:


The empty commands are used to pop the command stack, two pops are necessary to remove first the "Peek16" functiom, and then the "Bus" class, so that the System class can be used.
The empty commands are used to pop the command stack, two pops are necessary to remove first the "Peek16" functiom, and then the "Bus" class, so that the System class can be used.
}}


Due to the command stack, it is not considered an error if there is a partial command left when tsctl exits.  It is important to remember this to avoid confusion in case you accidentally specify a partial command.  For instance, the following command will generate no output and no error, because it does not do anything.
Due to the command stack, it is not considered an error if there is a partial command left when tsctl exits.  It is important to remember this to avoid confusion in case you accidentally specify a partial command.  For instance, the following command will generate no output and no error, because it does not do anything.

Revision as of 16:34, 6 May 2013

tsctl
Tsctl.png
Files
Latest tsctl sources

Overview

Tsctl was created as a way to ease software development, allow programs developed for one board to be easily re-used on other boards, and provide a way to control boards from any language and operating system that supports TCP/IP. You can also write your program to talk directly to the hardware via libtsctl. Tsctl has a consistent client API across all access methods. Currently it supports programming in C, Python, shell, Javascript, and Java, as well as any other language in which you can write code to talk to a TCP socket. tsctl is object oriented, and currently defines classes for AIO (Analog I/O, i.e. DAC and ADC), Bus (useful for direct register access), CAN, DIO, EDIO (Extended DIO for PWM, Quadrature counting and more), Pin, Time (timekeeping), TWI, and SPI hardware as well as a System class. Tsctl server runs as a single (user-space) multi-threaded server instance on the board to provide access to board features over TCP/IP.

The older canctl, dioctl, and spictl servers are implemented as libtsctl applications to provide the ability to run those applications on any hardware supported by tsctl.

Support

The following boards are currently supported by tsctl:

TS-Socket CPU
TS-4200
TS-4500
TS-4700
TS-4800
TS-Socket Baseboards
TS-8100
TS-8160
TS-8200
TS-8390
TS-8820
TS-8900
TS Single Board Computers
TS-7552
TS-7553
TS-7558
PC-104 Peripheral Boards
TS-RELAY8
TS-DIO24

Design Philosophy

Technologic System develops and manufactures single-board computers. Newly designed boards have features and configuration intended to meet newly emerging needs in the marketplace, as well as to respond to customer feedback concerning what is useful to them. However, over time many boards developed by Technologic Systems share in common certain features such as Ethernet, serial ports, CAN, and so forth. Some of these features are well supported by the Linux operating system which our boards ship with. However some are not, and in other cases the interface to accessing a particular feature has changed over time, sometimes dramatically.

Technologic System products are targeted towards the embedded market. The software development model in this space is often quite different from the rest of the software industry. Embedded devices typically go through a development cycle which terminates in a "frozen" state for all software on the board. Unlike other parts of the industry, upgrades or change of any kind in the state of the software as shipped is undesirable as it represents a high degrees of risk, risk that assumptions other software relies on will no longer be valid resulting in "breakage" of previously working software. As such, it is important that Technologic System provide software for the features on its board which reaches a frozen state quickly, allowing developers using our products to confidently freeze their own software in a timely manner.

At the same time, there are other important, but sometimes conflicting goals. These are:

  1. To bring new products to market quickly.
  2. To provide software for all the features on the board.
  3. To have a uniform interface to each feature allowing code developed for one board to work on another.

To meet these goals, tsctl does the following:

  • defines object classes, which encapsulates a specific piece of TS hardware behind a standard, uniform API across all supported TS products.
  • provides easy extensibility to add new objects and new API calls on existing objects without breaking any existing code.
  • provides a single, centralized, self-contained, backward compatible binary for each platform containing all TS functionality (which conforms to the tsctl spec)
  • utilizes pthreads, which allows for high performance locking of individual resources
  • provides a consistent interface across C, text and binary protocols, and various languages facilitates backward compatibility at the command line and protocol level with canctl, dioctl, and spictl
  • optimizes individual objects for maximum performance where applicable, i.e. CAN which can transmit and receive close to wire speed at 1Mbps via the high performance canctl protocol.
  • provides the new tsctl network protocol which allows all objects to be used through a single port, providing sequentiality and simultaneous access to multiple objects through the same protocol and connection.

Getting Started

The tsctl command line client for direct access

To help you get up and running with Technologic Systems hardware as fast as possible we provide tsctl, a libtsctl client/server application.

First, download the latest pre-compiled tsctl binary for your platform.

For the TS-4500, TS-7552, TS-7553 or TS-7558, download the "cavium" binary here: [1]

For the TS-4200, TS-4700, or TS-4800, download the "noncavium" binary here: [2]

Install the binary anywhere in your PATH. Before installing, you may wish to make sure you do not already have an older version of tsctl by attempting to run the "tsctl" command. If the command is found, be sure to replace the existing binary with the newly downloaded one in order to ensure you are running the most up to date copy.

Now you can see immediate results. Locate the red and green LEDs on your board. For TS-SOCKET boards these LEDs are usually on the base board (e.g. the TS-8XXX series) while TS-75XX boards have the LEDs directly on the board. Type the following commands:

tsctl DIO SetAsync GREEN_LED LOW
tsctl DIO SetAsync RED_LED LOW
tsctl DIO SetAsync GREEN_LED HIGH
tsctl DIO SetAsync RED_LED HIGH

You should see the green and red LEDs go off and on. (If they are already off then the first two commands will have no effect.)

Now let's talk about how the above commands work. Unlike many Linux utilities, tsctl provides direct access to a number of different functions across several classes using a "generic to specific" way of invoking the functionality you want.

First, you specify the host that you want to invoke the functionality on. This part is optional. The host is specified as the @ symbol followed by an IP address or host name, and indicates that the TCP/IP protocol is to be used. If no host is specified (as in the examples above), localhost is used if the tsctl server is running on the board, otherwise direct access is used.

Second, you specify what class of functionality you want to use. The available classes, in alphabetical order, are AIO, Bus, CAN, DIO, DIORaw, EDIO, Mode, Pin, SPI, System, Time, and TWI. If you specify "?" instead of a class, the available classes will be shown.

Third, you specify which function in the given class you want to invoke. If you specify "?" the list of functions available for that class will be shown. Above, we specified the SetAsync function.

Fourth, you specify the parameters for the function. If you specify "?" the expected parameters will be shown. The format of any parameter is quite flexible: you can enter a numeric value in octal, decimal, hexadecimal, or using a special string name which has a mapping to a value in the System lookup table, which we will discuss later. The SetAsync function takes two parameters: the DIO number and the state to set the DIO to. We used a special string for each: GREEN_LED, for example, having an entry in the mapping that corresponds to the DIO number for the GREEN_LED, and LOW/HIGH being enumerated values for 0 and 1, respectively.

Note that the SetAsync function does not returned any data, so the above commands produce no output. For our next example, let's use the GetAsync function to obtain the current state of the green LED pin:

tsctl DIO GetAsync GREEN_LED

When you run the above command, what output will you get? The answer to this is that it depends on the current output mode. The default mode is to output a "name=value" pair for each function, where the name is the name of the function you invoked, with an underscore and a number after it, and where the value is formatted in hexadecimal for integers and as an escaped, quoted string for arrays of 8-bit integers, and colon separated hexadecimal integers for all other arrays. If the output is an enumerated value, the default is to print the string corresponding to the enum value if the enum is not a flags enum, and otherwise to print the string value for each flag set separated by a plus symbol. The output mode can be changed by calling functions in the Mode class.

In the case of GetAsync, the value returned is an ordinary (non-flags) enumerated value, which can be one of the following: HIGH, LOW, INPUT, INPUT_LOW, and INPUT_HIGH. So in the following example we see the default output if the green LED was on:

$ tsctl DIO GetAsync GREEN_LED
GetAsync_0=HIGH

You might be wondering why there is an underscore and a number after the function name in the output. The reason is that tsctl allows you to issue multiple commands in a single invocation of tsctl. Each output has a unique name (accomplished by appending a different number for each command) in order to allow the results to be read by a shell script and assigned to shell variables. There are two schemes that can be used. By default (for backward compatibility), each function has its own counter, starting at 0, and incrementing by 1 each time it is called. The second method that can be used is (for slightly better performance) to use a single counter for all functions, so that this counter will increment once each time any command is called.

There are several ways that you can issue multiple commands with only a single invocation of tsctl. The first is to string together multiple tsctl commands by separating each one with a semi-colon. Since most shells use the semi-colon to separate shell commands, usually you will need to quote the semi-colon. So for example you could get the value of both the red and green LED with only a single invocation of tsctl as follows:

tsctl DIO GetAsync GREEN_LED \; DIO GetAsync RED_LED

Depending on your shell, the following should also work:

tsctl "DIO GetAsync GREEN_LED;DIO GetAsync RED_LED"

Note that no space is necessary on either sides of the semi-colon. The only white-space required is to separate each argument, and this white-space can be in any amount. The only thing to be aware of is that the newline character both terminates a command and triggers an invocation of all commands on the current line, so it is a bit more efficient to separate commands with semi-colons rather than white space unless you need a given output before issuing the next command.

If the red LED is on and the green LED is off, the default output of either of the above commands will look like this:

GetAsync_0=LOW
GetAsync_1=HIGH

Another way to issue multiple commands to a single invocation of tsctl is by reading the commands directly from the standard input, or from a file.

To read commands directly from the standard input until end of file (e.g. CTRL+D is pressed) invoke tsctl as follows:

tsctl --

To read commands directly from a file, invoke tsctl as follows:

tsctl -f filename

The format of each command when reading from standard input or a file is identical to that of the command line. Every command always is of the form:

@host class command arguments...

where @host is optional.

Note:

Advanced Topic: The Command Stack Sometimes you may want to issue several commands, and the first part of each command will be the same. As a simple example, consider reading the example of reading the red and green LEDs given above. If read from a file, these commands would look like this:

DIO GetAsync GREEN_LED
DIO GetAsync RED_LED

Each command starts with a common prefix, namely "DIO GetAsync". To reduce the amount of typing (and length of the command) needed, tsctl provides a "command stack".

The tsctl command stack can be thought of as follows. When you specify a command, it consists of several words, separated by whitespace, starting with the (optional) host name and continuing until all the arguments have been specified. Conceptually, as each word is read, it is pushed onto a stack. Once a complete command is on the stack, it is executed. However, if the current command terminates without a complete command being present, then the current command stack is then saved as the context for future commands. Each future command will then be read with this context, this pre-initialized stack. Each time an empty command is encountered, the last element on the stack - if present - is popped off.

In the above example the result would look like this:

DIO GetAsync
GREEN_LED
RED_LED

The first line effectively selects the DIO class and the GetAsync function. Subsequent commands then operate in this context and only need to specify the arugments to the GetAsync function. If we wanted to use another DIO function we would enter a blank line to pop the "GetAsync" function, and if we were done with DIO we could enter another blank line to pop the "DIO" class from the stack. Any extra blank lines would be ignored.

If you wanted to issue both commands in the same server invocation you could simply the above set of commands to the following:

DIO GetAsync;GREEN_LED;RED_LED

This can be a very efficient method for calling the same function repeatedly with the same arguments. For instance, suppose you wanted to read the SYSCON registers at offset 0,2,4,6,8,and 10 of Bus 0, and then call System function ModelId you could do so as follows:

Bus Peek16;0;2;4;6;8;10;;;System Model

The empty commands are used to pop the command stack, two pops are necessary to remove first the "Peek16" functiom, and then the "Bus" class, so that the System class can be used.

Due to the command stack, it is not considered an error if there is a partial command left when tsctl exits. It is important to remember this to avoid confusion in case you accidentally specify a partial command. For instance, the following command will generate no output and no error, because it does not do anything.

tsctl Bus Peek16


The last way to issue multiple commands with a single invocation of tsctl is to start the tsctl shell, as follows:

tsctl

There are a few differences between running the tsctl shell versus providing commands directly from the command line or from a file. The readline library is used to allow command editing and history. Starting with version 0.91, output in shell mode is in decimal (Mode Dec) and the values from each command are printed without an an assigment (Mode NoAssign).

This will print a startup message and then give the tsctl shell prompt, "tsctl> ". To supress the startup message use the "--quiet" option:

tsctl --quiet

Note: UNIMPLEMENTED

The tsctl command shell displays "tsctl" plus the current command stack (if any) before the prompt. The above example of using the command stack has been extended (to show popping the stack) in the tsctl shell.

$ tsctl
tsctl 0.91-ts (Nov 30 2012 22:06:57)   
Type "?" to get context-sensitive help.
tsctl> DIO 
tsctl DIO> GetAsync 
tsctl DIO GetAsync> GREEN_LED 
HIGH
tsctl DIO GetAsync> RED_LED
LOW
tsctl DIO GetAsync>
tsctl DIO>
tsctl>

You can also use semi-colons to put multiple commands or parts of a command on a single line.

To exit the tsctl shell, press CTRL+D, or enter the word "end" by itself on the current line with no extra whitespace.

You can control the format of the output of each command using the Mode class. The output mode is divided into two parts: the encoding and the base.

The output encoding is one of the following: Raw, Newline, Assign, and JSON.

Raw encoding outputs each value returned by the command in the current base, one after the other with no other characters in between each value. It is mainly intended for base -1 and base 0, as with all other bases it would be difficult or impossible to determine where one value ended and the next started. Newline encoding outputs each value returned by the command in the current base, with a new-line character after each value. Assign encoding outputs a "name=value" pair for each value returned by the command, where value is in the current base, and name is the name of the function, with an underscore and numeric count appended. JSON encoding wraps each output in a "name":value format, and separates each element with a comma as well as wrapping arrays in brackets and the entire reply in braces.

Output base is one of the following: -1 (escaped binary), 0 (binary), 2 (ASCII binary), 8 (octal), 10 (decimal), or 16 (hexadecimal). Separate bases are active for character strings and other numbers. Note that for ASCII base output (2 and above) there are no identifying characters to tell what base it is. For instance, there is no "0x" preceding the hexadecimal value in base 16 mode.

Base 0 is the raw internal, little-endian "binary" representation of the value. Although it is the actual binary format of the value this should not be confused with base 2, which is the ASCII representation of the binary value, which consists of only '0' and '1' characters. Base -1 is the same as Base 0, except that only 8-bit values in the range of 32 and 126 (excluding 92, which is the ASCII backslash character) are output as-is. All other values are output as a backslash followed by three octal digits representing the ASCII value of the byte.

In addition, there input modes, and is divided into two parts: the encoding and the base.

The input encoding is one of the following: HTTP and Command.

Command encoding indicates that the server immediately processes input as commands. This is the default and only mode available in client mode. HTTP encoding is only available through the TCP port. In this mode, an HTTP POST header is assumed to occur before the start of any commands. Two empty newlines terminate the header and put the connection back into Command mode. The input base is either Binary or Text.

The tsctl client, whether invoked as a command-line sequence of commands, as the tsctl client, or reading commands from the standard input or a file, defaults to input encoding Command, input base Text, output encoding Assign, output base 16.

You can find more information in the tsctl "Getting Started" guide for the hardware you are using.

The tsctl command line client for remote access

Using the tsctl server from HTML/Javascript

Using the tsctl server from Python

Using the tsctl server from Java

Writing your own libtsctl direct access application in C

Using the tsctl server from C

Concepts

Objects

Tsctl uses objects to perform most important functionality. These objects are divided into classes which correspond to various resources available on the board: AIO, Bus, CAN, DIORaw, DIO, EDIO, Pin, System, Time, TWI, and SPI. These objects are implement in C using a structure which contains a pointer to the API for the class. To use an object, it is first necessary to call its initialization function to get a pointer to the object. Objects are referenced by initialization by number. Some numbers for a given class are standard across all hardware, while others are specified to a given board.

Classes

API Reference

Systems

The system object provides access to control functions implemented by the server itself. For a given architecture, there is a singleton System object for the entire board. The system object provides information about the server, as well as allowing for control functionality.

ClassCount

Typically used for debugging, this function obtain the number of classes defined by the server. The value returned is one greater than the maximum value allowed to be passed as the class parameter in any tsctl protocol request to the server.

API Call
Name Return Value Arguments
ClassCount 32-bit integer Initialized "System" object
System *sys = SystemInit(0);
printf("There are %d classes defined by the system.\n",sys->ClassCount(sys));

This call is also available over the TCP interface on port 5001.

TCP Request Packet TCP Reply Packet
Offset Bytes Field Value Offset Bytes Field Value
0 2 Class 0x0000 0 2 class 0x0000
2 1 Instance Instance 2 1 Command 0x00
3 1 Command 0x00 3 1 Tag 0x13
4 4 ClassCount ClassCount
8 1 tag 0x80

InstanceCount

Typically used for debugging, this function obtains the number of instances of the specified class which are available on the server for clients to make requests for through the tsctl protocol. The value returned is one greater than the maximum value allowed to be passed as the instance parameter in any tsctl protocol request to the specified class; if a value equal or greater is passed, the server will signal an exception by closing the connection to the client.

API Call
Name Return Value Arguments
InstanceCount 32-bit integer Initialized "System" object

This call is also available over the TCP interface on port 5001.

TCP Request Packet
Offset Bytes Field Value
0 2 class 0x0000
2 1 instance instance
TCP Reply Packet
Offset Bytes Field Value

Template

API Call
Name Return Value Arguments
Initialized "System" object

This call is also available over the TCP interface on port 5001.

TCP Request Packet
Offset Bytes Field Value
TCP Reply Packet
Offset Bytes Field Value

Advanced

Locking

libtsctl is design to make it possible to share resources. It does this by allowing resources to be locked. A lock can be a shared lock, such as might be appropriate for reading a value, or it can be an exclusive lock, which would be appropriate for changing a value.

All resources that provide an interface to lock and unlock them must be locked before use and unlocked after use. This is because in some cases the locking mechanism, in addition to acquiring shared or exclusive access to the resource, also performs per access initialization. For instance, multi-function pins are automatically set to the correct function during locking.

From the perspective of a client there are object locks, which in the server ultimately result in one or more system locks being held, under control of the object being locked and any sub-objects it contains. All tsctl objects which provide a Lock function offer the client to hold an object lock on that object. Each class defines the circumstances under which the client must hold an object lock. A client should not hold an object lock any longer than necessary.

Getting Started with tsctl on the TS-4200