fix: Flash-Zugriffe der ninlight-Tasks per Mutex serialisieren

This commit is contained in:
Michael Sauer
2026-09-11 16:10:09 +02:00
parent 55b162b0a0
commit 21dcdcb13b
+51 -3
View File
@@ -4,22 +4,70 @@
#include "config/nl_flash.h" #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) 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) 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_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) int nl_flash_erase_sector(uint32_t addr)
{ {
tls_os_mutex_t *lock;
int r;
if (addr % NL_FLASH_SECTOR_SIZE) if (addr % NL_FLASH_SECTOR_SIZE)
return -1; 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) uint32_t nl_flash_region_base(void)