test(vd960DBN): SPI写密度模拟实验 + factory写止血 — VDD跌落诊断

- peripheral_main: sim_snap_spi 模拟快照落盘节奏 (20ms 64B页写 + 每64条切扇区擦除+头写)
- cfig_flash: magic不匹配时跳过 factory SPI_Flash_Write, 用内存默认值继续
  (SPI写触发硬件复位死循环止血: 参数区0x00写也崩, RST=0x00000000)
- 诊断修正: CH32V208GBU6 QFN28 无 NRST 引脚, 共线假设作废;
  SPI写/擦除→电流尖峰→VDD跌落→内部POR/PDR(2.4V)复位;
  BLE射频+SPI电流叠加是头号嫌疑
This commit is contained in:
wangfq
2026-08-13 11:27:08 +08:00
parent 99ef6348d7
commit 87c8e01936
2 changed files with 120 additions and 5 deletions
@@ -241,11 +241,56 @@ void load_cfg_from_flash(void)
if(strncmp(mBuff, DEV_USER_FLASH_MAGIC, sizeof(DEV_USER_FLASH_MAGIC)) != 0)
{
free(mBuff);
PRINT("Will_Factory_dev_____\n");
factory_dev_info();
NVIC_SystemReset();
/* ===== 止血 (2026-08-13): factory SPI 写触发硬件复位死循环 =====
现场: SPI_Flash_Write(参数区 0x00, 512B) → RST=0x00000000 硬件复位
→ magic 写不进 → 无限复位循环。SPI 写触发硬件复位实锤(与快照区无关)。
临时方案: 不写 Flash, 用内存默认配置继续 (恢复原逻辑删本块即可) */
PRINT("CFG: magic mismatch - MEMORY DEFAULTS (factory SPI write disabled)\n");
memset(g_dev_number, 0, 6);
memcpy(g_dev_number, gMacAddr, 6);
sprintf(g_dev_number_str, "%02X%02X%02X%02X%02X%02X",
g_dev_number[0], g_dev_number[1], g_dev_number[2],
g_dev_number[3], g_dev_number[4], g_dev_number[5]);
g_sub_code_enable.code_set = 0x0001;
g_max_counter_bt_min = BT_DISABLE_IDLE_TIMEOUT;
g_max_counter_bt_timeout = g_max_counter_bt_min * 60 * 1000;
g_storage_uart_baud = UART_BAUD_DEFAULT_PORT_1;
g_storage_uart_baud_2 = UART_BAUD_DEFAULT_PORT_2;
memcpy(g_dev_password, "123456", 6);
memcpy(local_net_cfg.mac, g_dev_number, 6);
local_net_cfg.lip[0] = 192; local_net_cfg.lip[1] = 168; local_net_cfg.lip[2] = 1; local_net_cfg.lip[3] = 188;
local_net_cfg.sub[0] = 255; local_net_cfg.sub[1] = 255; local_net_cfg.sub[2] = 255; local_net_cfg.sub[3] = 0;
local_net_cfg.gw[0] = 192; local_net_cfg.gw[1] = 168; local_net_cfg.gw[2] = 1; local_net_cfg.gw[3] = 1;
local_net_cfg.dns[0] = 192; local_net_cfg.dns[1] = 168; local_net_cfg.dns[2] = 1; local_net_cfg.dns[3] = 1;
local_net_cfg.port_ssc_tcp = 5550;
local_net_cfg.port_ssc_udp = NET_REPORT_INTERVAL;
local_net_cfg.port_ssc_udp_message = 5505;
local_net_cfg.port_dev_tcp = 5550;
local_net_cfg.port_dev_udp = 4900;
net_center_info.lssc_ip[0] = 192; net_center_info.lssc_ip[1] = 168; net_center_info.lssc_ip[2] = 1; net_center_info.lssc_ip[3] = 222;
net_center_info.msg_port = 4999;
net_center_info.tcp_port = 5550;
net_center_info.udp_port = NET_REPORT_INTERVAL;
net_center_info.sw_ver[0] = 1; net_center_info.sw_ver[1] = 2;
memset(iot_net_info.remote_addr, 0, 64);
memcpy(iot_net_info.remote_addr, "121.37.20.199", 13);
iot_net_info.mqtt_port = 1883;
memset(iot_net_info.client_id, 0, 64);
memset(iot_net_info.username, 0, 64); memcpy(iot_net_info.username, "admin", 5);
memset(iot_net_info.password, 0, 32); memcpy(iot_net_info.password, "password", 8);
iot_net_info.mode = 0;
g_iot_topic.clientid_enable = 0;
memset(g_iot_topic.topic_pub, 0, 64);
memset(g_iot_topic.topic_sub, 0, 64);
g_sub_code_enable.net_enable = 1;
g_sub_code_enable.iot_enable = 0;
g_sub_code_enable.custom_enable = 0;
g_sub_code_enable.loop_enable = 0;
g_sub_code_enable.dgdus_enable = 0;
g_sub_code_enable.wbdus_enable = 0;
g_sub_code_enable.radar_enable = 0;
PRINT("CFG: memory defaults OK (no factory write)\n");
return;
}
_offset = DEV_NUMER_ADDR_OFFSET;
@@ -217,6 +217,75 @@ void key_event_srv(void){
}
/*********************************************************************
* @fn sim_snap_spi
*
* @brief 实验(2026-08-13 第一步): 模拟快照区 SPI 写密度
*
* 当前固件: snap_init 已 #if 0 跳过 (纯读基座, 日志读写正常)。
* 本函数恢复快照落盘的写节奏, 隔离"SPI 写频率" vs "快照逻辑 bug":
* - 每 20ms: 64B 页写 (SPI_Flash_Write_NoCheck, 模拟 snap_write_raw)
* - 每 64 条: 切扇区序列 (读首条 magic + 擦除 45ms +
* 头区 SPI_Flash_Write 读-改-写整扇区, 模拟 snap_flush_head)
* 复现复位 → SPI 高频写触发硬件问题 (PA7/NRST 共线怀疑坐实);
* 不复现 → 快照区有具体逻辑 bug, 转向代码审查。
* 注意: 会覆盖快照区旧数据, 恢复快照功能前需 snap_clear。
*
* @return none
*/
#define SIM_SNAP_HEAD_BASE 0x110000UL
#define SIM_SNAP_DATA_BASE 0x111000UL
#define SIM_SNAP_DATA_SIZE (4096UL * 751UL) /* 与 snapshot.c 数据扇区数一致 */
static uint32_t _sim_snap_wr = SIM_SNAP_DATA_BASE;
static uint32_t _sim_snap_cnt = 0;
static uint32_t _sim_snap_last = 0;
void sim_snap_spi(void)
{
uint32_t _now = mstick();
if ((uint32_t)(_now - _sim_snap_last) < 20) return; /* 20ms 节拍 = 50Hz 帧率 */
_sim_snap_last = _now;
/* 切扇区: 每 64 条 (4096/64) 一次, 与 snap_write_raw 同节奏 */
if (_sim_snap_cnt > 0 && (_sim_snap_cnt & 63) == 0)
{
uint8_t _r[64];
uint8_t _h[32];
/* 1) snap_sector_has_data: 读目标扇区首条 magic */
SPI_Flash_Read(_r, _sim_snap_wr, 64);
/* 2) SPI_Flash_Erase_Sector (~45ms) */
SPI_Flash_Erase_Sector(_sim_snap_wr / 4096);
/* 3) snap_flush_head: 头区读-改-写 (SPI_Flash_Write 内部
读4096 + 擦 + 写回4096, ~100ms) */
memset(_h, 0xFF, sizeof(_h));
_h[0] = 'S'; _h[1] = 'N'; _h[2] = 'P'; _h[3] = 'M';
_h[8] = (uint8_t)(_sim_snap_cnt & 0xFF);
_h[9] = (uint8_t)((_sim_snap_cnt >> 8) & 0xFF);
_h[10] = (uint8_t)((_sim_snap_cnt >> 16) & 0xFF);
_h[11] = (uint8_t)((_sim_snap_cnt >> 24) & 0xFF);
SPI_Flash_Write(_h, SIM_SNAP_HEAD_BASE, 32);
}
/* 模拟 snap_write_raw: 64B 页写 */
{
static uint8_t _b[64];
uint8_t _i;
for (_i = 0; _i < 64; _i++) _b[_i] = (uint8_t)(_sim_snap_cnt + _i);
_b[0] = 'S'; _b[1] = 'N'; _b[2] = 'P'; _b[3] = 'M';
SPI_Flash_Write_NoCheck(_b, _sim_snap_wr, 64);
_sim_snap_wr += 64;
if (_sim_snap_wr >= SIM_SNAP_DATA_BASE + SIM_SNAP_DATA_SIZE)
_sim_snap_wr = SIM_SNAP_DATA_BASE;
_sim_snap_cnt++;
if ((_sim_snap_cnt & 0x3F) == 0)
PRINT("SIM: cnt=%lu wr=0x%08lx\n",
(unsigned long)_sim_snap_cnt, (unsigned long)_sim_snap_wr);
}
}
/*********************************************************************
* @fn Main_Circulation
*
@@ -269,6 +338,7 @@ void Main_Circulation(void)
uart_srv();
snap_flush(); /* 快照落盘: 无条件挂主循环 (原在 iot_enable 分支, TCP 模式不落盘) */
sim_snap_spi(); /* 实验第一步(2026-08-13): 模拟快照区 SPI 写密度, 定位复位触发源 */
poll_dbn_ble();