feat: Persistenz, Einschaltverhalten, Werksreset und Watchdog
This commit is contained in:
@@ -34,6 +34,8 @@ set(NL_FW_SOURCES
|
||||
src/light/nl_control.c
|
||||
src/light/nl_boot_state.c
|
||||
src/config/nl_settings.c
|
||||
src/config/nl_state_log.c
|
||||
src/config/nl_reset_counter.c
|
||||
src/config/nl_flash_w600.c
|
||||
src/drivers/nl_led.c
|
||||
src/drivers/nl_pwm_leds.c
|
||||
|
||||
+67
-7
@@ -1,9 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wm_include.h"
|
||||
#include "wm_watchdog.h"
|
||||
|
||||
#include "board/nl_board.h"
|
||||
#include "config/nl_flash.h"
|
||||
#include "config/nl_flash_layout.h"
|
||||
#include "config/nl_reset_counter.h"
|
||||
#include "config/nl_settings.h"
|
||||
#include "config/nl_state_log.h"
|
||||
#include "drivers/nl_led.h"
|
||||
#include "light/nl_boot_state.h"
|
||||
#include "light/nl_control.h"
|
||||
@@ -32,12 +37,24 @@ nl_settings_t *nl_app_settings(void) { return &s_settings; }
|
||||
|
||||
int nl_app_save_settings(void)
|
||||
{
|
||||
return 0; /* persistence follows in task 12 */
|
||||
int r;
|
||||
nl_app_lock();
|
||||
r = nl_settings_save(&s_settings);
|
||||
nl_app_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
void nl_app_factory_reset(void)
|
||||
{
|
||||
printf("factory reset: not implemented yet\r\n");
|
||||
printf("factory reset\r\n");
|
||||
nl_app_lock();
|
||||
nl_engine_blink(3);
|
||||
nl_app_unlock();
|
||||
tls_os_time_delay(2 * HZ); /* 3 blinks = 1.8 s, the light task keeps running */
|
||||
nl_settings_erase();
|
||||
nl_state_log_erase();
|
||||
nl_resetcnt_clear();
|
||||
tls_sys_reset();
|
||||
}
|
||||
|
||||
static void led_out(const uint8_t ch[NL_CH_COUNT], void *ctx)
|
||||
@@ -65,29 +82,72 @@ static void light_task(void *arg)
|
||||
static void app_task(void *arg)
|
||||
{
|
||||
const nl_board_t *board = nl_board_get();
|
||||
uint32_t base = nl_flash_region_base();
|
||||
nl_engine_cfg_t cfg;
|
||||
nl_light_state_t initial;
|
||||
nl_light_state_t last, initial, pending;
|
||||
bool have_last, counter_cleared = false;
|
||||
uint8_t boots;
|
||||
uint32_t boot_ms, beat_seen;
|
||||
|
||||
(void)arg;
|
||||
nl_settings_defaults(&s_settings);
|
||||
nl_resetcnt_init(base + NL_FL_RESETCNT);
|
||||
boots = nl_resetcnt_boot();
|
||||
nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B);
|
||||
nl_settings_load(&s_settings);
|
||||
nl_state_log_init(base + NL_FL_STATE_0, base + NL_FL_STATE_1);
|
||||
have_last = nl_state_log_load(&last);
|
||||
printf("boot #%u, settings: pob=%u fade=%u/%u, last state: %s\r\n", boots,
|
||||
s_settings.power_on_behaviour, s_settings.fade_in_ms, s_settings.fade_out_ms,
|
||||
have_last ? "yes" : "no");
|
||||
|
||||
nl_led_init(board);
|
||||
cfg.ct_min = board->ct_min;
|
||||
cfg.ct_max = board->ct_max;
|
||||
cfg.output = led_out;
|
||||
cfg.ctx = NULL;
|
||||
initial = nl_boot_state((nl_pob_t)s_settings.power_on_behaviour, have_last ? &last : NULL, board);
|
||||
nl_app_lock();
|
||||
nl_engine_init(&cfg);
|
||||
nl_ctrl_init(board, s_settings.fade_in_ms, s_settings.fade_out_ms);
|
||||
initial = nl_boot_default_state(board);
|
||||
nl_ctrl_boot(&initial);
|
||||
nl_app_unlock();
|
||||
|
||||
tls_os_task_create(NULL, "nl_light", light_task, NULL, (u8 *)s_light_stack, sizeof(s_light_stack), NL_LIGHT_PRIO, 0);
|
||||
|
||||
if (boots >= NL_FACTORY_RESET_BOOTS)
|
||||
nl_app_factory_reset(); /* does not return */
|
||||
|
||||
tls_watchdog_init(20u * 1000u * 1000u); /* 20 s */
|
||||
nl_console_start();
|
||||
|
||||
for (;;)
|
||||
tls_os_time_delay(HZ);
|
||||
boot_ms = nl_app_now_ms();
|
||||
beat_seen = s_light_beat;
|
||||
for (;;) {
|
||||
uint32_t now;
|
||||
bool due;
|
||||
|
||||
tls_os_time_delay(HZ / 10); /* 100 ms */
|
||||
now = nl_app_now_ms();
|
||||
|
||||
if (!counter_cleared && now - boot_ms >= NL_RESETCNT_CLEAR_MS) {
|
||||
nl_resetcnt_clear();
|
||||
counter_cleared = true;
|
||||
}
|
||||
|
||||
nl_app_lock();
|
||||
due = nl_ctrl_persist_due(now, &pending);
|
||||
nl_app_unlock();
|
||||
if (due && nl_state_log_append(&pending) == 0) {
|
||||
nl_app_lock();
|
||||
nl_ctrl_persisted(&pending);
|
||||
nl_app_unlock();
|
||||
}
|
||||
|
||||
if (s_light_beat != beat_seen) {
|
||||
beat_seen = s_light_beat;
|
||||
tls_watchdog_clr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UserMain(void)
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
#include "wm_include.h"
|
||||
#include "wm_flash_map.h"
|
||||
#include "wm_internal_flash.h"
|
||||
|
||||
#include "config/nl_flash.h"
|
||||
|
||||
/* Temporary stub, replaced by the real W600 implementation in task 12. */
|
||||
int nl_flash_read(uint32_t addr, void *buf, uint32_t len) { (void)addr; (void)buf; (void)len; return -1; }
|
||||
int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) { (void)addr; (void)buf; (void)len; return -1; }
|
||||
int nl_flash_erase_sector(uint32_t addr) { (void)addr; return -1; }
|
||||
uint32_t nl_flash_region_base(void) { return 0; }
|
||||
int nl_flash_read(uint32_t addr, void *buf, uint32_t len)
|
||||
{
|
||||
return tls_fls_read(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
int nl_flash_write(uint32_t addr, const void *buf, uint32_t len)
|
||||
{
|
||||
/* tls_fls_write only erases when the target is not 0xFF; the stores always write erased areas. */
|
||||
return tls_fls_write(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
int nl_flash_erase_sector(uint32_t addr)
|
||||
{
|
||||
if (addr % NL_FLASH_SECTOR_SIZE)
|
||||
return -1;
|
||||
return tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
uint32_t nl_flash_region_base(void)
|
||||
{
|
||||
/* The first user sector is TLS_FLASH_PARAM_DEFAULT (SDK), ninlight starts one sector later. */
|
||||
return USER_ADDR_START + NL_FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user