update session access lock

This commit is contained in:
Steven Dan
2026-04-11 23:33:27 +08:00
parent d0c20efd15
commit 9db18e03e4
5 changed files with 133 additions and 26 deletions

View File

@@ -1106,13 +1106,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol,
debug_printf("Factory reset: clearing flash "
"and rebooting\n");
unsafe {
lfs_remove_file("game_mode");
lfs_remove_file("mic_vol");
lfs_remove_file("dac_vol");
lfs_remove_file("footstep");
lfs_remove_file("monitor_sw");
lfs_remove_file("mic_mute");
lfs_remove_file("hp_mute");
lfs_format_all();
}
led_on(&led_ctx, LED_MUSIC);

View File

@@ -161,6 +161,7 @@ int eq_flash_init(void) {
while (retry_count < 3 && lfs_init_result != 0) {
lfs_init_result = lfs_init();
if (lfs_init_result != 0) {
lfs_deinit(); // 释放session锁避免下次循环自死锁
retry_count++;
DPRINTF("Failed to initialize LFS, retry %d/3\n", retry_count);
if (retry_count < 3) {
@@ -252,10 +253,16 @@ int eq_flash_load_mode(uint8_t mode) {
return -1;
}
if (lfs_init() != 0) {
lfs_deinit();
return -1;
}
// 获取当前采样率的EQ数组指针
eq_mode_data_t (*eq_array)[NUM_EQ_MODES][NUM_EQ_CHANS] = get_eq_array_ptr(g_eq_sample_rate);
if (!eq_array) {
DPRINTF(" Error: Failed to get EQ array for current sample rate %lu\n", (unsigned long)g_eq_sample_rate);
lfs_deinit();
return -1;
}
@@ -378,6 +385,7 @@ int eq_flash_load_mode(uint8_t mode) {
DPRINTF(" Successfully loaded EQ parameters for mode %d, channel %d\n", mode, ch);
}
lfs_deinit();
return 0;
}
@@ -729,6 +737,11 @@ int eq_save_dirty_params(void) {
return -1;
}
if (lfs_init() != 0) {
lfs_deinit();
return -1;
}
//DPRINTF(" Single param database count: %d\n", single_param_database.param_count);
int saved_count = 0;
@@ -769,6 +782,7 @@ int eq_save_dirty_params(void) {
if (saved_count > 0) {
DPRINTF(" Saved %d dirty single parameters\n", saved_count);
}
lfs_deinit();
return 0;
}
/**
@@ -787,14 +801,21 @@ int eq_save_dirty_gain(void) {
return 0;
}
if (lfs_init() != 0) {
lfs_deinit();
return -1;
}
DPRINTF(" Saving dirty gain\n");
// 使用新的独立保存函数
if (eq_save_gain() == 0) {
gain_dirty = 0; // 只清除增益脏标志
DPRINTF(" Successfully saved gain\n");
lfs_deinit();
return 0;
} else {
DPRINTF(" Error: Failed to save gain\n");
lfs_deinit();
return -1;
}
}
@@ -814,6 +835,11 @@ int eq_save_dirty_names(void) {
return 0;
}
if (lfs_init() != 0) {
lfs_deinit();
return -1;
}
DPRINTF(" Saving dirty mode names\n");
// 使用新的独立保存函数逐个保存每个用户模式的name
int saved_count = 0;
@@ -833,12 +859,15 @@ int eq_save_dirty_names(void) {
if (saved_count > 0) {
DPRINTF(" Successfully saved %d mode name(s), skipped %d\n", saved_count, skipped_count);
lfs_deinit();
return 0;
} else if (skipped_count > 0) {
DPRINTF(" All mode names skipped (same as default or empty), %d skipped\n", skipped_count);
lfs_deinit();
return 0; // 跳过是正常的,不算错误
} else {
DPRINTF(" Error: Failed to save mode names\n");
lfs_deinit();
return -1;
}
}
@@ -989,6 +1018,8 @@ int eq_save_name(uint8_t mode) {
* @return 0: 成功, -1: 失败
*/
int eq_save_gain_and_names(void) {
if (lfs_init() != 0) { lfs_deinit(); return -1; }
int ret = 0;
// 保存gain
@@ -1005,6 +1036,7 @@ int eq_save_gain_and_names(void) {
// result == 1 表示跳过,这是正常的
}
lfs_deinit();
return ret;
}
@@ -1168,6 +1200,8 @@ int eq_load_name(uint8_t mode) {
* @return 0: 成功, -1: 失败
*/
int eq_load_gain_and_names(void) {
if (lfs_init() != 0) { lfs_deinit(); return -1; }
int ret = 0;
// 加载gain
@@ -1183,6 +1217,7 @@ int eq_load_gain_and_names(void) {
}
DPRINTF("Successfully loaded gain and mode names\n");
lfs_deinit();
return ret;
}
@@ -1204,10 +1239,13 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 获取EQ数组指针
eq_mode_data_t (*eq_array)[NUM_EQ_MODES][NUM_EQ_CHANS] = get_eq_array_ptr(sample_rate);
if (!eq_array) {
DPRINTF(" Error: Failed to get EQ array for sample rate %u\n", sample_rate);
lfs_deinit();
return -1;
}
@@ -1224,6 +1262,7 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t
//DPRINTF(" Loaded %d single parameters and calculated coefficients for mode %d\n",
// loaded_count, mode);
lfs_deinit();
return 0;
}
@@ -1271,10 +1310,13 @@ int eq_flash_save_mode(uint8_t mode) {
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 获取当前采样率的EQ数组指针
eq_mode_data_t (*eq_array)[NUM_EQ_MODES][NUM_EQ_CHANS] = get_eq_array_ptr(g_eq_sample_rate);
if (!eq_array) {
DPRINTF(" Error: Failed to get EQ array for current sample rate %lu\n", (unsigned long)g_eq_sample_rate);
lfs_deinit();
return -1;
}
@@ -1332,6 +1374,7 @@ int eq_flash_save_mode(uint8_t mode) {
DPRINTF(" Successfully saved EQ parameters for mode %d, channel %d\n", mode, ch);
}
lfs_deinit();
return 0;
}
@@ -1515,6 +1558,8 @@ int delete_flash_eq_params(uint8_t mode) {
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
int deleted_count = 0;
if (mode == 0xFF) {
@@ -1556,6 +1601,7 @@ int delete_flash_eq_params(uint8_t mode) {
}
DPRINTF(" Deleted %d parameter files\n", deleted_count);
lfs_deinit();
return 0;
}
@@ -1577,6 +1623,8 @@ int delete_flash_gain_and_names(uint8_t mode) {
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 处理删除所有模式的情况
if (mode == 0xFF) {
DPRINTF(" Deleting all user mode gains and names\n");
@@ -1604,18 +1652,21 @@ int delete_flash_gain_and_names(uint8_t mode) {
}
}
lfs_deinit();
return 0;
}
// 检查模式有效性
if (mode >= NUM_EQ_MODES) {
DPRINTF(" Error: Invalid mode %d\n", mode);
lfs_deinit();
return -1;
}
// 预设模式(0-5)的增益和名称不存储在Flash中不需要删除
if (mode < EQ_USER_MODE_MIN) {
DPRINTF(" Mode %d is a preset mode, no Flash data to delete\n", mode);
lfs_deinit();
return 0;
}
@@ -1674,11 +1725,13 @@ int delete_flash_gain_and_names(uint8_t mode) {
DPRINTF(" Gains file does not exist: %s\n", file_path);
}
lfs_deinit();
return 0;
}
// 其他模式如模式9不需要处理
DPRINTF(" Mode %d does not require Flash data deletion\n", mode);
lfs_deinit();
return 0;
}
@@ -1775,6 +1828,8 @@ int eq_flash_save_eq_enable(uint8_t enable)
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 构建独立文件路径
// 改动原因使用独立的文件名存储eq_enable与模式存储完全分离
char file_path[FILE_PATH_MAX_LENGTH];
@@ -1801,6 +1856,7 @@ int eq_flash_save_eq_enable(uint8_t enable)
// 写入文件
lfs_write_config(file_path, file_data, sizeof(file_data));
DPRINTF(" Successfully saved EQ enable %d to Flash (independent file: %s)\n", enable, file_path);
lfs_deinit();
return 0;
}
@@ -1826,6 +1882,8 @@ int eq_flash_save_current_mode(uint8_t mode)
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 构建独立文件路径
// 改动原因使用独立的文件名存储模式与eq_enable存储完全分离
char file_path[FILE_PATH_MAX_LENGTH];
@@ -1852,6 +1910,7 @@ int eq_flash_save_current_mode(uint8_t mode)
// 写入文件
lfs_write_config(file_path, file_data, sizeof(file_data));
DPRINTF(" Successfully saved EQ mode %d to Flash (independent file: %s)\n", mode, file_path);
lfs_deinit();
return 0;
}
@@ -1872,6 +1931,8 @@ int eq_flash_load_current_mode(void)
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 加载模式(从独立文件)
char mode_file_path[FILE_PATH_MAX_LENGTH];
snprintf(mode_file_path, sizeof(mode_file_path), "%s", g_eq_flash_mode_file);
@@ -1951,6 +2012,7 @@ int eq_flash_load_current_mode(void)
g_eq_enable = eq_enable;
DPRINTF(" Successfully loaded mode %d and EQ enable %d from Flash (independent files)\n", mode, eq_enable);
lfs_deinit();
return mode;
}
@@ -1970,6 +2032,8 @@ int eq_flash_load_eq_enable(void)
return -1;
}
if (lfs_init() != 0) { lfs_deinit(); return -1; }
// 加载使能状态(从独立文件)
char enable_file_path[FILE_PATH_MAX_LENGTH];
snprintf(enable_file_path, sizeof(enable_file_path), "%s", g_eq_flash_enable_file);
@@ -2012,5 +2076,6 @@ int eq_flash_load_eq_enable(void)
g_eq_enable = eq_enable;
DPRINTF(" Successfully loaded EQ enable %d from Flash (independent file)\n", eq_enable);
lfs_deinit();
return eq_enable;
}

View File

@@ -3,6 +3,7 @@
#if __XC__
int lfs_init(void);
void lfs_deinit(void);
int lfs_format_all(void);
void lfs_read_config(unsigned char * unsafe config, unsigned char * unsafe buffer, unsigned size);
void lfs_write_config(unsigned char * unsafe config, unsigned char * unsafe buffer, unsigned size);
// EQ参数专用函数
@@ -15,6 +16,7 @@ int lfs_create_directory(const char * unsafe dir_path);
int lfs_init(void);
void lfs_deinit(void);
int lfs_format_all(void);
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size);
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size);
// EQ参数专用函数

View File

@@ -1,3 +1,9 @@
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#else
#define DEBUG_PRINT_ENABLE 0
#endif
#include <stdlib.h>
#include <xs1.h>
#include <platform.h>
@@ -68,8 +74,29 @@ const struct lfs_config cfg = {
.block_cycles = 500,
};
// Session-based exclusive flash access:
// lfs_init() — acquire lock, init QSPI hardware, mount LFS. Lock is HELD.
// lfs_deinit() — unmount LFS, release lock.
// All flash I/O between init/deinit is protected. No per-operation locking needed.
// Only ONE core can hold the session at a time. Other cores block in lfs_init().
#if HID_DFU_EN
extern unsigned g_in_fw_upgrade;
#endif
static int lfs_session_active = 0;
int lfs_init(void) {
#if HID_DFU_EN
// 固件升级期间禁止LFS操作避免与DFU flash访问冲突
if (g_in_fw_upgrade) {
debug_printf("lfs_init: blocked during firmware upgrade\n");
lfs_session_active = 0;
return -2;
}
#endif
swlock_acquire(&lfs_lock);
lfs_session_active = 1;
rtos_qspi_flash_init(
qspi_flash_ctx,
FLASH_CLKBLK,
@@ -87,32 +114,61 @@ int lfs_init(void) {
if (err) {
debug_printf("no lfs partiton is found, formating ...\n");
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
swlock_release(&lfs_lock);
return -1;
err = lfs_mount(&lfs, &cfg);
if (err) {
debug_printf("lfs_init: format+remount failed, err=%d\n", err);
lfs_session_active = 0;
swlock_release(&lfs_lock);
return -1;
}
// Format succeeded and FS is now mounted — return 0 so callers
// can proceed with reads/writes on the (now empty) filesystem.
debug_printf("lfs_init: formatted and remounted successfully\n");
return 0;
}
swlock_release(&lfs_lock);
// Lock remains held until lfs_deinit() is called
return 0;
}
void lfs_deinit(void) {
swlock_acquire(&lfs_lock);
if (!lfs_session_active) {
return; // lfs_init was blocked (e.g. during firmware upgrade), nothing to clean up
}
lfs_unmount(&lfs);
lfs_session_active = 0;
swlock_release(&lfs_lock);
}
int lfs_format_all(void) {
int res = lfs_init();
if (res != 0) {
return res; // Already failed and released lock, or blocked
}
// Mount succeeded, but we want to format, so unmount first
lfs_unmount(&lfs);
// 格式化整个LFS分区清除所有数据
int err = lfs_format(&lfs, &cfg);
// Even if format fails, we must cleanup the session
lfs_session_active = 0;
swlock_release(&lfs_lock);
return err;
}
// All functions below must be called within an lfs_init()/lfs_deinit() session.
// No internal locking — the session lock protects the entire operation sequence.
#pragma stackfunction 1500
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
debug_printf("lfs_read_config: %s, size: %d\n", config, size);
int result = lfs_file_open(&lfs, &file, config, LFS_O_RDWR | LFS_O_CREAT);
debug_printf("lfs_read_config: %s, result: %d\n", config, result);
if (result != 0) {
debug_printf("lfs_read_config: %s, open file failed\n", config);
swlock_release(&lfs_lock);
return;
}
debug_printf("lfs_read_config: %s, file opened\n", config);
@@ -120,39 +176,30 @@ void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned si
debug_printf("lfs_read_config: %s, result: %d\n", config, result);
if (result < 0) {
debug_printf("lfs_read_config: %s, read file failed, error: %d\n", config, result);
// Update: Added lfs_file_close to ensure file is closed even on error.
// Missing this caused subsequent open calls to assert/crash.
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return;
}
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
}
#pragma stackfunction 1500
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
debug_printf("lfs_write_config: %s, size: %d\n", config, size);
int result = lfs_file_open(&lfs, &file, config, LFS_O_RDWR | LFS_O_CREAT);
if (result != 0) {
debug_printf("lfs_write_config: open file failed\n");
swlock_release(&lfs_lock);
return;
}
result = lfs_file_rewind(&lfs, &file);
if (result != 0) {
debug_printf("lfs_write_config: rewind file failed\n");
// Update: Added lfs_file_close to prevent file remaining open if rewind fails.
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return;
}
lfs_file_write(&lfs, &file, buffer, size);
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
}
@@ -160,15 +207,12 @@ void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned s
#pragma stackfunction 1200
int lfs_file_exists(const char * file_path)
{
swlock_acquire(&lfs_lock);
lfs_file_t file;
int result = lfs_file_open(&lfs, &file, file_path, LFS_O_RDONLY);
if (result == 0) {
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return 1; // 文件存在
}
swlock_release(&lfs_lock);
return 0; // 文件不存在
}

View File

@@ -83,6 +83,7 @@ void save_value(unsigned char *path, unsigned char value)
//uint32_t t = get_reference_time();
if (lfs_init() == 0)
{
debug_printf("save value %02x to %s\n", value, path);
lfs_write_config(path, (unsigned char*) &value, sizeof(value));
}
@@ -95,6 +96,7 @@ unsigned char load_value(unsigned char *path)
if (lfs_init() == 0)
{
lfs_read_config(path, (unsigned char*) &value, sizeof(value));
debug_printf("load value from %s %02x\n", path, value);
}
else
{