RK3588平台双存储(SPI+PCIE)OTA升级方案教学文档

电子说

1.4w人已加入

描述

 

 

一、方案概述

 

1.1 背景与目标

 

在嵌入式设备中,单一存储介质可能存在容量限制或可靠性风险。RK3588 平台的双存储 OTA 升级方案支持SPI(如 SPI NAND/NOR)与 PCIE 存储(如 PCIE SSD 混合部署场景,通过统一升级引擎实现跨存储设备的固件管理,解决多存储介质下的升级兼容性问题,同时保障升级过程的安全性与可靠性。

 

 

1.2 核心特性

 

混合存储支持:同时适配 SPIMTD 设备)与 PCIE(块设备)存储,支持不同类型分区独立升级。

 

 

固件格式扩展:新增多存储固件格式,兼容原有单存储固件。

 

 

精细化存储识别:每个分区独立标记存储类型(MTD / 非 MTD),替代全局判断。

 

 

安全校验增强:针对不同存储类型优化校验逻辑,确保数据完整性。

 

 

二、环境配置与编译准备

 

2.1 Buildroot 配置(rk3588.config

 

开启升级功能并指定新升级引擎,确保编译时包含必要组件:

 

 

开启升级相关功能

 

 

BR2_PACKAGE_RECOVERY=y

 

 

使用新升级程序(替代原有流程)

 

 

BR2_PACKAGE_RECOVERY_USE_UPDATEENGINE=y

 

 

编译recovery二进制文件

 

 

BR2_PACKAGE_RECOVERY_RECOVERYBIN=y

 

 

编译新升级引擎二进制文件

 

 

BR2_PACKAGE_RECOVERY_UPDATEENGINEBIN=y

 

 

关闭UI(适用于无显示场景)

 

 

BR2_PACKAGE_RECOVERY_NO_UI=y

 

 

2.2 依赖调整(glibc.mk

 

为兼容双存储升级引擎,将 glibc 版本从 2.38 降级至 2.31

 

 

原版本

 

 

# GLIBC_VERSION = 2.38-27-g750a45a783906a19591fb8ff6b7841470f1f5701

 

 

调整后版本

 

 

GLIBC_VERSION = 2.31-54-g6fdf971c9dbf7dac9bea552113fe4694015bbc4d

 

 

注:版本调整需根据实际兼容性测试结果确认。

 

 

三、核心技术实现

 

3.1 存储类型定义与标识

 

3.1.1 存储类型枚举(rkimage.h

 

定义支持的存储类型,包含 SPI 与 PCIE

 

 

typedef enum {

 

 

    STORAGE_FLASH_CODE = 1<<0,      // 闪存

 

 

    STORAGE_EMMC_CODE = 1<<1,       // eMMC

 

 

    STORAGE_SD0_CODE = 1<<2,        // SD0

 

 

    STORAGE_SD1_CODE = 1<<3,        // SD1

 

 

    STORAGE_SPINOR_CODE = 1<<9,     // SPI NORMTD设备)

 

 

    STORAGE_SPINAND_CODE = 1<<8,    // SPI NANDMTD设备)

 

 

    STORAGE_USB_CODE = 1<<7,        // USB存储

 

 

    STORAGE_PCIE_CODE = 1<<11       // PCIE存储(块设备)

 

 

    // 其他存储类型...

 

 

} STORAGE_CODE;

 

 

3.1.2 固件标签标识(defineHeader.h

 

通过标签区分固件类型:

 

 

// 多存储固件标签(SPI+PCIE等混合存储)

 

 

#define SSFW_TAG 0x57465353  

 

 

// 普通单存储固件标签

 

 

#define RKFW_TAG 0x57464B52  

 

 

3.2 多存储固件格式设计

 

双存储固件采用分层打包结构,外层为容器,内层包含各存储设备的独立固件:

 

 

update_ssfw.img(外层容器)

 

 

├── STORAGE_FW_HDR(头部,4KB

 

 

│   ├── tag: SSFW_TAG(标识多存储固件)

 

 

│   ├── head_size: 头部大小

 

 

│   ├── entry_count: 存储设备数量(如2个:SPIPCIE

 

 

│   └── entry_size: 每个存储条目的大小

 

 

├── STORAGE_ENTRY(条目表,可变长)

 

 

│   ├── [SPI存储条目]

 

 

│   │   ├── storage: STORAGE_SPINAND_CODE(存储类型)

 

 

│   │   ├── offset: SPI固件在内层的偏移量

 

 

│   │   └── size: SPI固件大小

 

 

│   └── [PCIE存储条目]

 

 

│       ├── storage: STORAGE_PCIE_CODE

 

 

│       ├── offset: PCIE固件在内层的偏移量

 

 

│       └── size: PCIE固件大小

 

 

├── SPI固件(内层,RKFW格式)

 

 

└── PCIE固件(内层,RKFW格式)

 

 

3.3 固件解析流程

 

3.3.1 解析入口(rkimage.c

 

analyticImage函数根据固件标签判断类型,分支处理:

 

 

int analyticImage(const char *filepath, PRKIMAGE_HDR phdr, PRKIMAGE_STORAGE image_storage, int num) {

 

 

    // 读取固件头部标签

 

 

    if (rkimage_tag == SSFW_TAG) {

 

 

        // 解析多存储固件(SPI+PCIE

 

 

        return analyticDualStorageImage(filepath, phdr, image_storage, num);

 

 

    } else if (rkimage_tag == RKFW_TAG) {

 

 

        // 解析普通单存储固件

 

 

        return analyticRKFWImage(filepath, phdr, 0, fileSize);

 

 

    }

 

 

}

 

 

3.3.2 多存储固件解析(analyticDualStorageImage

 

1.读取外层容器头部,验证 SSFW_TAG

 

 

2.解析条目表,获取 SPI 和 PCIE 固件的偏移量与大小;

 

 

3.分别解析内层 SPI 固件和 PCIE 固件(调用analyticRKFWImage);

 

 

4.整合所有分区信息,并标记每个分区的存储类型(is_mtd):

 

 

SPI 存储的分区(如 SPI NAND)标记为is_mtd = true

 

 

PCIE 存储的分区标记为is_mtd = false

 

 

3.4 升级执行适配

 

3.4.1 存储类型感知的烧写逻辑(flash_image.c

 

将全局存储类型判断改为分区级判断,适配 SPIMTD)与 PCIE(块设备):

 

 

// 原逻辑:全局判断是否为MTD设备

 

 

// if (is_sdboot || is_usbboot || !isMtdDevice()) {

 

 

// 新逻辑:使用当前分区的is_mtd属性

 

 

if (is_sdboot || is_usbboot || !pcmd->is_mtd) {

 

 

    // 块设备操作(如PCIE存储):直接写入/dev/block路径

 

 

} else {

 

 

    // MTD设备操作(如SPI存储):通过mtd-utils工具操作

 

 

}

 

 

3.4.2 校验逻辑适配(md5sum.c

 

comparefile函数增加is_mtd参数,根据存储类型选择校验方式:

 

 

// 新增is_mtd参数

 

 

bool comparefile(..., bool is_mtd) {

 

 

    if (is_mtd) {

 

 

        // MTD设备校验(SPI存储):使用mtd读取接口

 

 

        checkdata_mtd(dest_path, md5sum_dest, dest_offset, checkSize);

 

 

    } else {

 

 

        // 块设备校验(PCIE存储):使用普通文件读取接口

 

 

        checkdata(dest_path, md5sum_dest, dest_offset, checkSize);

 

 

    }

 

 

}

 

 

3.4.3 升级流程整合(update.c

 

1.升级前解析固件时,通过image_storage记录各分区的is_mtd属性;

 

 

2.升级执行时,为每个分区的update_cmd设置is_mtd

 

 

3.调用烧写函数(flash_normal/flash_bootloader)和校验函数(comparefile)时,传入is_mtd参数,确保操作与存储类型匹配。

 

 

四、关键技术点总结

 

技术点

 

 

作用

 

 

实现方式

 

 

多存储固件格式

 

 

支持 SPI 与 PCIE 固件打包

 

 

外层 SSFW 容器 内层 RKFW 固件

 

 

分区级存储标识

 

 

区分每个分区的存储类型

 

 

is_mtd属性(true=SPIfalse=PCIE

 

 

动态烧写适配

 

 

针对存储类型选择操作接口

 

 

块设备直接写入 / MTD 设备通过 mtd-utils

 

 

校验逻辑适配

 

 

确保不同存储类型的校验准确性

 

 

根据is_mtd选择校验方法

 

 

五、测试与验证

 

5.1 测试场景

 

1.基础功能测试:分别升级 SPI 和 PCIE 存储的分区,验证单独升级有效性;

 

 

2.混合升级测试:同时升级 SPI(如 uboot)和 PCIE(如 rootfs)分区,验证跨存储协同;

 

 

3.容错测试:升级中断后重启,检查是否支持断点续传或回滚;

 

 

4.兼容性测试:验证对原有单存储固件(RKFW_TAG)的兼容能力。

RK3588RK3588

5.2 验证指标

 

升级成功率:≥99.5%1000 次测试);

 

 

升级速度:SPI NAND≥8MB/s),PCIE SSD≥30MB/s);

 

 

校验准确性:100% 识别数据篡改(通过人工修改固件测试)。

 

 

六、总结

 

本方案通过扩展固件格式、引入分区级存储标识、适配动态烧写与校验逻辑,实现了 RK3588 平台 SPI 与 PCIE 双存储的 OTA 升级。方案兼顾兼容性与灵活性,可满足复杂存储场景下的升级需求,为多存储设备的嵌入式系统提供可靠的固件更新能力。

 

 


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分