一、以太网协议简介
以太网是一种产生较早,使用相当广泛的局域网技术。目前以太网根据速度等级分类大概分为:标准以太网(10Mbit/s),快速以太网(100Mbit/s),千兆以太网(1000Mbit/s),以及更快的万兆以太网(10Gbit/s)。
以太网常用于大型数据传输(如:视频数据),以太网也叫以太网协议,就是一种传输规则,发收双方必须遵守这种规则才能正确地进行数据传输和接收。以太网通信是以数据包的形式传输, 其单包数据量达到几十, 甚至成百上千个字节。
下面图片是以太网通信的一帧数据格式,首先当用户发送数据时(应用层),将数据向下交给传输层,传输层会在数据前面加上传输层首部,然后向下交给网络层。 同样地,网络层会在数据前面加上网络层首部(IP首部), 然后将数据向下交给链路层,链路层会对数据进行最后一次封装, 即在数据前面加上链路层首部(此处使用以太网接口为例),然后将数据交给网卡。 最后,网卡将数据转换成物理链路上的电平信号,数据就这样被发送到了网络中。 当网络中的设备的网卡接收到某个数据包后,它会将其放置在网卡的接收缓存中,并告知TCP/IP内核。然后TCP/IP内核就开始工作了,它会将数据包从接收缓存中取出,并逐层解析数据包中的协议首部信息,并最终将数据交给某个应用程序。
(注意:TCP/IP是一个协议族,包含众多的协议。但对于网络应用开发人员,可能听到更多的是其中的应用层协议,比如HTTP、FTP、MQTT、TCP、UDP、IP等。)
二、LWIP简介
Light weight IP(LWIP)轻量化的 TCP/IP协议, LwIP 的设计初衷是:用少量的资源消耗(RAM)实现一个较为完整的 TCP/IP 协议栈, 在保持TCP协议主要功能的基础上减少对 RAM 的占用。
2.1 LWIP提供三种API:
(1)RAW API:
把协议栈和应用程序放到一个进程里边,该接口基于函数回调技术,为了接收数据,应用程序会向协议栈注册一个回调函数。该回调函数与特定的连接相关联,当该关联的连接到达一个信息包,该回调函数就会被协议栈调用。
RAW/Callback API 的缺点:
基于回调函数开发应用程序时的思维过程比较复杂。在操作系统环境中, 应用程序代码与内核代码处于同一个线程,虽然能够节省任务间通信和切换任务的开销,但是相应地,应用程序的执行会制约内核程序的执行,不同的应用程序之间也会互相制约。
(2)NETCONN API:
基于操作系统的 IPC 机制(即信号量和邮箱机制) 实现的, 它的设计将 LwIP 内核代码和网络应用程序分离成了独立的线程。如此一来, LwIP 内核线程就只负责数据包的 TCP/IP 封装和拆封,而不用进行数据的应用层处理,大大提高了系统对网络数据包的处理效率。
NETCONN API 使用了操作系统的 IPC 机制, 对网络连接进行了抽象,用户可以像操作文件一样操作网络连接(打开/关闭、读/写数据)。 但是 NETCONN API 并不如操作文件的 API 那样简单易用。举个例子,调用 f_read 函数读文件时,读到的数据会被放在一个用户指定的数组中,用户操作起来很方便,而 NETCONN API 的读数据 API,就没有那么人性化了。 用户获得的不是一个数组,而是一个特殊的数据结构 netbuf,用户如果想使用好它,就需要对内核的 pbuf 和 netbuf 结构体有所了解。 NETCONN API 之所以采取这种不人性的设计,是为了避免数据包在内核程序和应用程序之间发生拷贝,从而降低程序运行效率。当然, 用户如果不在意数据递交时的效率问题, 也可以把 netbuf 中的数据取出来拷贝到一个数组中,然后去处理这个数组。
简单来说, NETCONN API 的优缺点是:相较于 RAW/Callback API, NETCONN API 简化了编程工作,使用户可以按照操作文件的方式来操作网络连接。 但相较于 Socket API, NETCONN API 避免了内核程序和网络应用程序之间的数据拷贝,提高了数据递交的效率。
(3)SOCKET API:
Socket,即套接字,它对网络连接进行了高级的抽象,使得用户可以像操作文件一样操作网络连接。它十分易用, 许多网络开发人员最早接触的就是 Socket 编程, Socket 已经成为了网络编程的标准。在不同的系统中,运行着不同的 TCP/IP 协议,但是只要它实现了Socket 的接口,那么用 Socket 编写的网络应用程序就能在其中运行。可见用 Socket 编写的网络应用程序具有很好的可移植性。
它的最大特点是使应用程序移植到其它系统时比较容易,但内核程序和应用程序之间通信存在数据的拷贝,这会降低数据递交的效率。 在嵌入式设备中一般不会使用。
2.2 MII与RMII接口
2.2.1 MII接口
独立于介质的接口(MII)用于MAC与外接的PHY互联,支持10Mbit/s和100Mbit/s数据传输模式。MII的信号线如下图所示:
MII_TX_CLK:发送数据使用的时钟信号,对于10M位/s的数据传输,此时钟为2.5MHz,对于100M位/s的数据传输,此时钟为25MHz。
MII_RX_CLK:接收数据使用的时钟信号,对于10M位/s的数据传输,此时钟为2.5MHz,对于100M位/s的数据传输,此时钟为25MHz。
MII_TX_EN:传输使能信号,此信号必需与数据前导符的起始位同步出现,并在传输完毕前一直保持。
MII_TXD[3:0]:发送数据线,每次传输4位数据,数据在MII_TX_EN信号有效时有效。MII_TXD[0]是数据的最低位,MII_TXD[3]是最高位。当MII_TX_EN信号无效时,PHY忽略传输的数据。
MII_CRS:载波侦听信号,仅工作在半双工模式下,由PHY控制,当发送或接收的介质非空闲时,使能此信号。 PHY必需保证MII_CRS信号在发生冲突的整个时间段内都保持有效,不需要此信号与发送/接收的时钟同步。
MII_COL:冲突检测信号,仅工作在半双工模式下,由PHY控制,当检测到介质发生冲突时,使能此信号,并且在整个冲突的持续时间内,保持此信号有效。此信号不需要和发送/接收的时钟同步。
MII_RXD[3:0]:接收数据线,每次接收4位数据,数据在MII_RX_DV信号有效时有效。MII_RXD[0]是数据的最低位,MII_RXD