stm32f407 SD卡升级 bootloader程序 基于sdio和fatfs系统的stm32 bootloader程序 使用fatfs系统读取bin文件。 功能简介: 本程序使用fatfs系统读取bin文件。 开机后会自动检测sd卡,检测到sd卡后,再读取固定名称的bin文件,之后会对bin文件进行首包校验,判断该升级包的起始地址是否正确,正确的话,就循环读取bin文件并写入到flash中。 完成升级。 详细流程请看流程图

最近在项目里折腾了个基于SD卡的IAP升级方案,用到了STM32F407的SDIO接口和FatFs文件系统。整个过程踩了不少坑,记录些关键点给需要的小伙伴参考。

stm32f407 SD卡升级 bootloader程序 基于sdio和fatfs系统的stm32 bootloader程序 使用fatfs系统读取bin文件。 功能简介: 本程序使用fatfs系统读取bin文件。 开机后会自动检测sd卡,检测到sd卡后,再读取固定名称的bin文件,之后会对bin文件进行首包校验,判断该升级包的起始地址是否正确,正确的话,就循环读取bin文件并写入到flash中。 完成升级。 详细流程请看流程图

先来点干货,整个流程的核心代码结构长这样:

// SDIO初始化(关键参数设置)
if(FATFS_LinkDriver(&SD_Driver, SDPath) != 0) return;
f_mount(&fs, "", 1);

// 文件操作
FRESULT res = f_open(&fil, "firmware.bin", FA_READ);
f_read(&fil, buffer, sizeof(buffer), &br);

// 首包校验
if(*(uint32_t*)buffer != APP_ADDRESS) {
    // 弹窗警告
    show_error("起始地址错误!");
    return;
}

// Flash写入
HAL_FLASH_Unlock();
FLASH_Erase_Sector(FLASH_SECTOR_6, VOLTAGE_RANGE_3);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, APP_ADDRESS, data);
HAL_FLASH_Lock();

硬件层那些事儿

SDIO的时钟配置直接关系到读写稳定性。实测发现当SD卡工作在4bit模式时,SDIOCLK设置为48MHz比较稳。遇到过几次文件系统挂载失败,后来发现是DMA传输时没做好内存对齐:

// 内存池必须4字节对齐!
__align(4) uint8_t buffer[512];

FatFs的暗坑

文件系统初始化时,特别注意f_mount返回值。有个隐蔽bug:当SD卡突然拔出时,直接重新初始化会导致死锁。后来改成超时重试机制:

for(int retry=0; retry<3; retry++){
    if(f_mount(&fs, "", 1) == FR_OK) break;
    HAL_Delay(100);
}

首包校验的玄机

升级文件头四个字节必须是应用程序的起始地址。但直接读取可能会遇到大小端问题。后来改用联合体处理:

typedef union {
    uint32_t address;
    uint8_t bytes[4];
} header_check;

if(header_check.address != 0x08008000) // 应用程序起始地址

Flash操作的实战技巧

  1. 擦除前必须解锁,操作完记得上锁
  2. 建议按扇区擦除而不是整片擦除
  3. 写入时开启电源监控,防止电压不稳导致写入失败
// 带异常处理的擦除操作
if(FLASH_WaitForLastOperation(1000) != HAL_OK){
    // 擦除超时处理
    flash_error_handler();
}

性能优化点

  • 使用双缓冲机制:一边写入Flash,一边读取下一块数据
  • 提前计算文件CRC32,和预先存储的校验值对比
  • 升级完成后自动复位,避免手动重启
// 双缓冲示例
while(!f_eof(&fil)){
    f_read(&fil, buf[active_buf], BLOCK_SIZE, &br);
    // 等待前一个块写入完成
    while(flash_busy);
    memcpy(flash_buffer, buf[active_buf], BLOCK_SIZE);
    active_buf ^= 1; // 切换缓冲区
}

避坑指南:测试阶段务必连接调试器,在Flash写入函数里设置断点。遇到过最诡异的问题是SD卡文件系统正常,但升级后程序跑飞,最后发现是中断向量表偏移量没设置。解决方案是在跳转应用前加这么一句:

SCB->VTOR = APP_ADDRESS & 0x1FFFFF80;

整个方案实测升级1MB的固件文件约6秒完成,稳定性通过了连续100次拔插测试。关键还是处理好异常状态,毕竟实际使用中什么奇葩情况都可能出现——比如升级到一半用户突然拔卡,这时候需要在Flash里保存升级状态,下次启动时继续完成。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐