Files
mcu-codegen-template/Shared/ota_config.h
T

131 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __OTA_CONFIG_H
#define __OTA_CONFIG_H
#include <stdint.h>
#include <string.h>
#define OTA_PAGE_SIZE 256UL /* Flash 页大小(硬件固定 256B,任何模式通用)*/
/* ════════════════════════════════════════════════════════════════
* OTA 模式配置 — 客户唯一配置入口
*
* 本文件被 APPCore/ota_ab.c)与 Bootloaderboot_main.c)共用,
* 修改后需重新编译两个工程。
*
* 只需改 ① OTA_BACKUP_MODE(备份模式)。其余配置均由 #if 条件
* 编译保护,自动只编译生效模式需要的部分:
* ① OTA_BACKUP_MODE = SINGLE / AB 备份模式(唯一必选)
* ② OTA_SWAP_STRATEGY = SCRATCH / RAM 仅 AB 模式生效
* ③ OTA_SCRATCH_* 仅 AB+SCRATCH 生效
* 结构体 ota_param_t 的 seq/progress/phase 仅 AB 模式存在,
* OTA_STATE_SWAPPING 仅 AB 模式存在(单备份下不编译)。
*
* ┌─ 三种模式优缺点速查 ─────────────────────────────────────────┐
* │ SINGLE(单备份) │
* │ 优:最简单;最省 Flash(主区+BAK 各 58K,无需额外区) │
* │ 缺:升级失败/变砖只能整片重烧,无自动回滚 │
* │ AB + RAM(双备份 + RAM 缓冲交换) │
* │ 优:新固件崩溃可自动回滚旧固件;不预留 scratch; │
* │ 无 scratch 擦写磨损;占 Flash = A/B 各 58K │
* │ 缺:升级耗时较长(~7~12s,逐页 RAM 缓冲交换); │
* │ 固件需 2× Flash(A、B 两份) │
* │ AB + SCRATCH(双备份 + Flash 暂存区交换) │
* │ 优:升级最快(~1~3s);掉电恢复最稳 │
* │ 缺:需预留 scratch 区(暂存区,仅 1 页); │
* │ scratch 固定页反复擦写有磨损(固件越大页数越多、 │
* │ 磨损越快);固件需 2× Flash(A、B 两份) │
* │ 注:双备份两策略都需 2× 固件 Flash,scratch 仅多 1 页缓冲; │
* │ 128K 芯片上固件 > ~57K 时 2× 放不下,需外部 SPI Flash。 │
* └────────────────────────────────────────────────────────────┘
* ════════════════════════════════════════════════════════════════ */
/* ① 备份模式 ----------------------------------------------------- */
#define OTA_MODE_SINGLE 0 /* 单备份:BAK 下载→校验→拷贝覆盖主区(同 AppVersion*/
#define OTA_MODE_AB 1 /* 双备份:A/B 区交换(新固件崩溃可回滚旧固件)*/
#define OTA_BACKUP_MODE OTA_MODE_SINGLE /* 默认单备份:最省 Flash、最简单、无磨损 */
/* ═══════ 以下 ②③ 配置仅 OTA_BACKUP_MODE == OTA_MODE_AB 时生效 ═══════ */
#if (OTA_BACKUP_MODE == OTA_MODE_AB)
/* ② 双备份交换策略 ----------------------------------------------- */
#define OTA_SWAP_SCRATCH 0 /* Flash 暂存区交换:升级快、掉电恢复最稳(需预留暂存区)*/
#define OTA_SWAP_RAM 1 /* RAM 缓冲交换:不预留暂存区,A/B 保持 55K */
#define OTA_SWAP_STRATEGY OTA_SWAP_SCRATCH
/* ③ 暂存区参数(仅 OTA_SWAP_STRATEGY == OTA_SWAP_SCRATCH 生效) --- */
#if (OTA_SWAP_STRATEGY == OTA_SWAP_SCRATCH)
#define OTA_SCRATCH_ADDR 0x0801F800UL /* 暂存区起始地址:放在 Flash 最底部(必须页对齐)*/
#define OTA_SCRATCH_SIZE OTA_PAGE_SIZE /* 暂存区只需 1 页:交换时每次仅暂存 1 页(256B),
故大小=1 页即可;Bootloader 每次也只擦这 1 页,
避免原 1KB 整块擦除的 4 倍磨损浪费 */
#endif /* OTA_SWAP_STRATEGY == SCRATCH */
#endif /* OTA_BACKUP_MODE == AB */
/* ════════════════════════════════════════════════════════════════
* 布局宏自动联动(以下由上面配置推导,勿手工修改)
* ════════════════════════════════════════════════════════════════ */
#define OTA_PARAM_ADDR_BASE 0x08002C00UL /* OTA 状态区,1KB(固定):Bootloader 11K 后 */
#define OTA_PARAM_MAX_SIZE (1UL * 1024)
#if (OTA_BACKUP_MODE == OTA_MODE_AB) && (OTA_SWAP_STRATEGY == OTA_SWAP_SCRATCH)
/* 双备份 + 暂存区:A/B 各 57KB128K-12K固定-256B暂存区 ≈ 57K/份),
B 区收尾于 0x0801F800scratch(1页)紧接其后放在 Flash 最底部 0x0801F800 */
#define OTA_RUN_ADDR_BASE 0x08003000UL /* A 区 = 运行区(固件链接地址)*/
#define OTA_BAK_ADDR_BASE 0x08011400UL /* B 区 = 备份区 */
#define OTA_SLOT_MAX_SIZE (57UL * 1024)
#else
/* 单备份(主区+BAK 或 双备份+RAM(A/B 各 58K):布局相同,A+B 正好填满 128K */
#define OTA_RUN_ADDR_BASE 0x08003000UL /* 主区/A 区 = 运行区 */
#define OTA_BAK_ADDR_BASE 0x08011800UL /* BAK/B 区 */
#define OTA_SLOT_MAX_SIZE (58UL * 1024)
#endif
#define OTA_SLOT_PAGE_NB (OTA_SLOT_MAX_SIZE / OTA_PAGE_SIZE)
/* ════════════════════════════════════════════════════════════════
* OTA 状态机(APP 与 Bootloader 共用)
*
* 单备份:IDLE → PENDING →(Bootloader 拷贝主区)→ 运行,无回滚
* 双备份:IDLE → PENDING →(Bootloader 交换)→ BOOT_NEW →(APP 确认)→ IDLE
* SWAPPING = 交换掉电中断,下次启动续做
* 新固件崩溃(IWDG复位):BOOT_NEW 未确认 → 反向交换回滚 → IDLE
* ════════════════════════════════════════════════════════════════ */
#define OTA_MAGIC 0xA55A
#define OTA_STATE_IDLE 0x00 /* 正常运行 */
#define OTA_STATE_PENDING 0x01 /* 新固件已下载,待 Bootloader 校验/拷贝/交换 */
#if (OTA_BACKUP_MODE == OTA_MODE_AB)
#define OTA_STATE_SWAPPING 0x02 /* 双备份:交换进行中(掉电恢复入口)*/
#endif
#define OTA_STATE_BOOT_NEW 0x03 /* 已切到新固件,等待 APP 确认(未确认=回滚)*/
/* ════════════════════════════════════════════════════════════════
* OTA 状态结构(APP 与 Bootloader 共用,flash.c 负责读写)
*
* seq / progress / phase 仅双备份需要(4 页轮换判新、交换掉电恢复),
* 由 #if 保护 —— 单备份模式下字段不存在,结构体更小(20B vs 28B)。
* ════════════════════════════════════════════════════════════════ */
typedef struct
{
#if (OTA_BACKUP_MODE == OTA_MODE_AB)
uint32_t seq; /* 写入序号:4 页轮换判新(参与 CRC16 保护)*/
#endif
uint16_t magic; /* OTA_MAGIC,有效标志 */
uint8_t state; /* IDLE / PENDING / [SWAPPING] / BOOT_NEW */
uint8_t rsv;
uint32_t fw_size; /* 新固件长度(字节) */
uint32_t fw_crc32; /* 新固件 CRC32 */
uint32_t fw_version; /* 新固件版本(透传,可留 0) */
#if (OTA_BACKUP_MODE == OTA_MODE_AB)
uint16_t progress; /* 双备份:交换已完成页数(掉电恢复) */
uint8_t phase; /* 双备份:交换阶段标志(掉电恢复) */
#endif
uint8_t rsv2;
uint16_t crc16; /* 结构体自身 CRC16CRC-16/CCITT)保护 */
} ota_param_t;
#define OTA_PARAM_SIZE ((uint16_t)sizeof(ota_param_t))
#endif /* __OTA_CONFIG_H */