From 7502f4f02239ba8afe084b37db28e49aab8b35bd Mon Sep 17 00:00:00 2001 From: Michael Sauer Date: Fri, 11 Sep 2026 16:14:15 +0200 Subject: [PATCH] fix: Flash-Mutex beim Boot statt im kritischen Abschnitt anlegen --- src/app_main.c | 1 + src/config/nl_flash.h | 3 +++ src/config/nl_flash_w600.c | 44 ++++++++++++++++++-------------------- test/fake_flash.c | 4 ++++ 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/app_main.c b/src/app_main.c index 9c7ef10..2a21dd7 100644 --- a/src/app_main.c +++ b/src/app_main.c @@ -90,6 +90,7 @@ static void app_task(void *arg) uint32_t boot_ms, beat_seen; (void)arg; + nl_flash_init(); nl_resetcnt_init(base + NL_FL_RESETCNT); boots = nl_resetcnt_boot(); nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B); diff --git a/src/config/nl_flash.h b/src/config/nl_flash.h index 5003a58..0b9e324 100644 --- a/src/config/nl_flash.h +++ b/src/config/nl_flash.h @@ -5,6 +5,9 @@ #define NL_FLASH_SECTOR_SIZE 4096u +/* Must be called once before any other nl_flash_* call, before other tasks start. */ +void nl_flash_init(void); + /* All functions return 0 on success, < 0 on error. Addresses are absolute. */ int nl_flash_read(uint32_t addr, void *buf, uint32_t len); /* The target bytes must be erased (0xFF); the stores never rely on implicit erases. */ diff --git a/src/config/nl_flash_w600.c b/src/config/nl_flash_w600.c index ce122aa..453ff02 100644 --- a/src/config/nl_flash_w600.c +++ b/src/config/nl_flash_w600.c @@ -10,33 +10,30 @@ * fls_lock (see sdk/Platform/Drivers/internalflash/wm_internal_fls.c). The app task * (periodic nl_state_log_append) and the console task (nl_app_save_settings, * nl_app_factory_reset) can therefore issue concurrent SPI transactions and corrupt - * each other. Serialise all flash accesses with our own mutex, created lazily on - * first use so no caller has to be changed. + * each other. Serialise all flash accesses with our own mutex. + * + * The mutex is created once in nl_flash_init(), called as the very first statement + * of app_task() before any other task can touch flash - not lazily from inside a + * critical section, since tls_os_mutex_create() allocates and can block, which must + * not happen with interrupts disabled. If nl_flash_init() was forgotten (s_flash_lock + * still NULL), the accessors fall through unlocked rather than crash. */ static tls_os_mutex_t *s_flash_lock; -static tls_os_mutex_t *nl_flash_lock(void) +void nl_flash_init(void) { - u32 cpu_sr; - tls_os_mutex_t *lock; - - cpu_sr = tls_os_set_critical(); - if (s_flash_lock == NULL) - tls_os_mutex_create(0, &s_flash_lock); - lock = s_flash_lock; - tls_os_release_critical(cpu_sr); - - return lock; + tls_os_mutex_create(0, &s_flash_lock); } int nl_flash_read(uint32_t addr, void *buf, uint32_t len) { - tls_os_mutex_t *lock = nl_flash_lock(); int r; - tls_os_mutex_acquire(lock, 0); + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); r = tls_fls_read(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; - tls_os_mutex_release(lock); + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); return r; } @@ -44,28 +41,29 @@ int nl_flash_read(uint32_t addr, void *buf, uint32_t len) 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. */ - tls_os_mutex_t *lock = nl_flash_lock(); int r; - tls_os_mutex_acquire(lock, 0); + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); r = tls_fls_write(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; - tls_os_mutex_release(lock); + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); return r; } int nl_flash_erase_sector(uint32_t addr) { - tls_os_mutex_t *lock; int r; if (addr % NL_FLASH_SECTOR_SIZE) return -1; - lock = nl_flash_lock(); - tls_os_mutex_acquire(lock, 0); + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); r = tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1; - tls_os_mutex_release(lock); + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); return r; } diff --git a/test/fake_flash.c b/test/fake_flash.c index 58f2296..a827f76 100644 --- a/test/fake_flash.c +++ b/test/fake_flash.c @@ -20,6 +20,10 @@ void fake_flash_fail_after(long bytes) s_fail_after = bytes; } +void nl_flash_init(void) +{ +} + int nl_flash_read(uint32_t addr, void *buf, uint32_t len) { if (addr + len > FAKE_FLASH_SIZE)