First RTEMS boot¶
This walkthrough takes you from zero to a real RTEMS hello-world running on the emulator, using the RCC 1.3.2 SPARC cross-toolchain.
Prerequisites¶
- A working build of Lince (see Installation).
- The RCC 1.3.2 toolchain installed under
/opt/rcc-1.3.2-gcc/. The path is hard-coded in the test build scripts; if you install elsewhere, setRCC_PREFIXaccordingly.
1. Build or obtain the hello-world image¶
The repository includes a pre-built binary at tests/rtems/bin/hello-world.elf.
If you want to rebuild it from source, use the RCC toolchain:
# From the repository root (requires sparc-gaisler-rtems5-gcc on PATH):
cmake --build build --target sparc_test_binaries
# The cross-compiled ELF ends up in the build directory.
You can also use your own RCC toolchain and link script to produce a
compatible ELF — just place it at tests/rtems/bin/hello-world.elf for
the integration tests to find it.
The RTEMS BSP leon3 is configured without MMU (default for the
MVP) and without networking. The image links a single user task that
calls printf("Hello World\n") and exits cleanly.
2. Run it¶
Expected output:
*** BEGIN OF TEST HELLO WORLD ***
*** TEST VERSION: 5.x.y
*** TEST STATE: EXPECTED-PASS
*** TEST BUILD:
*** TEST TOOLS: 7.5.0 20191114 (RCC 1.3.2 [bcc-2.2.2-gcc])
Hello World
*** END OF TEST HELLO WORLD ***
The CLI returns exit code 0 when the simulated time budget expires
naturally. RTEMS itself never calls exit() in this configuration; it
returns to the idle thread, which immediately enters power-down via
asr19. The emulator's idle-time skip
then fast-forwards simulated time to the deadline.
3. Run the SPTEST integration suite¶
The repository ships ten SPARC RTEMS sptests as pre-built ELFs
(in tests/rtems/sptests/bin/, generated by a build script):
A sptest is recorded as PASS when its captured UART contains the
exact string *** END OF TEST. As of the MVP all 10 of sp01, sp02,
sp03, sp04, sp05, sp06, sp07, sp08, sp11, sp12 pass.
4. Capture the UART programmatically¶
If you are integrating Lince in a CI pipeline, replace the default
StdoutCharDevice with the test-support CapturingCharDevice:
#include "lince/runtime/emulator.hpp"
#include "tests/support/capturing_char_device.hpp"
auto cap = std::make_unique<lince::test_support::CapturingCharDevice>();
auto* ref = cap.get();
emu->set_character_device(std::move(cap));
emu->initialize();
emu->load_elf("hello-world.elf");
emu->run_for(lince::SimTimeNs{2'000'000'000ULL});
if (ref->captured().find("*** END OF TEST") != std::string::npos) {
/* PASS */
}
See UART and console for more capture strategies.
What is happening under the hood?¶
The boot sequence on real GR712RC and on Lince is byte-identical:
_startruns from the ELF entry point (typically0x40000000).- The RTEMS bootstrap probes the MemCtrl (FTMCTRL) for memory layout, programs the GPTimer prescaler for a 1 ms tick, and unmasks IRQs at the IRQMP.
- The first user task is created and scheduled.
printfwrites through the APBUART data register; Lince's APBUart peripheral forwards every byte to the injectedICharacterDevice.- The task ends, the idle thread halts each CPU via
wr %g0, %asr19, and the emulator skips simulated time to the next pending event.
A trace comparator tool is planned for a future release to automate verification of instruction counts and MMIO sequences against a reference.