Getting started with Revera¶
This walks you from nothing to a running kernel — first on your desktop (no hardware, no cross-toolchain), then under an emulator, then your own first app. It should take about ten minutes.
Revera is a small real-time kernel: your application is C that you compile and link with the kernel into one program. There is no installer and no daemon — you build an example (or your own project) for a board and run it.
1. What you need¶
To run on… |
You need |
|---|---|
your desktop ( |
a C compiler — |
an emulator (QEMU boards) |
QEMU + the target’s cross-compiler, e.g. |
real hardware |
the board’s cross-toolchain + its flash tool. See board-bringup.md. |
Everything below is run from the repository root. To see every board you can target:
make -C examples/threads boards
2. Run your first kernel (on your desktop)¶
The threads example brings up the kernel and runs two threads. Run it natively:
make -C examples/threads BOARD=host run
You’ll see two lines repeating — one about every 100 ms, one about every 200 ms — each tagged with a distinct thread id and a timestamp that advances:
[tid=1 arg=100] iter=0 t=0 ms
[tid=2 arg=200] iter=0 t=0 ms
[tid=1 arg=100] iter=1 t=100 ms
...
Press Ctrl-C to stop. That’s the whole kernel — scheduler, threads, timekeeping, console — running on your
machine.
3. Run it under an emulator¶
The same source runs on a bare-metal target under QEMU. On RISC-V:
make -C examples/threads BOARD=qemu_riscv32_virt run # quit QEMU with Ctrl-A then X
or on 64-bit ARM (BOARD=qemu_arm64_virt). Nothing in main.c changed — only the board did. That is the
point of the board contract: the kernel and your app are portable; the
board fragment supplies the hardware.
4. Run the tests¶
The repo-root quality gate builds and runs the unit suites:
make test # host unit-test suites (no hardware, no cross-toolchain)
make test-arch # live-kernel context-switch + SMP under QEMU (needs cross-gcc + QEMU)
make test exits non-zero if any test fails, so it drops straight into CI.
5. Anatomy of the app¶
Open examples/threads/main.c — it’s commented as a guided tour. Every
Revera program follows the same six steps:
#include "tk_kernel.h"
#include "tk_time.h"
#include "tk_board.h"
#include "tk_console.h"
/* Every thread needs its OWN stack. Size it for the work the thread does — the context-switch frame,
* how deep it calls, and its locals. Cells are bytes (ADR 0001). */
static tk_stack_cell_t stack[1024];
static void* worker(void* arg)
{
for (;;) {
tk_print("hello from a thread\n");
tk_sleep_ms(500); /* blocks THIS thread and gives the CPU away — not a busy-wait */
}
return 0;
}
int main(void)
{
tk_board_init(); /* 1. clock + pins + UART — nothing works before this */
tk_console_init(TK_UART_CH_DEBUG); /* 2. point tk_print() at the debug UART */
tk_kernel_init(); /* 3. initialise the kernel (before creating threads) */
tk_time_init(); /* 4. zero the millisecond clock */
tk_thread_t* t = tk_thread_create(worker, NULL, stack, sizeof stack, TK_PRIO_MIN + 1u);
if (t == NULL) { return -1; } /* 5. create threads (always check the handle) */
tk_kernel_start(); /* 6. hand control to the scheduler — does not return */
return 0;
}
Two ideas worth internalising early:
A thread’s argument is not its identity. The
argyou pass is your data; the thread’s id (tk_thread_id(tk_thread_self())) is assigned by the kernel. Two threads can share an argument and still have different ids.Priority is a number, not a vague level. Higher = higher priority; equal priorities round-robin. Express priorities relative to
TK_PRIO_MIN(one step above the idle floor). Don’t size a working thread atARCH_MIN_STACK_SIZE— that’s only the bare context-switch floor, too small to call into.
6. Write your own app¶
A project is a directory with a main.c and a three-line Makefile:
mkdir -p examples/hello
examples/hello/Makefile:
PROJECT := hello
SRCS := main.c
include ../../make/tk.mk
Put your code in examples/hello/main.c (start from the skeleton above), then:
make -C examples/hello BOARD=host run
To build a project that lives outside the tree, point TK_DIR at the kernel and include from there — see
the header of make/tk.mk. make -C examples/hello print-config shows the resolved
board, arch, and flags.
7. Tuning the build (profiles + knobs)¶
The kernel ships minimal-safe by default (no MPU guard, no profiling, no unprivileged threads). Turn features on with compile-time knobs, or pick a ready-made profile:
make -C examples/threads BOARD=host PROFILE=../../profiles/tk_profile_nano.h run
Profiles range from tk_profile_nano.h (smallest) to tk_profile_full.h. Every knob — its values, default,
requirements, and effect — is documented in one place: kernel/tk_config.h. Ask
for hardware a board or arch can’t provide and the build fails loud at compile time, never silently.
Where to go next¶
Examples catalogue — one example per feature (sync, isolation, SMP/AMP, trace, faults…).
Public API reference — the stable 0.1.0 surface, per symbol.
Configuration knobs — every
TK_CONFIG_*.Architecture docs — how the scheduler, sync, timekeeping, SMP, and the isolation fence work.
Board bring-up / Arch porting — add a new board or CPU.
The isolation differentiator — per-thread and per-island memory fencing, Revera’s distinguishing feature.