# Memory Management and Footprint > **The criterion.** Resource constraints dictate viability: static compile-time allocation (no heap, no > fragmentation), a small ROM/RAM footprint (often 2–10 KB for a tight kernel), and clean MPU integration to > separate kernel from user threads. ## How Revera answers it Revera does **no dynamic allocation** — there is no kernel heap. Every object is either a static pool (threads, semaphores, mutexes, condition variables) or **caller-provided** memory (you hand each thread its own stack). That eliminates heap fragmentation and out-of-memory failures by construction, and makes the footprint a compile-time constant you can see and bound. MPU integration — separating kernel RAM and each thread's stack from unprivileged code — is Revera's headline; it has its own axis ([Memory Protection & Isolation](memory-protection-isolation.md)). **A real figure:** a complete minimal two-thread application — kernel + CPU port + board + app — links to **~3.3 KB of code** (`text`) under the `nano` profile on RISC-V RV32 (measured with `make ... size`). RAM is dominated by the stacks *you* size, so it is yours to control. Measure your own build with `make size`; the kernel publishes no number it can't back on your target. ## Feature · how to turn it on · how to use it · where it works | Feature | Turn on with | Use these APIs | Where | |---|---|---|---| | Static thread stacks | — | `TK_THREAD_STACK(name, cells)` (caller-owned, ADR 0001 cells) | all | | Static kernel-object pools | `TK_CONFIG_MAX_THREADS` / `_SEMAPHORES` / `_MUTEXES` / `_CONDS` | `tk_sem_create` / `tk_mutex_create` / `tk_cond_create` | all | | No dynamic allocation | default (there is no heap) | — | all | | Footprint control | `PROFILE=profiles/tk_profile_nano.h` | `make -C BOARD= size` | all | | MPU kernel/thread separation | see the isolation axis | `TK_THREAD_STACK`, `TK_CONFIG_ENABLE_MPU_ISOLATION` | MPU arches | *Full signatures and contracts: [API reference](../reference/api.md).* ## Limits & roadmap - The no-heap design is deliberate (a feature, not a gap): if you need dynamic memory, bring your own allocator at the application layer. - Pool sizes and stack sizes are compile-time; sizing a working thread at `ARCH_MIN_STACK_SIZE` (the bare context-switch floor) is a common mistake — size for the work the thread does. ## Learn more - **How it works:** [Memory Protection & Isolation](memory-protection-isolation.md) · [kernel tiers](../architecture/kernel-tiers.md). - **Measure it:** `make -C examples/threads BOARD= PROFILE=../../profiles/tk_profile_nano.h size`. - **Full API:** [API reference](../reference/api.md).