What is semihosting? …Examples of these facilities include keyboard input, screen output, and disk I/O. For example, you can use this mechanism to enable functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host instead of having a screen and keyboard on the target system…
So you need to output some debug messages via your host debugging session (via JTAG or such) or working with QEMU to prototype some ARM code? Well semihosting is simple use, but it can come at a large price in memory and overhead if you use stdio to do it…
You can skip the “#include <stdio.h>” and linking the semihosting newlib library (assuming you have the syscalls inplementated) and just use some simple inline assembly to get the job done.
Lets take a quick look at two of the twenty-some service calls (SVC) that are available, SYS_WRITEC (0x03) and WRITE0 (0x04).
* SYS_WRITEC outputs a single character, an address pointer to that character is loaded in register R1. Register R0 is loaded with 0x03 and then you can execute a SuperVisor Call (SVC 0x00123456).
* SYS_WRITE0 outputs a null-term string, the string’s beginning address is stored in R1, R0 is loaded with 0x04 and you execute a supervisor call again.
If we translate that knowledge into inline assembly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Note: This is not pretty inline styling as it is meant to break each step down. Normally you would create a couple of functions (i.e: a ‘PutChar’ for SYS_WRITEC) and include the R0/R1 clobbers, etc…
And the output that we get:
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
PS: SYS_TMPNAM and SYS_READC are not implemented in Qemu (up to and including 1.7.0), so consult the “qemu/target-arm/arm-semi.c” source if you are have questions about how those SVC calls are implemented.