fix: Flash-Mutex beim Boot statt im kritischen Abschnitt anlegen
This commit is contained in:
@@ -90,6 +90,7 @@ static void app_task(void *arg)
|
|||||||
uint32_t boot_ms, beat_seen;
|
uint32_t boot_ms, beat_seen;
|
||||||
|
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
nl_flash_init();
|
||||||
nl_resetcnt_init(base + NL_FL_RESETCNT);
|
nl_resetcnt_init(base + NL_FL_RESETCNT);
|
||||||
boots = nl_resetcnt_boot();
|
boots = nl_resetcnt_boot();
|
||||||
nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B);
|
nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B);
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#define NL_FLASH_SECTOR_SIZE 4096u
|
#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. */
|
/* All functions return 0 on success, < 0 on error. Addresses are absolute. */
|
||||||
int nl_flash_read(uint32_t addr, void *buf, uint32_t len);
|
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. */
|
/* The target bytes must be erased (0xFF); the stores never rely on implicit erases. */
|
||||||
|
|||||||
+20
-22
@@ -10,33 +10,30 @@
|
|||||||
* fls_lock (see sdk/Platform/Drivers/internalflash/wm_internal_fls.c). The app task
|
* 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,
|
* (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
|
* 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
|
* each other. Serialise all flash accesses with our own mutex.
|
||||||
* first use so no caller has to be changed.
|
*
|
||||||
|
* 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 *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);
|
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)
|
||||||
{
|
{
|
||||||
tls_os_mutex_t *lock = nl_flash_lock();
|
|
||||||
int r;
|
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;
|
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;
|
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)
|
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. */
|
||||||
tls_os_mutex_t *lock = nl_flash_lock();
|
|
||||||
int r;
|
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;
|
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;
|
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;
|
int r;
|
||||||
|
|
||||||
if (addr % NL_FLASH_SECTOR_SIZE)
|
if (addr % NL_FLASH_SECTOR_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
lock = nl_flash_lock();
|
if (s_flash_lock)
|
||||||
tls_os_mutex_acquire(lock, 0);
|
tls_os_mutex_acquire(s_flash_lock, 0);
|
||||||
r = tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1;
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ void fake_flash_fail_after(long bytes)
|
|||||||
s_fail_after = bytes;
|
s_fail_after = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nl_flash_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int nl_flash_read(uint32_t addr, void *buf, uint32_t len)
|
int nl_flash_read(uint32_t addr, void *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
if (addr + len > FAKE_FLASH_SIZE)
|
if (addr + len > FAKE_FLASH_SIZE)
|
||||||
|
|||||||
Reference in New Issue
Block a user