Running SDK programs
qemu-system-hexagon can run SDK programs that normally run under
hexagon-sim. The boot image depends on the runtime the program expects:
Use case |
Initial image |
Subsequent stages |
|---|---|---|
SDK standalone OS |
|
Startup code calls the program’s |
SDK QuRT dynamic program |
|
QuRT loads |
SDK programs and semihosting
The simulator-compatible machines, such as V66G_1024 and
V68N_1024, provide semihosting by default. The SDK runtime uses
trap0 calls for services such as console I/O, host file access, and
program termination.
See Semihosting for more info.
The examples below use v68 SDK artifacts with -M V68N_1024.
Standalone OS programs
By default, hexagon-clang links a bare-metal executable with the SDK’s
standalone OS startup code and C runtime. This small runtime initializes
the machine, calls main(), and implements hosted services through
semihosting.
For example, save the following as prog.c:
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
With the SDK tools on PATH, build and run it with:
hexagon-clang -mv68 prog.c -o prog.elf
qemu-system-hexagon -M V68N_1024 -display none \
-kernel ./prog.elf -append "foo bar"
The program prints:
argv[0] = ./prog.elf
argv[1] = foo
argv[2] = bar
Guest command-line arguments
The example above passes the arguments with -append. QEMU uses the
-kernel filename as the first semihosting argument and splits
-append on spaces to supply the remaining arguments. The host shell
quotes keep foo bar together as the value of the QEMU option; the
guest runtime subsequently parses the semihosting command line.
You can instead specify the semihosting command line with arg= options:
qemu-system-hexagon -M V68N_1024 -display none -kernel ./prog.elf \
-semihosting-config 'enable=on,target=native,arg=./prog.elf,arg=foo,arg=bar'
Include the program name as the first arg= value.
target=native selects QEMU’s implementation of semihosting even when
a debugger is connected. To connect the semihosting console explicitly to
the terminal, add a character device and select it with chardev=:
qemu-system-hexagon -M V68N_1024 -display none \
-chardev stdio,id=semi \
-semihosting-config enable=on,target=native,chardev=semi \
-kernel ./prog.elf -append "foo bar"
QuRT programs and the SDK loader chain
An SDK QuRT dynamic test consists of three guest images:
runelf.pbnboots QuRT and loads a user process from a host file.run_main_on_hexagon_simis that process. It initializes the dynamic loader and loads the application’s shared object.userprog.soexportsmain(int argc, char **argv), which the runner invokes.
QEMU initially loads only runelf.pbn. The subsequent stages read the
other images through semihosting. Use matching SDK architecture variants
for the boot image, runner, and application. For example, with Hexagon
SDK 6.4 and its toolv19 v68 artifacts:
runelf="$HEXAGON_SDK_ROOT/rtos/qurt/computev68/sdksim_bin/runelf.pbn"
runner="$HEXAGON_SDK_ROOT/libs/run_main_on_hexagon/ship/hexagon_toolv19_v68/run_main_on_hexagon_sim"
qemu-system-hexagon -M V68N_1024 -display none \
-kernel "$runelf" -append "$runner -- ./userprog.so foo bar"
Build userprog.so with the SDK’s QuRT shared-library build rules,
including any libraries needed by the application, and place its shared
dependencies where the SDK dynamic loader can find them.
The command line exposed through semihosting is:
<runelf.pbn path> <runner path> -- ./userprog.so foo bar
The fields have the following roles:
Field |
Consumer |
Meaning |
|---|---|---|
<runelf.pbn path> |
SDK startup |
Boot image name |
<runner path> |
runelf.pbn |
Process ELF to load |
– |
run_main_on_hexagon_sim |
End of runner options |
./userprog.so |
Dynamic loader |
Shared object exporting main() |
foo bar |
Application |
argv[1] and argv[2] |
The application’s argv[0] is ./userprog.so. When translating an
SDK simulator command runelf.pbn -- runner -- userprog.so, omit the
separator immediately after runelf.pbn from QEMU’s -append value.
The separator after the runner remains part of the guest command line.
The equivalent explicit semihosting configuration is:
qemu-system-hexagon -M V68N_1024 -display none -kernel "$runelf" \
-semihosting-config "enable=on,target=native,arg=$runelf,arg=$runner,arg=--,arg=./userprog.so,arg=foo,arg=bar"