/* * 模块名称:FatFs OS 依赖层 (ffsystem) * 模块功能:FF_FS_REENTRANT 卷互斥钩子 + get_fattime 时间钩子(直引用系统墙钟) * 适用平台:STM32F407ZGTx(MCU 端;模拟器端不编译 FatFS) * 作者:王建锋 * 创建日期:2026-09-13 * 修改记录: * v1.0 2026-09-13 王建锋 初始版本:osMutex 卷锁(1s 超时) * v1.1 2026-09-13 王建锋 get_fattime 采用运行时间伪时(零 I2C 流量、无 RTC 依赖) * v1.2 2026-09-13 王建锋 get_fattime 移入独立适配文件 App/ff_time.c(与调试日志墙钟同源);本文件仅留互斥钩子 * v1.3 2026-09-13 王建锋 get_fattime 回归本文件并改为时间提供回调(App 启动时注册墙钟, * 本文件不引用 App 头文件,保持分层单向) * v1.4 2026-09-13 王建锋 get_fattime 改为直引用 sys_clock 墙钟(去掉回调注册机制; * sys_clock 归 ④中间件层(App/util/),层内引用,无反向依赖) */ #include "ff.h" #include "cmsis_os2.h" #include "sys_clock.h" /* 墙钟:层内中间件引用(sys_clock 归 ④中间件层,App/util/) */ #if (!FF_FS_NORTC) /* * 函数名称:FatFs 时间钩子 (get_fattime) —— 提供当前时间的 FAT 时间格式 * 入口参数:无 * 返 回 值:FAT 时间 ((year-1980)<<25 | month<<21 | day<<16 | hour<<11 | minute<<5 | second/2); * 墙钟无效时返回固定值(FF_NORTC 约定:2026-01-01 00:00:00) * 限定条件:sys_clock_init() 已调用(App 启动时,早于 osKernelStart) * 函数说明:1. 时间源 = 系统墙钟(与调试日志时间戳同源:开机 RTC 基准 + tick 推进,运行期零 I2C) * 2. 文件 mtime 与日志时间戳一致;ff.h 声明,ff.c 在目录项创建 / * 写后关文件 / f_mkfs 时调用 * 3. 本文件为 FatFs 指定的 OS 胶水文件——FatFs 与平台间的 * 唯一耦合点(互斥 + 时间) */ DWORD get_fattime(void) { sd2506_time_t t; if (sys_clock_get_time(&t) != 0 || t.year < 1980u) { return (((DWORD)(FF_NORTC_YEAR - 1980u) << 25) | ((DWORD)FF_NORTC_MON << 21) | ((DWORD)FF_NORTC_MDAY << 16)); } return ((DWORD)(t.year - 1980u) << 25) | ((DWORD)t.month << 21) | ((DWORD)t.day << 16) | ((DWORD)t.hour << 11) | ((DWORD)t.minute << 5) | (DWORD)(t.second / 2u); } #endif /* !FF_FS_NORTC */ #if FF_FS_REENTRANT /* * FatFs 可重入同步对象:[0] = 系统锁,[1..FF_VOLUMES] = 卷锁 * 首次 f_mount 时创建;获取超时(FF_FS_TIMEOUT)时对应 f_* 返回 FR_TIMEOUT * (优雅失败,由调用方下节拍重试,无死锁) */ static osMutexId_t s_fs_mutex[FF_VOLUMES + 1u]; int ff_mutex_create(int vol) { static const osMutexAttr_t s_attr = { "ffs", 0u, NULL, 0u }; if (s_fs_mutex[vol] != NULL) { return 1; } s_fs_mutex[vol] = osMutexNew(&s_attr); return (s_fs_mutex[vol] != NULL) ? 1 : 0; } void ff_mutex_delete(int vol) { if (s_fs_mutex[vol] != NULL) { (void)osMutexDelete(s_fs_mutex[vol]); s_fs_mutex[vol] = NULL; } } int ff_mutex_take(int vol) { if (s_fs_mutex[vol] == NULL) { return 1; /* 锁对象未创建 = 无并发,视为已取得 */ } return (osMutexAcquire(s_fs_mutex[vol], FF_FS_TIMEOUT) == osOK) ? 1 : 0; } void ff_mutex_give(int vol) { if (s_fs_mutex[vol] != NULL) { (void)osMutexRelease(s_fs_mutex[vol]); } } #endif /* FF_FS_REENTRANT */