Rebuild firmware scaffold for ESP32-C6/ESP-IDF, replacing NCS/Zephyr
The product pivoted away from a Matter-first nRF54L15 device to an ESP32-C6/ESP-IDF/C++17 platform where behaviour is defined by a Blockly-generated Lua program instead of custom firmware (see the updated kvida meta-repo vision). Removes the west/NCS/Zephyr scaffold and replaces it with: - A pinned ESP-IDF v6.0.2 Docker build environment (Espressif's official image already bundles the toolchain, unlike NCS/west). - A layered component structure (drivers -> sensors -> profiles -> lua_runtime -> transport) matching the new architecture principles, with per-component READMEs describing responsibilities. - An A/B OTA + LittleFS partition table and a minimal main.cpp. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
15
.gitignore
vendored
15
.gitignore
vendored
@@ -1,18 +1,13 @@
|
||||
# Zephyr / nRF Connect SDK
|
||||
# ESP-IDF
|
||||
/build/
|
||||
/.west/
|
||||
/bootloader/
|
||||
/modules/
|
||||
/nrf/
|
||||
/nrfxlib/
|
||||
/zephyr/
|
||||
/tools/
|
||||
/managed_components/
|
||||
/dependencies.lock
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
*.o
|
||||
*.elf
|
||||
*.hex
|
||||
*.bin
|
||||
*.map
|
||||
*.uf2
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
|
||||
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(kvida_os)
|
||||
31
README.md
31
README.md
@@ -1,36 +1,37 @@
|
||||
# kvida-os
|
||||
|
||||
Fastvare for Kvida — en universell, batteridrevet Matter-node (Nordic nRF54L15) fra Xylon.
|
||||
Fastvare for Kvida — en konfigurerbar automasjonsplattform (ESP32-C6) fra Xylon.
|
||||
|
||||
Visjon og arkitektur er beskrevet i meta-repoet [`kvida`](../kvida/AGENTS.md). Dette repoet inneholder kun fastvaren, bygget på Nordic nRF Connect SDK (Zephyr).
|
||||
Visjon og arkitektur er beskrevet i meta-repoet [`kvida`](../kvida/AGENTS.md). Dette repoet inneholder kun fastvaren, bygget på ESP-IDF (C++17).
|
||||
|
||||
## Forutsetninger
|
||||
|
||||
- Docker
|
||||
- WSL2
|
||||
- `usbipd-win` (for å videresende J-Link/SWD-probe fra Windows til WSL2 ved flashing)
|
||||
- `usbipd-win` (for å videresende ESP32-C6 sin USB-seriellport fra Windows til WSL2 ved flashing)
|
||||
|
||||
## Board
|
||||
## Arkitektur
|
||||
|
||||
Bygget er foreløpig satt opp mot Nordic sitt offisielle utviklingskort (`nrf54l15dk/nrf54l15/cpuapp`) som plassholder. Kvida sin egen hardware trenger et custom board-oppsett under `boards/` når skjema/pinout er klart — ikke gjort ennå.
|
||||
Lagdelt: `drivers` -> `sensors` -> `profiles` -> `lua_runtime` -> `transport`, se komponent-READMEene under `components/` og `AGENTS.md` for detaljer. Bruker konfigurerer enheten visuelt (Blockly -> Lua), ikke ved å skrive/kompilere fastvare.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Containeren kjører med arbeidsmappe `/workspace` (west-workspacets topdir), hvor dette repoet er mountet inn som undermappen `kvida-os/`. NCS/Zephyr-modulene havner som søsken av repoet (`/workspace/nrf`, `/workspace/zephyr`, ...) i et eget navngitt Docker-volum.
|
||||
|
||||
```sh
|
||||
# Bygg toolchain-imaget
|
||||
# Bygg toolchain-imaget (Espressif sitt offisielle ESP-IDF v6.0.2-image)
|
||||
docker compose build
|
||||
|
||||
# Hent NCS/Zephyr-moduler (kjøres én gang, lagres i det navngitte volumet)
|
||||
docker compose run --rm build west init -l kvida-os
|
||||
docker compose run --rm build west update
|
||||
# Velg target (kjøres én gang; genererer sdkconfig)
|
||||
docker compose run --rm build idf.py set-target esp32c6
|
||||
|
||||
# Bygg fastvaren
|
||||
docker compose run --rm build west build -b nrf54l15dk/nrf54l15/cpuapp kvida-os/app
|
||||
docker compose run --rm build idf.py build
|
||||
|
||||
# Flash (krever J-Link-probe videresendt via usbipd-win til WSL2)
|
||||
docker compose run --rm build west flash
|
||||
# Flash + monitor (krever seriellport videresendt via usbipd-win til WSL2)
|
||||
docker compose run --rm build idf.py -p <PORT> flash monitor
|
||||
```
|
||||
|
||||
`west.yml` er pinnet til NCS `v3.4.0`.
|
||||
Prosjektet er pinnet til ESP-IDF `v6.0.2` (se `docker/Dockerfile`).
|
||||
|
||||
## Status
|
||||
|
||||
`main/` bygger og logger oppstart. `components/*` inneholder foreløpig bare README-er som beskriver ansvar per lag — ingen reell logikk ennå. `partitions.csv` har et A/B OTA + LittleFS-oppsett med plassholder-størrelser (4MB flash) som bør justeres når ekte flash-størrelse/image-størrelse er kjent.
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(kvida_os)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
||||
# Module directories under src/ (hal, gpio_manager, power_manager,
|
||||
# matter_manager, ota, config_manager, sensor_profiles, rule_engine) are
|
||||
# currently placeholders with no source files. Add add_subdirectory()
|
||||
# calls for each once it gains a CMakeLists.txt and real sources.
|
||||
@@ -1 +0,0 @@
|
||||
rsource "Kconfig.zephyr"
|
||||
@@ -1,6 +0,0 @@
|
||||
# Minimal base configuration so the application boots and logs.
|
||||
# Matter, Thread, power management, and other feature-specific Kconfig
|
||||
# options are added as the corresponding modules gain real implementations.
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_GPIO=y
|
||||
@@ -1,3 +0,0 @@
|
||||
# config_manager
|
||||
|
||||
Stores and applies the user's device configuration (selected sensor profile, GPIO assignment, options) without requiring a firmware change.
|
||||
@@ -1,3 +0,0 @@
|
||||
# gpio_manager
|
||||
|
||||
Maps configured sensor profiles to physical GPIO/ADC/I2C pins at runtime, based on the active configuration rather than build-time wiring.
|
||||
@@ -1,3 +0,0 @@
|
||||
# hal
|
||||
|
||||
Hardware abstraction layer: wraps nRF54L15 peripherals (GPIO, ADC, I2C) behind a board-independent interface used by the other modules.
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(kvida_os, LOG_LEVEL_INF);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
LOG_INF("kvida-os starting");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# matter_manager
|
||||
|
||||
Exposes configured sensor profiles as Matter endpoints/clusters over Thread, and handles Matter commissioning.
|
||||
@@ -1,3 +0,0 @@
|
||||
# ota
|
||||
|
||||
Firmware update handling (DFU over Matter/Thread, image validation, rollback).
|
||||
@@ -1,3 +0,0 @@
|
||||
# power_manager
|
||||
|
||||
Battery-first power management: sleep/wake scheduling, power state transitions, and battery level reporting.
|
||||
@@ -1,3 +0,0 @@
|
||||
# rule_engine
|
||||
|
||||
Executes user-defined behavior rules (level 3: Lua scripts, level 2: Blockly-generated intermediate representation) without requiring a firmware rebuild.
|
||||
@@ -1,3 +0,0 @@
|
||||
# sensor_profiles
|
||||
|
||||
Reusable sensor profile implementations (reed switch, hall sensor, push button, pulse counter, analog input, DS18B20, BME280, leak sensor, PIR, generic I2C device) selectable via configuration.
|
||||
2
components/drivers/CMakeLists.txt
Normal file
2
components/drivers/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
idf_component_register()
|
||||
|
||||
5
components/drivers/README.md
Normal file
5
components/drivers/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# drivers
|
||||
|
||||
Hardware abstraction: wraps ESP32-C6 peripherals (GPIO, ADC, I2C) behind a board-independent interface used by `sensors`. No dependency on other Kvida components.
|
||||
|
||||
TODO: mounting the `storage` LittleFS partition (see `partitions.csv`) belongs here once a LittleFS component (e.g. `joltwallet/esp_littlefs` from the IDF Component Registry) is picked and pinned via `idf_component.yml`.
|
||||
3
components/lua_runtime/CMakeLists.txt
Normal file
3
components/lua_runtime/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
idf_component_register(
|
||||
REQUIRES profiles transport
|
||||
)
|
||||
5
components/lua_runtime/README.md
Normal file
5
components/lua_runtime/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# lua_runtime
|
||||
|
||||
Executes the sandboxed Lua program (compiled from Blockly) that defines device behaviour. Exposes the Kvida API (e.g. `publish("temperature", 21.3)`) to Lua scripts; Lua never touches ESP-IDF or `transport` directly. `REQUIRES profiles transport`.
|
||||
|
||||
TODO: needs an actual Lua interpreter dependency, pinned via `idf_component.yml` once a specific IDF Component Registry package/version is confirmed (not guessed here, same caution as pinning `west.yml`'s NCS revision previously).
|
||||
3
components/profiles/CMakeLists.txt
Normal file
3
components/profiles/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
idf_component_register(
|
||||
REQUIRES sensors
|
||||
)
|
||||
3
components/profiles/README.md
Normal file
3
components/profiles/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# profiles
|
||||
|
||||
Exposes reusable sensor/actuator capabilities (reed switch, hall sensor, push button, pulse counter, analog input, DS18B20, BME280, leak sensor, PIR, generic I2C device) to the Lua runtime, backed by `sensors`. `REQUIRES sensors`.
|
||||
3
components/sensors/CMakeLists.txt
Normal file
3
components/sensors/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
idf_component_register(
|
||||
REQUIRES drivers
|
||||
)
|
||||
3
components/sensors/README.md
Normal file
3
components/sensors/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# sensors
|
||||
|
||||
Turns raw `drivers` readings into typed sensor values (e.g. debounced contact state, calibrated analog readings). Knows values, not hardware. `REQUIRES drivers`.
|
||||
1
components/transport/CMakeLists.txt
Normal file
1
components/transport/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
idf_component_register()
|
||||
11
components/transport/README.md
Normal file
11
components/transport/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# transport
|
||||
|
||||
Wi-Fi connectivity, MQTT client, and Home Assistant MQTT Discovery payloads. Exposes a semantic `publish(topic, value)`-style API — application code (including Lua) never depends on MQTT directly, per the transport abstraction principle in `AGENTS.md`. No dependency on other Kvida components.
|
||||
|
||||
Also owns Wi-Fi/MQTT configuration storage for now (not broken out into its own component since `AGENTS.md` doesn't call out a separate config layer — revisit if this grows).
|
||||
|
||||
Future transports (Zigbee, Thread, Matter) should implement the same publish API as alternate backends behind this component's interface, without changing callers.
|
||||
|
||||
TODO: built on ESP-IDF's own `esp_wifi` and `mqtt_client` (`esp-mqtt`) components once real code lands — both ship with ESP-IDF, no extra registry dependency needed.
|
||||
|
||||
TODO: A/B OTA update-checking belongs here, driven by ESP-IDF's native `esp_ota_ops` against the `ota_0`/`ota_1` partitions in `partitions.csv` — no extra dependency needed either.
|
||||
@@ -3,23 +3,25 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile
|
||||
working_dir: /workspace
|
||||
working_dir: /project
|
||||
environment:
|
||||
- IDF_TARGET=esp32c6
|
||||
volumes:
|
||||
# West workspace topdir: holds .west/, and the NCS/Zephyr module
|
||||
# tree fetched by `west update` (nrf/, zephyr/, modules/, ...).
|
||||
- ncs-workspace:/workspace
|
||||
# This repo, bind-mounted as the manifest project inside the
|
||||
# workspace (matches `self.path: kvida-os` in west.yml).
|
||||
- .:/workspace/kvida-os
|
||||
# Project source, bind-mounted.
|
||||
- .:/project
|
||||
# Build output and IDF Component Registry cache, kept in named
|
||||
# volumes so they survive across container runs without polluting
|
||||
# the bind-mounted source tree.
|
||||
- build-cache:/project/build
|
||||
- managed-components-cache:/project/managed_components
|
||||
tty: true
|
||||
# USB/J-Link access (for `west flash`) is expected to be handled via
|
||||
# usbipd-win forwarding the probe into WSL2. If `west flash` needs to
|
||||
# run inside this container rather than on the WSL2 host, uncomment
|
||||
# and adjust one of the following once the forwarded device node is
|
||||
# known:
|
||||
# USB access (for `idf.py flash`/`monitor`) is expected to be handled
|
||||
# via usbipd-win forwarding the board's serial port into WSL2. If
|
||||
# flashing needs to run inside this container rather than on the WSL2
|
||||
# host, uncomment and adjust once the forwarded device node is known:
|
||||
# devices:
|
||||
# - "/dev/bus/usb:/dev/bus/usb"
|
||||
# privileged: true
|
||||
# - "/dev/ttyUSB0:/dev/ttyUSB0"
|
||||
|
||||
volumes:
|
||||
ncs-workspace:
|
||||
build-cache:
|
||||
managed-components-cache:
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
# Build-only toolchain image for kvida-os.
|
||||
#
|
||||
# Provides the Zephyr SDK toolchain, west, CMake, Ninja and Python that
|
||||
# NCS builds need. It intentionally does NOT bake in the NCS/Zephyr
|
||||
# module tree (nrf/, zephyr/, modules/, ...) fetched by `west update` --
|
||||
# that is left to a named volume mounted at /workspace at container run
|
||||
# time, so the image stays small and NCS revisions can be bumped without
|
||||
# rebuilding it.
|
||||
# Unlike the previous NCS/Zephyr setup, Espressif's official image already
|
||||
# bakes in the full ESP-IDF toolchain and the SDK itself for the pinned
|
||||
# version, so there is no separate multi-GB "fetch SDK into a volume" step
|
||||
# here -- just pin the image tag.
|
||||
#
|
||||
# NOTE: verify this base image tag still exists/is current before relying
|
||||
# on it -- it could not be checked against the live registry while
|
||||
# writing this Dockerfile.
|
||||
FROM ghcr.io/zephyrproject-rtos/zephyr-build:latest
|
||||
# NOTE: verify this tag still exists before relying on it -- it could not
|
||||
# be checked against the live registry while writing this Dockerfile. If
|
||||
# the exact patch tag "v6.0.2" isn't published, fall back to "release-v6.0".
|
||||
FROM espressif/idf:v6.0.2
|
||||
|
||||
RUN pip3 install --no-cache-dir -U west
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
# TODO: install Nordic's nRF Command Line Tools / nrfutil here if
|
||||
# `west flash` should run from inside this container against a J-Link
|
||||
# probe forwarded into WSL2 via usbipd-win, instead of from the host.
|
||||
WORKDIR /project
|
||||
|
||||
5
main/CMakeLists.txt
Normal file
5
main/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "main.cpp"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES drivers sensors profiles transport lua_runtime
|
||||
)
|
||||
10
main/main.cpp
Normal file
10
main/main.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
namespace {
|
||||
constexpr const char *TAG = "kvida_os";
|
||||
}
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "kvida-os starting");
|
||||
}
|
||||
12
partitions.csv
Normal file
12
partitions.csv
Normal file
@@ -0,0 +1,12 @@
|
||||
# ESP-IDF partition table: A/B OTA app slots + LittleFS storage.
|
||||
#
|
||||
# Sized for a 4MB flash module (TODO: adjust once real flash size and
|
||||
# firmware image size are known).
|
||||
#
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
otadata, data, ota, 0xf000, 0x2000,
|
||||
phy_init, data, phy, 0x11000, 0x1000,
|
||||
ota_0, app, ota_0, 0x20000, 0x180000,
|
||||
ota_1, app, ota_1, 0x1A0000, 0x180000,
|
||||
storage, data, littlefs, 0x320000, 0xE0000,
|
||||
|
6
sdkconfig.defaults
Normal file
6
sdkconfig.defaults
Normal file
@@ -0,0 +1,6 @@
|
||||
# Shared defaults. Target-specific settings are generated into `sdkconfig`
|
||||
# by `idf.py set-target esp32c6` (first-time setup, see README) rather than
|
||||
# hardcoded here.
|
||||
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
7
test/README.md
Normal file
7
test/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# test
|
||||
|
||||
Host-based unit tests for business logic that doesn't need real hardware, per the testing philosophy in `AGENTS.md`: "Everything that can be tested on a desktop should be."
|
||||
|
||||
Primary candidates once they have real code: `components/sensors`, `components/profiles`, and the non-hardware parts of `components/lua_runtime` (Lua sandboxing/API surface, not GPIO access).
|
||||
|
||||
ESP-IDF supports building against its `linux` target (`idf.py --preview set-target linux`) to run component unit tests on the host without a board. No test scaffolding is wired up yet since there's no logic to test.
|
||||
23
west.yml
23
west.yml
@@ -1,23 +0,0 @@
|
||||
# West manifest for kvida-os (freestanding NCS application).
|
||||
#
|
||||
# This repo is meant to sit as a named subdirectory ("kvida-os") inside a
|
||||
# west workspace topdir, e.g. `/workspace/kvida-os`. Running
|
||||
# `west init -l kvida-os && west update` from the topdir fetches sdk-nrf
|
||||
# (which pulls in Zephyr, MCUboot, Matter, etc. via its own manifest) as
|
||||
# siblings of this repo (`/workspace/nrf`, `/workspace/zephyr`, ...).
|
||||
#
|
||||
# Pinned to NCS v3.4.0.
|
||||
manifest:
|
||||
remotes:
|
||||
- name: ncs
|
||||
url-base: https://github.com/nrfconnect
|
||||
|
||||
projects:
|
||||
- name: nrf
|
||||
remote: ncs
|
||||
repo-path: sdk-nrf
|
||||
revision: v3.4.0
|
||||
import: true
|
||||
|
||||
self:
|
||||
path: kvida-os
|
||||
Reference in New Issue
Block a user