W6300 使用 SOCKET-less 指令实现 ARP 请求
更新于 2026年10月10日
本篇总结
基于 W6300 的 SOCKET-less Command(SLCR)ARP4 指令实现 ARP 请求,通过 SLIR 判断结果,并从 SLDHAR 读取目标 MAC 地址。
硬件平台:本例程基于 W6300-EVB-M4 开发板运行。
采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板
本示例演示如何在 W6300 芯片上使用 SOCKET-less Command(SLCR)实现 ARP 请求。W6300 的 TOE 引擎内置了 ARP4 指令,可以直接通过写 SLCR 寄存器触发一次 ARP 请求,ARP 报文的构造、发送、接收、解析全部由硬件完成,结果通过 SLIR 寄存器判断,目标 MAC 地址可从 SLDHAR 寄存器直接读取。例程通过 do_arp() 控制流程,arp_run() 驱动状态机,周期性发起 ARP 请求并打印目标 MAC 地址。
前置工具准备
开始本例程前,请确认以下工具已安装:
- WIZ UartTool V1.0:串口调试工具:点击下载
ARP 免套接字指令简介
ARP(Address Resolution Protocol)用于在局域网中把 IPv4 地址解析为对应的 MAC 地址。W6300 提供 SOCKET-less Command(SLCR),可以在不使用 Socket 资源的情况下,直接通过寄存器触发 ARP 请求、PING 请求、NS、RS 等网络层报文。命令执行结果通过 SLIR 寄存器确认,命令未完成前不能执行下一条命令。
ARP4 指令相关寄存器如下:
| 寄存器 | 说明 |
|---|---|
| SLDIPR | SOCKET-less Destination IPv4 Address Register,设置 ARP 请求的目标 IPv4 地址 |
| SLCR[ARP4] | SOCKET-less Command Register 的 ARP4 位,写 1 发送 ARP 请求;命令完成后自动清 0,未完成前不能执行新命令 |
| SLIR[ARP4] | 收到 ARP Reply 后置位 |
| SLIR[TOUT] | 重传次数超过 SLRCR 后置位,表示超时 |
| SLIRCLR | 写 1 清除 SLIR 中对应位 |
| SLDHAR | SOCKET-less Destination Hardware Address Register,收到 ARP Reply 后,硬件自动将对方 MAC 地址写入该寄存器 |
| SLRTR / SLRCR | SOCKET-less Retransmission Time/Count Register,控制重传时间(单位 100us)与重传次数,超过次数则 SLIR[TOUT] 置位 |
| SLIMR | SOCKET-less Interrupt Mask Register,可屏蔽 SLIR 中对应的中断位 |
ARP4 指令执行流程:
- 配置:设置 SLDIPR(目标 IP)、SLRTR / SLRCR(重传时间与次数)、SLIMR(中断屏蔽位)
- 触发命令:写 SLCR[ARP4] = 1,等待 SLCR 回到 0 表示命令完成
- 等待响应:轮询 SLIR,若 SLIR[ARP4] = 1 表示收到 ARP Reply;若 SLIR[TOUT] = 1 表示超时
- 获取结果:收到 ARP Reply 后,从 SLDHAR 读取目标 MAC 地址;写 SLIRCLR 清除对应中断位
W6300 的优势
W6300 的 TOE 引擎原生支持 ARP4 免套接字指令,ARP 报文的构造、发送、接收、解析、重传全部由硬件完成。用户只需通过寄存器配置目标 IP,触发 SLCR[ARP4] 后轮询 SLIR 结果,成功后从 SLDHAR 直接读取目标 MAC 地址。整个过程不占用 Socket 资源。
硬件连接与拓扑
请注意:
测试需要 PC 端和 W6300 处于同一网段,且目标 IP 对应的设备已经在线。
- Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
- 网线连接开发板 RJ45 网口 到路由器 LAN 口
- 确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
│ 路由器(DHCP Server) │
│ 192.168.1.1 │
└────┬──────────────────┬───────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ W6300 │ │ PC │
│ SLCR ARP │ │ 192.168.1.20│
│ IP: DHCP │ │ MAC: D8:43:AE:17:65:A4│
└────┬──────┘ └───────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │─────→ WIZ UartTool
│ MCU │
└───────────┘
工程结构
工程核心文件如下:
Project/
├── main.c ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
└── USER/
├── user_main.c ← 网络地址定义 + ARP 目标 + user_run() 主流程
├── arp.c ← ARP 状态机核心(do_arp / arp_run / arp_init)
├── arp.h
├── wiz_platform.c/h ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
└── wiz_interface.c/h ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测、软件定时器
本例程的核心:通过 SLCR[ARP4] 免套接字指令触发 ARP 请求,轮询 SLIR 判断结果,从 SLDHAR 读取目标 MAC 地址。ARP 状态机在 arp_run() 中运行,通过 do_arp() 完成一次性初始化。
步骤1:主循环调用
文件:USER/user_main.c。在主循环中调用 do_arp() 函数,传入 Socket 号、网络缓冲区和目标主机 IP。
uint8_t dest_ip[4] = {192, 168, 1, 20};
while (1)
{
do_arp(SOCKET_ID, ethernet_buf, dest_ip);
}
do_arp() 函数起到了控制 ARP 操作流程的作用,首次调用完成一次性初始化(设置目标 IP、超时参数等),之后每次调用运行 arp_run() 状态机,周期性发起 ARP 请求。
步骤2:do_arp() 流程控制
文件:USER/arp.c。首次调用时进行一次性初始化,之后每次调用运行 arp_run() 状态机。
void do_arp(uint8_t sn, uint8_t *buf, uint8_t *dest_ip)
{
arp_config_t config;
(void)sn;
(void)buf;
if (s_arp_compat_initialized == 0U)
{
if (dest_ip == NULL)
{
return;
}
memset(&config, 0, sizeof(config));
config.target_use_gateway = 0U;
memcpy(config.target_ip, dest_ip, sizeof(config.target_ip));
config.interval_ms = 5000U;
config.command_timeout_ms = 100U;
config.response_timeout_ms = 5000U;
if (arp_init(&config) < 0)
{
return;
}
s_arp_compat_initialized = 1U;
}
arp_run();
}
do_arp() 首次调用时根据传入的目标 IP 构造 arp_config_t 配置,调用 arp_init() 完成初始化;之后每次调用 arp_run() 驱动状态机,每隔 interval_ms 发起一次 ARP 请求。
步骤3:arp_run() 状态机
文件:USER/arp.c。ARP 操作的核心状态机:IDLE 状态下按间隔触发 ARP 请求,WAIT_COMMAND 等待 SLCR 命令完成,WAIT_RESULT 轮询 SLIR 判断结果。
void arp_run(void)
{
uint32_t now = wiz_platform_get_tick();
uint8_t slir;
uint8_t target_mac[6];
switch (s_arp_state)
{
case ARP_STATE_IDLE:
if ((uint32_t)(now - s_arp_state_tick) >= s_arp_config.interval_ms)
{
arp_start(now);
}
break;
case ARP_STATE_WAIT_COMMAND:
if (getSLCR() == 0U)
{
s_arp_state = ARP_STATE_WAIT_RESULT;
}
else if ((uint32_t)(now - s_arp_request_tick) >= s_arp_config.command_timeout_ms)
{
printf("ARP command: timeout\r\n");
arp_finish_cycle(now);
}
break;
case ARP_STATE_WAIT_RESULT:
slir = getSLIR();
if ((slir & SLIR_ARP4) != 0U)
{
getSLDHAR(target_mac);
printf("ARP reply: %u.%u.%u.%u -> %02X:%02X:%02X:%02X:%02X:%02X, elapsed=%lu ms\r\n",
(unsigned int)s_arp_target_ip[0],
(unsigned int)s_arp_target_ip[1],
(unsigned int)s_arp_target_ip[2],
(unsigned int)s_arp_target_ip[3],
(unsigned int)target_mac[0],
(unsigned int)target_mac[1],
(unsigned int)target_mac[2],
(unsigned int)target_mac[3],
(unsigned int)target_mac[4],
(unsigned int)target_mac[5],
(unsigned long)(now - s_arp_request_tick));
arp_finish_cycle(now);
}
else if ((slir & SLIR_TOUT) != 0U)
{
printf("ARP timeout: %u.%u.%u.%u\r\n",
(unsigned int)s_arp_target_ip[0],
(unsigned int)s_arp_target_ip[1],
(unsigned int)s_arp_target_ip[2],
(unsigned int)s_arp_target_ip[3]);
arp_finish_cycle(now);
}
else if ((uint32_t)(now - s_arp_request_tick) >= s_arp_config.response_timeout_ms)
{
printf("ARP response: timeout\r\n");
arp_finish_cycle(now);
}
break;
default:
arp_finish_cycle(now);
break;
}
}
状态机三个状态:IDLE 每隔 interval_ms 触发一次 ARP 请求;WAIT_COMMAND 等待 getSLCR() 返回 0(命令完成),超时则判定失败;WAIT_RESULT 轮询 getSLIR(),若 SLIR_ARP4 置位表示收到 ARP Reply,从 getSLDHAR() 读取目标 MAC;若 SLIR_TOUT 置位表示超时。
步骤4:arp_start() 触发 ARP 命令
文件:USER/arp.c。通过免套接字指令触发 ARP 请求:写入目标 IP,然后设置 SLCR_ARP4 触发命令。
static void arp_start(uint32_t now)
{
arp_clear_result();
setSLDIP4R(s_arp_target_ip);
setSLCR(SLCR_ARP4);
s_arp_request_tick = now;
s_arp_state = ARP_STATE_WAIT_COMMAND;
printf("ARP request: %u.%u.%u.%u\r\n",
(unsigned int)s_arp_target_ip[0],
(unsigned int)s_arp_target_ip[1],
(unsigned int)s_arp_target_ip[2],
(unsigned int)s_arp_target_ip[3]);
}免套接字指令要点
setSLDIP4R() 写入目标 IP,setSLCR(SLCR_ARP4) 触发 ARP 请求。整个过程无需用户构造 ARP 报文,也无需解析 ARP 应答,TOE 硬件会自动完成。请求成功或超时后由 SLIR 置位通知。
步骤5:arp_finish_cycle() 结束循环
文件:USER/arp.c。每次 ARP 循环完成后清中断标志、复位状态机,等待下一次触发。
static void arp_finish_cycle(uint32_t now)
{
arp_clear_result();
s_arp_state = ARP_STATE_IDLE;
s_arp_state_tick = now;
}运行验证
烧录例程运行后,首先进行 PHY 链路检测,然后打印设置网络信息,最后周期性地对 ARP 目标 IP 发起请求并打印目标 MAC 地址。打开 WIZ UartTool V1.0,连接 DEBUG USB 对应 COM 口(115200 / 8N1),观察开发板串口输出。
MH2457 W6300 QSPI example start
W6300 ARP request example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
DHCP running
DHCP success!
====================================================================================================
W6300 network configuration : DHCP
MAC : 00:08:DC:12:34:56
IP : 192.168.1.8
Subnet Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
====================================================================================================
ARP target: 192.168.1.20
ARP request: 192.168.1.20
ARP reply: 192.168.1.20 -> D8:43:AE:17:65:A4, elapsed=2 ms
ARP request: 192.168.1.20
ARP reply: 192.168.1.20 -> D8:43:AE:17:65:A4, elapsed=2 ms

常见问题
Q: 免套接字指令与普通 Socket 方式有什么区别
免套接字指令通过写 SLCR 寄存器直接触发 ARP、PING、NS、RS 等网络层报文,不占用 8 个硬件 Socket 中的任何一个,也不需要构造 ARP 报文和解析应答。普通 Socket 方式需要创建一个 MACRAW Socket,由用户手动构造报文并处理收发。对于只需要解析某个 IP 对应 MAC 地址的场景,免套接字指令更简洁。
Q: ARP 请求超时(ARP timeout)怎么办
首先检查 PC 端与 W6300 是否处于同一网段;其次确认目标 IP 地址是否正确,且对应设备在线;再检查网络物理连接是否正常(网线、PHY 链路状态)。若目标设备开启了防火墙或关闭了 ARP 响应,可能无法收到应答。程序中超时由 SLIR_TOUT 置位触发,或者 response_timeout_ms 到期后主动判定超时。
Q: 为什么需要区分 WAIT_COMMAND 和 WAIT_RESULT 两个状态
SLCR_ARP4 命令是异步的:写入命令后需要等待命令完成(SLCR 回到 0),然后等待 ARP 应答到达(SLIR_ARP4 或 SLIR_TOUT 置位)。两个阶段分别对应两个超时:command_timeout_ms 防止命令迟迟不完成,response_timeout_ms 防止响应迟迟不返回。分开处理可以更精确地定位问题。
Q: 目标 MAC 地址从哪里读取
收到 ARP 应答后,TOE 硬件会自动把对方的 MAC 地址写入 SLDHAR 寄存器(SOCKET-less Destination Hardware Address Register)。软件通过 getSLDHAR() 即可读取,无需自己解析 ARP 报文。
Q: ARP 请求间隔时间如何调整
ARP 请求间隔由 arp_config_t 中的 interval_ms 决定(示例为 5000ms)。调整该值可改变两次 ARP 请求之间的间隔。命令超时由 command_timeout_ms 控制(默认 100ms),响应超时由 response_timeout_ms 控制(默认 5000ms)。
总结
本文基于 W6300 的 SOCKET-less Command(SLCR)ARP4 指令实现了 ARP 请求功能:
- ARP 原理:把 IPv4 地址解析为对应的 MAC 地址,用于局域网内二层数据帧封装
- 免套接字指令:W6300 TOE 引擎内置 ARP4 指令,通过 SLCR 寄存器触发,不占用 Socket 资源,硬件自动构造 ARP 报文
- 核心函数:do_arp() 控制流程、arp_init() 初始化、arp_run() 状态机、arp_start() 触发命令、arp_finish_cycle() 结束循环
- 关键寄存器:SLDIPR(目标 IP)、SLCR(命令)、SLIR(结果)、SLDHAR(目标 MAC)
- 状态机设计:IDLE → WAIT_COMMAND → WAIT_RESULT 三态切换,分别处理命令超时和响应超时