memkit targets embedded systems on MCU and MPU — bare-metal firmware and embedded-Linux/MPU-class hosts share the same container cores; compile-time flags choose static/arena vs heap/virtual backing. This guide walks through the 80% path for each target: static storage on MCU, virtual arena + tier-2 C on MPU. For the full API see README. To pick a container see CONTAINER_GUIDE.md.
Both MCU and MPU are first-class. make all defaults to MCU because it is the most constrained build, not because MPU is optional.
| You are… | Start here |
|---|---|
| New to memkit — want the “why” | Design philosophy |
| STL vs memkit, MCU/MPU flags, vendoring one container | Adoption guide |
| Bare-metal / RTOS firmware (MCU) | C++ on MCU or C on MCU |
| Embedded Linux, edge gateway, MPU dev host | MPU builds |
| Runnable examples | Examples |
| Choosing a container | CONTAINER_GUIDE.md |
| RTOS, ISR, or multi-task sharing | CONCURRENCY.md |
Include one header, use a static array for storage, check memkit::ok() on init and mutating calls.
#include <memkit/memkit.hpp>
struct sensor_sample {
std::uint32_t timestamp_ms;
std::int16_t value;
};
int main()
{
memkit::stl::array<sensor_sample, 16> storage{};
memkit::Queue<sensor_sample> samples;
if (!memkit::ok(samples.init(storage))) {
return 1;
}
const sensor_sample s{100u, 42};
if (!memkit::ok(samples.push_back(s))) {
return 1;
}
const auto front = samples.try_peek_front();
if (front.has_value()) {
// use front->timestamp_ms, front->value
}
return 0;
}Next steps: examples/example_mcu.cpp, tests/test_stack_queue_cpp.cpp, README C++ API.
Tier 1 C containers: arena, ring, queue, vector, stack, bitset, objpool, handle_pool.
Use memkit_helpers.h to skip boilerplate:
#include <memkit.h>
#include <memkit_helpers.h>
typedef struct sensor_sample {
uint32_t timestamp_ms;
int16_t value;
} sensor_sample_t;
int main(void)
{
MEMKIT_ELEM_STORAGE(sensor_sample_t, 16, queue_buf);
queue_t queue;
if (!queue_status_ok(MEMKIT_QUEUE_INIT_STATIC(&queue, sensor_sample_t, queue_buf))) {
return 1;
}
const sensor_sample_t sample = {100u, 42};
if (!queue_status_ok(queue_push(&queue, &sample))) {
queue_deinit(&queue);
return 1;
}
sensor_sample_t out = {0};
if (!queue_status_ok(queue_pop(&queue, &out))) {
queue_deinit(&queue);
return 1;
}
queue_deinit(&queue);
return 0;
}When the buffer is full, drop the oldest entry instead of failing:
MEMKIT_ELEM_STORAGE(sensor_sample_t, 8, log_buf);
ring_t log;
MEMKIT_RING_INIT_STATIC_OVERWRITE(&log, sensor_sample_t, log_buf);Allocate several containers from one bump arena:
static uint8_t arena_backing[1024];
arena_t arena;
MEMKIT_ARENA_INIT_STATIC(&arena, arena_backing);
ring_t *ring = NULL;
ring_create(&ring, sizeof(sensor_sample_t), 8u, &arena, RING_FLAG_OVERWRITE_ON_FULL);
/* … use ring … */
ring_destroy(ring);
arena_deinit(&arena);Next steps: examples/example_mcu_c.c, tests/test_queue_c.c, README C API.
MPU builds target embedded Linux services (Yocto, Buildroot, edge gateways) and MPU dev hosts — not general desktop apps. They enable heap, virtual-memory arenas, growable policies, and tier-2 C containers (hashmap, btree, deque, …). Use EMBEDDED_LINUX=1 on Linux embedded images; macOS and Windows use MEMKIT_MPU=1 alone. Arena virtual backing is POSIX mmap on Unix and VirtualAlloc on Windows.
make mpu
./build/example_mpu
./build/example_mpu_cTypical MPU pattern — virtual-memory arena and *_create:
#include <memkit.h>
arena_t *arena = NULL;
arena_create(&arena, 262144u); /* default virtual backing on MPU */
hashmap_t *map = NULL;
hashmap_create(&map, sizeof(uint32_t), sizeof(int32_t), 16u,
HASHMAP_STRATEGY_CHAINING, arena, HASHMAP_FLAG_GROWABLE);
hashmap_destroy(map);
arena_destroy(arena);C++ MPU: same 32 utilities as MCU; add mmap_arena, heap_arena, growable policies, and tier-2 C *_create helpers.
#include <memkit/memkit.hpp>
auto backing = memkit::memory::mmap_storage::map(4096u);
memkit::memory::mmap_arena arena{std::move(backing)};
memkit::Ring<log_line> logs;
logs.init_from_arena(arena, 32u, memkit::ring_policy::overwrite_on_full);All 14 C containers and arena_t are available with full tier-2 support on MPU. They delegate to the same cores as C++. The 18 C++-only utilities (lock-free trio, ByteRing, …) require #include <memkit/memkit.hpp> — there are no C bindings. See C API reference — parity.
Heap-backed arena (C++):
#include <memkit/memkit.hpp>
auto backing = memkit::memory::heap_storage::allocate(4096u);
memkit::memory::heap_arena arena{std::move(backing)};
memkit::Ring<int> log;
log.init_from_arena(arena, 16u, memkit::ring_policy::overwrite_on_full);Next steps: examples/example_mpu.c, examples/example_mpu.cpp, tests/test_hashmap_c.c, tests/test_heap_arena_cpp.cpp.
git clone https://github.com/NetKit-Labs/memkit.git
cd memkit
make all # MCU: lib + tests + 4 MCU examples
make mpu # MPU: tier-2 C tests + heap arena test + 2 MPU examples + integration testcmake -B build # MCU
cmake -B build -DMEMKIT_EMBEDDED_LINUX=ON # MPU on embedded Linux
cmake -B build -DMEMKIT_MPU=ON # MPU (Linux, macOS, Windows)
cmake --build build
ctest --test-dir buildOn Windows, -DMEMKIT_MPU=ON uses VirtualAlloc for arena backing (no EMBEDDED_LINUX required).
include(FetchContent)
FetchContent_Declare(
memkit
GIT_REPOSITORY https://github.com/NetKit-Labs/memkit.git
GIT_TAG v0.2.4
)
FetchContent_MakeAvailable(memkit)
add_executable(my_firmware main.c)
target_link_libraries(my_firmware PRIVATE memkit)
target_compile_definitions(my_firmware PRIVATE MEMKIT_MCU=1)Add -I paths are handled by the memkit target (target_include_directories is PUBLIC).
If you ship prebuilt objects to C-only MCU firmware, build the freestanding archive:
make lib-mcu-c # build/libmemkit_mcu_c.a
make check-lib-mcu-c # verify no libstdc++ symbols
make test-lib-mcu-c-link # smoke-test: link with cc onlyCustomers link with cc, not c++, and do not need -lstdc++. See DISTRIBUTING_MCU_C.md.
- Add
-DMEMKIT_MCU=1(MCU), or-DMEMKIT_MPU=1withEMBEDDED_LINUX=1on embedded Linux, or-DMEMKIT_MPU=1alone on Windows/macOS host MPU builds. - For C++ firmware, compile with
-fno-exceptions -fno-rtti(set automatically by Makefile/CMake). - Link the static
memkitlibrary (arena.cpp,mmap_backing.cpp,c_api/bindings.cpp). - Include
<memkit/memkit.hpp>(C++) or<memkit.h>/ individual*.h(C). All C headers includememkit_config.hfor target flags. - Prefer static storage on MCU; use arena when several containers share one buffer.
- Always check status (
memkit::ok,*_status_ok). - Size buffers yourself — use
MEMKIT_ELEM_STORAGEor equivalent so capacity is explicit; see Design philosophy — bounds and sizing. - Concurrency: memkit is zero-overhead and OS-agnostic — lock-free trio vs single-threaded containers; Cortex-M0/M0+ cannot use the lock-free trio.
| Mistake | Fix |
|---|---|
Using Ring when you want strict FIFO |
Use Queue — ring can overwrite; queue returns FULL |
Using queue_t / Queue from an ISR |
Not safe — use SpscQueue / MpscQueue (C++) or RTOS queue; see CONCURRENCY.md |
| Two tasks sharing one container without a lock | Single owner per instance, or wrap with your RTOS mutex |
Forgetting ring_deinit / queue_deinit |
Call deinit for *_init; *_destroy for *_create |
uint8_t storage with strict alignment types |
Use MEMKIT_ELEM_STORAGE(type, cap, name) |
| Tier-2 C API on MCU | Use C++ headers or stick to tier 1 in C |
| Ignoring status codes | Check every init/push/pop; use memkit_*_status_string during bring-up |
| Target | Build | Examples |
|---|---|---|
| MCU | make all |
example_mcu.cpp, example_mcu_c.c, example_embedded_patterns.cpp, example_comm_pipeline.cpp |
| MPU | make mpu |
example_mpu.cpp, example_mpu.c (+ test_c_api_extended.c integration test) |
See README § Examples for what each demo covers.
- CONCURRENCY.md — RTOS/ISR contract, lock-free trio, FreeRTOS patterns
- ADOPTION_GUIDE.md — STL mapping, build flags, ownership, piecemeal / prebuilt
.aintegration - C_API_REFERENCE.md — C config fields, flags, and function parameters
- CXX_API_REFERENCE.md — C++ init overloads, policies, methods
- DESIGN_PHILOSOPHY.md — MCU vs MPU, memory models, C/C++ and STL policy
- CONTAINER_GUIDE.md — which container for your use case
- DISTRIBUTING_MCU_C.md — ship prebuilt C API lib without libstdc++
- README — complete API reference
examples/example_mpu.cpp,examples/example_mpu.c— MPU virtual arena + tier-2 C pathexamples/example_embedded_patterns.cpp— DMA, MPSC, calibration, bit streams (MCU)examples/example_comm_pipeline.cpp— ByteRing + SPSC + TokenBucket (MCU)