feat: 完善Mesh继电器OTA与地址协议

- 增加STM8 Bootloader工程及出厂固件恢复流程\n- 增加W25Q64外部Flash驱动和OTA分包接收、CRC16校验、断点续传状态管理\n- 增加固件版本查询、升级结果上报与主机确认机制\n- 将业务帧从55 AA帧头调整为发送方Mesh短地址+CMD+LEN+DATA+CRC16\n- 修正JDY-28M外层地址与业务发送方地址的职责划分,支持广播请求定向应答\n- 同步更新硬件引脚、存储分区、OTA流程和主机通信协议文档\n- 已使用SDCC重新编译,应用代码大小为5512字节,链接地址为0x8800
This commit is contained in:
十七
2026-11-03 11:29:55 +08:00
parent d275a3523b
commit 42a4650a78
30 changed files with 2318 additions and 108 deletions
+21
View File
@@ -0,0 +1,21 @@
/**
* @file bootloader.h
* @brief Bootloader 顶层流程接口。
*/
#ifndef STM8_BOOTLOADER_H
#define STM8_BOOTLOADER_H
#include <stdint.h>
/** 初始化 Bootloader 所需的最小硬件资源。 */
void Bootloader_Init(void);
/** 判断应用程序区域是否包含可执行程序。 */
uint8_t Bootloader_IsApplicationValid(void);
/** 跳转到应用程序入口地址,函数成功后不返回。 */
void Bootloader_JumpToApplication(void);
/** Bootloader 主任务,后续OTA接收和搬运流程在此扩展。 */
void Bootloader_Task(void);
/** 检查W25Q64中的升级请求并完成固件搬运。 */
uint8_t Bootloader_ProcessUpgrade(void);
#endif
@@ -0,0 +1,57 @@
/**
* @file bootloader_config.h
* @brief Bootloader 的固定地址和安全策略配置。
*/
#ifndef STM8_BOOTLOADER_CONFIG_H
#define STM8_BOOTLOADER_CONFIG_H
#include <stdint.h>
/** Bootloader 在 STM8 程序 Flash 中的起始地址。 */
#define BOOTLOADER_START_ADDRESS 0x8000u
/** Bootloader 预留空间,当前规划为 1KB。 */
#define BOOTLOADER_SIZE_BYTES 0x0800u
/** 应用程序固定入口地址,必须与应用工程链接地址一致。 */
#define APPLICATION_START_ADDRESS 0x8800u
/** STM8S003F3P6 程序 Flash 的最后一个地址。 */
#define APPLICATION_END_ADDRESS 0x9FFFu
/** 应用程序允许使用的最大空间。 */
#define APPLICATION_MAX_SIZE_BYTES \
(APPLICATION_END_ADDRESS - APPLICATION_START_ADDRESS + 1u)
/** W25Q64 中保存出厂固件镜像的固定地址,容量64KiB。 */
#define FACTORY_IMAGE_ADDRESS 0x000000ul
/** W25Q64 中保存出厂固件元数据的固定地址,独占4KiB扇区。 */
#define FACTORY_METADATA_ADDRESS 0x010000ul
/** W25Q64 中保存OTA升级固件的固定地址,容量64KiB。 */
#define OTA_IMAGE_ADDRESS 0x020000ul
/** W25Q64 中保存OTA元数据的固定地址,独占4KiB扇区。 */
#define OTA_METADATA_ADDRESS 0x030000ul
/** 升级元数据魔数,用于避免误把普通数据当成升级请求。 */
#define OTA_METADATA_MAGIC 0x4F544131ul
/** 出厂恢复镜像元数据魔数。 */
#define FACTORY_METADATA_MAGIC 0x46414331ul
/* 元数据字段相对于各自元数据扇区起始地址的固定偏移。 */
#define METADATA_MAGIC_OFFSET 0x00u
#define METADATA_IMAGE_SIZE_OFFSET 0x04u
#define METADATA_VERSION_OFFSET 0x08u
#define METADATA_CRC16_OFFSET 0x0Au
#define METADATA_IMAGE_VALID_OFFSET 0x0Eu
#define METADATA_UPGRADE_REQUEST_OFFSET 0x0Fu
#define METADATA_UPGRADE_RESULT_OFFSET 0x10u
/** 镜像已经完整写入并通过校验时使用的有效标志。 */
#define METADATA_IMAGE_VALID_VALUE 0xA5u
/** 应用程序有效标记,避免把空白 Flash 当作可执行程序。 */
#define APPLICATION_FIRST_BYTE_INVALID 0x00u
#define APPLICATION_FIRST_BYTE_ERASED 0xFFu
/** Bootloader 看门狗刷新周期,必须小于硬件看门狗超时时间。 */
#define BOOTLOADER_WATCHDOG_REFRESH_LOOP 20000u
/** 上电恢复按键判定时间,单位为毫秒。 */
#define FACTORY_BUTTON_HOLD_TIME_MS 5000u
/** Bootloader忙等待1ms的循环次数,需结合实际系统时钟校准。 */
#define BOOTLOADER_DELAY_1MS_LOOPS 1200u
#endif
@@ -0,0 +1,72 @@
/**
* @file stm8_bootloader_registers.h
* @brief Bootloader 使用的 STM8S003F3P6 最小寄存器定义。
*/
#ifndef STM8_BOOTLOADER_REGISTERS_H
#define STM8_BOOTLOADER_REGISTERS_H
#include <stdint.h>
#define REG8(address) (*((volatile uint8_t *)(address)))
/* FLASH 外设寄存器地址,地址来自 STM8S003 数据手册。 */
#define FLASH_CR1_ADDR 0x505Au
#define FLASH_CR2_ADDR 0x505Bu
#define FLASH_NCR2_ADDR 0x505Cu
#define FLASH_IAPSR_ADDR 0x505Fu
#define FLASH_PUKR_ADDR 0x5062u
#define FLASH_CR1 REG8(FLASH_CR1_ADDR)
#define FLASH_CR2 REG8(FLASH_CR2_ADDR)
#define FLASH_NCR2 REG8(FLASH_NCR2_ADDR)
#define FLASH_IAPSR REG8(FLASH_IAPSR_ADDR)
#define FLASH_PUKR REG8(FLASH_PUKR_ADDR)
/* Flash 控制位。 */
#define FLASH_CR2_PRG 0x01u
#define FLASH_CR2_WPRG 0x10u
#define FLASH_IAPSR_HVOFF 0x08u
/* IWDG 寄存器。 */
#define IWDG_KR_ADDR 0x50E0u
#define IWDG_PR_ADDR 0x50E1u
#define IWDG_RLR_ADDR 0x50E2u
#define IWDG_KR REG8(IWDG_KR_ADDR)
#define IWDG_PR REG8(IWDG_PR_ADDR)
#define IWDG_RLR REG8(IWDG_RLR_ADDR)
/* SPI1 外设寄存器。 */
#define SPI1_CR1_ADDR 0x5200u
#define SPI1_CR2_ADDR 0x5201u
#define SPI1_ICR_ADDR 0x5202u
#define SPI1_SR_ADDR 0x5203u
#define SPI1_DR_ADDR 0x5204u
#define SPI1_CR1 REG8(SPI1_CR1_ADDR)
#define SPI1_CR2 REG8(SPI1_CR2_ADDR)
#define SPI1_SR REG8(SPI1_SR_ADDR)
#define SPI1_DR REG8(SPI1_DR_ADDR)
#define GPIOA_ODR REG8(0x5000u)
#define GPIOA_IDR REG8(0x5001u)
#define GPIOA_DDR REG8(0x5002u)
#define GPIOA_CR1 REG8(0x5003u)
#define GPIOC_ODR REG8(0x500Au)
#define GPIOC_DDR REG8(0x500Cu)
#define GPIOC_CR1 REG8(0x500Du)
#define SPI_CR1_SPE 0x40u
#define SPI_CR1_MSTR 0x04u
#define SPI_CR1_BR0 0x08u
#define SPI_CR1_BR1 0x10u
#define SPI_CR1_BR2 0x20u
#define SPI_CR2_SSI 0x01u
#define SPI_CR2_SSM 0x02u
#define SPI_SR_RXNE 0x01u
#define SPI_SR_TXE 0x02u
#define SPI_SR_BSY 0x80u
#define FLASH_IAPSR_EOP 0x04u
#define FLASH_CR2_PRG 0x01u
#define FLASH_CR2_ERASE 0x20u
#endif
+26
View File
@@ -0,0 +1,26 @@
/**
* @file w25q64.h
* @brief W25Q64JV 硬件SPI访问接口。
*/
#ifndef STM8_BOOTLOADER_W25Q64_H
#define STM8_BOOTLOADER_W25Q64_H
#include <stdint.h>
/** 初始化STM8硬件SPI和W25Q64片选。 */
void W25Q64_Init(void);
/** 读取W25Q64 JEDEC ID,便于启动时确认芯片存在。 */
uint32_t W25Q64_ReadJedecId(void);
/** 从W25Q64连续读取数据。 */
void W25Q64_Read(uint32_t address, uint8_t *buffer, uint16_t length);
/** 擦除包含指定地址的4KB扇区。 */
uint8_t W25Q64_EraseSector(uint32_t address);
/** 向W25Q64页内写入数据,长度不能跨越256字节页边界。 */
uint8_t W25Q64_PageProgram(uint32_t address, const uint8_t *data,
uint16_t length);
/** 将升级元数据中的request字节清零,表示升级已处理。 */
uint8_t W25Q64_ClearUpgradeRequest(void);
/** 写入Bootloader升级结果码,供主程序启动后上报。 */
uint8_t W25Q64_WriteUpgradeResult(uint8_t result);
#endif