FileX + LevelX中异常错误处理:
移植FileX+LevelX实现基于NorFlash的文件系统,访问文件系统时,出现错误返回FX_IO_ERROR 时,寻找隐藏在背后的真实原因。问题描述:
在STM32上移植FileX及LevelX后,对使用的NorFlash文件系统进行测试,通过使用反复写入大量数据与文件的方法,考察文件系统稳定性。测试中发现,当空闲扇区耗尽时,不仅创建新文件时会报FX_INVALID_PATH错误,读取文件时也会报FX_IO_ERROR 错误,误导调试方向。原因分析:
测试中,在写入大量文件后,访问文件系统时出现奇怪的错误返回,读取文件、写入文件、创建文件、遍历目录都异常出错。跟踪源码运行后分析,是由于空闲扇区耗尽所致。在文件系统内部实现的各类访问操作时,会频繁修改文件分区中的BootSector内容,引起扇区的更新写入操作。当访问调用写扇区的操作时,由于无足够空闲扇区引发访问错误.
刚开始出现问题时,是发生在打开文件并读取时,调用文件读操作时报错,没想到读取背后还隐藏了写操作,因而误导了调试精力,一直在排查Flash的读取驱动程序上。
原始的错误是发生在内部的写入扇区操作时,调用了驱动层的 _lx_nor_flash_sector_write 函数,其中在调用 lx_nor_flash_physical_sector_allocate 函数获取空闲扇区失败,此时设置了错误码为 LX_NO_SECTORS,反映的是真实的错误原因:
else
{
/* Indicate the write was unsuccessful. */
status = LX_NO_SECTORS;
}
/* Return the completion status. */
return(status);
但是在其上一级的驱动框架中,驱动函数是没有返回值的空返回函数。在判断了返回值不为 LX_SUCCESS 的话,设置了系统控制数据结构中的驱动状态数据后,直接返回:
/* Determine if the write was successful. */
if (status != LX_SUCCESS)
{
/* Return an I/O error to FileX. */
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
return;
}
因此更上一级的访问接口 _fx_utility_logical_sector_read 在调用驱动层函数时,无法感知真实错误原因,只能通过引用上述控制结构中的状态变量来判断结果:
/* Invoke the driver to read the sector. */
(media_ptr -> fx_media_driver_entry) (media_ptr); //调用底层驱动框架中的接口,该接口无直接返回值
/* Clear the system write flag. */
media_ptr -> fx_media_driver_system_write = FX_FALSE;
/* Check for successful completion. */
if (media_ptr -> fx_media_driver_status) //而是判断系统控制数据中的状态变量
{
/* Error writing a cached sector out. Return the
error status. */
return(media_ptr -> fx_media_driver_status); //错误时,直接返回了该状态变量
}
这样,访问的错误码就从原始的 LX_NO_SECTORS 转而变成了 FX_IO_ERROR。
如果以上流程发生在读取文件时,就会获得一个 FX_IO_ERROR 错误码,掩盖了真实的“空间不足”错误原因(LX_NO_SECTORS)。这导致在不熟悉FileX+LevelX系统时,调试中很难推测到,打开文件读取数据失败的原因,是因为系统中没有空闲扇区造成的。
如果该流程发生在创建文件时的 fx_file_create 调用中,在上述流程调用返回 FX_IO_ERROR 后,还会继续向下运行。在创建文件时,上面的流程发生在查询文件是否已存在的操作中,如果返回为 FX_SUCCESS 表明在文件系统中查询到了该文件,返回 FX_ALREADY_CREATED。但如果在查询过程中遇到上述错误,没有完成查询就在半路上返回时了FX_IO_ERROR ,后续的判断认为是没有查找到该文件存在,可以继续创建该文件。但在接下来创建文件时,由于之前调用查询函数时是非正常返回,查询结果异常,而在后续的操作中又用到该查询结果,进而出现错误返回:
/* Search the system for the supplied file name. */
status = _fx_directory_search(media_ptr, file_name, &dir_entry, &search_directory, &name_ptr);
/* Determine if the search was successful. */
if (status == FX_SUCCESS) //返回成功,表明找到了要创建的文件名
{
#ifdef FX_ENABLE_FAULT_TOLERANT
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
#endif /* FX_ENABLE_FAULT_TOLERANT */
/* Release media protection. */
FX_UNPROTECT
/* File found - Return the error code. */
return(FX_ALREADY_CREATED);
}
//返回非 FX_SUCCESS 时,表明没找到要创建的文件名
/* Determine if there is anything left after the name. */
if (_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[

在STM32上移植FileX和LevelX后,测试发现当空闲扇区耗尽时,文件操作返回错误FX_IO_ERROR,而非真实的LX_NO_SECTORS。错误源于驱动层无法正确返回扇区分配失败的状态,导致错误码被覆盖。解决方案是在写入或创建文件前检查空闲扇区,避免空间不足导致的异常。
最低0.47元/天 解锁文章
1437





