mirror of
https://github.com/ruvnet/RuView
synced 2026-07-31 18:51:42 +00:00
feat(firmware): scaffold ruv_temporal ESP-IDF Rust component (ADR-095 Phase 4, #513)
Phase 4 of the #513 roadmap: ESP-IDF component skeleton at `firmware/esp32-csi-node/components/ruv_temporal/`. Source is complete and self-consistent; cross-compile to xtensa-esp32s3-none-elf is blocked by a known-broken esp-rs nightly snapshot (details in the component README). What's in the scaffold: - `Cargo.toml` — staticlib, no_std + alloc, deps on the path-vendored `ruvllm_sparse_attention` (matching ADR-096's host-side dep) and `esp-alloc`/`critical-section` for the no_std allocator and lock primitives. - `src/lib.rs` — public C ABI (init / push / classify / destroy / self_test) with `#[no_mangle]` exports, a `[#used]` keepalive table to defeat aggressive linker stripping, esp-alloc as the global allocator (heap region added at runtime by the firmware), and a loop-on-panic handler (Phase 5 will route through esp_system_abort). - `src/window.rs` — `FrameRing`, the rolling-window buffer that `ruv_temporal_push` writes to. Chronological iteration via `iter_chronological()` so the kernel sees oldest-first. - `include/ruv_temporal.h` — the public C header consumed by edge_processing.c. Threading contract documented inline (single dedicated FreeRTOS task, no internal locks). - `CMakeLists.txt` — runs `cargo +esp build` as an ESP-IDF pre-component-register step, then registers the static library through `idf_component_register` + `target_link_libraries(... INTERFACE ...)`. `shim.c` exists only because `idf_component_register` requires SRCS. - `.cargo/config.toml` + `rust-toolchain.toml` — pin the build to `xtensa-esp32s3-none-elf` and the `esp` toolchain channel so `cargo build` without flags Just Works once the toolchain is unblocked. - `README.md` — Phase status table, Phase 5 toolchain blocker explanation, and the espup install fix. ABI calls into edge_processing.c (Phase 6) and COM8 validation (Phase 7) follow once the cross-compile is unblocked. Closes nothing yet; advances #513. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* ESP32-S3 on-device temporal head — public C ABI (ADR-095, #513).
|
||||
*
|
||||
* Consumed by edge_processing.c / adaptive_controller.c. Backed by a
|
||||
* Rust staticlib that wraps `ruvllm_sparse_attention`. See
|
||||
* components/ruv_temporal/src/lib.rs for the implementation.
|
||||
*
|
||||
* Threading: NOT internally synchronised. Per ADR-095 §3.3 callers run
|
||||
* a single dedicated FreeRTOS task that owns the context and
|
||||
* serialises push() and classify(). init() and destroy() are NOT safe
|
||||
* against concurrent push/classify on the same handle.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct RuvTemporalCtx ruv_temporal_ctx_t;
|
||||
|
||||
/* Allocate a temporal-head context.
|
||||
*
|
||||
* weights — flat-buffer of model weights (Phase 5 wires the format),
|
||||
* may be NULL during Phase 4 scaffolding.
|
||||
* weights_len — bytes of `weights`, 0 if weights is NULL.
|
||||
* input_dim — feature dimension per frame (e.g. 60 for rv_feature_state_t).
|
||||
* window_len — number of frames in the rolling window (e.g. 256).
|
||||
* n_classes — output logit count (e.g. 4 for gesture, 3 for fall).
|
||||
* out_ctx — receives the new context pointer on ESP_OK.
|
||||
*
|
||||
* Returns ESP_OK on success, ESP_ERR_INVALID_ARG for null/zero inputs,
|
||||
* ESP_ERR_NO_MEM if buffer allocation fails.
|
||||
*/
|
||||
esp_err_t ruv_temporal_init(const uint8_t *weights,
|
||||
size_t weights_len,
|
||||
uint32_t input_dim,
|
||||
uint32_t window_len,
|
||||
uint32_t n_classes,
|
||||
ruv_temporal_ctx_t **out_ctx);
|
||||
|
||||
/* Push one feature frame into the rolling window. Hot path — cheap,
|
||||
* no allocation. `frame` must point to at least `input_dim` floats.
|
||||
*/
|
||||
esp_err_t ruv_temporal_push(ruv_temporal_ctx_t *ctx, const float *frame);
|
||||
|
||||
/* Run the temporal-head forward and write `n_classes` class logits
|
||||
* into the caller-owned `logits` buffer (must be at least n_classes
|
||||
* floats). `n_classes` must match the value passed to init().
|
||||
*/
|
||||
esp_err_t ruv_temporal_classify(ruv_temporal_ctx_t *ctx,
|
||||
float *logits,
|
||||
uint32_t n_classes);
|
||||
|
||||
/* Release a context allocated by ruv_temporal_init. Safe on NULL. */
|
||||
void ruv_temporal_destroy(ruv_temporal_ctx_t *ctx);
|
||||
|
||||
/* Self-test — proves the upstream sparse-attention kernel links and
|
||||
* runs. Returns ESP_OK on success. Useful as a smoke check on first
|
||||
* boot before allocating a real context.
|
||||
*/
|
||||
esp_err_t ruv_temporal_kernel_self_test(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user