dhcp.h
源文件路径:
midware/ethernt/lan/dhcp.h所属模块:midware/ethernt/lan(W5500 以太网协议栈应用层 — DHCP/DNS/Socket) 代码行数:152
1. 文件职责
本文件是 WIZnet W5500 官方 DHCP 客户端库的头文件,声明了 DHCP 客户端对外暴露的全部 API:初始化、周期运行、1 秒计时、回调注册、停止、以及从 DHCP 服务器取回 IP/网关/掩码/DNS/租期。
在 EMS 中它不是直接被业务层调用,而是由 midware/ethernt/ethernet.c 引入:W5500_Init() 中调用 reg_dhcp_cbfunc() + DHCP_init(),dhcp_function() 中周期调用 DHCP_run(),internet_time_handle() 中调用 DHCP_time_handler();DHCP 拿到的地址最终经 my_ip_assign() 写入 g_stNetInfo 并触发 network_init()。
因此本文件处在"上电网络参数协商"这一环节,是"静态 IP 配置 / 动态 DHCP 获取"两种模式下动态那条路径的接口契约;文件本身不含任何逻辑,只有宏常量、返回值枚举与函数原型。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
_DHCP_DEBUG_ | 宏 | 调试开关,被注释掉(第 53 行)。一旦打开会引入 <stdio.h>,dhcp.c 中所有 #ifdef _DHCP_DEBUG_ 的串口打印才会编译进来 |
MAX_DHCP_RETRY | 宏 | 单轮 DHCP 超时重发上限,值 2(第 57 行) |
DHCP_WAIT_TIME | 宏 | 每级状态等待超时,值 10,单位秒(第 58 行) |
DHCP_SERVER_PORT | 宏 | DHCP 服务器端口 67(第 62 行) |
DHCP_CLIENT_PORT | 宏 | DHCP 客户端端口 68(第 63 行) |
MAGIC_COOKIE | 宏 | DHCP option 魔数 0x63825363,即线上字节 99.130.83.99(第 66 行) |
DCHP_HOST_NAME | 宏 | 客户端主机名字符串 "WIZnet\0",注意宏名拼写为 DCHP(第 68 行,官方笔误被保留) |
DHCP_run() 返回值枚举 | 枚举 | 匿名枚举(第 73-81 行):DHCP_FAILED=0、DHCP_RUNNING、DHCP_IP_ASSIGN、DHCP_IP_CHANGED、DHCP_IP_LEASED、DHCP_STOPPED(依次为 1~5) |
本文件没有定义结构体、联合体或位域;DHCP 报文结构体 RIP_MSG 定义在 dhcp.c(第 172-188 行),不对外暴露。
3. 函数清单
本文件只有函数声明,没有函数定义。
| 函数名 | 作用域 | 说明(一句话) |
|---|---|---|
DHCP_init(uint8_t s, uint8_t * buf) | 全局(声明,第 88 行) | DHCP 客户端初始化:绑定 socket 号与报文缓冲区,复位状态机到 STATE_DHCP_INIT |
DHCP_time_handler(void) | 全局(声明,第 94 行) | 1 秒节拍回调,需注册到系统 1s tick 中,供 DHCP 超时计时 |
reg_dhcp_cbfunc(assign, update, conflict) | 全局(声明,第 102 行) | 注册三个回调:首次分到 IP、IP 变更、IP 冲突 |
DHCP_run(void) | 全局(声明,第 116 行) | 主循环函数,由用户主任务周期调用,内部驱动 DHCP 状态机并返回上表枚举值 |
DHCP_stop(void) | 全局(声明,第 122 行) | 关闭 DHCP socket 并置状态为 STATE_DHCP_STOP;重启需重新 DHCP_init() |
getIPfromDHCP(uint8_t* ip) | 全局(声明,第 129 行) | 取回 DHCP 分配的 IP 地址(4 字节) |
getGWfromDHCP(uint8_t* ip) | 全局(声明,第 134 行) | 取回 DHCP 下发的网关地址 |
getSNfromDHCP(uint8_t* ip) | 全局(声明,第 139 行) | 取回 DHCP 下发的子网掩码 |
getDNSfromDHCP(uint8_t* ip) | 全局(声明,第 144 行) | 取回 DHCP 下发的 DNS 服务器地址 |
getDHCPLeasetime(void) | 全局(声明,第 150 行) | 取回租期,单位秒;返回 0xFFFFFFFF 表示无限租期 |
4. 核心逻辑解析
本文件不含可执行逻辑,此处只说明它约定的接口契约与调用时序,具体实现见 dhcp.c 文档。
4.1 返回值契约与调用方分派
DHCP_run() 的返回值是整个 DHCP 模块对外唯一的"事件通道"(无回调以外的信号机制)。调用方 ethernet.c:310 的 dhcp_pro_fun() 按值分派:
DHCP_RUNNING/DHCP_IP_ASSIGN/DHCP_IP_CHANGED:空分支,实际动作由注册的回调完成;DHCP_IP_LEASED:置g_stNetSysInfo.u8DHCPOk = TRUE,作为"DHCP 已就绪"的总闸;DHCP_FAILED:ethernet.c自己的重试计数器my_dhcp_retry累加,超过MY_MAX_DHCP_RETRY(ethernet.h:102,值 3)后调用DHCP_stop()并network_init()退回静态网络参数;DHCP_STOPPED:不再处理。
DHCP_IP_ASSIGN / DHCP_IP_CHANGED 在头文件注释中被描述为"若未注册回调则表现为默认行为",但实现上 reg_dhcp_cbfunc() 无论传什么都会先把三个函数指针重置为 default_*,因此不注册回调也不会空指针。
4.2 计时契约
DHCP_time_handler() 的约定是"注册到系统 1s tick"。本工程的接线是:ethernet.c:1086 的 internet_time_handle()(由 task_system_aux,优先级 8,midware/auxiliary/system_aux.c:2075 调用)中以 OSTimeGet() - s_u32Ticks > SENCOND_1S(1000 tick,OS_TICKS_PER_SEC=1000 即 1 秒)为闸门,每秒调用一次 DHCP_time_handler()。
关键点:DHCP 状态机运行在 task_ethernet(优先级 17,更低),而秒计数由优先级更高的 task_system_aux 递增,这决定了 dhcp.c 中忙等方式等待秒计数能被推进(详见 dhcp.c.md 的 check_DHCP_leasedIP() 分析)。
4.3 参数常量与帧大小的隐含耦合
头文件只给出 MAX_DHCP_RETRY/DHCP_WAIT_TIME 两个时间常量,报文缓冲区大小 MAX_DHCP_BUF_SIZE(548)定义在 ethernet.h:103,与 dhcp.c 里的 RIP_MSG_SIZE = 236 + OPT_SIZE(312) = 548 严格相等。缓冲区由 ethernet.c:37 的 u8 g_u8DHCPBuf[MAX_DHCP_BUF_SIZE] 提供并透传给 DHCP_init(),两侧任一处改动都会造成越界,属跨文件的隐式契约。
5. 对外接口
本文件导出的函数(均在 dhcp.c 中实现):
DHCP_init()、DHCP_run()、DHCP_stop()、DHCP_time_handler()、reg_dhcp_cbfunc()、getIPfromDHCP()、getGWfromDHCP()、getSNfromDHCP()、getDNSfromDHCP()、getDHCPLeasetime()
本文件导出的宏/枚举(供调用方判断状态):MAX_DHCP_RETRY、DHCP_WAIT_TIME、DHCP_SERVER_PORT、DHCP_CLIENT_PORT、MAGIC_COOKIE、DCHP_HOST_NAME,以及匿名枚举中的 DHCP_FAILED/DHCP_RUNNING/DHCP_IP_ASSIGN/DHCP_IP_CHANGED/DHCP_IP_LEASED/DHCP_STOPPED。
本文件不引用任何外部函数或变量(不 include 任何头文件,纯自包含声明),因此被 include 时没有顺序敏感性。
6. 依赖关系
- 依赖:无。本文件不 include 任何头文件,函数原型只用
<stdint.h>的uint8_t/uint32_t;实际使用时由包含方(dhcp.c)先 includesocket.h(后者拉入wizchip_conf.h→w5500.h→includes.h)再 include 本文件。 - 被依赖:
midware/ethernt/lan/dhcp.c(第 53 行 include)、midware/ethernt/ethernet.c(第 16 行#include "dhcp.h")。全工程仅此两处。
7. 备注与风险点
- 缺少
<stdint.h>的显式 include。与dns.h(第 54 行有#include <stdint.h>)相比,本文件直接用uint8_t/uint32_t却没有自行包含,单独 include 会报错,强依赖包含顺序。 DHCP_run()的返回值枚举是匿名枚举,没有typedef名字,无法作为类型使用,只能以宏式的整数常量比较。DCHP_HOST_NAME宏名拼写错误(少了H),且值为带显式\0的字符串字面量"WIZnet\0",长度为 8 字节,dhcp.c中用它做主机名 + MAC 后 3 字节拼接,长度依赖这一未写死的终止符。- 第 149 行文档注释
@retrun unit 1s拼写错误(应为@return),属官方遗留。 - 头文件声明
DHCP_init的第二个参数buf要求"足够容纳 DHCP 报文",但未给出尺寸约束(既无宏也无断言),实际约束藏在ethernet.h/dhcp.c中,接口不安全。 MAX_DHCP_RETRY=2、DHCP_WAIT_TIME=10为硬编码,DHCP 失败最长耗时 = 2×10 s(单轮)×(1 +MY_MAX_DHCP_RETRY轮),在网络异常现场恢复时间较长。