feat(device): 添加早期诊断功能并优化SPI通信实现

- 在startup_gd32e50x_cl.s中添加USART0早期诊断代码,在Reset_Handler中
  发送'R'字符以确认启动过程

- 修改system_gd32e50x.c中的时钟初始化逻辑,支持动态检测当前时钟源
  (PLL或IRC8M)并相应调整串口波特率设置

- 在系统时钟配置函数中添加HXTAL故障诊断输出,当外部晶振启动失败时
  通过USART0输出"HXTAL FAIL"错误信息

- 在AppSpiCommand类中实现DMA传输机制,使用DMA0_CH2进行SPI0数据发送,
  提升传输效率并与BOOT端保持一致

- 重构SPI命令处理逻辑,优化PING命令响应格式,包含APP和BOOT版本信息
  以及运行时间统计

- 添加事务过滤机制,忽略全0xFF或全0x00的数据包以及短帧

- 更新配置文件定义APP固件版本号和OTA配置页面地址

- 修复region配置文件中的ROM大小数值精度问题

- 调整NVIC中断优先级设置,优化SPI中断处理
This commit is contained in:
cbb
2026-06-03 03:13:49 +08:00
parent 771d34398f
commit d0b6d9537e
10 changed files with 502 additions and 49 deletions
@@ -1,4 +1,4 @@
#ifndef REGIONS_GD32E508VE_H
#ifndef REGIONS_GD32E508VE_H
#define REGIONS_GD32E508VE_H
@@ -17,7 +17,7 @@
#define __ROM0_BASE 0x08048000
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
// <i> Defines size of memory region. Default: 0x00080000
#define __ROM0_SIZE 0x00036000
#define __ROM0_SIZE 0x00035FFC
// </h>
// <h> __ROM1 (unused)
@@ -175,6 +175,48 @@ Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
;=== EARLY DIAG: send 'R' via raw USART0 before any C code ===
; 使 GPIOA + USART0 时钟可用
LDR R1, =0x40021018 ; RCU_APB2EN
LDR R2, [R1]
ORRS R2, R2, #(1 << 2) ; RCU_GPIOA
ORRS R2, R2, #(1 << 14) ; RCU_USART0
STR R2, [R1]
; PA9 设为 AF_PP 50MHz (CTL1 bits[7:4] = 0xB)
LDR R1, =0x40010804 ; GPIOA_CTL1
LDR R2, [R1]
LDR R3, =0xFFFFFF0F ; mask: keep all except bits[7:4]
ANDS R2, R2, R3
ORRS R2, R2, #0xB0 ; bits[7:4] = 0xB (AF_PP 50MHz)
STR R2, [R1]
; 检测当前时钟源,选择正确波特率
LDR R1, =0x40021000 ; RCU_CFG0
LDR R2, [R1]
LSRS R2, R2, #2 ; SCSS bits [3:2]
ANDS R2, R2, #0x3
CMP R2, #0x2 ; SCSS == PLL ?
LDR R3, =1562 ; 180MHz / 115200
LDR R4, =69 ; 8MHz / 115200
ITE EQ
MOVEQ R2, R3 ; PLL -> 180MHz baud divisor
MOVNE R2, R4 ; IRC8M -> 8MHz baud divisor
LDR R1, =0x40013808 ; USART0_BAUD
STR R2, [R1]
LDR R1, =0x40013800 ; USART0_CTL0
MOVS R2, #(1 << 3) ; TE
ORRS R2, R2, #(1 << 13) ; | USARTEN
STR R2, [R1]
LDR R1, =0x40013804 ; USART0_DATA
MOVS R2, #'R'
STR R2, [R1]
LDR R1, =0x40013800 ; USART0_CTL0
_rh_wait_tc
LDR R2, [R1]
LSRS R2, R2, #7 ; TC bit
BCC _rh_wait_tc
;=== END EARLY DIAG ===
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
@@ -162,7 +162,7 @@ static void _soft_delay_(uint32_t time)
*/
void SystemInit (void)
{
/* ===== DIAG: raw USART0 output at IRC8M (8MHz) ===== */
/* ===== DIAG: raw USART0 output — detect current clock for baudrate ===== */
/* Enable AFIO + GPIOA + USART0 clocks via raw register */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
/* PA9 = AF_PP, 50MHz (CTL=0b11, MD=0b11) -> CTL1 bit[4..7]=0b1011 */
@@ -172,8 +172,18 @@ void SystemInit (void)
ctl |= (0xBU << 4); /* AF_PP 50MHz */
*((volatile uint32_t *)0x40010804U) = ctl;
}
/* USART0 baud: BAUD = 8000000/115200 = 69 */
*((volatile uint32_t *)0x40013808U) = 69U;
/* Detect current system clock: if PLL is selected, assume 180MHz; otherwise IRC8M=8MHz.
* This handles both cold boot (IRC8M) and BOOT jump (PLL 180MHz). */
{
uint32_t scss = (*((volatile uint32_t *)0x40021000U) >> 2) & 0x3U; /* RCU_CFG0 SCSS bits */
uint32_t baud_div;
if (scss == 0x2U) { /* PLL selected as system clock -> 180MHz */
baud_div = 180000000U / 115200U; /* = 1562 */
} else { /* IRC8M or HXTAL -> 8MHz */
baud_div = 8000000U / 115200U; /* = 69 */
}
*((volatile uint32_t *)0x40013808U) = baud_div;
}
/* USART0 CTL0: TE + EN = bit3 + bit13 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
/* Send "APP" via USART0 DATA register */
@@ -647,8 +657,18 @@ static void system_clock_hxtal(void)
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
/* HXTAL failed: output diagnostic via USART0 at IRC8M */
*((volatile uint32_t *)0x40021018U) |= (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
/* AHB = SYSCLK */
@@ -693,8 +713,18 @@ static void system_clock_72m_hxtal(void)
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
/* HXTAL failed: output diagnostic via USART0 at IRC8M */
*((volatile uint32_t *)0x40021018U) |= (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1);
@@ -801,8 +831,18 @@ static void system_clock_120m_hxtal(void)
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
/* HXTAL failed: output diagnostic via USART0 at IRC8M */
*((volatile uint32_t *)0x40021018U) |= (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3);
@@ -910,8 +950,18 @@ static void system_clock_168m_hxtal(void)
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
/* HXTAL failed: output diagnostic via USART0 at IRC8M */
*((volatile uint32_t *)0x40021018U) |= (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);
@@ -1019,8 +1069,18 @@ static void system_clock_180m_hxtal(void)
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
/* HXTAL failed: output diagnostic via USART0 at IRC8M */
*((volatile uint32_t *)0x40021018U) |= (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);