Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
226
project/network.c
Normal file
226
project/network.c
Normal file
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @file network.c
|
||||
* @brief 网络栈初始化与 DHCP 管理
|
||||
*
|
||||
* 本文件是 TXW82x FPV SDK 的网络子系统初始化模块,负责:
|
||||
* - 初始化 LwIP TCP/IP 协议栈
|
||||
* - 注册 WiFi / 以太网网络接口
|
||||
* - 启动 DHCP 服务器(AP 模式下为客户端分配 IP)
|
||||
* - 周期性检查 DHCP 客户端状态并处理超时重试
|
||||
*/
|
||||
|
||||
/* ========================= 头文件包含 ========================= */
|
||||
|
||||
/* 系统配置与平台基础头文件 */
|
||||
#include "sys_config.h" // 系统总体配置宏定义(外设使能、功能开关等)
|
||||
#include "basic_include.h" // 基础类型和宏定义(uint8 等)
|
||||
#include "hal/adc.h" // ADC 硬件抽象层(可能用于电源监测等)
|
||||
#include "lib/rpc/cpurpc.h" // CPU 间 RPC 通信库(多核通信)
|
||||
#include "lib/atcmd/libatcmd.h" // AT 指令解析库
|
||||
#include "lib/common/atcmd.h" // AT 指令公共定义
|
||||
#include "lib/umac/ieee80211.h" // IEEE 802.11 协议定义(WiFi 上层 MAC)
|
||||
#include "lib/lmac/lmac.h" // 低层 MAC 驱动(WiFi 下层 MAC)
|
||||
#include "lib/bluetooth/uble/ble_demo.h" // BLE 蓝牙低功耗演示接口
|
||||
|
||||
/* LwIP 协议栈相关头文件 */
|
||||
#include "lwip/err.h" // LwIP 错误码定义
|
||||
#include "lwip/sockets.h" // LwIP POSIX socket 兼容层
|
||||
#include "lwip/netdb.h" // LwIP 网络主机数据库(DNS 解析等)
|
||||
#include "lwip/sys.h" // LwIP 系统抽象层(OS 适配)
|
||||
#include "lwip/ip_addr.h" // LwIP IP 地址操作工具
|
||||
#include "lwip/tcpip.h" // LwIP TCP/IP 核心初始化接口
|
||||
#include "netif/ethernetif.h" // 以太网网络接口适配层
|
||||
|
||||
/* 自定义网络工具与服务 */
|
||||
#include "lib/net/dhcpd/dhcpd.h" // DHCP 服务器实现
|
||||
#include "lib/net/utils.h" // 网络通用工具函数
|
||||
#include "lib/net/skmonitor/skmonitor.h" // Socket 监控器(检测 socket 状态/异常)
|
||||
#include "syscfg.h" // 用户可配置参数结构体(sys_cfgs)
|
||||
#include "app/user_app.h" // 用户应用层接口(sys_status 等)
|
||||
|
||||
/* ========================= 函数实现 ========================= */
|
||||
|
||||
/**
|
||||
* @brief 添加一个网络接口并注册到 LwIP 协议栈
|
||||
*
|
||||
* 根据 devid 获取对应的网络设备,设置静态 IP 或启用 DHCP 客户端,
|
||||
* 然后将该网络接口注册到 LwIP 中,使其可以收发 IP 报文。
|
||||
*
|
||||
* @param devid 设备 ID,例如 HG_WIFI0_DEVID(WiFi)或 HG_GMAC_DEVID(以太网)
|
||||
* @param name 接口名称字符串,如 "w0"(WiFi)、"e0"(以太网)
|
||||
* @param dhcpc 是否启用 DHCP 客户端:1 = 启用,0 = 使用静态 IP
|
||||
* @param setip 是否使用配置的静态 IP 地址:1 = 使用,0 = 使用默认(0.0.0.0)
|
||||
*
|
||||
* @note 该函数用 __init 修饰,表示仅在系统初始化阶段调用,
|
||||
* 运行完后其代码空间可被回收以节省 RAM。
|
||||
*/
|
||||
__init static void sys_network_add_netif(uint8 devid, char *name, uint8 dhcpc, uint8 setip)
|
||||
{
|
||||
/* 定义 IP 地址、子网掩码、默认网关三个地址变量 */
|
||||
ip_addr_t ipaddr, netmask, gw;
|
||||
|
||||
/* 根据 devid 从设备管理器中获取对应的 netdev 结构体指针 */
|
||||
struct netdev *ndev = (struct netdev *)dev_get(devid);
|
||||
|
||||
if (ndev) {
|
||||
/* 从全局配置 sys_cfgs 中读取预设的静态 IP 地址参数 */
|
||||
ipaddr.addr = sys_cfgs.ipaddr; // 本机 IP 地址
|
||||
netmask.addr = sys_cfgs.netmask; // 子网掩码
|
||||
gw.addr = sys_cfgs.gw_ip; // 默认网关地址
|
||||
|
||||
/* 打印接口名称和配置的 IP/掩码/网关信息,方便调试 */
|
||||
os_printf(KERN_INFO"netif %s setttings: "IPSTR"/"IPSTR"/"IPSTR"!\r\n", name, IP2STR_N(ipaddr.addr), IP2STR_N(netmask.addr), IP2STR_N(gw.addr));
|
||||
|
||||
/**
|
||||
* 将该网络接口添加到 LwIP 协议栈:
|
||||
* - 若 setip=1,传入 IP/掩码/网关指针,使用静态地址
|
||||
* - 若 setip=0,三个参数传 NULL,接口地址默认为 0.0.0.0
|
||||
* (后续通过 DHCP 获取)
|
||||
*/
|
||||
lwip_netif_add(ndev, name, (setip ? &ipaddr : NULL), (setip ? &netmask : NULL), (setip ? &gw : NULL));
|
||||
|
||||
if (dhcpc) {
|
||||
/* 标记 DHCP 客户端尚未完成,供 sys_dhcpc_check() 使用 */
|
||||
sys_status.dhcpc_done = 0; // 0 表示 DHCP 还未获取到地址
|
||||
|
||||
/* 启动该接口的 DHCP 客户端,向 DHCP 服务器请求 IP 地址 */
|
||||
lwip_netif_set_dhcp(ndev, 1); // 参数 1 表示开启 DHCP
|
||||
|
||||
/* 打印日志提示 DHCP 客户端已启动 */
|
||||
os_printf(KERN_INFO"netif %s start dhcp client!\r\n", name);
|
||||
}
|
||||
} else {
|
||||
/* 设备 ID 无效或对应设备未注册,打印错误信息 */
|
||||
os_printf(KERN_ERR"No Netdev: %d\r\n", devid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 系统网络初始化总入口
|
||||
*
|
||||
* 依次完成以下工作:
|
||||
* 1. 初始化 LwIP TCP/IP 协议栈
|
||||
* 2. 初始化 socket 监控器
|
||||
* 3. 注册 WiFi 接口 (w0),可选启用 DHCP 客户端
|
||||
* 4. 若以太网 (GMAC) 使能,注册以太网接口 (e0)
|
||||
* 5. 将 DHCP 客户端结果的初始值设为静态配置(作为 DHCP 失败时的回退)
|
||||
*
|
||||
* @note 由 main.c 在系统启动阶段调用,__init 修饰表示仅执行一次。
|
||||
*/
|
||||
__init void sys_network_init(void)
|
||||
{
|
||||
/* 初始化 LwIP TCP/IP 协议栈核心,传入 NULL 表示不使用回调通知 */
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
/* 初始化 socket 监控器,用于检测和管理 socket 连接状态 */
|
||||
sock_monitor_init();
|
||||
|
||||
/* 注册 WiFi 接口 "w0",根据 sys_cfgs.dhcpc_en 决定是否启用 DHCP 客户端,
|
||||
setip=1 表示同时设置静态 IP 作为回退地址 */
|
||||
sys_network_add_netif(HG_WIFI0_DEVID, "w0", sys_cfgs.dhcpc_en, 1);
|
||||
|
||||
/* 将 "w0" 设为 LwIP 的默认网络接口(用于路由选择) */
|
||||
lwip_netif_set_default2("w0");
|
||||
|
||||
#if GMAC_EN // 如果以太网 GMAC 功能在编译配置中启用
|
||||
/* 定义 6 字节数组用于存储 MAC 地址 */
|
||||
uint8_t mac[6];
|
||||
|
||||
/* 从 eFuse 中读取并计算 MAC 地址(每个芯片有唯一值) */
|
||||
sysctrl_efuse_mac_addr_calc(mac);
|
||||
|
||||
/**
|
||||
* 将 MAC 地址最后一字节最低两位置 1:
|
||||
* - bit0 = 1 表示本地管理地址(locally administered)
|
||||
* - bit1 = 1 使地址与 WiFi 接口的 MAC 区分开
|
||||
*/
|
||||
mac[5] |= 3;
|
||||
|
||||
/* 为以太网设备设置修改后的 MAC 地址 */
|
||||
netdev_set_macaddr((struct netdev *)dev_get(HG_GMAC_DEVID), mac);
|
||||
|
||||
/* 注册以太网接口 "e0",DHCP 设置与 WiFi 接口一致 */
|
||||
sys_network_add_netif(HG_GMAC_DEVID, "e0", sys_cfgs.dhcpc_en, 1);
|
||||
|
||||
/**
|
||||
* 将 "e0" 设为默认网络接口,覆盖之前 "w0" 的设置。
|
||||
* 这样做是因为有线连接通常比 WiFi 更稳定可靠,
|
||||
* 当两者同时存在时优先使用以太网。
|
||||
*/
|
||||
lwip_netif_set_default2("e0");
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 将 DHCP 客户端结果的初始值设为静态配置中的 IP 参数。
|
||||
* 这在 DHCP 尚未完成或失败时,确保 sys_status 中有有效的 IP 信息可用。
|
||||
*/
|
||||
sys_status.dhcpc_result.ipaddr = sys_cfgs.ipaddr; // 默认 IP = 静态配置
|
||||
sys_status.dhcpc_result.netmask = sys_cfgs.netmask; // 默认掩码 = 静态配置
|
||||
sys_status.dhcpc_result.router = sys_cfgs.gw_ip; // 默认网关 = 静态配置
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动 DHCP 服务器
|
||||
*
|
||||
* 在 WiFi AP(接入点)模式下启动 DHCP 服务器,为连接到本设备的
|
||||
* 客户端(如手机、图传接收端)自动分配 IP 地址。
|
||||
*
|
||||
* @note 仅当配置中同时满足 dhcpd_en=1 且 wifi_mode=AP 时才启动。
|
||||
* 服务器运行在 "w0"(WiFi)接口上。
|
||||
*/
|
||||
//启动DHCP服务器 // Start DHCP server(中文:启动 DHCP 服务器)
|
||||
void sys_dhcpd_start()
|
||||
{
|
||||
/* DHCP 服务器参数结构体 */
|
||||
struct dhcpd_param param;
|
||||
|
||||
/* 仅在 DHCP 服务器已启用 且 WiFi 工作在 AP 模式时才执行 */
|
||||
if (sys_cfgs.dhcpd_en && sys_cfgs.wifi_mode == WIFI_MODE_AP) {
|
||||
/* 清零参数结构体,确保所有字段有确定的初始值 */
|
||||
os_memset(¶m, 0, sizeof(param));
|
||||
|
||||
/* 从全局配置中逐一读取 DHCP 服务器参数 */
|
||||
param.start_ip = sys_cfgs.dhcpd_startip; // DHCP 分配的起始 IP 地址
|
||||
param.end_ip = sys_cfgs.dhcpd_endip; // DHCP 分配的结束 IP 地址
|
||||
param.netmask = sys_cfgs.netmask; // 子网掩码
|
||||
param.lease_time = sys_cfgs.dhcpd_lease_time; // IP 租约时间(秒)
|
||||
param.dns1 = sys_cfgs.dhcpd_dns1; // 主 DNS 服务器地址
|
||||
param.dns2 = sys_cfgs.dhcpd_dns2; // 备用 DNS 服务器地址
|
||||
param.router = sys_cfgs.dhcpd_router; // 下发給客户端的默认网关地址
|
||||
|
||||
/* 在 "w0"(WiFi AP)接口上启动 DHCP 服务器,失败则打印错误 */
|
||||
if (dhcpd_start("w0", ¶m)) {
|
||||
os_printf("dhcpd start error\r\n"); // DHCP 服务器启动失败
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 周期性检查 DHCP 客户端状态
|
||||
*
|
||||
* 该函数应在主循环或定时器中被周期性调用。
|
||||
* 当 DHCP 客户端已启用但尚未获取到 IP 地址时,每调用约 7 次
|
||||
* (约 7 个周期)后重新发起 DHCP 请求,防止因网络抖动导致
|
||||
* DHCP 流程卡死。
|
||||
*
|
||||
* @note 使用 static 局部变量 __loop 计数,无需外部传入计数器。
|
||||
*/
|
||||
void sys_dhcpc_check(void)
|
||||
{
|
||||
/* 静态计数器,记录连续检查到 DHCP 未完成的次数 */
|
||||
static uint8 __loop;
|
||||
|
||||
/* 仅在 DHCP 客户端已启用 且 尚未成功获取 IP 时进入检查逻辑 */
|
||||
if (sys_cfgs.dhcpc_en && !sys_status.dhcpc_done) {
|
||||
if (__loop++ > 6) {
|
||||
/**
|
||||
* 连续超过 6 次检查仍未完成 DHCP,认为当前 DHCP 流程可能卡死,
|
||||
* 重新在 "w0" 接口上发起 DHCP 请求。
|
||||
*/
|
||||
lwip_netif_set_dhcp2("w0", 1); // 重新触发 DHCP 发现流程
|
||||
|
||||
/* 重置计数器,开始下一轮超时检测 */
|
||||
__loop = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user