Files
GD32E50X_BOOT/GD32E50X_BOOT/sys/config.h
T
cbb 1223be9ca9 fix(boot): 修复SPI OTA协议中的ACK丢失死锁和缓冲区管理问题
- 修复ACK丢失导致的死锁问题:修改onCsRelease()逻辑,只有在ESP32发送
  有效v2请求帧时才清除s_txPending,避免dummy poll误清待发ACK

- 优化缓冲区管理和信用机制:实现增量式flash缓冲区排空(drainFlashBufferOne),
  避免一次性排空阻塞主循环;CREDIT计算同时考虑ISR DATA队列待处理数量

- 添加重复序列处理增强:当DATA仍在主循环排队时优先回复ACK(type=0x80),
  避免ESP32长时间接收WAIT导致连接中断

- 修复缓冲区满时的数据包丢失:在handleLinkMessage中同步排空已写入槽位,
  腾出空间后继续处理当前包,防止永久DUP-SEQ错误

- 优化主循环处理顺序:先处理ISR DATA队列并及时回复ACK,再进行flash写入,
  减少ESP32超时重发导致的断续问题

- 增加FLASH写入错误检查:验证fmc_word_program返回状态,写入失败时及时
  返回避免数据损坏
2026-07-14 12:10:25 +08:00

131 lines
5.5 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 __CONFIG_H__
#define __CONFIG_H__
#include <stdint.h>
#include "gd32e50x.h"
/** 项目内部统一使用的简写类型。 */
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
/** 调试打印总开关。置 1 时所有 printf 调试输出编译进去;置 0 时完全剔除,零开销。 */
#define DEBUG_PRINT 1
/* BOOT 固件版本号 */
#define BOOT_FW_VERSION_MAJOR 1U
#define BOOT_FW_VERSION_MINOR 0U
#define BOOT_FW_VERSION_PATCH 1U
#define BOOT_FW_VERSION_BUILD 2U
/**
* Flash 布局说明(GD32E508VE,512KB)
* -----------------------------------
* 0x08000000 ~ 0x08011FFF : Bootloader 区(72KB)
* 0x08012000 ~ 0x08047FFF : 备份应用区(216KB)
* 0x08048000 ~ 0x0807DFFF : 当前主应用区(216KB)
* 0x0807E000 ~ 0x0807E7FF : OTA 状态配置页
* 0x0807E800 ~ 0x0807EFFF : 睡眠配置页
*/
inline constexpr u32 BOOTLOADER_START_ADDR = 0x08000000U;
inline constexpr u32 BOOTLOADER_SIZE = 0x00012000U; /**< 72KB */
inline constexpr u32 APPBACK_START_ADDR = 0x08012000U; /**< 备份应用起始地址 */
inline constexpr u32 APPLATEST_START_ADDR = 0x08048000U; /**< 当前有效应用起始地址 */
inline constexpr u32 APP_MAX_SIZE = 0x00035FFCU; /**< 216KB - 4B,末尾预留 CRC32 */
inline constexpr u32 FMC_PAGE_SIZE = 0x00000800U; /**< 2KB,GD32E50x 单页大小 */
inline constexpr u32 OTA_CONFIG_PAGE_ADDR = 0x0807E000U; /**< OTA 元数据页 */
inline constexpr u32 APP_CRC_SIZE = 4U; /**< 固件区末尾 CRC32 占用字节数 */
inline constexpr u32 APP_FIRMWARE_SIZE = APP_MAX_SIZE - APP_CRC_SIZE; /**< 实际固件大小(不含 CRC) */
inline constexpr u32 n_APP_LATEST_CRC_ADDR = APPLATEST_START_ADDR + APP_FIRMWARE_SIZE; /**< A区 CRC 存储地址 */
inline constexpr u32 n_APP_BACKUP_CRC_ADDR = APPBACK_START_ADDR + APP_FIRMWARE_SIZE; /**< B区 CRC 存储地址 */
inline constexpr u32 SLEEP_CONFIG_START = 0x0807E800U; /**< 睡眠配置页起始 */
inline constexpr u32 SLEEP_CONFIG_END = 0x0807F000U; /**< 睡眠配置页结束(开区间) */
/** Flash 默认擦除值,以及睡眠开关标志值。 */
inline constexpr u32 FLASH_EMPTY = 0xFFFFFFFFU;
inline constexpr u32 SLEEP_ENABLE = 0x11111111U;
inline constexpr u32 SLEEP_DISABLE = 0x00000000U;
/**
* OTA 配置页一共使用 8 个 word:
* word 0~5: latest_aval / backup_aval / latest_en / backup_en / latest_check / backup_check
* word 6~7: BOOT 版本号(major|minor / patch|build)
*/
inline constexpr u32 OTA_CONFIG_NUM = 8U;
inline constexpr u32 n_APP_LATEST_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x00U;
inline constexpr u32 n_APP_BACKUP_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x04U;
inline constexpr u32 n_APP_LATEST_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x08U;
inline constexpr u32 n_APP_BACKUP_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x0CU;
inline constexpr u32 n_APP_LATEST_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x10U;
inline constexpr u32 n_APP_BACKUP_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x14U;
inline constexpr u32 n_BOOT_VERSION_ADDR0 = OTA_CONFIG_PAGE_ADDR + 0x18U; /**< BOOT版本 word0: major|minor */
inline constexpr u32 n_BOOT_VERSION_ADDR1 = OTA_CONFIG_PAGE_ADDR + 0x1CU; /**< BOOT版本 word1: patch|build */
/**
* 本项目把 0x00000000 视为“有效/可用”,
* 把 0xFFFFFFFF 视为“无效/未写入”。
* 这样设计是因为 Flash 擦除态天然就是 0xFFFFFFFF。
*/
inline constexpr u32 OTA_NOT_AVAL = 0xFFFFFFFFU;
inline constexpr u32 OTA_AVAL = 0x00000000U;
inline constexpr u32 FLASH_EEPROM_OK = 0U;
inline constexpr u32 FLASH_EEPROM_ERROR = 1U;
/** CAN-FD OTA 链路使用的扩展帧 ID。 */
inline constexpr u32 CANFD_OTA_REQ_ID = 0x00000100U;
inline constexpr u32 CANFD_OTA_DATA_ID = 0x00000101U;
inline constexpr u32 CANFD_OTA_ACK_ID = 0x00000102U;
inline constexpr u32 CANFD_OTA_WAIT_ID = 0x00000103U;
inline constexpr u32 CANFD_OTA_CANCEL_ID = 0x00000000U;
/**
* SPI Ready 握手输出引脚(PB6 复用为 SPI Ready)。
* 与 DCU_APP sys/config.h 保持一致,适配 ESP32 waitSpiReady 硬件握手:
* - CS 下降沿拉低 PB6,表示从机忙碌
* - 响应帧就绪后拉高 PB6,通知主机可发起下一笔事务
*/
inline constexpr u32 CONFIG_SPI_READY_PORT = GPIOB;
inline constexpr u32 CONFIG_SPI_READY_PIN = GPIO_PIN_6;
/** GD32E50x 芯片 UID 三段地址。 */
inline constexpr u32 DEVICE_SERIAL_ADDR_LSB = 0x1FFFF7E8U;
inline constexpr u32 DEVICE_SERIAL_ADDR_MID = 0x1FFFF7ECU;
inline constexpr u32 DEVICE_SERIAL_ADDR_MSB = 0x1FFFF7F0U;
/**
* OTA 数据包设计:
* - 每帧总长 64 字节
* - 其中真实加密固件数据为 48 字节
* - 其余用于会话号、包序号、结束标志和 CRC32
*/
inline constexpr u32 OTA_PACKET_SIZE = 48U;
/** 便于按字节/按字访问同一个 32bit 数值。 */
typedef union {
u32 u;
u8 b[4];
} u32_union_t;
/**
* 主密钥:用于 OTA 握手阶段派生会话密钥。
* 当前是写死在固件中的固定密钥。
*/
inline constexpr uint8_t K_master[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
};
/**
* 超时与启动等待参数:
* - OTA_TIMEOUT:OTA 会话超时时间计数上限
* - APP_DELAY_BOOT_TIME:发现应用存在但被禁用时,Bootloader 等待 OTA 请求的窗口
*/
inline constexpr u32 OTA_TIMEOUT = 50000U;
inline constexpr u32 APP_DELAY_BOOT_TIME = 10000U;
/** 常用尺寸常量。 */
static const u8 SIZE_U32 = sizeof(uint32_t);
static const u8 SIZE_FLOAT = sizeof(float);
#endif