Files
vd_960/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/cfig_flash.c
T
wangfq 8e58d5fdd1 fix(vd960DBN): 恢复 factory 配置写入 — 换新空片后配置永久丢失
8-13 止血(SPI 写触发复位)根因已 8-17 闭环(栈溢出+printf 重入, 非 SPI 问题),
offlog/snapshot 8-18 起持续 SPI 写入稳定 → 解除止血。
新空片(W25Q128)参数区无 magic + write_net_config 不写 magic → 每次上电
memory defaults, 保存配置永久丢失。恢复: mismatch 分支调 factory_dev_info()
写 magic+默认参数到 flash, 首次上电自动初始化。
2026-08-19 15:13:18 +08:00

504 lines
18 KiB
C

/**
******************************************************************************
* @file CFIG_FLASH.h
* @author wfq
* @version V1.0
* @date 2025-02-07
* @brief ??????????????????????????
* @attention
******************************************************************************
*/
#include "storage.h"
#include "config.h"
#include "cmcng.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "net_srv.h"
#define DEV_USER_FLASH_MAGIC PRODUCT_MODEL
#define CFG_FLASH_BLOCK_SIZE 0x200
#define DEV_CNG_ADDR_BASE (0x00) // + 0x200)
void factory_dev_info(void)
{
uint16_t i, j;
uint32_t _offset = 0;
uint16_t len = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
memcpy(mBuff, DEV_USER_FLASH_MAGIC, sizeof(DEV_USER_FLASH_MAGIC));
_offset = DEV_NUMER_ADDR_OFFSET;
memcpy(g_dev_number, gMacAddr, 6);
memcpy(&mBuff[_offset], g_dev_number, sizeof(g_dev_number));
mBuff[DEV_SUB_CODE_ADDR_OFFSET] = 0x01; // SSC net
mBuff[DEV_BUS_BAUD_ADDR_OFFSET] = BT_DISABLE_IDLE_TIMEOUT;
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 1] = (uint8_t)UART_BAUD_DEFAULT_PORT_1;
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 2] = (uint8_t)(UART_BAUD_DEFAULT_PORT_1 >> 8);
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 3] = (uint8_t)(UART_BAUD_DEFAULT_PORT_1 >> 16);
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 4] = 0x02;
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 5] = (uint8_t)UART_BAUD_DEFAULT_PORT_2;
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 6] = (uint8_t)(UART_BAUD_DEFAULT_PORT_2 >> 8);
mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 7] = (uint8_t)(UART_BAUD_DEFAULT_PORT_2 >> 16);
sprintf((char *)(&mBuff[DEV_PASSWORD_ADDR_OFFSET]), "%s", "123456");
// for(i = 0; i < CFG_FLASH_BLOCK_SIZE; i++){
// PRINT(" %02X", mBuff[i]);
// }
// PRINT("\nWill_Write_cng:");
SPI_Flash_Write(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
free(mBuff);
Delay_Ms(50);
Local_Net_Cfg lcfg = {
{gMacAddr[0], gMacAddr[1], gMacAddr[2], gMacAddr[3], gMacAddr[4], gMacAddr[5]},
{192,168,1,188},
{255,255,255,0},
{192,168,1,1},
{192,168,1,1},
5550,NET_REPORT_INTERVAL, 5505, // Master Port: tcp, udp, udp_message
5550, 4900 // Dev Port: tcp, udp
};
NET_CENTER_INFO ccfg = {
{192,168,1,222},
4999,5550,NET_REPORT_INTERVAL, {1,2}
};
IOT_NET_INFO icfg = {
"121.37.20.199",
1883,
" ",
"admin",
"password",
0
};
// 使用实际设备序列号生成默认 topic(V1.01 双主题协议)
char sn_str[13];
sprintf(sn_str, "%02X%02X%02X%02X%02X%02X",
gMacAddr[0], gMacAddr[1], gMacAddr[2],
gMacAddr[3], gMacAddr[4], gMacAddr[5]);
char default_pub[64], default_sub[64];
sprintf(default_pub, "dld960/%s/dev", sn_str);
sprintf(default_sub, "dld960/%s/srv", sn_str);
IOT_Topic _topic = {
0,
{0},
{0}
};
strncpy((char *)_topic.topic_pub, default_pub, MAX_TOPIC_LENGTH - 1);
strncpy((char *)_topic.topic_sub, default_sub, MAX_TOPIC_LENGTH - 1);
write_net_config(&lcfg, &ccfg, &icfg, &_topic);
}
char get_ble_safe_flag(void)
{
return g_ble_safe_flag;
}
void open_ble_safe_flag(void)
{
if(g_ble_safe_flag == 1)
{
return;
}
g_ble_safe_counter_dst = 0;
g_ble_safe_counter_ori = g_ble_safe_counter_dst;
g_ble_safe_flag = 1;
}
void close_ble_safe_flag(void)
{
if(g_ble_safe_flag == 0)
{
return;
}
g_ble_safe_flag = 0;
}
char check_ble_safe_pass(uint8_t * devpass)
{
if((g_dev_password[0] != devpass[0]) ||
(g_dev_password[1] != devpass[1]) ||
(g_dev_password[2] != devpass[2]) ||
(g_dev_password[3] != devpass[3]) ||
(g_dev_password[4] != devpass[4]) ||
(g_dev_password[5] != devpass[5]))
{
close_ble_safe_flag();
return 0;
}
open_ble_safe_flag();
return 1;
}
void set_ble_safe_pass(uint8_t * devpass)
{
uint16_t len = 0;
uint16_t _offset = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
_offset = DEV_PASSWORD_ADDR_OFFSET;
mBuff[_offset++] = devpass[0];
mBuff[_offset++] = devpass[1];
mBuff[_offset++] = devpass[2];
mBuff[_offset++] = devpass[3];
mBuff[_offset++] = devpass[4];
mBuff[_offset++] = devpass[5];
SPI_Flash_Write(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
free(mBuff);
}
void write_net_config(Local_Net_Cfg *local, NET_CENTER_INFO *center, IOT_NET_INFO *iotcfg, IOT_Topic *iottopic)
{
uint16_t i;
uint32_t _offset = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
_offset = NET_LOCAL_CFG_ADDR_OFFSET;
memcpy(&mBuff[_offset], local, sizeof(Local_Net_Cfg));
_offset = NET_CENTER_CFG_ADDR_OFFSET;
memcpy(&mBuff[_offset], center, sizeof(NET_CENTER_INFO));
_offset = IOT_NET_CFG_ADDR;
memcpy(&mBuff[_offset], iotcfg, sizeof(IOT_NET_INFO));
_offset = IOT_TOPIC_CFG_ADDR;
memcpy(&mBuff[_offset], iottopic, sizeof(IOT_Topic));
// for(i = 0; i < CFG_FLASH_BLOCK_SIZE; i++){
// PRINT(" %02X", mBuff[i]);
// }
// PRINT(" \nEND_Factory\n");
SPI_Flash_Write(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
free(mBuff);
Delay_Ms(50);
}
void load_cfg_from_flash(void)
{
uint16_t i, j;
uint32_t _offset = 0;
uint16_t len = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
// for(i = 0; i < CFG_FLASH_BLOCK_SIZE; i++){
// PRINT(" %02X", mBuff[i]);
// }
// PRINT("\n");
if(strncmp(mBuff, DEV_USER_FLASH_MAGIC, sizeof(DEV_USER_FLASH_MAGIC)) != 0)
{
free(mBuff);
/* ===== 恢复 factory 写入 (2026-08-19) =====
8-13 止血背景: factory SPI 写触发硬件复位死循环 — 根因已在 8-17 闭环
(.bss 挤占 RAM → 栈溢出 + printf 重入, 非 SPI 硬件问题);
offlog/snapshot 自 8-18 起持续 SPI 写入稳定。
换新空片 (W25Q128) 参数区无 magic → 每次上电 memory defaults,
且 write_net_config 保存配置不写 magic → 配置永久丢失。
恢复: 首次 mismatch 写出厂默认 (magic+参数) 到 flash, 后续上电正常加载。 */
factory_dev_info();
PRINT("CFG: magic mismatch - factory defaults written\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 (factory written)\n");
return;
}
_offset = DEV_NUMER_ADDR_OFFSET;
memcpy(g_dev_number, &mBuff[_offset], 6);
memcpy(g_dev_number, &mBuff[DEV_NUMER_ADDR_OFFSET], 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 = *(uint16_t *)(&mBuff[DEV_SUB_CODE_ADDR_OFFSET]);
g_max_counter_bt_min = mBuff[DEV_BUS_BAUD_ADDR_OFFSET];
g_max_counter_bt_timeout = g_max_counter_bt_min * 60 * 1000;
g_storage_uart_baud = (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 1]) | (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 2] << 8) | (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 3] << 16);
g_storage_uart_baud_2 = (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 5]) | (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 6] << 8) | (mBuff[DEV_BUS_BAUD_ADDR_OFFSET + 7] << 16);
memcpy(g_dev_password, &mBuff[DEV_PASSWORD_ADDR_OFFSET], 6);
memcpy(local_net_cfg.mac, g_dev_number, 6);
_offset = NET_LOCAL_CFG_ADDR_OFFSET;
Local_Net_Cfg *lnet = (Local_Net_Cfg *)(&mBuff[_offset]);
// memcpy(local_net_cfg.mac, lnet->mac, 6);
memcpy(local_net_cfg.lip, lnet->lip, 4);
memcpy(local_net_cfg.sub, lnet->sub, 4);
memcpy(local_net_cfg.gw, lnet->gw, 4);
memcpy(local_net_cfg.dns, lnet->dns, 4);
local_net_cfg.port_ssc_tcp = lnet->port_ssc_tcp;
local_net_cfg.port_ssc_udp = lnet->port_ssc_udp;
local_net_cfg.port_ssc_udp_message = lnet->port_ssc_udp_message;
local_net_cfg.port_dev_tcp = lnet->port_dev_tcp;
local_net_cfg.port_dev_udp = lnet->port_dev_udp;
_offset = NET_CENTER_CFG_ADDR_OFFSET;
NET_CENTER_INFO *cinfo = (NET_CENTER_INFO *)(&mBuff[_offset]);
memcpy(net_center_info.lssc_ip, cinfo->lssc_ip, 4);
net_center_info.msg_port = cinfo->msg_port;
net_center_info.tcp_port = cinfo->tcp_port;
net_center_info.udp_port = cinfo->udp_port;
memcpy(net_center_info.sw_ver, cinfo->sw_ver, 2);
_offset = IOT_NET_CFG_ADDR;
IOT_NET_INFO *iinfo = (IOT_NET_INFO *)(&mBuff[_offset]);
memcpy(iot_net_info.remote_addr, iinfo->remote_addr, 64);
iot_net_info.mqtt_port = iinfo->mqtt_port;
memcpy(iot_net_info.client_id, iinfo->client_id, 64);
memcpy(iot_net_info.username, iinfo->username, 64);
memcpy(iot_net_info.password, iinfo->password, 32);
//check dns or ip mode
iot_net_info.mode = iinfo->mode; //dns or ip mode
_offset = IOT_TOPIC_CFG_ADDR;
IOT_Topic *_topic = (IOT_Topic *)(&mBuff[_offset]);
g_iot_topic.clientid_enable = _topic->clientid_enable;
memcpy(g_iot_topic.topic_pub, _topic->topic_pub, 64);
memcpy(g_iot_topic.topic_sub, _topic->topic_sub, 64);
/* 2026-08-17: 字符串 0 终止保险 — Flash 中字符串若不足定长且后续 0xFF,
%s 打印会越界(历史乱码根因之一)。强制定长缓冲末字节为 '\0' */
iot_net_info.remote_addr[63] = '\0';
iot_net_info.client_id[63] = '\0';
iot_net_info.username[63] = '\0';
iot_net_info.password[31] = '\0';
g_iot_topic.topic_pub[63] = '\0';
g_iot_topic.topic_sub[63] = '\0';
free(mBuff);
g_sub_code_enable.net_enable = g_sub_code_enable.code_set & 0x01;
g_sub_code_enable.iot_enable = (g_sub_code_enable.code_set >> 1) & 0x01;
g_sub_code_enable.custom_enable = (g_sub_code_enable.code_set >> 2) & 0x01;
g_sub_code_enable.loop_enable = (g_sub_code_enable.code_set >> 3) & 0x01;
g_sub_code_enable.dgdus_enable = (g_sub_code_enable.code_set >> 4) & 0x01;
g_sub_code_enable.wbdus_enable = (g_sub_code_enable.code_set >> 5) & 0x01;
g_sub_code_enable.radar_enable = (g_sub_code_enable.code_set >> 6) & 0x01;
/* 2026-08-17 栈溢出修复后恢复 */
PRINT("\nSub_Code: 0x%04X, net_enable:%d, iot_enable:%d\n", g_sub_code_enable.code_set, g_sub_code_enable.net_enable, g_sub_code_enable.iot_enable);
// g_sub_code_enable.laser_enable = (g_sub_code_enable.code_set >> 9) & 0x01;
// g_sub_code_enable.lora_enable = (g_sub_code_enable.code_set >> 15) & 0x01;
}
void output_cfg_from_flash(void)
{
// if(g_flag_debug)
// {
PRINT("\nBaud1:%d, Baud2:%d\n", g_storage_uart_baud, g_storage_uart_baud_2);
PRINT("\nSub_Code:0x%04X\n", g_sub_code_enable.code_set);
PRINT("\nGet Net config:\n");
PRINT("Local Net Config: "
" mac:%02X-%02X-%02X-%02X-%02X-%02X\n"
" ip:%d.%d.%d.%d\n"
" submask:%d.%d.%d.%d\n"
" gateway:%d.%d.%d.%d\n"
" dns:%d.%d.%d.%d\n"
" ssc_port tcp: %d, udp:%d, udp_msg:%d\n"
" dev_port tcp: %d, udp:%d\n",
local_net_cfg.mac[0],local_net_cfg.mac[1],local_net_cfg.mac[2],local_net_cfg.mac[3],local_net_cfg.mac[4],local_net_cfg.mac[5],
local_net_cfg.lip[0],local_net_cfg.lip[1],local_net_cfg.lip[2],local_net_cfg.lip[3],
local_net_cfg.sub[0],local_net_cfg.sub[1],local_net_cfg.sub[2],local_net_cfg.sub[3],
local_net_cfg.gw[0],local_net_cfg.gw[1],local_net_cfg.gw[2],local_net_cfg.gw[3],
local_net_cfg.dns[0],local_net_cfg.dns[1],local_net_cfg.dns[2],local_net_cfg.dns[3],
local_net_cfg.port_ssc_tcp, local_net_cfg.port_ssc_udp, local_net_cfg.port_ssc_udp_message,
local_net_cfg.port_dev_tcp, local_net_cfg.port_dev_udp
);
PRINT("Net Center Config:\n");
PRINT(
" lssc_ip:%d.%d.%d.%d\n"
" msg_port:%d, tcp_port:%d, udp_port:%d, sw_ver:%d.%d\n",
net_center_info.lssc_ip[0], net_center_info.lssc_ip[1], net_center_info.lssc_ip[2], net_center_info.lssc_ip[3],
net_center_info.msg_port, net_center_info.tcp_port, net_center_info.udp_port,
net_center_info.sw_ver[0], net_center_info.sw_ver[1]);
PRINT("Iot Net Config:\n");
PRINT(
" remote_addr:%s\n"
" mqtt_port:%d, client_id:%s\n"
" username:%s\n"
" password:%s\n"
" mode:%d\n\n",
iot_net_info.remote_addr, iot_net_info.mqtt_port, iot_net_info.client_id,
iot_net_info.username, iot_net_info.password, iot_net_info.mode);
PRINT("Iot Topic Config:\n");
PRINT(
" clientid_enable:%d\n"
" topic_pub:%s\n"
" topic_sub:%s\n",
g_iot_topic.clientid_enable, g_iot_topic.topic_pub, g_iot_topic.topic_sub);
// }
}
// g_sub_code_enable.code_set get ready first.
void update_sub_code_enable(void)
{
uint32_t _offset = 0;
uint16_t len = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
PRINT("Err_When_malloc__\n");
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
_offset = DEV_SUB_CODE_ADDR_OFFSET;
memcpy(&mBuff[_offset], &(g_sub_code_enable.code_set), sizeof(g_sub_code_enable.code_set));
SPI_Flash_Write(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
free(mBuff);
Delay_Ms(50);
}
//
void alter_dev_serila(uint8_t *serial)
{
uint32_t _offset = 0;
uint16_t len = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
memcpy(&mBuff[DEV_NUMER_ADDR_OFFSET], serial, 6);
SPI_Flash_Write(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
free(mBuff);
}
void alter_dev_baud(uint8_t *baudbuf)
{
uint32_t _offset = 0;
uint8_t *mBuff = (uint8_t *)malloc(CFG_FLASH_BLOCK_SIZE);
if(mBuff == NULL)
{
return;
}
memset(mBuff, 0, CFG_FLASH_BLOCK_SIZE);
SPI_Flash_Read(mBuff, DEV_CNG_ADDR_BASE, CFG_FLASH_BLOCK_SIZE);
memcpy(&mBuff[DEV_BUS_BAUD_ADDR_OFFSET], baudbuf, 8);
free(mBuff);
}