Compare commits

2 Commits

Author SHA1 Message Date
32fe244fcf sync 2026-05-11 19:28:06 +02:00
5ae098962d feat: add settings mgmt and split debug transport snippets 2026-05-11 16:19:37 +02:00
16 changed files with 367 additions and 56 deletions

View File

@@ -1,11 +1,11 @@
### Console / Logging: RTT
CONFIG_USE_SEGGER_RTT=y
CONFIG_CONSOLE=y
CONFIG_RTT_CONSOLE=y
### Console / Logging: disabled in base board config (enable via debug snippet)
CONFIG_USE_SEGGER_RTT=n
CONFIG_CONSOLE=n
CONFIG_RTT_CONSOLE=n
CONFIG_LOG_BACKEND_RTT=n
CONFIG_UART_CONSOLE=n
CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_BACKEND_RTT=y
# Keep SPI NOR page layout aligned with generated LittleFS block size (4KB).
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

View File

@@ -1,4 +1,5 @@
### Console / Logging: UART
CONFIG_UART_CONSOLE=y
CONFIG_LOG_BACKEND_UART=y
### Console / Logging: disabled in base board config (enable via debug snippet)
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_BACKEND_RTT=n

View File

@@ -1,5 +1,6 @@
### Logging
CONFIG_LOG=y
CONFIG_DEBUG=y
CONFIG_AUDIO_LOG_LEVEL_DBG=y
CONFIG_DEBUG_OPTIMIZATIONS=y

8
firmware/debug_rtt.conf Normal file
View File

@@ -0,0 +1,8 @@
### Debug transport: RTT
CONFIG_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_UART_CONSOLE=n
CONFIG_LOG_BACKEND_UART=n

7
firmware/debug_uart.conf Normal file
View File

@@ -0,0 +1,7 @@
### Debug transport: UART
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_RTT_CONSOLE=n
CONFIG_LOG_BACKEND_RTT=n

View File

@@ -1,3 +1,4 @@
add_subdirectory(settings_mgmt)
add_subdirectory(fw_mgmt)
add_subdirectory(fs_mgmt)
add_subdirectory(ble_mgmt)

View File

@@ -1,6 +1,7 @@
rsource "settings_mgmt/Kconfig"
rsource "fw_mgmt/Kconfig"
rsource "fs_mgmt/Kconfig"
rsource "ble_mgmt/Kconfig"
rsource "buzz_proto/Kconfig"
rsource "audio/Kconfig"
rsource "event_mgmt/Kconfig"
rsource "event_mgmt/Kconfig"

View File

@@ -64,8 +64,6 @@ if BLE_MGMT
default y
# Automatic updates
config BT_AUTO_PHY_UPDATE
default y
config BT_AUTO_DATA_LEN_UPDATE
default y
config BT_GAP_AUTO_UPDATE_CONN_PARAMS

View File

@@ -12,13 +12,16 @@
LOG_MODULE_REGISTER(fs_mgmt, CONFIG_FS_MGMT_LOG_LEVEL);
/* Prefer external LittleFS partition when present, otherwise internal storage partition. */
#if DT_NODE_EXISTS(DT_NODELABEL(ext_flash_lfs))
/*
* Under sysbuild, Partition Manager generates PM_<name>_ID symbols.
* Without PM, we fall back to the DTS node label.
*/
#if defined(PM_littlefs_storage_ID)
#define FokITION_ID(littlefs_storage)
#elif DT_NODE_EXISTS(DT_NODELABEL(ext_flash_lfs))
#define FS_PARTITION_ID FIXED_PARTITION_ID(ext_flash_lfs)
#elif DT_NODE_EXISTS(DT_NODELABEL(storage_partition))
#define FS_PARTITION_ID FIXED_PARTITION_ID(storage_partition)
#else
#error "No compatible LittleFS partition node label found (expected ext_flash_lfs or storage_partition)"
#error "No compatible LittleFS partition found (expected PM littlefs_storage or DTS ext_flash_lfs)"
#endif
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(fs_storage_data);

View File

@@ -0,0 +1,5 @@
if(CONFIG_SETTINGS_MGMT)
zephyr_library()
zephyr_library_sources(src/settings_mgmt.c)
zephyr_include_directories(include)
endif()

View File

@@ -0,0 +1,14 @@
menuconfig SETTINGS_MGMT
bool "Settings Management"
default y
select SETTINGS
select ZMS
help
Library for initializing and managing the settings subsystem.
ZMS (Zephyr Memory Storage) backend is automatically selected when ZMS is enabled.
if SETTINGS_MGMT
module = SETTINGS_MGMT
module-str = settings_mgmt
source "subsys/logging/Kconfig.template.log_config"
endif # SETTINGS_MGMT

View File

@@ -0,0 +1,34 @@
#ifndef SETTINGS_MGMT_H
#define SETTINGS_MGMT_H
#include <zephyr/types.h>
struct app_settings_t {
/* System */
char dev_name[33];
/* Audio */
uint8_t vol;
uint8_t shuffle_mode; /* 0: Rnd, 1: No-Rep */
/* BLE */
uint32_t ble_timeout; /* Seconds, 0xFFFFFFFF = forever */
uint16_t ble_interval; /* Milliseconds */
/* Power & Calibration */
uint8_t chg_mode; /* 0: 500mA, 1: 1A, 2: Auto */
uint16_t off_threshold;/* mV */
int16_t adc_gain;
int16_t adc_offset;
};
/* Global access to the current runtime configuration */
extern struct app_settings_t app_cfg;
/* Initializes the settings subsystem and loads values from flash */
int settings_mgmt_init(void);
/* Sets a setting via string path (for your protocol) */
int settings_mgmt_set_by_path(const char *path, const void *value, size_t len);
#endif

View File

@@ -0,0 +1,239 @@
#include <zephyr/settings/settings.h>
#include <zephyr/logging/log.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "settings_mgmt.h"
LOG_MODULE_REGISTER(settings_mgmt, LOG_LEVEL_INF);
/* Sanity check limits */
#define VOL_MIN 0
#define VOL_MAX 100
#define SHUFFLE_MODE_MIN 0
#define SHUFFLE_MODE_MAX 1
#define BLE_TIMEOUT_MIN 1000
#define BLE_TIMEOUT_MAX 0xFFFFFFFF
#define BLE_INTERVAL_MIN 10
#define BLE_INTERVAL_MAX 10000
#define CHG_MODE_MIN 0
#define CHG_MODE_MAX 2
#define OFF_THRESHOLD_MIN 2900 /* mV, LiPo cut-off */
#define OFF_THRESHOLD_MAX 3500 /* mV, LiPo nominal */
#define ADC_GAIN_MIN -100
#define ADC_GAIN_MAX 100
#define ADC_OFFSET_MIN -1000
#define ADC_OFFSET_MAX 1000
/* The "Source of Truth" in RAM */
struct app_settings_t app_cfg = {
.dev_name = "Edis Buzzer",
.vol = 100, /* 0-100 % */
.shuffle_mode = 0,
.ble_timeout = 0xFFFFFFFF,
.ble_interval = 100,
.chg_mode = 2, /* Auto */
.off_threshold = 3000, /* mV */
.adc_gain = 0,
.adc_offset = 0,
};
static int read_exact(settings_read_cb read_cb, void *cb_arg,
void *dst, size_t expected_len)
{
int rc = read_cb(cb_arg, dst, expected_len);
if (rc < 0) {
return rc;
}
if ((size_t)rc != expected_len) {
return -EINVAL;
}
return 0;
}
/* Sanity check helpers */
static int check_uint8_range(uint8_t val, uint8_t min, uint8_t max,
const char *name)
{
if (val < min || val > max) {
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
return -EINVAL;
}
return 0;
}
static int check_uint16_range(uint16_t val, uint16_t min, uint16_t max,
const char *name)
{
if (val < min || val > max) {
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
return -EINVAL;
}
return 0;
}
static int check_uint32_range(uint32_t val, uint32_t min, uint32_t max,
const char *name)
{
if (val < min || val > max) {
LOG_WRN("%s out of range: %u (valid: %u-%u)", name, val, min, max);
return -EINVAL;
}
return 0;
}
static int check_int16_range(int16_t val, int16_t min, int16_t max,
const char *name)
{
if (val < min || val > max) {
LOG_WRN("%s out of range: %d (valid: %d-%d)", name, val, min, max);
return -EINVAL;
}
return 0;
}
/* Callback: Called by settings_load() or settings_runtime_set() */
static int buzzy_settings_set(const char *name, size_t len,
settings_read_cb read_cb, void *cb_arg)
{
const char *next;
int rc;
/* Path matching: "buzzy/sys/name" -> name is "sys/name" here */
if (settings_name_steq(name, "sys/name", &next) && !next) {
rc = read_cb(cb_arg, app_cfg.dev_name, sizeof(app_cfg.dev_name) - 1);
if (rc >= 0) app_cfg.dev_name[rc] = '\0';
return 0;
}
if (settings_name_steq(name, "audio/vol", &next) && !next) {
uint8_t vol;
rc = read_exact(read_cb, cb_arg, &vol, sizeof(vol));
if (rc == 0) {
rc = check_uint8_range(vol, VOL_MIN, VOL_MAX, "audio/vol");
if (rc == 0) {
app_cfg.vol = vol;
}
}
return rc;
}
if ((settings_name_steq(name, "audio/shuffle", &next) ||
settings_name_steq(name, "audio/shuffle_mode", &next)) && !next) {
uint8_t shuffle;
rc = read_exact(read_cb, cb_arg, &shuffle, sizeof(shuffle));
if (rc == 0) {
rc = check_uint8_range(shuffle, SHUFFLE_MODE_MIN, SHUFFLE_MODE_MAX, "shuffle_mode");
if (rc == 0) {
app_cfg.shuffle_mode = shuffle;
}
}
return rc;
}
if (settings_name_steq(name, "ble/to", &next) && !next) {
uint32_t timeout;
rc = read_exact(read_cb, cb_arg, &timeout, sizeof(timeout));
if (rc == 0) {
rc = check_uint32_range(timeout, BLE_TIMEOUT_MIN, BLE_TIMEOUT_MAX, "ble/to");
if (rc == 0) {
app_cfg.ble_timeout = timeout;
}
}
return rc;
}
if ((settings_name_steq(name, "ble/interval", &next) ||
settings_name_steq(name, "ble/int", &next)) && !next) {
uint16_t interval;
rc = read_exact(read_cb, cb_arg, &interval, sizeof(interval));
if (rc == 0) {
rc = check_uint16_range(interval, BLE_INTERVAL_MIN, BLE_INTERVAL_MAX, "ble/interval");
if (rc == 0) {
app_cfg.ble_interval = interval;
}
}
return rc;
}
if ((settings_name_steq(name, "power/chg_mode", &next) ||
settings_name_steq(name, "sys/chg_mode", &next)) && !next) {
uint8_t chg_mode;
rc = read_exact(read_cb, cb_arg, &chg_mode, sizeof(chg_mode));
if (rc == 0) {
rc = check_uint8_range(chg_mode, CHG_MODE_MIN, CHG_MODE_MAX, "chg_mode");
if (rc == 0) {
app_cfg.chg_mode = chg_mode;
}
}
return rc;
}
if ((settings_name_steq(name, "power/off_threshold", &next) ||
settings_name_steq(name, "sys/off_threshold", &next)) && !next) {
uint16_t threshold;
rc = read_exact(read_cb, cb_arg, &threshold, sizeof(threshold));
if (rc == 0) {
rc = check_uint16_range(threshold, OFF_THRESHOLD_MIN, OFF_THRESHOLD_MAX, "off_threshold [mV]");
if (rc == 0) {
app_cfg.off_threshold = threshold;
}
}
return rc;
}
if (settings_name_steq(name, "adc/gain", &next) && !next) {
int16_t gain;
rc = read_exact(read_cb, cb_arg, &gain, sizeof(gain));
if (rc == 0) {
rc = check_int16_range(gain, ADC_GAIN_MIN, ADC_GAIN_MAX, "adc/gain");
if (rc == 0) {
app_cfg.adc_gain = gain;
}
}
return rc;
}
if (settings_name_steq(name, "adc/offset", &next) && !next) {
int16_t offset;
rc = read_exact(read_cb, cb_arg, &offset, sizeof(offset));
if (rc == 0) {
rc = check_int16_range(offset, ADC_OFFSET_MIN, ADC_OFFSET_MAX, "adc/offset");
if (rc == 0) {
app_cfg.adc_offset = offset;
}
}
return rc;
}
return -ENOENT;
}
struct settings_handler buzzy_handler = {
.name = "buzzy",
.h_set = buzzy_settings_set
};
int settings_mgmt_set_by_path(const char *path, const void *value, size_t len)
{
char full_path[64];
snprintf(full_path, sizeof(full_path), "buzzy/%s", path);
/* Schreibt in ZMS UND triggert buzzy_settings_set zur RAM-Aktualisierung */
return settings_runtime_set(full_path, value, len);
}
int settings_mgmt_init(void)
{
int rc = settings_subsys_init();
if (rc) return rc;
rc = settings_register(&buzzy_handler);
if (rc) return rc;
/* Lädt alle gespeicherten Werte aus dem ZMS in die app_cfg Struktur */
return settings_load();
}

View File

@@ -1,4 +1,39 @@
# External Flash
# Static Partition Manager layout for sysbuild builds.
# Keep this aligned with boards/iten/buzzy/buzzy.dts internal flash partitions.
mcuboot:
address: 0x0
size: 0xC000
region: flash_primary
mcuboot_pad:
address: 0xC000
size: 0x200
region: flash_primary
app:
address: 0xC200
size: 0x75E00
region: flash_primary
mcuboot_primary:
address: 0xC000
size: 0x76000
region: flash_primary
span: [mcuboot_pad, app]
mcuboot_secondary:
address: 0x82000
size: 0x76000
region: flash_primary
# Internal flash tail partition (8 x 4 KiB pages) for ZMS/settings-style usage.
storage:
address: 0xF8000
size: 0x8000
region: flash_primary
# External flash LittleFS image area.
littlefs_storage:
address: 0x0
size: 0x800000

View File

@@ -1,39 +0,0 @@
# mcuboot:
# address: 0x0
# size: 0xC000
# region: flash_primary
# # Primary Slot: Start bleibt 0xC000, Größe 200KB (0x32000)
# mcuboot_primary:
# address: 0xC000
# size: 0x32000
# region: flash_primary
# mcuboot_pad:
# address: 0xC000
# size: 0x200
# region: flash_primary
# # Die App startet nach dem Padding des Primary Slots
# app:
# address: 0xC200
# size: 0x31E00 # (0x32000 - 0x200)
# region: flash_primary
# # Secondary Slot: Startet jetzt bei 0xC000 + 0x32000 = 0x3E000
# mcuboot_secondary:
# address: 0x3E000
# size: 0x32000
# region: flash_primary
# # NVS storage am Ende des Flashs, 16KB (0x4000)
# settings_storage:
# address: 0xFC000
# size: 0x4000
# region: flash_primary
# External Flash
littlefs_storage:
address: 0x0
size: 0x800000 # 8MB
region: external_flash

View File

@@ -1,6 +1,9 @@
### Bluetooth
CONFIG_BLE_MGMT=y
### Audio
CONFIG_BUZZ_AUDIO=y
### Error handling
CONFIG_HW_STACK_PROTECTION=y
CONFIG_RESET_ON_FATAL_ERROR=y