From 21dcdcb13b0324c751e32cfbe81ddf53f11edc00 Mon Sep 17 00:00:00 2001 From: Michael Sauer Date: Fri, 11 Sep 2026 16:10:09 +0200 Subject: [PATCH] fix: Flash-Zugriffe der ninlight-Tasks per Mutex serialisieren --- src/config/nl_flash_w600.c | 54 +++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/config/nl_flash_w600.c b/src/config/nl_flash_w600.c index 20d7518..ce122aa 100644 --- a/src/config/nl_flash_w600.c +++ b/src/config/nl_flash_w600.c @@ -4,22 +4,70 @@ #include "config/nl_flash.h" +/* + * The ninlight flash region lies above FLASH_1M_END_ADDR, where the SDK routes + * tls_fls_read/write/erase to the external SPI flash path without taking its own + * 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. + */ +static tls_os_mutex_t *s_flash_lock; + +static tls_os_mutex_t *nl_flash_lock(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; +} + 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; + tls_os_mutex_t *lock = nl_flash_lock(); + int r; + + tls_os_mutex_acquire(lock, 0); + r = tls_fls_read(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; + tls_os_mutex_release(lock); + + return r; } 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; + tls_os_mutex_t *lock = nl_flash_lock(); + int r; + + tls_os_mutex_acquire(lock, 0); + r = tls_fls_write(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; + tls_os_mutex_release(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; - return tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1; + + lock = nl_flash_lock(); + tls_os_mutex_acquire(lock, 0); + r = tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1; + tls_os_mutex_release(lock); + + return r; } uint32_t nl_flash_region_base(void)