As described in the previous section, QSPY is the host-resident component in the QP/Spy software tracing system. QSPY is a simple console application without a GUI, because its primary purpose is to provide communication with the QS target-resident component, parsing of the QP/Spy Data Protocol, and displaying the data in a simple human-readable format.
QSPY can also export the data in various other formats, such as a format suitable for MATLAB/GNU-Octave, and a format suitable for generating sequence diagrams. Additionally, QSPY can also save the symbolic information about the Target objects in the form of QSPY dictionaries. An example of a QSPY session is shown in the Introduction to QP/Spy.
Finally, QSPY also supports an extensible UDP-socket connection, which allows it to serve as a "Back-End" for attaching various "Front-Ends" (such as the QUTest Front-End and QView Front-End).
The QSPY host utility is free to download and free to use, but in the default mode is limited to 100KB of tracing data from the target system. The following screenshot shows a QSPY run after exceeding the data limit.
To remove this limitation, the QSPY host utility requires a QP License Certificate↑, which can be specified to QSPY by the -l <license.qlc> command-line option. Please note that the QSPY utility verifies the integrity and validity of the license certificate. Specifically, the certificate is evaluated against the QP framework type reported by the target (qpc vs. qpcpp) and against the support end-date vs. the QP release date reported by the target. If either does not match, the QSPY utility reverts to the limited mode, as illustrated in the following screenshot:
The QSPY application accepts several command-line parameters to configure the data link to the Target, backwards-compatible with previous versions, and target dependencies, such as pointer sizes, signal sizes, etc. This means that the single QSPY host application can process data from any Target running the QS component. QSPY has been tested with a wide range of 8-, 16-, 32-, and 64-bit CPUs.
The general form of invoking QSPY is as follows:
qspy [options]
Where options are described in the following table:
Usage: qspy [options] <arg> = required, [arg] = optional
| Option | Example | Default (key) | Must match QP macro | Comments |
|---|---|---|---|---|
| -h | -h | (key-h) | Help. Prints the summary of options | |
| -q [num] | -q 99 | (key-q) | Quiet mode (reduced stdout output) | |
| -u [UDP_port|0] | -u | 7701 | UDP socket for "Front-Ends". -u0 suppresses opening the UDP socket | |
| -l <license.qlc> | license file (*.qlc) | |||
| -v <QS_version> | -v 6.2 | 7.0 | Enforce backwards-compatibility with the specific QS version | |
| -r <c0|c1|c2> | -r c2 | c1 | Rendering options (c0=no-color|c1-color1|c2-color2) | |
| -k | -k | suppress keyboard input | ||
| -o | -o | (key-o) | Produce output to the specified file | |
| -s | -s | (key-s) | Save the binary input to a file. Not compatible with -f | |
| -m | -m | (key-m) | Produce MATLAB/GNU-Octave output to a file | |
| -g [object-list] | -g obj1,obj2 | (key-g) | Produce Sequence diagram output to a file | |
| -t [TCP-port] | -t | 6601 | TCP/IP input selection. Not compatible with -c, -b, -f | |
| -c <port> | -c COM2 | COM1 | COM port selection. Not compatible with -t, -p, -f | |
| -b <baud> | -b 38400 | 115200 | Baud rate selection. Not compatible with -t, -p, -f | |
| -f <file> | -f qs.spy | File input selection. Not compatible with -c, -b, -t, -p | ||
| -d [file] | -d my_app.dic | Read dictionaries from a file. | ||
| Options for configuring Target object sizes: The Target can report its configuration to QSPY, which means that you don't need to provide any upper-case options (such as: -T, -O, -F, etc.). | ||||
| Option | Example | Default (key) | Must match QP macro | Comments |
| -T <size> | -T 2 | 4 | QS_TIME_SIZE | Time stamp size in bytes. Valid values: 1, 2, 4 |
| -O <size> | -O 2 | 4 | QS_OBJ_PTR_SIZE | Object pointer size in bytes. Valid values: 1, 2, 4, 8 |
| -F <size> | -F 2 | 4 | QS_FUN_PTR_SIZE | Function pointer size in bytes. Valid values: 1, 2, 4, 8 |
| -E <size> | -E 1 | 2 | QF_EVENT_SIZ_SIZE | Event-size size in bytes (i.e., the size of variables that hold event size). Valid values: 1, 2, 4 |
| -Q <size> | -Q 2 | 1 | QF_EQUEUE_CTR_SIZE | Queue counter size in bytes. Valid values 1, 2 |
| -P <size> | -P 4 | 2 | QF_MPOOL_CTR_SIZE | Pool counter size in bytes. Valid values: 1, 2, 4 |
| -B <size> | -B 1 | 2 | QF_MPOOL_SIZ_SIZE | Block size size in bytes. (i.e., the size of variables that hold memory block size). Valid values 1, 2, 4 |
| -C <size> | -C 2 | 4 | QF_TIMEEVT_CTR_SIZE | Time event counter size. Valid values: 1, 2, 4 |
Your primary concern when invoking QSPY is to match precisely the target system you are using. The fourth column of the table above lists the configuration macros used by the target system as well as the platform-specific QP header files where those macros are defined. You need to use the corresponding QSPY command-line option only when the QP macro differs from the default. The default values assumed by QSPY are consistent with the defaults used in QP.
~ ~ ~ <COMMS> ERROR 4 bytes unused in Rec=QS_QEP_INTERN_TRAN ~ ~ ~ <COMMS> ERROR 2 bytes unused in Rec=QS_QEP_DISPATCH
The QSPY application invoked without any parameters defaults to the following configuration:
C:\tmp>qspy -h QSPY 8.0.0 Copyright (c) 2005-2024 Quantum Leaps Documentation: https://www.state-machine.com/qtools/qspy.html -u 7701 UDP socket with optional port, 0-no UDP (-l) no license file (*.qlc) -v 7.0 compatibility with QS version -r c1 text output rendering (c1-color1) (-k) no suppress keyboard input (-o) no screen output to a file (-s) no binary QS data to a file (-m) no Matlab output to a file (-g) no Sequence diagram to a file -t 6601 TCP/IP input with optional port (default) (-c) no COM/Serial port input -b 115200 baud rate for the com port (-f) no file input (postprocessing) (-d) no dictionary files -T 4 QS timestamp size (bytes) -O 4 object pointer size (bytes) -F 4 function pointer size (bytes) -S 2 event signal size (bytes) -E 2 event size size (bytes) -Q 1 queue counter size (bytes) -P 2 pool counter size (bytes) -B 2 pool block-size size (bytes) -C 4 QTimeEvt counter size (bytes)
Specifically, by default, QSPY opens the UDP socket at the default port (-u 7701) for "back-ends" (such as QUTest) and opens the TCP/IP socket at the default port (-t 6601) for communication with the Targets.
The other parameters correspond to 32-bit Target CPUs, such as ARM and x86, compiled in 32-bit mode. The x86 is relevant for running the embedded software on host machines based on x86 processors.
The QSPY host application can be terminated locally in the following ways:
The QSPY host application can also be terminated remotely by sending a special UDP packet to QSPY. A cross-platform Python script qspy_kill.py (located in qtools/qspy folder) is provided to send such a UDP packet. This Python script can be used for test automation or automating other activities involving the QSPY host application.
The qspy_kill.py takes the following command-line options:
usage: python qspy_kill.py [-h] [-v] [-q [QSPY]]
QSPY-exit
options:
-h, --help show this help message and exit
-v, --version Display QSPY-exit version
-q [QSPY], --qspy [QSPY]
optional qspy host, [:ud_port]
More info: https://www.state-machine.com/qspy.html#qspy_kill
In the absence of the -k (suppress keyboard) command-line option, the QSPY console application accepts keyboard input. The following table shows the currently supported key strokes:
| Key | Action |
|---|---|
| <Esc> | Exit QSPY |
| h | display keyboard help and QSPY status |
| c | clear the screen |
| q | toggle quiet mode (no Target output to the screen) |
| r | send RESET command to the Target |
| i | send INFO request to the Target (see also QSPY Dictionaries) |
| t | send TIKC[0] command to the Target |
| u | send TICK[1] command to the Target |
| d | save QP/Spy Dictionaries to a file |
| o | toggle QSPY Human-Readable Output to a file (open/close) |
| s/b | toggle binary file output (open/close) |
| m | toggle MATLAB Output to a file (open/close) |
| g | toggle Sequence Output to a file (open/close) |
QSPY currently provides the following communication links to the QS target-resident component:
| Communication Link | Command-Line Option |
|---|---|
| TCP/IP | -t [TCP_port] (default) |
| Serial port | -c <COM_port> and -b<baud_rate> |
| Binary File | -f <file_name> |
| Other link (e.g., JTAG debug probe) | can be added to the QSPY Platform Abstraction Layer |
QSPY can save the tracing data from the Target in various formats into files. QSPY assigns file names automatically. Also, QSPY can open/close various files multiple times in a single session, so it is no longer necessary to exit QSPY and relaunch it with different command-line parameters to save data to a different file.
QSPY uses a very simple naming convention to assign file names. All names start with qspy<time-stamp>, where the time-stamp format is: YYMMDD_hhmmss, where YY is 2-digit year, MM is a 2-digit month, DD is a 2-digit day of the month, hh is a 2-digit hour, mm is a 2-digit minute, and ss is a 2-digit second. The time-stamp is accurate to a one second, so it's virtually impossible to have name conflicts for files generated on the same machine. The following extensions distinguish the various types of files:
| Command-Line Option | Keyboard Option | File Extension | Example | Comment |
|---|---|---|---|---|
| -o | o | .txt | qspy150914_132234.txt | text (screen) output |
| -s | s | .qs | qspy150914_132234.qs | raw binary output |
| -d | d | .dic | qspy150901_101203.dic | dictionary output |
| -m | m | .mat | qspy150914_132234.mat | MATLAB output |
| -g | g | .seq | qspy150914_132234.seq | Sequence diagram output |
The following sub-sections explain the following QSPY features: