mirror of
https://github.com/ruvnet/RuView
synced 2026-08-02 19:11:46 +00:00
feat(firmware): wire temporal_task.c + Kconfig + ruv_temporal component (Phase 6, #513)
Phase 6 of #513: C-side wiring for the on-device temporal head. Builds cleanly with feature OFF (default); 8MB binary delta is +96 bytes vs v0.6.4-esp32 — that's the no-op shim path. Feature ON depends on the Rust component (Phase 5, currently blocked by upstream esp-rs nightly). Files: - main/temporal_task.{c,h} — owns the FreeRTOS task lifecycle. Per ADR-095 §3.3 the task has its own 16 KB stack pinned to Core 1 and is fed via a 32-deep FreeRTOS queue. With feature OFF the .c file collapses to three ESP_ERR_NOT_SUPPORTED stubs so callers don't need #ifdefs at every call site. - main/temporal_task.h — defines rv_temporal_pkt_t (40 bytes, magic 0xC5110007 — next free in the existing 0xC5110001..0006 family) and the task lifecycle API. Build-time _Static_assert pins the wire format. - main/Kconfig.projbuild — new menu "On-device temporal head (ADR-095, #513)" with CONFIG_CSI_TEMPORAL_HEAD_ENABLED (default n) plus four runtime-tuneable knobs: TEMPORAL_INPUT_DIM (16), TEMPORAL_WINDOW_LEN (256), TEMPORAL_N_CLASSES (4), and TEMPORAL_CLASSIFY_PERIOD_MS (1000). - main/CMakeLists.txt — adds temporal_task.c to SRCS unconditionally (the .c file feature-gates internally), and adds ruv_temporal to REQUIRES only when the feature is enabled so default builds don't pull in the Rust component. - main/adaptive_controller.c — fast_loop_cb now extracts the 9 feature floats from the pkt it just built and pushes them into temporal_task_push_frame after the existing stream_sender_send. Non-blocking; queue-full drops are coalesced and logged 1/sec. - main/main.c — temporal_task_start() called right after adaptive_controller_init(). Wrapped in #ifdef so feature-off builds don't reference the (no-op-anyway) function. - components/ruv_temporal/CMakeLists.txt — restructured. Top-level Kconfig guard registers an empty component when the feature is off (avoids running cargo without a working toolchain). add_custom_command moved AFTER idf_component_register so it doesn't fire in script mode (required by ESP-IDF v5.4). Validation: - Firmware builds clean with default config (feature OFF) on ESP-IDF v5.4 / esp32s3 target. Binary 1062 KiB / 2 MiB partition, 48 % free. - Static assertion catches wire-format drift (rv_temporal_pkt_t size). - Host-side `cargo test -p wifi-densepose-temporal` still 5/5 from the earlier commit (no regression, this commit only touches firmware/). Phase 7 (flash to COM8 + soak) deferred this iteration — board is currently not enumerating on COM8; will pick up next iteration when the ESP32 is reattached. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -1,16 +1,27 @@
|
||||
# ESP-IDF component manifest for the ruv_temporal Rust staticlib (ADR-095).
|
||||
#
|
||||
# Build flow:
|
||||
# 1. Run `cargo +esp build --release --target xtensa-esp32s3-none-elf` in
|
||||
# this directory. Output: target/xtensa-esp32s3-none-elf/release/libruv_temporal.a
|
||||
# 2. Register the resulting static library and the public header dir
|
||||
# with idf_component_register so it shows up on the firmware's
|
||||
# include path and link line.
|
||||
# - When CONFIG_CSI_TEMPORAL_HEAD_ENABLED is OFF (default): register an
|
||||
# empty stub. main/temporal_task.c compiles the no-op shim path, no
|
||||
# cargo, no Rust toolchain dependency. Default firmware build is
|
||||
# unaffected.
|
||||
# - When CONFIG_CSI_TEMPORAL_HEAD_ENABLED is ON: invoke
|
||||
# `cargo +esp build --release --target xtensa-esp32s3-none-elf`,
|
||||
# register the resulting libruv_temporal.a, and expose include/.
|
||||
#
|
||||
# Phase 4: scaffold only — registered but no kernel work runs yet.
|
||||
# Phase 5: cross-compile validated, binary delta measured.
|
||||
# Phase 6: enabled via CONFIG_CSI_TEMPORAL_HEAD_ENABLED Kconfig flag and
|
||||
# fed from edge_processing.c.
|
||||
# add_custom_command is intentionally placed AFTER idf_component_register
|
||||
# because ESP-IDF runs every component's CMakeLists.txt twice — once in
|
||||
# script mode for dependency discovery (where add_custom_command is
|
||||
# forbidden), and once for the actual build.
|
||||
|
||||
if(NOT CONFIG_CSI_TEMPORAL_HEAD_ENABLED)
|
||||
# Feature disabled — register an empty component so the directory's
|
||||
# mere existence doesn't break the build, but do NOT invoke cargo
|
||||
# or pull include/ onto consumers' include paths (the C ABI header
|
||||
# would advertise capabilities we cannot honour).
|
||||
idf_component_register()
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(RUV_TEMPORAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(RUV_TEMPORAL_TARGET "xtensa-esp32s3-none-elf")
|
||||
@@ -18,9 +29,13 @@ set(RUV_TEMPORAL_PROFILE "release")
|
||||
set(RUV_TEMPORAL_LIB
|
||||
"${RUV_TEMPORAL_DIR}/target/${RUV_TEMPORAL_TARGET}/${RUV_TEMPORAL_PROFILE}/libruv_temporal.a")
|
||||
|
||||
# Run the cargo build as a custom command. ESP-IDF's CMake runs at
|
||||
# configure time; we want the staticlib to exist before idf_component_register
|
||||
# runs so it can be added as INTERFACE_LINK_LIBRARIES.
|
||||
idf_component_register(
|
||||
SRCS "shim.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES "esp_common"
|
||||
)
|
||||
|
||||
# Custom command + target run only at build time, not in script mode.
|
||||
add_custom_command(
|
||||
OUTPUT "${RUV_TEMPORAL_LIB}"
|
||||
WORKING_DIRECTORY "${RUV_TEMPORAL_DIR}"
|
||||
@@ -30,12 +45,5 @@ add_custom_command(
|
||||
)
|
||||
add_custom_target(ruv_temporal_rust_build ALL DEPENDS "${RUV_TEMPORAL_LIB}")
|
||||
|
||||
idf_component_register(
|
||||
SRCS "shim.c" # tiny C shim so idf_component_register has a SRCS
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES "esp_common"
|
||||
)
|
||||
|
||||
# Wire the staticlib in.
|
||||
add_dependencies(${COMPONENT_LIB} ruv_temporal_rust_build)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "${RUV_TEMPORAL_LIB}")
|
||||
|
||||
Reference in New Issue
Block a user