---
title: "W5500 drivers for LWiP using ioLibrary"
url: "https://maker.wiznet.io/chen/projects/lwip%E9%9B%86%E6%88%90w5500%E9%A9%B1%E5%8A%A8%EF%BC%8C%E5%BC%80%E5%8F%91%E8%B0%83%E8%AF%95%E6%80%BB%E7%BB%93/"
markdown_url: "https://maker.wiznet.io/chen/projects/lwip%E9%9B%86%E6%88%90w5500%E9%A9%B1%E5%8A%A8%EF%BC%8C%E5%BC%80%E5%8F%91%E8%B0%83%E8%AF%95%E6%80%BB%E7%BB%93/md"
type: "UCC: User Created Content"
author: "Brian.Chen"
author_url: "https://blog.csdn.net/Chuancey_CC/article/details/122172468?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166366096116782391822010%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166366096116782391822010&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~times_rank-8-122172468-null-null.142%5ev47%5epc_rank_34_ecpm25,201%5ev3%5econtrol_1&utm_term=w5500&spm=1018.2226.3001.4449"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "Brian.Chen"
original_url: "https://blog.csdn.net/Chuancey_CC/article/details/122172468?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166366096116782391822010%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166366096116782391822010&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~times_rank-8-122172468-null-null.142%5ev47%5epc_rank_34_ecpm25,201%5ev3%5econtrol_1&utm_term=w5500&spm=1018.2226.3001.4449"
license: "Apache License 2.0 (Apache-2.0)"
published: "2022-09-30"
language: "en"
tags: ["W5500"]
hardware: ["WIZnet W5500"]
likes: 5
views: 6643
comments: 2
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# W5500 drivers for LWiP using ioLibrary

> LwIP + W5500 Blog article

Original author: Brian.Chen (source: https://blog.csdn.net/Chuancey_CC/article/details/122172468?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166366096116782391822010%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166366096116782391822010&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~times_rank-8-122172468-null-null.142%5ev47%5epc_rank_34_ecpm25,201%5ev3%5econtrol_1&utm_term=w5500&spm=1018.2226.3001.4449)

## Components

- **WIZnet W5500** x 1 ([docs](https://docs.wiznet.io/Product/Chip/Ethernet/W5500))

WIZnet parts: W5500 ([Datasheet](https://docs.wiznet.io/Product/Chip/Ethernet/W5500/datasheet?utm_source=maker&utm_medium=project&utm_campaign=w5500), [product hub](https://maker.wiznet.io/products/w5500/))

## Article

1. 文档和资料搜集
官方网站：https://www.iwiznet.cn
github：https://github.com/Wiznet

官方网站可以找到所有和w5500相关的资料，包括最新的中英文版datasheet、基于各类常用平台的测试例程、应用指导等。

github上有各类和w5500相关的代码库，包括驱动、socket api封装等。

对我来说，只需要一个中文版的datasheet和一份github上down下来的名为ioLibrary_Driver的代码库即可。
datasheet用中文对w5500的所有寄存器的配置和功能进行了详尽的描述。
ioLibrary_Driver代码库则集成了包含w5500在内的各类wiznet网卡驱动代码。

2. 文档阅读
w5500是一个内置了tcpip协议栈的网卡芯片，即所谓的硬件协议栈。
通过对寄存器的配置，可以控制w5500工作在协议栈的哪个层级。

由于我要将w5500驱动集成进lwip中，只需要让其工作在mac层协议即可。

这显然是对w5500的一种资源浪费。
官方为方便用户设计、节约用户软硬件资源、提高用户处理器的效率，将tcpip协议栈放在了网卡芯片中。
如果能充分利用w5500内置的上层协议（主要指tcp/udp等），cpu可以省下时间做其他更多的活。
这里只用到了mac层协议，将以太网数据提交给了处理器中的tcpip协议栈lwip，将这个可以由w5500来解析处理的工作，交给了lwip。
整体上看，一套系统运行了两份tcpip协议，从提高资源利用率上看，显然是不合理的设计。
但是为了和用户处理器中的socket接口做兼容，唯一合理的方式就是将w5500驱动集成到lwip中，上层socket接口由lwip统一掉。

这里着重描述其MACRAW模式（工作在mac层协议）的配置。

通过对datasheet的阅读，可以对w5500有以下几点了解：

2.1 寄存器和内存的整体布局
w5500硬件上支持8路socket。
在寄存器上分为通用寄存器，和8组相同的socket寄存器和内存空间。

通用寄存器用来配置芯片的通用选项，如模式、IP地址、网关地址、子网掩码、MAC地址、中断管理等等。
socket寄存器和内存空间包括socket-n寄存器、socket-n发送缓存、socket-n接收缓存。

8路socket的所有的发送缓存大小共16KB，所有的接收缓存大小共16KB。
每一路socket的发送或接收缓存大小可以通过寄存器配置，但是总大小不能超过16KB。

需要注意的是，MACRAW模式只能使用socket-0通道，所以充分利用发送和接收的缓存区，即均设置为16KB。

2.2 spi的配置
支持spi 0和3两种模式、时钟频率最大80MHz、MSB first。
支持可变数据长度模式 和 固定数据长度模式
可变数据长度模式：片选引脚cs的选择和释放表示着w5500工作在可变数据长度模式
固定数据长度模式：片选引脚cs由硬件一直拉低，spi数据帧中的数据长度只能是1/2/4字节
2.3 数据帧格式
spi的数据帧由以下3部分组成：

| 字段 | 地址 | 控制段 | 数据段 |
| — — | — | — |
| 长度（字节） | 2 |1 | N |

地址段：为w5500的寄存器或TX/RX缓存区指定了16位的偏移地址
控制段：指定了地址段设定的偏移区域归属、读/写访问模式及SPI工作模式
地址段设定的偏移区域归属：即通过控制段的高5位，即BSB[4:0]，来确定当前spi通信访问的是通用寄存器、socket-n寄存器、socket-n发送缓存，还是socket-n接收缓存。（具体参考datasheet）
读/写访问模式：由控制段的位2决定，0为读，1为写。
SPI工作模式：由控制段的位1和位0决定，即OM[1:0]
00：可变数据长度模式
01：固定数据长度模式，长度为1
10：固定数据长度模式，长度为2
11：固定数据长度模式，长度为4
3. 驱动代码开发
3.1 bsp初始化
spi协议：模式0或3、时钟频率尽量接近80MHz、MSB-first
cs输出引脚：输出，初始化为高电平
网卡复位输出引脚：输出，初始化为高电平
中断检测输入引脚：输入，初始化为上拉输入（事件发生时，w5500输出持续的低电平，清除中断标志后可能会拉高）
配置为下降沿触发。但若在当前中断标志清零之前，又来了新的事件，根据INTLEVEL寄存器的配置，为0，中断标志清零后不会再次触发由高到低的跳变；为非0时，根据datasheet的公式，计算一个时间，中断标志清零后先拉到高电平，该时间过后会再次触发一个高到低的跳变。所以当INTLEVEL寄存器值为0时，只靠下降沿触发的中断，会丢失事件。当INTLEVEL寄存器值非0时，即使新事件立即发生了，也需要在上次拉高后再等待一段时间才能触发新的下降沿中断，效率较低。
配置为电平触发。对于支持电平触发外部中断的处理器（比如51单片机）来说，只要触发了中断，一定是有事件还没处理完（前提是每次处理事件时都要清除中断标志）。代码编写简单、工作效率高。
3.2 注册临界区、spi读写、拉cs引脚的回调函数
进入和退出临界区的接口可由开关中断或mutex上锁解锁来实现
spi读写需要注册读字节、写字节、读buffer、写buffer的接口（没有注册读写buffer或字节的接口，也是为了编程方便）
需要注意的是，在我调试的平台上(EC800N)，spi的读写接口内部主动做了拉cs引脚的操作，这会导致官方的驱动代码中，在拉低cs引脚后多次调用读写接口进行数据传输，最后再拉高cs引脚的机制失效（因为一次spi通信只能拉低一次cs，而EC800N做了多次片选）。
解决方案是：增加一个同时具有读写属性的spi收发接口，将需要发送的数据重新打包为一个完整的数据包，拷贝到malloc的一块内存中，将多次读或写接口的调用，替换为一次读写接口的调用（malloc的调用会增加内存碎片化的风险，猜测这就是为何官方会多次调用读或写的接口，分批次发送一包数据的原因）。
3.3 创建信号量和中断处理线程
中断处理线程用来接收中断处理函数发送的信号量。

中断处理线程被触发执行时，说明有相应的事件发生。
读取SIR寄存器的值，获取哪一路socket产生了事件。

读取Sn_IR寄存器的值，获取这一路socket产生了什么事件（本代码中只关心mac层的数据接收事件）。

将SIR和Sn_IR寄存器的值回写入SIR和Sn_IR，即写1清除中断标志。

中断处理线程的流程图如下：

中断处理线程
等待信号量
读取SIR和Sn_IR寄存器
清除中断标志
如果是socket0事件
如果是接收事件
如果接收缓存数据不为0
读取开头两个字节，获取包长度
读取包长度对应的数据
将数据递交给lwip
读取当前中断引脚电平
如果为低电平
发送信号量
yes
no
yes
no
yes
no
yes
no
中断处理函数的流程如下：

系统启动
CPU中断检测
外部中断产生
发送信号量
3.4 网卡初始化流程
网卡初始化
bsp回调接口注册
bsp初始化
创建中断处理信号量和线程
网卡芯片硬件复位
读取网卡版本号
如果不等于0x04
重试次数自加1
如果重试次数超过5
返回-1
结束
等待10ms
网卡芯片软件复位
设置socket-0发送接收缓存大小各为16KB
设置INELEVEL寄存器的值为0
设置mac地址
物理层设置（自动协商/100M带宽/全双工）
开启socket-0中断
开启socket-0接收中断
设置为MACRAW协议，并屏蔽目的地非本网卡的mac帧
打开macraw协议
触发接收功能
返回0
yes
no
yes
no
4. lwip网卡注册
按照lwip网卡注册的流程操作即可。
————————————————
版权声明：本文为CSDN博主「Brian.Chen」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/Chuancey_CC/article/details/122172468

---

Source: https://maker.wiznet.io/chen/projects/lwip%E9%9B%86%E6%88%90w5500%E9%A9%B1%E5%8A%A8%EF%BC%8C%E5%BC%80%E5%8F%91%E8%B0%83%E8%AF%95%E6%80%BB%E7%BB%93/
