修复了网络参数的保存逻辑
This commit is contained in:
@@ -57,11 +57,19 @@ int lftpd_inet_get_socket_port(int socket)
|
||||
|
||||
int lftpd_inet_accept(int socket)
|
||||
{
|
||||
/* 网络重建(net_init)后旧 Socket 已失效:检测到代次变化即返回 -1,
|
||||
* 由 lftpd_start 外层循环重建监听(网络未就绪时其 listen 会重试) */
|
||||
uint32_t gen = net_get_generation();
|
||||
|
||||
while (1) {
|
||||
int s = net_accept(socket, NULL, NULL);
|
||||
if (s >= 0) {
|
||||
return s;
|
||||
}
|
||||
if (net_get_generation() != gen) {
|
||||
DBG_ERROR("network re-init: abort accept, relisten");
|
||||
return -1;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/*
|
||||
* 模块名称:Network Configuration
|
||||
* 模块功能:网络子系统配置宏定义,包括最大Socket数量、缓冲区大小、
|
||||
* 超时时间等参数配置
|
||||
* 模块功能:网络子系统编译期参数——Socket 数量、收发超时、TCP KeepAlive。
|
||||
* 仅保留**实际被引用**的宏;未使用项已清理。
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
* 2026-09-10 王建锋 清理未引用宏(TCP Server 监听 Socket 索引、收发缓冲、
|
||||
* 连接/接受超时、select/队列/轮询);KeepAlive 三宏改为
|
||||
* 实际生效值 60s/5s/3 并在 net_socket.c 引用(原宏为无效遗留值)
|
||||
*/
|
||||
|
||||
#ifndef NET_CONFIG_H
|
||||
@@ -22,37 +25,10 @@ extern "C" {
|
||||
#define NET_MAX_SOCKETS 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP Server 多连接模式配置
|
||||
* 监听 Socket 索引和数据 Socket 起始索引
|
||||
*/
|
||||
#ifndef NET_TCP_SERVER_LISTEN_SOCK
|
||||
#define NET_TCP_SERVER_LISTEN_SOCK 0 /* 监听 Socket 索引 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 缓冲区大小配置
|
||||
*/
|
||||
#ifndef NET_SEND_BUF_SIZE
|
||||
#define NET_SEND_BUF_SIZE 4096 /* 发送缓冲区大小(字节) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_RECV_BUF_SIZE
|
||||
#define NET_RECV_BUF_SIZE 4096 /* 接收缓冲区大小(字节) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 超时时间配置(毫秒)
|
||||
* 0 = 无限等待(阻塞模式)
|
||||
*/
|
||||
#ifndef NET_CONNECT_TIMEOUT_MS
|
||||
#define NET_CONNECT_TIMEOUT_MS 5000 /* 连接超时 */
|
||||
#endif
|
||||
|
||||
#ifndef NET_ACCEPT_TIMEOUT_MS
|
||||
#define NET_ACCEPT_TIMEOUT_MS 0 /* 接受连接超时(0=无限等待) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_SEND_TIMEOUT_MS
|
||||
#define NET_SEND_TIMEOUT_MS 1000 /* 发送超时 */
|
||||
#endif
|
||||
@@ -62,39 +38,19 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP KeepAlive 配置
|
||||
* TCP KeepAlive 配置(单位 ms;须为 500 的倍数且 IDLE > INTVL)
|
||||
* 由 net_socket.c 的 net_init() 在 ch395f_init() 之前下发
|
||||
*/
|
||||
#ifndef NET_KEEPALIVE_IDLE_MS
|
||||
#define NET_KEEPALIVE_IDLE_MS 7200000 /* KeepAlive 空闲时间(默认2小时) */
|
||||
#define NET_KEEPALIVE_IDLE_MS 60000 /* 空闲 60 秒后开始探测 */
|
||||
#endif
|
||||
|
||||
#ifndef NET_KEEPALIVE_INTVL_MS
|
||||
#define NET_KEEPALIVE_INTVL_MS 75000 /* KeepAlive 探测间隔(默认75秒) */
|
||||
#define NET_KEEPALIVE_INTVL_MS 5000 /* 5 秒探测一次 */
|
||||
#endif
|
||||
|
||||
#ifndef NET_KEEPALIVE_CNT
|
||||
#define NET_KEEPALIVE_CNT 9 /* KeepAlive 探测次数(默认9次) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* select/poll 最大 fd 数量
|
||||
*/
|
||||
#ifndef NET_SELECT_MAX_FDS
|
||||
#define NET_SELECT_MAX_FDS NET_MAX_SOCKETS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 轮询延时配置(毫秒)
|
||||
*/
|
||||
#ifndef NET_POLL_DELAY_MS
|
||||
#define NET_POLL_DELAY_MS 1 /* 非阻塞轮询延时 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 消息队列配置
|
||||
*/
|
||||
#ifndef NET_MSG_QUEUE_LENGTH
|
||||
#define NET_MSG_QUEUE_LENGTH 8 /* 消息队列深度 */
|
||||
#define NET_KEEPALIVE_CNT 3 /* 最多探测 3 次 */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -40,6 +40,7 @@ static int s_net_errno = 0; /* 最后错误码 */
|
||||
static uint8_t s_net_initialized = 0; /* 初始化标志 */
|
||||
static uint8_t s_local_ip[4]; /* 本机 IP 缓存(网络序,net_getsockname 用) */
|
||||
static uint16_t s_dynamic_port = 49152; /* 动态端口分配起始值 */
|
||||
static volatile uint32_t s_net_generation = 0; /* 网络代次号:网络重建完成时递增(服务据此重建监听) */
|
||||
|
||||
/*
|
||||
* 消息队列 - 线程安全核心
|
||||
@@ -142,10 +143,11 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
||||
ch395f_set_retrans_count(8); /* 重传 8 次*/
|
||||
ch395f_set_retrans_period(500); /* 每次间隔 500ms,总计 4s 重传窗口 */
|
||||
|
||||
/* 设置 TCP KeepAlive 参数(必须在 INIT_CH395 之前,单位 ms,必须为 500 的倍数,且 IDLE > INTVL)*/
|
||||
ch395f_set_keepalive_idle(60000); /* 空闲 60 秒后开始探测*/
|
||||
ch395f_set_keepalive_intvl(5000); /* 5 秒探测一次*/
|
||||
ch395f_set_keepalive_cnt(3); /* 最多探 3 次*/
|
||||
/* 设置 TCP KeepAlive 参数(必须在 INIT_CH395 之前,单位 ms,必须为 500 的倍数,且 IDLE > INTVL)
|
||||
* 值来自 net_config.h 的 NET_KEEPALIVE_*(60s/5s/3)*/
|
||||
ch395f_set_keepalive_idle(NET_KEEPALIVE_IDLE_MS); /* 空闲 60 秒后开始探测*/
|
||||
ch395f_set_keepalive_intvl(NET_KEEPALIVE_INTVL_MS); /* 5 秒探测一次*/
|
||||
ch395f_set_keepalive_cnt(NET_KEEPALIVE_CNT); /* 最多探 3 次*/
|
||||
|
||||
/* 设置网络参数(必须在 INIT_CH395 之前调用 */
|
||||
if (ip != NULL) {
|
||||
@@ -207,6 +209,28 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:取网络代次号
|
||||
* 入口参数:无
|
||||
* 返回值:代次号(每次网络重建完成递增) uint32_t
|
||||
* 限定条件:无
|
||||
* 函数说明:见 net_socket.h 同名函数说明
|
||||
*/
|
||||
uint32_t net_get_generation(void) {
|
||||
return s_net_generation;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:递增网络代次号(网络重建完成、对外可用时调用)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:net_init() 成功且 PHY/链路就绪后调用(当前仅 net_stack_bring_up)
|
||||
* 函数说明:见 net_socket.h 同名函数说明
|
||||
*/
|
||||
void net_generation_inc(void) {
|
||||
s_net_generation++;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:轮询 CH395F 中断状态,更新 Socket 连接状态并处理事件
|
||||
* 返回值:本次轮询中发生事件的 Socket 数量 int >= 0
|
||||
|
||||
@@ -62,6 +62,27 @@ typedef struct {
|
||||
*/
|
||||
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac);
|
||||
|
||||
/*
|
||||
* 函数功能:取网络代次号
|
||||
* 入口参数:无
|
||||
* 返回值:代次号(每次网络重建完成递增) uint32_t
|
||||
* 限定条件:无
|
||||
* 函数说明:TCP 服务(FTP / 对时 / 远程显示)据此感知"网络已重建"——代次变化
|
||||
* 表示旧 Socket 已随芯片复位失效,服务应放弃旧监听并重建。
|
||||
* 递增点在 net_stack_bring_up() 末尾(PHY/链路就绪后),避免服务在网络
|
||||
* 尚未可用时抢先重建、也避免 uiTask 阻塞在消息队列上。
|
||||
*/
|
||||
uint32_t net_get_generation(void);
|
||||
|
||||
/*
|
||||
* 函数功能:递增网络代次号(网络重建完成、对外可用时调用)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:net_init() 成功且 PHY/链路就绪后调用(当前仅 net_stack_bring_up)
|
||||
* 函数说明:见 net_get_generation()
|
||||
*/
|
||||
void net_generation_inc(void);
|
||||
|
||||
/*
|
||||
* 函数功能:轮询所有 Socket 状态(必须在主循环中调用)
|
||||
* 返回值:有事件发生的 socket 数量
|
||||
|
||||
@@ -58,6 +58,7 @@ static net_cfg_t s_cfg = {
|
||||
};
|
||||
static uint8_t s_active_mac[6]; /* 芯片实际 MAC 影子(netTask 回写) */
|
||||
static uint8_t s_active_valid; /* 影子有效标志(0 = 尚未回写) */
|
||||
static net_cfg_apply_cb_t s_apply_cb; /* "立即应用"平台回调(未注册 = 空操作) */
|
||||
|
||||
/* 函数定义区 */
|
||||
|
||||
@@ -178,10 +179,34 @@ int net_cfg_save(void) {
|
||||
DBG_ERROR("save: store write FAILED");
|
||||
return -1;
|
||||
}
|
||||
DBG_INFO("save: OK (effective at next power-on)");
|
||||
DBG_INFO("save: OK (file written)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:注册"立即应用"回调
|
||||
* 入口参数:cb - 回调函数(NULL = 注销) net_cfg_apply_cb_t
|
||||
* 返回值:无
|
||||
* 限定条件:应用启动早期注册一次即可
|
||||
* 函数说明:见 net_cfg.h 同名函数说明
|
||||
*/
|
||||
void net_cfg_set_apply_cb(net_cfg_apply_cb_t cb) {
|
||||
s_apply_cb = cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:请求立即应用当前 RAM 配置
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:无(未注册回调时空操作)
|
||||
* 函数说明:见 net_cfg.h 同名函数说明
|
||||
*/
|
||||
void net_cfg_request_apply(void) {
|
||||
if (s_apply_cb != NULL) {
|
||||
s_apply_cb();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:取 RAM 配置副本(只读指针)
|
||||
* 入口参数:无
|
||||
|
||||
@@ -57,6 +57,35 @@ int net_cfg_load(void);
|
||||
*/
|
||||
int net_cfg_save(void);
|
||||
|
||||
/*
|
||||
* "立即应用"回调类型:平台挂钩(可选)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 函数说明:MCU 端由 netTask 注册——置 SYS_EVT_NET_RECONFIG 事件,由 netTask
|
||||
* 重建网络;模拟器无网络栈,不注册(空操作)。经回调而非直接调用,
|
||||
* 避免 NETCFG(驱动层)反向依赖 App 层。
|
||||
*/
|
||||
typedef void (*net_cfg_apply_cb_t)(void);
|
||||
|
||||
/*
|
||||
* 函数功能:注册"立即应用"回调
|
||||
* 入口参数:cb - 回调函数(NULL = 注销) net_cfg_apply_cb_t
|
||||
* 返回值:无
|
||||
* 限定条件:应用启动早期注册一次即可
|
||||
* 函数说明:见 net_cfg_apply_cb_t
|
||||
*/
|
||||
void net_cfg_set_apply_cb(net_cfg_apply_cb_t cb);
|
||||
|
||||
/*
|
||||
* 函数功能:请求立即应用当前 RAM 配置
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:无(未注册回调时空操作)
|
||||
* 函数说明:UI"网口设置"页保存行写盘成功后调用;真正生效由平台回调完成
|
||||
* (MCU:netTask 重建网络,无需重启)
|
||||
*/
|
||||
void net_cfg_request_apply(void);
|
||||
|
||||
/*
|
||||
* 函数功能:取 RAM 配置副本(只读指针)
|
||||
* 入口参数:无
|
||||
|
||||
@@ -35,6 +35,8 @@ static uint8_t g_rx[64];
|
||||
|
||||
static int g_listen = -1;
|
||||
static int g_client = -1;
|
||||
static uint16_t g_port; /* 监听端口(网络重建后重监听用) */
|
||||
static uint32_t g_gen; /* 建立监听时的网络代次号(变化 = 网络已重建) */
|
||||
|
||||
/*
|
||||
* 函数功能:计算 RemoDispBus 数据段异或校验值
|
||||
@@ -204,6 +206,7 @@ static void remo_handle(const uint8_t *f, int n)
|
||||
*/
|
||||
int ui_net_sink_start(uint16_t port)
|
||||
{
|
||||
g_port = port;
|
||||
g_listen = net_socket(NET_AF_INET, NET_SOCK_STREAM);
|
||||
if (g_listen < 0) {
|
||||
return -1;
|
||||
@@ -225,6 +228,7 @@ int ui_net_sink_start(uint16_t port)
|
||||
return -1;
|
||||
}
|
||||
g_client = -1;
|
||||
g_gen = net_get_generation(); /* 成功才记录代次;失败保持旧值以便下轮重试 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -236,9 +240,21 @@ int ui_net_sink_start(uint16_t port)
|
||||
* 函数说明:1. 无客户端时尝试接受连接(不主动上报 INIT,由客户端按需请求)
|
||||
* 2. 有客户端时非阻塞收帧并解析
|
||||
* 3. 连接关闭或异常时复位,等待重监听,不阻塞界面刷新
|
||||
* 4. 网络重建(net_init 代次变化)时关闭旧监听并重建(IP 变更后自愈)
|
||||
*/
|
||||
void ui_net_sink_poll(void)
|
||||
{
|
||||
/* 网络重建(net_init 代次变化):旧监听/客户端已随芯片复位失效,重建监听 */
|
||||
if (net_get_generation() != g_gen) {
|
||||
if (g_listen >= 0) {
|
||||
net_close(g_listen);
|
||||
g_listen = -1;
|
||||
}
|
||||
g_client = -1;
|
||||
(void)ui_net_sink_start(g_port); /* 失败则下轮再试(g_gen 未更新) */
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_listen < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
* 模块名称:UI Page Net Cfg (网口设置内容页)
|
||||
* 模块功能:网口设置叶子节点的内容页数据 + 行为——5 行地址列表(IP 地址/子网
|
||||
* 掩码/默认网关/MAC 地址 + 保存行,5 行每页共 1 页);
|
||||
* 行槽顶 = 24+14i、选中白带 x=2..156 高 13、名 x=6 / 值 x=60;
|
||||
* 行槽顶 = 24+14i、选中白带 x=2..156 高 13、名 x=4 / 值 x=54;
|
||||
* 值取自 net_cfg RAM 副本(netTask 上电自 Flash 加载并回写实际 MAC);
|
||||
* 编辑模式:ENTER 进选中地址行(字节光标 = 活动字节,反显标记),
|
||||
* ↑↓调字节 0..255(环绕、值列实时刷新)、←→移字节光标(首↔末环绕)、
|
||||
* ENTER 确认退出编辑;
|
||||
* 权限:edit_capable=1——查看密码 → 只读(编辑/保存键无效),
|
||||
* 修改密码 → 可编辑;保存行 ENTER → net_cfg_save()(下次上电生效);
|
||||
* 修改密码 → 可编辑;保存行 ENTER → net_cfg_save() 写盘 +
|
||||
* net_cfg_request_apply() 通知 netTask 立即重建网络(无需重启);
|
||||
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
@@ -29,8 +30,9 @@
|
||||
/*
|
||||
* 布局常量(设备像素;1bpp 屏 160x160):
|
||||
* 5 行共 1 页(行槽顶 y = 24+14i,末行止于 y=93,与页脚 y=143 无冲突);
|
||||
* 名 x=6 / 值 x=60(值列须 ≥60:4 汉字名占 48px + 间隙;值列宽——
|
||||
* IP/掩码/网关 11 ASCII 字符 = 66px 止于 126,MAC 12 hex 字符 = 72px 止于 132)
|
||||
* 名 x=4 / 值 x=54(值列须 ≥54:4 汉字名占 48px + 间隙;值列宽——
|
||||
* IP/掩码/网关 11 ASCII 字符 = 66px 止于 119,MAC 17 字符(冒号分隔)= 102px 止于 155,
|
||||
* 均在选中白带 x=2..156 内)
|
||||
*/
|
||||
#define NC_ROW_COUNT 5u /* 4 地址行 + 1 保存行 */
|
||||
#define NC_ADDR_ROW_MAX 4u /* 地址行范围 0..3(IP/掩码/网关/MAC) */
|
||||
@@ -38,8 +40,8 @@
|
||||
#define NC_TOP_Y 24 /* 首行槽顶 y */
|
||||
#define NC_PITCH 14 /* 行距 */
|
||||
#define NC_BAND_H 13 /* 选中白带高 */
|
||||
#define NC_LEFT_X 6 /* 左列 x(名) */
|
||||
#define NC_RIGHT_X 60 /* 右列 x(值) */
|
||||
#define NC_LEFT_X 4 /* 左列 x(名) */
|
||||
#define NC_RIGHT_X 54 /* 右列 x(值) */
|
||||
#define NC_ROW_BUF_LEN 32u /* 行缓冲长度(与框架 CP_ROW_BUF_LEN 一致) */
|
||||
|
||||
/* 静态变量定义区 */
|
||||
@@ -84,7 +86,7 @@ static uint8_t nc_octet_count(uint16_t row) {
|
||||
* 返回值:无
|
||||
* 限定条件:p_buf 非空
|
||||
* 函数说明:IP/掩码/网关 = "192.168.001.100"(每段 3 位补零定长,字节 i 恒在
|
||||
* 字符 4i 起);MAC = "A494B6123456"(无分隔 hex,字节 i 恒在字符 2i 起)
|
||||
* 字符 4i 起);MAC = "A4:94:B6:12:34:56"(冒号分隔,字节 i 恒在字符 3i 起)
|
||||
*/
|
||||
static void nc_fmt_value(uint16_t row, char *p_buf) {
|
||||
const net_cfg_t *cfg = net_cfg_get();
|
||||
@@ -93,7 +95,7 @@ static void nc_fmt_value(uint16_t row, char *p_buf) {
|
||||
uint8_t mac[6];
|
||||
|
||||
net_cfg_get_mac(mac);
|
||||
(void)lv_snprintf(p_buf, NC_ROW_BUF_LEN, "%02X%02X%02X%02X%02X%02X",
|
||||
(void)lv_snprintf(p_buf, NC_ROW_BUF_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
(unsigned)mac[0], (unsigned)mac[1], (unsigned)mac[2],
|
||||
(unsigned)mac[3], (unsigned)mac[4], (unsigned)mac[5]);
|
||||
return;
|
||||
@@ -196,7 +198,7 @@ static void nc_draw_cb(lv_layer_t *layer, const lv_area_t *clip) {
|
||||
}
|
||||
|
||||
nc_fmt_value(sel, value);
|
||||
start = (uint32_t)s_cursor * ((sel == 3u) ? 2u : 4u);
|
||||
start = (uint32_t)s_cursor * ((sel == 3u) ? 3u : 4u); /* 字节 i 字符偏移:IP/掩码/网关 4i,MAC 3i(冒号分隔) */
|
||||
seg_len = (sel == 3u) ? 2u : 3u;
|
||||
|
||||
slot_y = NC_TOP_Y + (int32_t)sel * NC_PITCH;
|
||||
@@ -223,10 +225,17 @@ static void nc_draw_cb(lv_layer_t *layer, const lv_area_t *clip) {
|
||||
|
||||
{
|
||||
lv_draw_label_dsc_t ld;
|
||||
char seg[4]; /* 段文本:IP/掩码/网关 3 字符、MAC 2 字符,+ '\0' */
|
||||
|
||||
/* 只绘制"段文本"本身:若传整串(value + start),LVGL 在未置 EXPAND 标志时
|
||||
* 按 coords 宽度(此处为段宽)折行,会逐行向盒下方绘制、溢出到其它行/空白区。
|
||||
* 传段文本(宽度 ≤ 盒宽)则单行绘制,恰好落在光标盒内。 */
|
||||
memcpy(seg, value + start, seg_len);
|
||||
seg[seg_len] = '\0';
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = value + start;
|
||||
ld.text = seg;
|
||||
ld.text_static = 0u; /* 栈缓冲(同帧有效) */
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = 1; /* box.x1 = x0-1,+1 = x0(与框架行文本原点一致) */
|
||||
@@ -295,6 +304,9 @@ static bool nc_key_cb(lv_key_t key) {
|
||||
}
|
||||
if (sel == NC_SAVE_ROW) {
|
||||
s_saved = (net_cfg_save() == 0) ? 1u : 2u;
|
||||
if (s_saved == 1u) {
|
||||
net_cfg_request_apply(); /* 立即应用:通知 netTask 重建网络(无需重启) */
|
||||
}
|
||||
ui_content_page_invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user