# 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** (`BOARD=host`) | a C compiler — `gcc` or `clang`. Nothing else. | | **an emulator** (QEMU boards) | QEMU + the target's cross-compiler, e.g. `qemu-system-riscv32` + `riscv-none-elf-gcc`, or `qemu-system-aarch64` + `aarch64-none-elf-gcc`. | | **real hardware** | the board's cross-toolchain + its flash tool. See [board-bringup.md](board-bringup.md). | Everything below is run from the repository root. To see every board you can target: ```sh make -C examples/threads boards ``` ## 2. Run your first kernel (on your desktop) The [`threads`](../../examples/threads) example brings up the kernel and runs two threads. Run it natively: ```sh 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: ```sh 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](../architecture/board-contract.md): 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: ```sh 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`](../../examples/threads/main.c) — it's commented as a guided tour. Every Revera program follows the same six steps: ```c #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 `arg` you 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 at `ARCH_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`: ```sh mkdir -p examples/hello ``` `examples/hello/Makefile`: ```make PROJECT := hello SRCS := main.c include ../../make/tk.mk ``` Put your code in `examples/hello/main.c` (start from the skeleton above), then: ```sh 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/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: ```sh 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`](../../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](examples.md)** — one example per feature (sync, isolation, SMP/AMP, trace, faults…). - **[Public API reference](../reference/api.md)** — the stable 0.1.0 surface, per symbol. - **[Configuration knobs](../../kernel/tk_config.h)** — every `TK_CONFIG_*`. - **[Architecture docs](../architecture/)** — how the scheduler, sync, timekeeping, SMP, and the isolation fence work. - **[Board bring-up](board-bringup.md)** / **[Arch porting](arch-porting.md)** — add a new board or CPU. - **[The isolation differentiator](../architecture/isolation/)** — per-thread and per-island memory fencing, Revera's distinguishing feature.