blob: dca8af27c47748b58a52d7fc13252b0c085073ac [file] [log] [blame] [view]
Hello World example
===================
This example shows a simple hello-world firmware image, with a single thread and a single compartment.
This uses the debug facilities to write a message directly to the UART.
The [`xmake.lua`](xmake.lua) file contains the build instructions for this example.
This file contains two libraries (one providing `memcpy`, the other `clz`) that can be used by multiple compartments, and a single compartment (beyond the RTOS components).
The code for the compartment is all in [`hello.cc`](hello.cc).
This file first imports the debug facilities:
```c++
using Debug = ConditionalDebug<true, "Hello world compartment">;
```
The `ConditionalDebug` template is intended to allow the first argument to be an expression that may include macro definitions so that debugging can be selectively enabled for subsets of a program at build time.
For now, we're just enabling it unconditionally so that we can use its `log` method to write to the UART.
This will, indirectly, use the `MMIO_CAPABILITY` macro, which imports a memory-mapped I/O device, the target platform's default UART.
Our example compartment will be granted direct access to the UART, which it can then use from its entry point function, `say_hello`.
Note that the definition of this function uses a macro to indicate the compartment that it is in (`"hello"`).
This macro is normally used on function definitions, rather than declarations, and allows the compiler to either export the function when it is defined or insert cross-compartment calls when it is used when compiling code for another compartment.
We also include the SDK header `fail-simulator-on-error.h`. This defines a
simple [compartment error handler](../docs/ErrorHandling.md) that reports any
unexpected errors and ends the simulation with exit code 1 (FAILURE). This is
necessary because the default behaviour would silently exit the thread,
potentially hiding errors.