Introduction#

The XTC Tools are a suite of tools to run on a host PC for working with XMOS target systems. A target system is typically a single printed circuit board populated with one or more XMOS devices. A target program, (which is a .xe-suffixed file produced by the xcc tool), may be downloaded into the target RAM and executed using the xrun tool. Symbolic debugging of a target program may be carried out using the xgdb tool. A target program may burned to non-volatile flash using the xflash tool. These tools require an XMOS xTAG to connect the target system to the host computer via a USB 2.0 interface.

Key target-based features#

The following target-related features are provided by the XTC Tools:

  1. Reset the target, download and launch a target program, and optionally support host-IO and xSCOPE operations

  2. Write a target program to a flash device in a target system

  3. Dump the current state of the target (does not reset the target)

  4. Provide symbolic debug of a target (where the program is either downloaded into RAM or booted from flash)

    1. The target may be debugged starting from a system-reset state or the debugger may be attached to a running program

    2. Host-IO and xSCOPE API calls may be left in programs which are deployed. The tools will optionally enable host-IO when a connection is made via an xTAG

  5. Provide an API for a developer to use on the host computer to transfer application data to and from the target

  6. Provide sample-based profiling of a target

  7. Management of all xTAGs attached to the host

    1. List the xTAGs and detect the type of target system attached

    2. For all the tools, an xTAG may be specified by its list index or by unique identifier

    3. If only one xTAG is connected to the host an identifier does not need to be supplied to the tools

Targets#

Two generations of XMOS target system are supported by the tools:

  • xCORE-200 (XS2A Instruction Set Architecture)

  • xcore.ai (XS3A Instruction Set Architecture)

Evaluation boards may be obtained from various sources, such as Farnell.

xTAG#

The xTAG is the physical host-to-target interface. Two types are supported by the tools; xTAG v3.0 (https://www.xmos.com/download/xTAG-3-Hardware-Manual(1.0).pdf) and xTAG v4.0. Both xTAG types have a USB 2.0 High Speed (Micro-B) interface for connection to the host which also supplies the power to the xTAG. The xTAG3 has a proprietary xSYS interface to the target board and the xTAG4 has an xSYS2 interface to the target board.

Both xSYS and xSYS2 provide 4-wire IEEE1149.1 JTAG interface and a duplex serial xCONNECT link (xLINK) interface, plus some additional control signals. Note the optional JTAG signal nTRST is not pinned out.

When an xTAG is attached to a host it listens for a connection by certain host programs (xrun, xgdb, xflash or xburn). The first connection will download firmware to the xTAG which will support target-related operations. The firmware is not downloaded on subsequent connections until the xTAG is power-cycled.

The elapsed time required to connect to an xTAG is highly variable, due to the possibility of a firmware download occurring, and because the host operating system can introduce delays. This period may extend when multiple xTAGs are attached to the host computer. When a connection is initiated a lock is taken which may pause the execution of other independent host tools each using their own xTAG. The lock is released once the connection is established. Automated test systems should ensure any timeout for an xTAG response is sufficient for the worst case which may need to be determined empirically.

If the xTAG has been used previously with an earlier Tools 15 release the first connection will attempt to install the firmware required for use with this release. The xTAG will automatically reboot as part of this process which will be shown by the xTAG LEDs.

Note 1: If an xTAG has been used with a tools release earlier than Tools 15 it must be manually power cycled prior to making a connection with Tools 15.

Note 2: If the host is rebooted it may fail to enumerate the attached xTAGs. The xTAGs must be power-cycled. Some USB hubs provide a mechanism to power-cycle their downstream ports, and these are recommended for remote lab environments. Note Windows hosts do not support this feature.

xTAG v3.0#

xTAG v3.0 datasheet: https://www.xmos.com/download/xTAG-3-Hardware-Manual(1.0).pdf

The xTAG v3.0 provides the xSYS target interface (IDC 20-pin 0.1”) and supports XCORE-200 target families. It supports only 3v3 target voltage levels.

xTAG v4.0#

The xTAG v4.0 provides the xSYS2 target interface (Amphenol Minitek127 20-pin 0.05”) and supports XCORE-200 and xcore.ai target families. It supports 1v8 and 3v3 target voltages, automatically and independently for JTAG and xLINK interfaces.

The xLINK is optional - if it is not connected a reduced-footprint connector may be employed on the target board. To reduce the connector cost to a minimum, for production programming and testing, a Tag-Connect Plug-Of-Nails may be used. Only the IEEEE1149.1 JTAG signals need to be connected.

Using xTAGs with Windows hosts#

On Windows host computers the click-through XTC installer sets up an xTAG service. This service starts following the installation procedure and each time the host boots, and requires no further administration.

On Windows hosts it is not possible to switch between an XTC Tools 15 series release and an earlier XTC Tools release and use the host tools which require access to an xTAG.

On Windows hosts the xTAG unique identifiers are shown in upper case but the tools are case-insensitive so scripts which drive the tools may be used interchangeably between all OS types supported by the tools.

Host tools#

The host tools that interface with the target system are xrun, xgdb, xflash and xburn.

Unless stated otherwise the following examples in this section assume a single xTAG and target system are attached to the host computer.

xrun#

The program xrun is used to:

  1. List the xTAGs and target systems attached to the host computer

  2. Download a target program to RAM and launch it

  3. Download a target program to RAM and launch it, managing host-IO

  4. Download a target program to RAM and launch it, and capture xSCOPE data to a file

  5. Download a target program to RAM and launch it, and allow a user-supplied host program capture xSCOPE data from the target and send data to the target

  6. Dump the state of a target either with a .xe target program so it may be represented symbolically or without a .xe to show state as raw data

List the attached xTAGs#

The command xrun -l lists the xTAGs attached to the host computer. When an xTAG is first plugged into the host the red LEDs should be illuminated in a dim state. These should change state when xrun -l is invoked. Sometimes the host fails to identify the xTAG. In this case it should be unplugged for several seconds and then re-inserted. If the xTAG is not listed check for its presence. On Linux hosts run the command:

$ lsusb

On Windows hosts open the Device Manager and expand Universal Serial Bus devices.

Launching a target program#

A target program may be launched on the target system with:

$ xrun my_program.xe

xrun will exit immediately, leaving the target program running indefinitely. If the target program fails it may be debugged by attaching with xgdb.

A target program may be launched with host-IO enabled with:

$ xrun --io my_program.xe

or with xSCOPE host-IO enabled:

$ xrun --xscope my_program.xe

xgdb#

The host tool xgdb is a variant of the open-source tool gdb. It supports the standard gdb command line options and commands, plus extra command options and builtin commands for use with XMOS targets.

It may be used to carry out all the functions supported by xrun, plus

  1. Interactive, symbolic debug of the downloaded program

  2. Scripted actions with the target

  3. Attaching to a target which is running a program which either booted from flash or was downloaded and launched with xrun or xgdb

Symbolic debug is only available for a source compilation unit (that is, a .c., .cpp or .xc file) if it is compiled with the -g option passed to xcc. Reducing the optimisation level used by xcc with the -O option will improve debuggability at the expense of potential changes in program behaviour.

Debugging a target program#

The following command will start a debug session of the program my_program.xe by connecting to the target, downloading the program and initialising the device based on the target XN used to build the program:

$ xgdb -ex "connect" -ex "load" my_program.xe

Commands supplied with the option -ex may be entered at the (gdb) prompt if preferred.

To start the program running the user must enter the command:

(gdb) continue

Before starting the program debugging commands may be supplied. For example, breakpoints may be set with the break command.

Once the target program is started the (gdb) prompt will not be available. Host-IO may appear on the console. Once started the target program may be stopped by pressing Ctrl-C which will report the stopped location and provide the (gdb) prompt.

The active logical cores may be listed with:

(gdb) info threads

Each active logical core is assigned a unique “gdb thread” number. Only active logical cores in all tiles in the system are listed. Note the “gdb thread” number assignments are not static and they may vary each time the target stops. A logical core may be selected for further inspection with the thread command. For example:

(gdb) thread 5

The back trace (call stack) for the logical core may be shown with the where command, for example:

(gdb) where

Local and global variables may be inspected with the standard gdb commands. See the gdb documentation for details.

Attaching to a target#

In some cases it may be desirable to inspect the state of a target system without resetting it. It is possible to attach to a running target. For example:

$ xgdb -ex attach my_program.xe

xgdb will stop all the tiles and provide the (gdb) prompt. xgdb commands may be issued as illustrated in the previous section.

Target interaction#

The JTAG interface is used by the tools to establish a connection to the target, to reset it and to download programs to RAM. It is used to interact with the target, for example, to extract register state and to set breakpoints. It is used to monitor the target to detect program termination, to detect the target taking a fatal exception and to interrupt the target. It may be used to handle host-IO.

Debug mode#

Each tile will be placed in its debug mode to: download a program, when a breakpoint is reached, to terminate a target program and when interrupted by a Ctrl-C operation in the xgdb console. In some cases it will enter debug mode to forward host-IO data. When a tile enters debug mode all its logical cores will be paused.

Exceptions#

The tools xrun and xgdb place a breakpoint on the exception handler entry point. When the target takes a fatal exception (for example, due to arithmetic divide-by-zero), the tools will report on the occurrence of the exception. xgdb may be used to debug the cause, symbolically, typically by showing the back-trace.

Note the message SIGTRAP is generated if a tile enters debug mode unexpectedly. This may occur when certain low-level operations are being carried out with the tiles. The target program has not taken an exception.

Launch with xrun#

If the target program is launched by xrun without any optional arguments, xrun loads and runs the program, then exits immediately leaving the target program running. If the --io option or any of the --xscope options are supplied to xrun it will not exit until the target program terminates - see below.

Termination#

If a tile’s control flow reaches the end of main() that tile will terminate and wait. When control flow for all tiles has reached the end of main(), the xrun session will terminate with a successful exit code. If the program was launched using xgdb it will report “Program exited normally “ on termination. (If xrun has been used to launch a program without either the xrun --io or xrun --xscope options, then it will detach after loading, and not await termination.)

If a tile calls exit() with a non-zero value, this will be returned by xrun as the process exit code. One tile calling exit() terminates the entire system. If launched by xgdb, the exit code will be shown on the console, and the xgdb --return-child-result option can be used to make xgdb return the exit code as its exit code.

Host-IO#

If the target program calls standard library IO functions from stdio.h such as printf(), fprintf(), fopen(), fread() and fwrite(), and the program was launched with xgdb, or with xrun and the xrun --io or xrun --xscope options, these calls will be redirected to act on the host computer’s filesystem (or its console, for stdin, stdout and stderr). This is part of the “semihosting” system which runs all system calls on the host system when the target is connected via a debug interface. By default, data is sent to and from the target via the JTAG interface. Using the JTAG interface, the tile making the call enters debug mode which pauses execution of all its logical cores.

These calls may be left in the program when it is deployed to boot from flash using xflash. The system calls will be skipped if a debugger is not connected, however much of the logic (such as the string formatting of printf) will still execute. If xrun or xgdb is later used with a such a system, the IO will be redirected to the host computer. There is a deployment penalty in run-time and memory used; each call will process its arguments before inspecting internal state to determine whether xrun or xgdb is connected.

Note stdio.h and other headers mentioned in the following sections can be found under the tools installation in the sub-directory target/include.

An example xrun command to enable host-IO:

$ xrun --adapter-id DFW7DTYY --io test.xe

An example xgdb command (note IO is enabled by default when using xgdb):

$ xgdb -ex "connect --adapter-id DFW7DTYY" -ex load -ex continue test.xe

Reduced-overhead print functions#

The header print.h provides a set of reduced overhead print functions such as printstr(). These do not perform any memory allocation or any runtime formatting, making them memory and run-time efficient compared with the standard library IO functions. For example, the following prints a set of characters without a new line:

printstr("Starting test 1");

Syscall host-IO#

The header syscall.h provides the functions _open(), _close(), _write() and _read(). These may be used to perform host-IO with a reduced run-time and memory overhead compared with the standard library IO functions. The standard library IO functions call these underlying syscall functions. For example:

int fd = _open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
if (_write(fd, buf, len) != len) { // Handle error }

xSCOPE APIs#

A set of target APIs is provided to send packets of data to the host to be visualised as waveforms with a 3rd party graphical tool. A set of virtual channels called ‘probes’ are defined in the target program and each appears as a separate waveform trace.

The xLINK is always used to transport the data sent from the target.

xSCOPE may be configured in lossy mode where data may be dropped if the host fails to keep pace with the target, or in lossless mode where logical core emitting the data may be paused while data is transferred.

Lossy or lossless data delivery may be selected using xscope_mode_lossless() and xscope_mode_lossy().

The APIs are defined in xscope.h. An example to emit float and integer data for two probes is:

void xscope_user_init(void) {
    // Register 2 probes. The first implicitly has ID 0, the second has ID 1.
    xscope_register(2,
                    XSCOPE_CONTINUOUS, "Float0",     XSCOPE_FLOAT, "mV",
                    XSCOPE_CONTINUOUS, "Iterations", XSCOPE_UINT,  "Steps");
}

void emit(float f, unsigned int i) {
    xscope_float(0, f);
    xscope_int(1, i);
}

The target program must be built with xSCOPE support, either by passing xcc -fxscope or an xSCOPE config file to xcc

The xrun option xrun --xscope-file must be supplied to specify a file into which the data will be written in IEEE 1364-2001 Verilog VCD format.

User-supplied host program#

The user may supply a host program which handles target data while the target program is running. The target can send data to the host program using either the xSCOPE APIs, the semihosting APIs (such as printf) or both sets. The host program can send data back to the target program.

The host program can be written in either the C or C++ programming language. The header xscope_endpoint.h provides the API for the host program. It must be linked against the shared library libxscope_endpoint.so on Linux and Mac hosts and xscope_endpoint.a on Windows hosts, using C linkage. These libraries are provided by the XTC Tools in the lib sub-directory of the installation root. See xSCOPE host library for more information.

In this example two consoles are used to launch the xgdb session and the host program.

<PORTNUM> must be substituted with a free system port number.

Console 1: launch the xgdb session:

$ xgdb -ex "connect --xscope-port --xscope-port localhost:<PORTNUM>"

Console 2: launch the host program:

$ host_example <PORTNUM>

Structure of the host program#

The host program starts by registering callback functions to handle selected target activities, such as target calls to printf() or target calls to xSCOPE APIs. It does this with calls to:

It then connects to the xgdb session using the <PORTNUM> argument passed to main():

result = xscope_ep_connect("localhost", argv[1]);

If result is zero, the connection was successful. If non-zero the xgdb server was not ready. The xscope_ep_connect() API call may be re-tried until a connection is made.

Once connected the program should sleep in an efficient manner. The callback functions will be called when necessary as a direct result of API calls by the target program.

Example host program and target programs#

In the following example the host program provides a set of call back functions which are called when the target-initiated events occur.

Compile#

$ xcc -g -fxscope -target=XCORE-AI-EXPLORER -o target.xe main.xc target.c
$ gcc -g -I "$(XMOS_TOOL_PATH)/include" ${XMOS_TOOL_PATH}/lib/xscope_endpoint.so -o host host.c

Run#

Open two consoles.

In console 1:

$ xrun --xscope-port : target.xe
XScope Realtime Server Enabled (localhost:37316)

In console 2: Supply the port number printed by xrun following localhost: above:

$ ./host 37316

Host program#

Listing 12 host.c#
#include <signal.h>
#include "xscope_endpoint.h"

/* Called when the target calls xscope_register() */
static void xscope_register(unsigned int id,
                            unsigned int type,
                            unsigned int r,
                            unsigned int g,
                            unsigned int b,
                            unsigned char *name,
                            unsigned char *unit,
                            unsigned int data_type,
                            unsigned char *data_name)
{
  // Handle the registration of the probe with the id 'id'
  // For this example, we would expect a registration for:
  // - Probe id=0, name = "V"
  // - Probe id=1, name = "I"
  // See the xscope_register call in the target file below
}

/* Called on each target call to xscope_int() and similar APIs */
static void xscope_record(unsigned int id,
                          unsigned long long timestamp,
                          unsigned int length,
                          unsigned long long dataval,
                          unsigned char *databytes)
{
    /* id is the probe number used by the target in the xSCOPE API call */
    switch (id) {
      /* handle each probe id */
      case 0:
      /* do something for probe 0 */
      break;
      case 1:
      /* do something for probe 1 */
      break;
    }
    /* Optional: Send a 2-byte reply to the host : max 256 bytes */
    const char* s = "ok";
    xscope_ep_request_upload(2, s);
}

static void xscope_print(unsigned long long timestamp,
                         unsigned int length,
                         unsigned char *data)
{
    for (int i = 0; i<length; i++) {
        printf("%c", data[i]);
    }
}

static volatile int running;

/* Called when the target program terminates */
static void sigint_handler(int) {
    running = 0;
}

int main(int argc, char *argv[])
{
    if(argc != 2){
        fprintf(stderr, "ERROR missing xscope port number: Usage example %s localhost:12340\n", argv[0]);
        exit(-1);
    }
    xscope_ep_set_print_cb(xscope_print);
    xscope_ep_set_register_cb(xscope_register);
    xscope_ep_set_record_cb(xscope_record);
    signal(SIGINT, &sigint_handler);

    int error = 1;
    unsigned attempts = 0;
    const unsigned MAX_ATTEMPTS = 240;

    while (attempts<MAX_ATTEMPTS) {
        error = xscope_ep_connect("localhost", argv[1]);
        if (0 == error) {
            break;
        }
        sleep(1);
        attempts++;
    }

    if (error) {
        fprintf(stderr, "xscope_ep_connect: failed %d attempts\n", attempts);
        return 1;
    }
    running = 1;
    while (running) {
        sleep(1);
    }
    xscope_ep_disconnect();
    return 0;
}

Target program#

Listing 13 main.xc#
#include <platform.h>
#include <xscope.h>

extern "C" {
    void main_tile0(chanend);
}

int main (void)
{
    chan xscope_chan;
    par
    {
        xscope_host_data(xscope_chan);
        on tile[0]: main_tile0(xscope_chan);
    }
    return 0;
}
Listing 14 test.c#
void xscope_user_init(void) {
    xscope_register(2,
        XSCOPE_CONTINUOUS, "V", XSCOPE_INT, "mV", /* Probe 0 */
        XSCOPE_CONTINUOUS, "I", XSCOPE_INT, "mA", /* Probe 1 */
    );
}

void main_tile0(chanend_t xscope_end)
{
    xscope_mode_lossless();
    xscope_connect_data_from_host(xscope_end);

    xscope_int(0, 45);              /* Send 45 to probe 0 */

    // Read response from host
    int bytes_read = 0;
    SELECT_RES(CASE_THEN(xscope_end, read_host_data)) {
        read_host_data: {
            xscope_data_from_host(xscope_end, (char *)buffer_ptr, &bytes_read);
        }
    }
    xscope_int(1, 578);             /* Send 578 to probe 1 */

    // Read response from host
    int bytes_read = 0;
    SELECT_RES(CASE_THEN(xscope_end, read_host_data)) {
        read_host_data: {
            xscope_data_from_host(xscope_end, (char *)buffer_ptr, &bytes_read);
        }
    }
}

Specifying a port number for xgdb and the user host program#

An example of an explicitly chosen port number is:

xgdb -ex "connect --xscope-port-blocking --xscope-port localhost:45678"  led-flash.xe

Allow xgdb to choose a port number and bind - avoiding a race condition#

It is often difficult to choose a port number and avoid the race condition where another program on the host computer binds to that number. This race can be prevented by allowing xgdb to choose the port number, and bind to it (which is an atomic operation and prevents another program from using that number). xgdb prints the port number it has used, which is then passed to the host program. The following example shows the xgdb this:

$ xgdb -ex "connect --xscope-port-blocking --xscope-port :"  led-flash.xe

See xSCOPE performance figures for benchmarks on xSCOPE performance.

Sample-based profiling of the target program#

The tools provide a mechanism to profile a target program and report the time spent executing its lines and functions, as a flat call graph. It does this non-intrusively by sampling at a low frequency, which might vary considerably, the program counter of each logical core. The samples are captured in a set of gprof data files, and a report generated with the tools xgprof.

This approach is useful for gaining insight into the behaviour of certain types of program, for example those which carry out a repetitive task. It may be useful for debugging a program which is failing to run as intended.

Capturing the sample data#

Run and capture sample data using the --gprof option to the connect command to xgdb. When xgdb is quit a set of gprof files (with the extension .gprof) will be written in the current working directory. The filename of each gprof file indicates the tile and logical core which it covers. For example, start capture with:

$ xgdb -ex "connect --gprof" -ex load -ex continue CircularBuffer.xe

Leave xgdb running for a period to capture samples, interrupt it with Ctrl-C and exit xgdb with the quit command. On exit the gprof profile data files will be written to the current working directory.

Analysing the profile data#

Spit the target program (.xe) file using the xobjdump -s to obtain the Elf files for each tile. For example:

$ xobjdump -s CircularBuffer.xe

For the next step, the Elf image_n0c0_2.elf is used for tile 0 analysis, the Elf image_n0c1_2.elf is used for tile 1 and so on. Ignore Elf images without the _2 suffix (these are bootstrap images used to provide system initialisation).

Generate a flat profile report for a logical core with the tool xgprof, supplying the Elf for the tile and the gprof file for the logical core of the tile. It is typically necessary use a selection of report levels to understand the behaviour of the target program. For example, a summary report may be shown with:

$ xgprof -b image_n0c0_2.elf  tile[0]_core0.gprof

A detailed report at the source line level may be shown with:

$ xgprof -l -b image_n0c0_2.elf tile[0]_core0.gprof

A very detailed report at the address level with hit-counts may be shown with:

$ xgprof -C -l -b image_n0c0_2.elf tile[0]_core0.gprof

Profiling a target program which boots from flash#

The following command may be used to capture profile data for a system which booted from flash:

$ xgdb -ex "attach --gprof" -ex "continue" test.xe

where test.xe was used to build the flash image (or to build the upgrade image within the flash device) and is currently executing.

Leave xgdb running for a period to capture samples, interrupt with Ctrl-C and exit xgdb with the quit command. On exit the gprof profile data files will be written to the current working directory.

Follow the steps described above to analyse the data files.

Target errors and warnings#

xSCOPE not supported#

The following message may be shown when xrun or xgdb is launched with the --xscope option. This occurs because the application does not make the call xscope_config_io(XSCOPE_IO_BASIC) from a function named xscope_user_init()

XScope connection was requested with '--xscope', but support does not appear to be
compiled into program (or symbols are missing). JTAG IO will be used. See -fxscope compiler option.

This implies any host-IO will be transported over the JTAG interface which is highly intrusive to the target program.

Failure to parse XN file#

When xrun or xgdb connects and loads a program to the target it configures the target using the target XN file (and associated configuration files) supplied to xcc with the -target option.

If the following message is shown the clocks and clock dividers in the target will not be set correctly and the target program may not function:

Warning: could not parse XN file, error /tmp/.xgdb21287-I8WMQBQG/platform.xn:11 Error: XN11101 Configuration file for node type "XTAG4" not found.
, PLL will not be set to expected value

This may be because a local XN file and configuration file was used to build the target program. In the example above the file XTAG4.cfg could not be found in the tools installation. The location of these local XN and configuration files may be specified by setting the search path environment variables XCC_TARGET_PATH and XCC_DEVICE_PATH respectively. For example, on a Linux host, the following command adds the current working directory to the paths that will be searched:

$ XCC_TARGET_PATH=. XCC_DEVICE_PATH=.:${XCC_DEVICE_PATH} xgdb …

Command examples#

XGDB examples#

In the following examples xgdb commands are often supplied as a sequence of -ex options on the xgdb command line. But the they may also be supplied in a command file or typed interactively at the gdb prompt. Commands may be abbreviated for convenience, but abbreviated forms must not be ambiguous.

Load and run a program#

The following example connects to a target, loads the target program test.xe into RAM and starts it running. Once launched the program must be interrupted with a Ctrl-C action if it does not terminate, either to quit xgdb or to enter further xgdb commands. A Ctrl-C action is made by the holding down both the Ctrl key and the C key on the keyboard:

$ xgdb -ex connect -ex load -ex continue test.xe

Note the load command runs two phases. The first phase loads a setup image (which is automatically generated by the tools) to the target SRAM which is executed to initialise it. The second phase loads the target program which was built from the user’s source code.

Breakpoints#

A breakpoint may be set symbolically or with a numerical address to stop execution of all tiles when the control flow of a logical core reaches that address. The gdb prompt is shown along with a diagnostic message indicating the reason the program stopped.

The xgdb command break inserts a soft breakpoint in RAM. There is no limit to the number of soft breakpoints that may be set. A soft breakpoint is implemented by writing a dcall instruction to the breakpoint address in the RAM of the tile.

For example:

(gdb) break my_func
(gdb) break *0x80402

In some cases a soft breakpoint cannot be used, for example where a program will be loaded to RAM over an external link after the breakpoint is set. The xgdb command hbreak can be used. This will use the hardware emulation debug feature within the tile to set a breakpoint. A maximum of three hardware breakpoints may be set:

(gdb) hbreak my_func

Watchpoints#

XGDB may set watchpoints (also known as data breakpoints) to stop all tiles when an access is made to a watched address. Two types of watchpoint command are supported:

watch <location>

stops execution when a store occurs to the specified location

awatch <location>

stops execution when store occurs to or a load occurs from the specified location

xgdb infers the address range to watch based on the type of the argument <location>.

For example, if my_counter is declared as type int in the target program the following will watch for write accesses only to its 4-byte range:

(gdb) watch my_counter

The following will watch for write and read accesses only to my_counter:

(gdb) awatch my_counter

A watch may be set on an address with a defined range. The following sets a watch on address 0x80250 with a range of 8 bytes:

(gdb) watch  (char [8]) *0x80250

The debug hardware which provides watch support monitors the address issued by a load or store instruction, checking whether it is greater than or equal to the lower bound and less than or equal to the upper bound. If the lower bound is the address of the third byte of a word, and the upper bound is the address of the fourth byte of the word, and a 2-byte store is made to the address of the third byte the watch will trigger. But if a 4-byte store is made to the address of first byte the watch will not trigger (although this store will write to the third and fourth byte which is being watched).

If a watch it is set on a global or static variable before the program is started it may be triggered when the startup code in the function _start() performs initialisation.

Attaching to a running target#

It is possible to perform symbolic debugging on a target which already has an application running. Such as if it has booted from flash, or if XRUN or XGDB had previously started a program then detached. The attach command can be used:

xgdb -ex "attach --adapter-id pr1V0_15"  led-flash.xe

If the target application was built to perform host-IO over JTAG (for example, by making a call to printstrln()) this will be enabled. XSCOPE communication will not function (See xSCOPE FAQ).

Attaching to a running target and capture data to generate a sample-based profiling report#

The following command can be used to attach to a system which is running and collect profile data without intrusion:

$ xgdb -ex "attach --gprof --adapter-id pr1V0_15" -ex "continue"  led-flash.xe

xrun examples#

Listing available xTAGs#

The -l option to the tool xrun will list all attached xTAGS, showing:

  • The integer value that may be supplied to the --id option to xrun or to the xgdb connect command

  • The xTAG type

  • The unique adapter-id string which may be supplied to the --adapter-id option to xrun, to the xgdb command connect or to the xflash option --adapter-id <>

  • The type of target connected to the xTAG. XS2A indicates an XCORE-200 XS2A architecture and XS3A indicates an xcore.ai XS3A architecture. The digits in ‘[]’ indicate the number of devices (XMOS nodes) (note there may be multiple in a package). A single 0 indicates one device.

% xrun -l
Available XMOS Devices
----------------------
  ID    Name                    Adapter ID      Devices
  --    ----                    ----------      -------
  0     XMOS XTAG-3             .BT0u0X2        XS3A[0]
  1     XMOS XTAG-4             BEJMRJ7V        XS2A[0]
  2     XMOS XTAG-3             KAKqyceA        XS2A[0]
  3     XMOS XTAG-4             pr1v0_20        XS3A[0]

A device is described as “In Use” if a currently running host tool is using it. In some cases, after interrupting a session, an xgdb process may be left without a parent (orphaned), and it continues to hold its xTAG. On Linux hosts the orphaned process should be killed with the command kill and if this fails, with kill -9.

If the device is described with “Invalid firmware” is was last used by a host tool from a different tools release (and may be used again by the same tool). If a connection is made to the device with xrun or xgdb the firmware will be replaced.

Dump the target state#

The following will dump the state of the target:

$ xrun --dump-state test.xe

where test.xe is the target program that was launched on the target by an invocation of xrun or was burned to flash with the xflash tool.

The following will dump the state of the target without a .xe file:

$ xrun --dump-state-no-xe

Note in both cases all tiles will be put in their debug mode which will stop execution of all logical cores. They will be resumed after the state has been dumped (although, if they have hit an exception, xrun will not take them out of the exception.)

Reboot an xTAG which fails to respond#

The --xtag=reboot option to the xgdb command connect will force the xTAG reboot:

$ xgdb -ex "connect --xtag=reboot"

If the xTAG is flagged in use by xrun -l the above command will release it. Note this reboot feature is not available on Windows due to limitations in the standard Windows USB driver.