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/
|
/build/
|
||||||
/.west/
|
/managed_components/
|
||||||
/bootloader/
|
/dependencies.lock
|
||||||
/modules/
|
sdkconfig
|
||||||
/nrf/
|
sdkconfig.old
|
||||||
/nrfxlib/
|
|
||||||
/zephyr/
|
|
||||||
/tools/
|
|
||||||
*.o
|
*.o
|
||||||
*.elf
|
*.elf
|
||||||
*.hex
|
|
||||||
*.bin
|
*.bin
|
||||||
*.map
|
*.map
|
||||||
*.uf2
|
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__/
|
__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
|
# 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
|
## Forutsetninger
|
||||||
|
|
||||||
- Docker
|
- Docker
|
||||||
- WSL2
|
- 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
|
## 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
|
```sh
|
||||||
# Bygg toolchain-imaget
|
# Bygg toolchain-imaget (Espressif sitt offisielle ESP-IDF v6.0.2-image)
|
||||||
docker compose build
|
docker compose build
|
||||||
|
|
||||||
# Hent NCS/Zephyr-moduler (kjøres én gang, lagres i det navngitte volumet)
|
# Velg target (kjøres én gang; genererer sdkconfig)
|
||||||
docker compose run --rm build west init -l kvida-os
|
docker compose run --rm build idf.py set-target esp32c6
|
||||||
docker compose run --rm build west update
|
|
||||||
|
|
||||||
# Bygg fastvaren
|
# 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)
|
# Flash + monitor (krever seriellport videresendt via usbipd-win til WSL2)
|
||||||
docker compose run --rm build west flash
|
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:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
working_dir: /workspace
|
working_dir: /project
|
||||||
|
environment:
|
||||||
|
- IDF_TARGET=esp32c6
|
||||||
volumes:
|
volumes:
|
||||||
# West workspace topdir: holds .west/, and the NCS/Zephyr module
|
# Project source, bind-mounted.
|
||||||
# tree fetched by `west update` (nrf/, zephyr/, modules/, ...).
|
- .:/project
|
||||||
- ncs-workspace:/workspace
|
# Build output and IDF Component Registry cache, kept in named
|
||||||
# This repo, bind-mounted as the manifest project inside the
|
# volumes so they survive across container runs without polluting
|
||||||
# workspace (matches `self.path: kvida-os` in west.yml).
|
# the bind-mounted source tree.
|
||||||
- .:/workspace/kvida-os
|
- build-cache:/project/build
|
||||||
|
- managed-components-cache:/project/managed_components
|
||||||
tty: true
|
tty: true
|
||||||
# USB/J-Link access (for `west flash`) is expected to be handled via
|
# USB access (for `idf.py flash`/`monitor`) is expected to be handled
|
||||||
# usbipd-win forwarding the probe into WSL2. If `west flash` needs to
|
# via usbipd-win forwarding the board's serial port into WSL2. If
|
||||||
# run inside this container rather than on the WSL2 host, uncomment
|
# flashing needs to run inside this container rather than on the WSL2
|
||||||
# and adjust one of the following once the forwarded device node is
|
# host, uncomment and adjust once the forwarded device node is known:
|
||||||
# known:
|
|
||||||
# devices:
|
# devices:
|
||||||
# - "/dev/bus/usb:/dev/bus/usb"
|
# - "/dev/ttyUSB0:/dev/ttyUSB0"
|
||||||
# privileged: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
ncs-workspace:
|
build-cache:
|
||||||
|
managed-components-cache:
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
# Build-only toolchain image for kvida-os.
|
# Build-only toolchain image for kvida-os.
|
||||||
#
|
#
|
||||||
# Provides the Zephyr SDK toolchain, west, CMake, Ninja and Python that
|
# Unlike the previous NCS/Zephyr setup, Espressif's official image already
|
||||||
# NCS builds need. It intentionally does NOT bake in the NCS/Zephyr
|
# bakes in the full ESP-IDF toolchain and the SDK itself for the pinned
|
||||||
# module tree (nrf/, zephyr/, modules/, ...) fetched by `west update` --
|
# version, so there is no separate multi-GB "fetch SDK into a volume" step
|
||||||
# that is left to a named volume mounted at /workspace at container run
|
# here -- just pin the image tag.
|
||||||
# time, so the image stays small and NCS revisions can be bumped without
|
|
||||||
# rebuilding it.
|
|
||||||
#
|
#
|
||||||
# NOTE: verify this base image tag still exists/is current before relying
|
# NOTE: verify this tag still exists before relying on it -- it could not
|
||||||
# on it -- it could not be checked against the live registry while
|
# be checked against the live registry while writing this Dockerfile. If
|
||||||
# writing this Dockerfile.
|
# the exact patch tag "v6.0.2" isn't published, fall back to "release-v6.0".
|
||||||
FROM ghcr.io/zephyrproject-rtos/zephyr-build:latest
|
FROM espressif/idf:v6.0.2
|
||||||
|
|
||||||
RUN pip3 install --no-cache-dir -U west
|
WORKDIR /project
|
||||||
|
|
||||||
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.
|
|
||||||
|
|||||||
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