feat: complete assembly mesh relay control path
- synchronize STM8 application and external flash layout updates\n- add assembly bootloader and assembly application test projects\n- add UART1 interrupt receive ring buffer\n- parse JDY-28M Mesh outer frames and source addresses\n- add CRC-16/MODBUS validation\n- implement relay control command 0x01 and response 0x81\n- support unicast and broadcast relay control frames\n- update host protocol, OTA documents, and serial tools
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
```text
|
||||
0x8000 ~ 0x83FF Bootloader,1KB
|
||||
0x8400 ~ 0x9FFF Application,7KB
|
||||
0x8500 ~ 0x9FFF Application,6.75KB
|
||||
```
|
||||
|
||||
当前版本完成的基础功能:
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
/** Bootloader 在 STM8 程序 Flash 中的起始地址。 */
|
||||
#define BOOTLOADER_START_ADDRESS 0x8000u
|
||||
/** Bootloader 预留空间,当前规划为 1KB。 */
|
||||
#define BOOTLOADER_SIZE_BYTES 0x0800u
|
||||
#define BOOTLOADER_SIZE_BYTES 0x0500u
|
||||
/** 应用程序固定入口地址,必须与应用工程链接地址一致。 */
|
||||
#define APPLICATION_START_ADDRESS 0x8800u
|
||||
#define APPLICATION_START_ADDRESS 0x8500u
|
||||
/** STM8S003F3P6 程序 Flash 的最后一个地址。 */
|
||||
#define APPLICATION_END_ADDRESS 0x9FFFu
|
||||
/** 应用程序允许使用的最大空间。 */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/** 初始化STM8硬件SPI和W25Q64片选;当前片选引脚为PD4。 */
|
||||
void W25Q64_Init(void);
|
||||
uint8_t W25Q64_Init(void);
|
||||
/** 读取W25Q64 JEDEC ID,便于启动时确认芯片存在。 */
|
||||
uint32_t W25Q64_ReadJedecId(void);
|
||||
/** 从W25Q64连续读取数据。 */
|
||||
|
||||
@@ -391,7 +391,6 @@ void Bootloader_Init(void)
|
||||
{
|
||||
Bootloader_WatchdogInit();
|
||||
Bootloader_ButtonInit();
|
||||
W25Q64_Init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -491,6 +490,19 @@ void Bootloader_Task(void)
|
||||
uint8_t upgrade_requested = 0u;
|
||||
uint8_t upgrade_success = 0u;
|
||||
uint8_t factory_button_held;
|
||||
uint8_t flash_ready;
|
||||
|
||||
flash_ready = W25Q64_Init();
|
||||
if (flash_ready == 0u)
|
||||
{
|
||||
/* 外部Flash故障不能阻止已有主程序启动;只有应用也无效时,
|
||||
* 才停止喂狗并等待硬件复位。 */
|
||||
if (Bootloader_IsApplicationValid() != 0u)
|
||||
{
|
||||
Bootloader_JumpToApplication();
|
||||
}
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
factory_button_held = Bootloader_IsFactoryButtonHeld();
|
||||
if (factory_button_held != 0u)
|
||||
|
||||
@@ -4,6 +4,30 @@
|
||||
*/
|
||||
#include "bootloader.h"
|
||||
|
||||
/**
|
||||
* @brief Bootloader固定TIM4向量的转发入口。
|
||||
*
|
||||
* STM8S003F3的TIM4 IRQ23固定位于0x8064。Bootloader占用0x8000区域后,
|
||||
* 应用程序位于0x8500,硬件不会自动改用应用程序向量表。因此这里将
|
||||
* Bootloader的TIM4中断请求转发到应用程序TIM4向量槽0x8564。
|
||||
*/
|
||||
void Bootloader_TIM4_Vector(void) __interrupt(23)
|
||||
{
|
||||
/* 使用项目此前已经完成实物验证的普通中断转发方式。 */
|
||||
__asm__("jpf 0x8564");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bootloader固定UART1接收向量的转发入口。
|
||||
*
|
||||
* UART1接收为IRQ18,固定硬件向量地址为0x8050。主程序对应向量槽为
|
||||
* 0x8550,转发后再由主程序向量进入实际UART接收ISR。
|
||||
*/
|
||||
void Bootloader_UART1_RX_Vector(void) __interrupt(18)
|
||||
{
|
||||
__asm__("jpf 0x8550");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bootloader 入口函数。
|
||||
* @return 理论上不会返回。
|
||||
|
||||
@@ -41,9 +41,13 @@ static void W25Q64_Deselect(void)
|
||||
*/
|
||||
static uint8_t W25Q64_Transfer(uint8_t value)
|
||||
{
|
||||
while ((SPI1_SR & SPI_SR_TXE) == 0u) {}
|
||||
uint16_t timeout = 60000u;
|
||||
while ((SPI1_SR & SPI_SR_TXE) == 0u && timeout-- != 0u) {}
|
||||
if (timeout == 0u) return 0xFFu;
|
||||
SPI1_DR = value;
|
||||
while ((SPI1_SR & SPI_SR_RXNE) == 0u) {}
|
||||
timeout = 60000u;
|
||||
while ((SPI1_SR & SPI_SR_RXNE) == 0u && timeout-- != 0u) {}
|
||||
if (timeout == 0u) return 0xFFu;
|
||||
return SPI1_DR;
|
||||
}
|
||||
|
||||
@@ -93,7 +97,7 @@ static uint8_t W25Q64_WaitReady(void)
|
||||
* SPI采用主机模式、模式0、MSB first,并使用较低初始时钟,降低上电阶段
|
||||
* 外部Flash尚未稳定时出现通信错误的概率。
|
||||
*/
|
||||
void W25Q64_Init(void)
|
||||
uint8_t W25Q64_Init(void)
|
||||
{
|
||||
/* PC5、PC6配置为推挽输出;PC7配置为输入;PD4配置为CS#输出。 */
|
||||
GPIOC_DDR |= 0x60u;
|
||||
@@ -106,6 +110,11 @@ void W25Q64_Init(void)
|
||||
SPI1_CR1 = (uint8_t)(SPI_CR1_MSTR | SPI_CR1_BR2 |
|
||||
SPI_CR1_BR1 | SPI_CR1_BR0 | SPI_CR1_SPE);
|
||||
SPI1_CR2 = (uint8_t)(SPI_CR2_SSM | SPI_CR2_SSI);
|
||||
if (W25Q64_ReadJedecId() != 0xEF4014ul)
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
return 1u;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user