RT-Thread论坛
直播中

刘辉

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

请问RT-FOTA固件校验通过但是解压缩失败是什么原因?

芯片:STM32F407ZGT6
FOTA流程:
从SD卡中读取固件(压缩过的RBL)校验通过后开始解压缩搬运到Flash的0x8020000地址

已经确认读取的固件大小是正确的但是到解压缩这一步就失败了。
代码中位置

跟进去

这是仿真时候的值,如何确定原因呢?

回帖(1)

1653339509.516700

2025-10-11 16:06:35

针对RT-FOTA固件校验通过但解压缩失败的问题(芯片:STM32F407ZGT6),以下是系统性的原因分析和解决步骤:




可能原因分析




  1. 压缩数据损坏  



    • 即便校验通过(如CRC32/MD5等),解压算法比校验算法更敏感,可能检测到细微数据异常(如SD卡读取干扰)。




  2. 内存资源不足  



    • 解压缩需要临时缓冲区(Heap/Stack)。STM32F407的RAM有限(192KB),若解压缓冲区过大或存在内存泄漏,会导致失败。




  3. Flash操作错误  



    • 解压后需写入Flash地址 0x8020000

      • 地址未对齐:STM32F4要求32位写入对齐。

      • 未擦除扇区:目标地址需预先擦除(FOTA流程通常需擦除目标扇区)。

      • 写保护:未解除Flash写保护(HAL_FLASH_Unlock())。





  4. 压缩格式/工具不兼容  



    • 使用的压缩算法(如LZ77、zlib)与设备端解压库不一致。

    • 压缩参数错误(如字典大小)。




  5. 解压缩库缺陷  



    • 解压库代码在特定条件下崩溃(如缓冲区边界处理错误)。




  6. 中断干扰  



    • 解压过程中高优先级中断打断任务,导致状态错乱(如SysTick/USART中断)。






调试步骤与解决方案


1. 检查解压缩函数返回值



  • 定位解压函数调用点,检查返回的错误代码:
     int ret = decompress_rbl(compressed_data, compressed_size, flash_address);
    if (ret != DECOMPRESS_OK) {
         printf("Decompress failed: Error %d", ret); // 输出错误码
    }

  • 根据解压库文档分析错误码(如内存不足、数据错误等)。


2. 验证压缩数据完整性



  • 导出SD卡数据到PC验证
     // 在读取SD卡后,将数据通过串口导出到PC
    for(int i=0; i      printf("%02X ", compressed_data[i]); // 以HEX格式输出
    }


    • 在PC用相同工具(如gzip/7z)解压,确认文件是否有效。


  • 对比工具链生成的压缩文件:确认设备压缩命令与SD卡文件一致。


3. 检查内存使用



  • 确保足够Heap空间
     extern uint8_t _end;   // 检查堆起始地址
    extern uint8_t _estack; // 栈顶地址
    printf("Free Heap: %d", &_estack - &_end - sbrk(0));

  • 优化解压缓冲区:改用静态缓冲区避免动态分配:
     static uint8_t decomp_buffer[8*1024]; // 静态缓冲区替代malloc


4. 验证Flash操作



  • 擦除目标扇区
     HAL_FLASH_Unlock(); // 解锁Flash
    FLASH_Erase_Sector(FLASH_SECTOR_5, VOLTAGE_RANGE_3); // 扇区5对应0x8020000


    • 参考《STM32F4xx参考手册》确定扇区映射。


  • 对齐写入地址
     flash_address = (uint32_t*)0x8020000;
    assert((uint32_t)flash_address % 4 == 0); // 确保4字节对齐


5. 检查中断影响



  • 在解压和写Flash期间禁用中断:
     __disable_irq();
    decompress_and_flash(data, size, dest);
    __enable_irq();

  • 观察是否避免失败(若解决,需重构流程减少临界区)。


6. 升级解压缩库



  • 确认设备端库(如miniz/fatfs)支持您的压缩格式。

  • 替换为更鲁邦的库(如lzma)。




仿真调试关键点




  1. 监控关键变量



    • 压缩数据地址、压缩大小、解压缓冲区地址、Flash目标地址。

    • 单步调试进入解压函数,观察崩溃点(如空指针、除零)。




  2. 堆栈溢出检测  



    • 在启动文件(如startup_stm32f407xx.s)增大栈空间:
      Stack_Size EQU 0x2000 ; 原值可能为0x400

    • 填充栈空间模式(如0xDEADBEEF)检测溢出。




  3. 硬件断点  



    • 在Flash写入函数(如HAL_FLASH_Program)设置断点,观察写入数据是否正确。






常用解决方法优先级



  1. 50%案例:内存不足/堆栈溢出 → 增大RAM分配  

  2. 30%案例:Flash操作错误 → 解锁、擦除、对齐写入  

  3. 20%案例:数据/库问题 → 验证文件+升级库


通过逐步排除,可快速定位问题。优先关注内存和Flash操作,这是STM32F4 FOTA的常见痛点。

举报

更多回帖

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