feat(protocol): 更新SPI Link协议至v2版本并优化CAN通信
- 将SPI OTA帧格式升级为SPI Link v2,采用新的帧格式: | SOF0 0xA5 | SOF1 0x5A | VER 0x02 | FLAGS | SESSION 4B LE | TX_SEQ | ACK_SEQ | CREDIT | TYPE | LEN 2B LE | RSV 2B | PAYLOAD | CRC32 4B LE | - 新增V2_OVERHEAD=20字节开销,APP最大payload为236字节,BOOT为108字节 - 修改帧类型定义:ENTER_BOOT从0xB5合并至0xB0,新增CAN业务类型0xC0~C3 - 更新CAN协议文档,支持SPI Link v2-only模式,调整最大业务payload计算 - 扩展0xC1帧功能,支持双向通信和1Hz主动推送ID快照 - 添加0xC3完整ID快照帧类型,包含seq/rx_count等完整字段 - 更新协议文档中的错误码定义和反馈payload格式 refactor(main): 重构主程序入口并添加CAN反馈任务 - 在main.cpp中添加CAN反馈任务,更新启动流程注释 - 创建createCriticalTask辅助函数,统一关键任务创建逻辑 - 调整SPI初始化顺序,确保CAN反馈任务依赖正确 - 优化错误处理机制,关键任务失败时立即重启 - 将GD32版本探测移至ota_relay任务处理 - 更新版本号至0.3.48,调整编译时间和Git哈希 config: 更新SPI和BLE配置参数 - 添加SPI主机相关配置参数,包括CS GPIO、READY GPIO等引脚定义 - 配置SPI缓冲区大小:APP为256字节,BOOT为128字节 - 更新BLE滑动窗口参数,ACK窗口设为32,数据队列深度为72 - 调整SPI工作队列大小至5120字节,增加任务堆栈监控说明
This commit is contained in:
+60
-27
@@ -1,75 +1,108 @@
|
||||
/*
|
||||
* protocol.h - 帧格式、CRC16、AES 加密解密
|
||||
* T2.2, T1.3
|
||||
* ESP-IDF 6.0 适配版本 - 使用硬件 AES-128-CBC + 硬件 RNG
|
||||
* protocol.h - OTA 握手辅助(nonce 扰码 + 会话密钥生命周期)
|
||||
*
|
||||
* Protocol 类封装协议层功能。
|
||||
* 本模块刻意保持轻量(原「帧格式 / CRC16 / AES-CBC」中间件已迁出):
|
||||
* - 不负责 SPI Link v2 帧 / CRC32
|
||||
* - 不负责 AES 加解密(OTA 数据包 AES-ECB 在 ota_relay 内)
|
||||
* - 仅提供:RNG 扰码常数、server nonce 生成、session key 存清
|
||||
*
|
||||
* AES 主密钥 MASTER_KEY[] 见 app_config.h。
|
||||
*/
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "app_config.h"
|
||||
|
||||
// 安全常量(定义在 app_config.h 中)
|
||||
inline constexpr size_t MASTER_KEY_HERE_LEN = 16; ///< AES-128 主密钥长度(字节)
|
||||
inline constexpr size_t CHIP_UID_LEN = 12; ///< GD32 芯片 UID 长度(字节)
|
||||
/** @brief AES-128 / 会话密钥长度(字节)。 */
|
||||
inline constexpr size_t SESSION_KEY_LEN = 16;
|
||||
|
||||
// AES 会话上下文
|
||||
/**
|
||||
* @brief OTA 会话密钥上下文。
|
||||
*
|
||||
* 仅缓存协商得到的 K_session;真正加解密在 ota_relay 中用该 key 做 AES-ECB。
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key[16]; // 会话密钥 K_session
|
||||
uint8_t key[SESSION_KEY_LEN]; ///< 会话密钥 K_session(16 字节)
|
||||
} session_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief 协议层类(单例)
|
||||
* @brief OTA 握手辅助类(单例)
|
||||
*
|
||||
* 封装 CRC16、AES-128-CBC、帧构建/解析、会话管理等功能。
|
||||
* 大部分方法为静态工具方法,单例仅持有初始化标志。
|
||||
* 持有 per-boot 扰码常数 m_scrambleConst;
|
||||
* sessionKeyInit / sessionKeyClear 为无状态静态工具,不依赖单例成员。
|
||||
*/
|
||||
class Protocol {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取 Protocol 单例实例。
|
||||
* @brief 获取 Protocol 单例实例。
|
||||
* @return Protocol 单例引用。
|
||||
*/
|
||||
static Protocol& instance();
|
||||
|
||||
/**
|
||||
* @brief 初始化协议层。
|
||||
* @brief 初始化协议层(幂等)。
|
||||
*
|
||||
* 使用硬件 RNG 填充 m_scrambleConst,供 scrambleGenerate 混合使用。
|
||||
* 可重复调用;已初始化则直接返回。
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* @brief 生成基于时间戳、地址和随机种子的扰码 nonce。
|
||||
* @param timestamp 时间戳。
|
||||
* @param mem_addr 内存地址。
|
||||
* @brief 生成基于时间戳、地址和随机种子的 16 字节 server nonce。
|
||||
* @param timestamp 时间戳(如 FreeRTOS tick)。
|
||||
* @param mem_addr 内存地址(增加熵,通常取栈/缓冲区地址)。
|
||||
* @param rand_seed 随机种子。
|
||||
* @param nonce_out 输出的 16 字节 nonce 缓冲区。
|
||||
* @param nonce_out 输出缓冲区,至少 16 字节;为 nullptr 时直接返回。
|
||||
*
|
||||
* @note 非标准 KDF,仅作 OTA 握手 nonce,勿当通用密钥派生。
|
||||
* @note 若尚未 init(),内部会自动调用 init()。
|
||||
*/
|
||||
void scrambleGenerate(uint32_t timestamp, uint32_t mem_addr,
|
||||
uint32_t rand_seed, uint8_t *nonce_out);
|
||||
uint32_t rand_seed, uint8_t *nonce_out);
|
||||
|
||||
/**
|
||||
* @brief 会话密钥初始化,将密钥拷贝到会话上下文。
|
||||
* @brief 会话密钥初始化,将密钥拷贝到会话上下文。
|
||||
* @param sess 会话上下文指针。
|
||||
* @param k_session 会话密钥数据。
|
||||
* @param k_session 会话密钥数据(至少 SESSION_KEY_LEN 字节)。
|
||||
* @return 成功返回 0,参数无效返回 -1。
|
||||
*/
|
||||
static int sessionKeyInit(session_ctx_t *sess, const uint8_t *k_session);
|
||||
|
||||
/**
|
||||
* @brief 清除会话上下文中的密钥数据。
|
||||
* @param sess 会话上下文指针。
|
||||
* @brief 清除会话上下文中的密钥数据(抗优化擦除)。
|
||||
* @param sess 会话上下文指针;为 nullptr 时忽略。
|
||||
*/
|
||||
static void sessionKeyClear(session_ctx_t *sess);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 私有默认构造函数。
|
||||
*/
|
||||
Protocol() = default;
|
||||
/**
|
||||
* @brief 私有析构函数。
|
||||
*/
|
||||
~Protocol() = default;
|
||||
/**
|
||||
* @brief 禁止复制构造。
|
||||
*/
|
||||
Protocol(const Protocol&) = delete;
|
||||
/**
|
||||
* @brief 禁止复制赋值。
|
||||
*/
|
||||
Protocol& operator=(const Protocol&) = delete;
|
||||
|
||||
uint8_t m_scrambleConst[SCRAMBLE_CONST_LEN] = {0};
|
||||
bool m_initialized = false;
|
||||
/**
|
||||
* @brief 抗编译器优化的内存擦除(volatile 逐字节写 0)。
|
||||
* @param p 起始地址;nullptr 忽略。
|
||||
* @param n 字节数。
|
||||
*/
|
||||
static void secureWipe(void *p, size_t n);
|
||||
|
||||
uint8_t m_scrambleConst[SCRAMBLE_CONST_LEN] = {0}; ///< per-boot 扰码常数(init 时 RNG 填充)
|
||||
bool m_initialized = false; ///< 是否已 init
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_H
|
||||
#endif // PROTOCOL_H
|
||||
|
||||
Reference in New Issue
Block a user