STM32L4外接AT45DB041E Flash挂载FATFS返回FR_NOT_READY求排查
FATFS挂载AT45DB041E返回FR_NOT_READY的问题排查与代码修正
你的代码存在几处关键问题,结合FR_NOT_READY的报错原因(通常指向磁盘未完成初始化或底层驱动适配错误),以下是具体分析和修正方案:
1. 卷标与文件路径格式错误
FATFS的卷标和路径有明确规范:
f_mount的第二个参数是驱动器标识符,正确格式应为"0:"(第一个驱动器)而非"fs";若使用自定义卷标,需开启FATFS配置中的_USE_LABEL并确保卷标已格式化到Flash中。- 调用
f_open时,路径需匹配挂载的驱动器,比如挂载"0:"后,文件路径应为"0:/update.bin",而非"/fs/update.bin"(这种格式会被解析为默认卷下的fs目录,与预期不符)。
2. 底层驱动与初始化逻辑缺失
虽然能读取Flash厂商ID,但FATFS依赖diskio.c中的底层磁盘操作函数(disk_initialize、disk_status等),这些函数必须适配AT45DB041E的特性:
- 确保
disk_initialize能完成Flash上电初始化,包括等待Flash内部就绪(AT45DB上电后需要短暂时间完成初始化,HAL_Delay(2)可能不足,建议在at45db_init()内部添加就绪检测逻辑)。 - 匹配FATFS扇区大小与AT45DB页配置:AT45DB041E可配置为512字节/页,需将FATFS的
_MAX_SS和_MIN_SS设为512,确保底层驱动以512字节为单位读写。 - FR_NOT_READY通常由
disk_status返回STA_NOINIT导致,需检查该函数是否正确返回STA_READY(0)。
3. 代码细节错误
- 未检查
malloc返回值:若内存分配失败,fs为NULL会导致挂载操作崩溃,需添加空指针检查。 - 手动控制片选引脚:FATFS底层驱动应自行管理Flash片选信号,手动拉低
GPIO_PIN_9可能与驱动内的片选操作冲突,需移除该逻辑。 - 未关闭打开的文件:若
f_open成功,需调用f_close(&fil)释放资源。
修正后的代码示例
FATFS *fs; FIL fil; FRESULT err = FR_NOT_READY; // 分配FATFS对象并检查内存 fs = malloc(sizeof(FATFS)); if(fs == NULL) { printf("FATFS memory allocation failed\n\r"); return; } // 初始化外部Flash(确保内部包含就绪等待逻辑) at45db_init(); // 手动触发磁盘初始化,排查底层问题 DSTATUS disk_stat = disk_initialize(0); if(disk_stat != RES_OK) { printf("Disk initialize failed, status: %d\n\r", disk_stat); free(fs); return; } // 挂载第一个驱动器(0:) err = f_mount(fs, "0:", 1); if (err == FR_OK) { printf("Mounted successfully\n\r"); // 打开目标文件 err = f_open(&fil, "0:/update.bin", FA_OPEN_EXISTING); if (err == FR_OK) { printf("The file exists in flash memory\n\r"); f_close(&fil); // 关闭文件释放资源 } else { printf("The file does not exist, error code: %d\n\r", err); } } else { printf("Mount failed, error code: %d\n\r", err); free(fs); }
额外排查步骤
- 验证
diskio.c中的disk_read、disk_write函数能正确与AT45DB通信,可通过读写测试确认扇区操作正常。 - 检查Flash是否已格式化FAT文件系统:若Flash空白或未格式化,FATFS无法挂载,需使用
f_mkfs函数先完成格式化(注意备份数据)。
内容的提问来源于stack exchange,提问作者ngrigoriadis
相关产品推荐
相关产品推荐

