From 9db18e03e41b29e7c1557513986b792e070cf6eb Mon Sep 17 00:00:00 2001 From: Steven Dan Date: Sat, 11 Apr 2026 23:33:27 +0800 Subject: [PATCH] update session access lock --- .../src/extensions/audiohw.xc | 8 +- .../src/extensions/eq_flash_storage.c | 65 +++++++++++++++ .../src/extensions/lfs_io.h | 2 + .../src/extensions/lfs_services.c | 82 ++++++++++++++----- .../src/extensions/user_func.c | 2 + 5 files changed, 133 insertions(+), 26 deletions(-) diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc index 8fd61e8..9f7d3ed 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc @@ -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); diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_flash_storage.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_flash_storage.c index 5501452..a5bc54d 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_flash_storage.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_flash_storage.c @@ -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; } diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_io.h b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_io.h index 4072c6c..5d53be6 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_io.h +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_io.h @@ -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参数专用函数 diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_services.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_services.c index b1c1173..d38d83c 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_services.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/lfs_services.c @@ -1,3 +1,9 @@ +#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED +#define DEBUG_PRINT_ENABLE 1 +#else +#define DEBUG_PRINT_ENABLE 0 +#endif + #include #include #include @@ -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; // 文件不存在 } diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c index 7064623..20edfa3 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/user_func.c @@ -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 {