RT-Thread论坛
直播中

杨静

8年用户 1526经验值
私信 关注
[问答]

nor挂载一个littlefs文件系统之后,把装置断电重启,重启后装置没有运行是为什么?


  • struct fal_flash_dev nor_flash0 =
  •     {
  •             .name = NOR_FLASH_DEV_NAME,
  •             /* If porting this code to the device with FLASH connected to XPI1, the address must be changed to 0x90000000 */
  •             .addr = NOR_FLASH_MEM_BASE,
  •             .len = 8 * 1024 * 1024,
  •             .blk_size = 4096,
  •             .ops = { .init = init, .read = read, .write = write, .erase = erase },
  •             .write_gran = 1
  •     };

  • #define NOR_FLASH_DEV_NAME             "norflash0"
  • #define NOR_FLASH_MEM_BASE             0x80000000UL
  • #define NOR_FLASH_SIZE_IN_BYTES        0x800000UL
  • #define FAL_PART_TABLE
  • {
  •     {FAL_PART_MAGIC_WORD,       "app", NOR_FLASH_DEV_NAME,         0,           8*1024*1024,    0},
  • }

  • int littlefsfilesystem(void)
  • {
  •     int result;

  •     result = fal_init();
  •     if(result <= 0)
  •     {
  •         rt_kprintf("fal_init failedrn");
  •     }
  •     // 创建 FAL MTD NOR 设备
  •     struct rt_device *flash_dev = fal_mtd_nor_device_create("app");
  •     if (flash_dev == NULL)
  •     {
  •         rt_kprintf("Can't create a block device on '%s' partition.", "app");
  •     }

  •     if (dfs_mount(flash_dev->parent.name, "/", "lfs", 0, 0) == 0)
  •     {
  •         rt_kprintf("Filesystem %s is mounted directly! mount point name is %srn","lfs",flash_dev->parent.name);
  •     }
  •     else
  •     {
  •         rt_kprintf("Directly mount lfs failed, formatting...n");

  •         // 检查是否为 MTD 设备
  •         if (flash_dev->type != RT_Device_Class_MTD)
  •         {
  •             rt_kprintf("Error: %s is not an MTD device!n", flash_dev->parent.name);
  •             result = -RT_ERROR;
  •             goto __exit;
  •         }

  •         // 格式化
  •         result = dfs_mkfs("lfs", "app");
  •         if(result)
  •         {
  •             rt_kprintf("dfs_mkfs app on the block device result:%d!rn",result);
  •             goto __exit;
  •         }

  •         //挂载 spi flash 中名为 "app" 的分区上的文件系统
  •         if (dfs_mount(flash_dev->parent.name, "/", "lfs", 0, 0) == 0)
  •         {
  •             rt_kprintf("Filesystem %s is mounted! mount point name is %srn","lfs",flash_dev->parent.name);
  •         }
  •         else
  •         {
  •             rt_kprintf("Failed to initialize %s!rn",flash_dev->parent.name);
  •         }
  •     }
  •     DIR* dir_tmp = opendir("/nor");
  •     if(dir_tmp == RT_NULL)
  •     {
  •         result = mkdir("/nor", 0777);
  •         if(result)
  •         {
  •             rt_kprintf("mkdir %s failedrn","/nor");
  •             return result;
  •         }
  •     }
  •     else
  •     {
  •         closedir(dir_tmp);
  •     }

  •     result = RT_EOK;
  • __exit:
  •     return result;
  • }

  • int main(void)
  • {
  •     printf("go into main  ! worldrn");
  •     static uint32_t led_thread_arg = 0;
  •     int ret;

  •     app_init_led_pins();
  •     rt_thread_t led_thread = rt_thread_create("led_th", thread_entry, &led_thread_arg, 1024, 30, 10);
  •     rt_thread_startup(led_thread);

  •     init_gpio_pins();

  • //    rt_kprintf("RT_HW_HEAP_BEGIN=%02x RT_HW_HEAP_END=%02xrn",RT_HW_HEAP_BEGIN,RT_HW_HEAP_END);
  • //    ret = sdram_test();

  •     ret = littlefsfilesystem();
  •     rt_kprintf("littlefs_test  ret=%drn",ret);

  •     ret = Yaffs2filesystem();
  •     rt_kprintf("Yaffs2filesystem  ret=%drn",ret);

  •     return 0;
  • }


装置再main中挂载一个littlefs文件系统,并再这个文件系统中创建一个文件夹,然后断电重启装置,装置没有再次正常启动程序,从串口看到得信息如下:

如果想要再次正常启动,就需要重新烧录程序,很奇怪,但是如果把文件系统挂载屏蔽掉,装置就能正常断电重启,有没有大佬能帮忙看一下?


回帖(1)

百灵千岛酱

2025-9-23 17:00:45

问题分析:设备断电重启后无法运行的原因


当NOR Flash挂载LittleFS文件系统后,设备断电重启无法运行,可能由以下原因导致:




核心原因及解决方案


1. 文件系统损坏(最常见原因)



  • 现象:LittleFS断电时若正在执行写操作(尤其是元数据更新),可能导致文件系统损坏。


  • 解决方案




    • 启动时添加自动修复逻辑


      #include 

      struct lfs_config cfg = {
         .read  = nor_read,
         .prog  = nor_prog,
         .erase = nor_erase,
         .sync  = nor_sync,
         .read_size = 256,
         .prog_size = 256,
         .block_size = 4096,    // 需匹配Flash擦除块大小
         .block_count = 2048,   // 8MB / 4096
         .block_cycles = 500,   // 磨损均衡周期
      };

      lfs_t lfs;
      int err = lfs_mount(&lfs, &cfg);
      if (err) {
         // 自动修复文件系统
         lfs_format(&lfs, &cfg);
         lfs_mount(&lfs, &cfg); // 重新挂载
      }





2. Flash配置错误



  • 关键参数

    • block_size:必须等于NOR Flash的物理擦除块大小(如4KB/64KB)。

    • block_count:需精确计算(len / block_size)。


  • 检查点
     struct fal_flash_dev nor_flash0 = {
         .name = "nor0",
         .addr = 0x8000000,       // 确认地址与硬件匹配
         .len  = 8 * 1024 * 1024, // 需与NOR实际容量一致
    };


    • 验证方法:通过Flash手册确认物理擦除块大小,并确保 cfg.block_size 与其一致。



3. 未处理挂载失败



  • 风险:挂载失败导致后续代码无法执行。

  • 修复方案:在初始化代码中添加容错机制:
     if (dfs_mount("nor0", "/", "lfs", 0, 0) != 0) {
         rt_kprintf("Mount failed! Formatting...n");
         dfs_mkfs("lfs", "nor0"); // 格式化文件系统
         dfs_mount("nor0", "/", "lfs", 0, 0); // 重新挂载
    }


4. Flash驱动未实现sync()



  • 关键点:LittleFS依赖sync函数确保断电安全。

  • 驱动实现示例
     int nor_sync(const struct lfs_config *cfg) {
         // 确保数据写入物理Flash(如执行写缓存刷新)
         nor_flash_sync(); // 自定义Flash同步函数
         return 0;
    }


    • 硬件要求:NOR Flash需支持原子操作(如写保护机制),避免写操作中途断电。



5. 硬件时序问题



  • 表现:重启后Flash初始化失败。

  • 检查

    • 确认NOR Flash的上电时序满足规格书要求。

    • SPI NOR需检查时钟频率(初始化时降低至10MHz以下,后续提升)。





调试步骤(快速定位问题)




  1. 输出错误日志


    int err = lfs_mount(&lfs, &cfg);
    if (err) {
       rt_kprintf("LittleFS mount error: %dn", err);
    }


    • 错误码参考:LFS_ERR_IO(驱动错误)、LFS_ERR_CORRUPT(文件系统损坏)。




  2. Flash读写验证



    • 在挂载前执行Flash读写测试:
      uint8_t buf[256];
      nor_read(0, buf, sizeof(buf)); // 读取首块数据
      nor_prog(0, "test", 4);        // 写入测试数据




  3. 使用FAL检查Flash


    #include 
    fal_init(); // 初始化FAL
    const struct fal_flash_dev *flash = fal_flash_find("nor0");
    if (flash) {
       uint8_t temp[4];
       fal_read(flash, 0, temp, 4); // 读取前4字节
    }





总结解决方案





































序号 问题类型 解决措施
1 文件系统损坏 添加lfs_format()自动修复逻辑
2 配置参数错误 校正block_size/block_count匹配物理特性
3 挂载流程无容错 增加挂载失败时的格式化重试
4 Flash驱动不完整 实现sync()并验证原子操作
5 硬件初始化失败 检查复位时序和时钟配置


关键建议:在首次启动时格式化NOR Flash(如使用lfs_format()),确保文件系统结构正确初始化。同时在产品设计中增加后备电池或超级电容,保障关键写操作完成。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分