- MII_TXD[3:0]:发送数据线,每次传输4位数据,数据在MII_TX_EN信号有效时有效。MII_TXD[0]是数据的最低位,MII_TXD[3]是最高位。当MII_TX_EN信号无效时,PHY忽略传输的数据。
- MII_RX_ER:接收出错信号,保持一个或多个时钟周期(MII_RX_CLK)的有效状态,表明MAC在接收过程中检测到错误。具体错误原因需配合MII_RX_DV的状态及MII_RXD[3:0]的数据值。
- MII_RX_DV:接收数据使能信号,由PHY控制,当PHY准备好数据供MAC接收时,使能该信号。此信号必需和帧数据的首位同步出现,并保持有效直到数据传输完成。在传送最后4位数据后的第一个时钟之前,此信号必需变为无效状态。为了正确的接收一个帧,有效电平不能滞后于数据线上的SFD位出现。
- MII_RX_CLK:接收数据使用的时钟信号,对于10M位/s的数据传输,此时钟为2.5MHz,对于100M位/s的数据传输,此时钟为25MHz。
- MII_RXD[3:0]:接收数据线,每次接收4位数据,数据在MII_RX_DV信号有效时有效。MII_RXD[0]是数据的最低位,MII_RXD[3]是最高位。当MII_RX_EN无效,而MII_RX_ER有效时,MII_RXD[3:0]数据值代表特定的信息(请参考表194)。
- MII_CRS:载波侦听信号,仅工作在半双工模式下,由PHY控制,当发送或接收的介质非空闲时,使能此信号。 PHY必需保证MII_CRS信号在发生冲突的整个时间段内都保持有效,不需要此信号与发送/接收的时钟同步。
- MII_COL:冲突检测信号,仅工作在半双工模式下,由PHY控制,当检测到介质发生冲突时,使能此信号,并且在整个冲突的持续时间内,保持此信号有效。此信号不需要和发送/接收的时钟同步。
1.2 精简的独立于介质的接口(RMII)
精简的独立于介质接口(RMII)规范减少了以太网通信所需要的引脚数。根据IEEE802.3标准,MII接口需要16个数据和控制信号引脚,而RMII标准则将引脚数减少到了7个。RMII具有以下特性:
时钟信号需要提高到50MHz.MAC和外部的以太网PHY需要使用同样的时钟源 ,使用2位宽度的数据收发
RMII的信号线如下图所示:

1.3 时钟源
1)MII时钟源
为了产生TX_CLK和RX_CLK时钟信号,外接的PHY模块必需有来自外部的25MHz时钟驱动。该时钟不需要与MAC时钟相同。可以使用外部的25MHz晶体。当时钟来源MCO引脚时需配置合适的PLL,保证MCO引脚输出的时钟为25MHZ。
2)RMII时钟源
通过将相同的时钟源接到MAC和以太网PHY的REF_CLK引脚保证两者时钟源的同步。可以通过外部的50MHZ信号或者GD32F107xx微控制器的MCO引脚提供这一时钟。当时钟来源MCO引脚时需配置合适的PLL,保证MCO引脚输出的时钟为50MHZ。
3)总结
采用MII接口,PYH的时钟频率要求25M,不需要与MAC层时钟一致。
采用RMII接口,PYH的时钟频率要求50M,需与MAC层时钟一致,通常从MAC层获取该时钟源。
二. 以太网芯片(DP83848介绍)
芯片datasheet如下:
1. DP83848芯片概述
DP83848是TI出的一款以太网物理层IC,有以下feature

一般工规芯片选择DP83848I就行了

2. DP83848引脚介绍
2.1 Serial Management Interface

2.2 MAC Data Interface



2.3 Clock Interface

2.4 LED Interface

2.5 Reset and Power Down

3. DP83848中断寄存器
这个在后面移植的low_level_init会用到





三. CubeMx配置以太网芯片DP83848
1. DP83848 GPIO配置

HR91105A是这个

CubeMx GPIO配置如下(通过原理图可以看到是RMII接口):

2. Cubemx Advanced Paramter配置
这里会牵扯到三个配置:
2.1 External PHY Configuration

此部分一共牵扯到以下部分:
PHY: 外部PHY芯片,我们开发板是选择的这个DP83848,所以默认可以直接勾选上
PHY Address Value: 外部PHY芯片的地址,可以看到DP83848芯片是根据map来的,默认PHYAD0是默认上拉的,PHYAD[4:1]是默认下来的,所以默认地址是0x01

其他默认配置就行了!
2.2 Common:External PHY Configuration

这个我们选择默认就好
2.3 Extended:External PHY Configuration

这个我们选择默认就好
四. lwip介绍
LwIP 全名:Light weight IP,意思是轻量化的 TCP/IP 协议,是瑞典计算机科学院 (SICS) 的 Adam Dunkels 开发的一个小型开源的 TCP/IP 协议栈。LwIP 的设计初衷是:用少量的资源消耗实现一个较为完整的TCP/IP 协议栈,其中“完整”主要指的是 TCP 协议的完整性,实现的重点是在保持 TCP 协议主要功能的基础上减少对 RAM 的占用。此外 LwIP 既可以移植到操作系统上运行,也可以在无操作系统的情况下独立运行。
LwIP 具有主要特性:
- 支持 ARP 协议(以太网地址解析协议)。
- 支持 ICMP 协议(控制报文协议),用于网络的调试与维护。
- 支持 IGMP 协议(互联网组管理协议),可以实现多播数据的接收。
- 支持 UDP 协议 (用户数据报协议)。
- 支持 TCP 协议 (传输控制协议),包括阻塞控制、RTT 估算、快速恢复和快速转发。
- 支持 PPP 协议(点对点通信协议),支持 PPPoE。
- 支持 DNS(域名解析)。
- 支持 DHCP 协议,动态分配 IP 地址。
- 支持 IP 协议,包括 IPv4、IPv6 协议,支持 IP 分片与重装功能,多网络接口下的数据包转发。
- 支持 SNMP 协议(简单网络管理协议)。
- 支持 AUTOIP,自动 IP 地址配置。
- 提供专门的内部回调接口 (Raw API),用于提高应用程序性能。
- 提供可选择的 Socket API、NETCONN API (在多线程情况下使用) 。
LwIP 在嵌入式中使用有以下优点:
- 资源开销低,即轻量化。LwIP 内核有自己的内存管理策略和数据包管理策略,使得内核处理数据包的效率很高。另外,LwIP 高度可剪裁,一切不需要的功能都可以通过宏编译选项去掉。LwIP 的流畅运行需要40KB 的代码 ROM 和几十 KB 的 RAM,这让它非常适合用在内存资源受限的嵌入式设备中。
- 支持的协议较为完整。几乎支持 TCP/IP 中所有常见的协议,这在嵌入式设备中早已够用。
- 实现了一些常见的应用程序:DHCP 客户端、DNS 客户端、HTTP 服务器、MQTT 客户端、TFTP 服务器、SNTP 客户端等等。
- 同时提供了三种编程接口:RAW API、NETCONN API (注:NETCONN API 即为 SequentialAPI,为了统一,下文均采用 NETCONN API)和 Socket API。这三种 API 的执行效率、易用性、可移植性以及时空间的开销各不相同,用户可以根据实际需要,平衡利弊,选择合适的 API 进行网络应用程序的开发。
- 高度可移植。其源代码全部用 C 实现,用户可以很方便地实现跨处理器、跨编译器的移植。另外,它对内核中会使用到操作系统功能的地方进行了抽象,使用了一套自定义的 API,用户可以通过自己实现这些 API,从而实现跨操作系统的移植工作。
- 开源、免费,用户可以不用承担任何商业风险地使用它。
- 相比于嵌入式领域其它的 TCP/IP 协议栈,比如 uC-TCP/IP、FreeRTOS-TCP 等,LwIP 的发展历史要更悠久一些,得到了更多的验证和测试。LwIP 被广泛用在嵌入式网络设备中,国内一些物联网公司推出的物联网操作系统,其 TCP/IP 核心就是 LwIP;物联网知名的 WiFi模块 ESP8266,其 TCP/IP 固件,使用的就是 LwIP。
LwIP 尽管有如此多的优点,但它毕竟是为嵌入式而生,所以并没有很完整地实现 TCP/IP 协议栈。相比于 Linux 和 Windows 系统自带的 TCP/IP 协议栈,LwIP 的功能不算完整和强大。但对于大多数物联网领域的网络应用程序,LwIP 已经足够了。
1.文件列表
可以通过这个链接去下载lwip的代码:http://download.savannah.nongnu.org/releases/lwip/
打开后就是这个模样:

文件列表大体分为几类:
1)drivers ,主要是提供一款32位的MCU(MCF5223X)部分驱动以及一款Eth的LAN芯片(CS8900A)
2)older_versions,主要是提供一些旧(1.4.0以前的版本)的lwip版本以及Contrib source code
3)contrib-xxxx,主要提供一些辅助代码(示例/移植等)
4)lwip-xxxxx,lwip对应版本的代码
2.LwIP 的三种编程接口
LwIP 提供了三种编程接口,分别为 RAW/Callback API、NETCONN API、SOCKET API。用户可以根据实际情况,平衡利弊,选择合适的 API 进行网络应用程序的开发。以下内容将分别介绍这三种 API。
2.1 RAW/Callback API
RAW/Callback API 是指内核回调型的 API,这在许多通信协议的 C 语言实现中都有所应用。
RAW/Callback API 是 LwIP 的一大特色,在没有操作系统支持的裸机环境中,只能使用这种 API进行开发,同时这种 API 也可以用在操作系统环境中。这里先简要说明一下“回调”的概念。新建了一个 TCP 或者UDP 的连接,你想等它接收到数据以后去处理它们,这时你需要把处理该数据的操作封装成一个函数,然后将这个函数的指针注册到 LwIP 内核中。 LwIP 内核会在需要的时候去检测该连接是否收到数据,如果收到了数据,内核会在第一时间调用注册的函数,这个过程被称为“回调”,这个注册函数被称为“回调函数”。这个回调函数中装着你想要的业务逻辑,在这个函数中,你可以自由地处理接收到的数据,也可以发送任何数据,也就是说,这个回调函数就是你的应用程序。到这里,我们可以发现,在回调编程中,LwIP 内核把数据交给应用程序的过程就只是一次简单的函数调用,这是非常节省时间和空间资源的。每一个回调函数实际上只是一个普通的 C 函数,这个函数在 TCP/IP 内核中被调用。每一个回调函数都作为一个参数传递给当前 TCP 或 UDP 连接。而且,为了能够保存程序的特定状态,可以向回调函数传递一个指定
的状态,并且这个指定的状态是独立于 TCP/IP 协议栈的。。在有操作系统的环境中,如果使用 RAW/Callback API,用户的应用程序就以回调函数的形式成为了内核代码的一部分,用户应用程序和内核程序会处于同一个线程之中,这就省去了任务间通信和切换任务的开销了。
简单来说,RAW/Callback API 的优点有两个:
(1)可以在没有操作系统的环境中使用。
(2)在有操作系统的环境中使用它,对比另外两种 API,可以提高应用程序的效率、节省内存开销。
RAW/Callback API 的优点是显著的,但缺点也是显著的:
(1)基于回调函数开发应用程序时的思维过程比较复杂。在后面与 RAW/Callback API 相关的章节中可以看到,利用回调函数去实现复杂的业务逻辑时,会很麻烦,而且代码的可读性较差。
(2)在操作系统环境中,应用程序代码与内核代码处于同一个线程,虽然能够节省任务间通信和切换任务的开销,但是相应地,应用程序的执行会制约内核程序的执行,不同的应用程序之间也会互相制约。在应用程序执行的过程中,内核程序将不可能得到运行,这会影响网络数据包的处理效率。如果应用程序占用的时间过长,而且碰巧这时又有大量的数据包到达,由于内核代码长期得不到执行,网卡接收缓存里的数据包就持续积累,到最后很可能因为满载而丢弃一些数据包,从而造成丢包的现象。
2.2 NETCONN API
在操作系统环境中,可以使用 NETCONN API 或者 Socket API 进行网络应用程序的开发。NETCONN API 是基于操作系统的 IPC 机制(即信号量和邮箱机制)实现的,它的设计将 LwIP 内核代码和网络应用程序分离成了独立的线程。如此一来,LwIP 内核线程就只负责数据包的 TCP/IP封装和拆封,而不用进行数据的应用层处理,大大提高了系统对网络数据包的处理效率。前面提到,使用 RAW/Callback API 会造成内核程序和网络应用程序、不同网络应用程序之间的相互制约,如果使用 NETCONN API 或者 Socket API,这种制约将不复存在。
在操作系统环境中,LwIP 内核会被实现为一个独立的线程,名为 tcpip_thread,使用 NETCONN API 或者 Socket API 的应用程序处在不同的线程中,我们可以根据任务的重要性,分配不同的优先级给这些线程,从而保证重要任务的时效性,分配优先级的原则具体见表格 。表格 线程优先级分配原则

NETCONN API 使用了操作系统的 IPC 机制,对网络连接进行了抽象,用户可以像操作文件一样操作网络连接(打开/关闭、读/写数据)。但是 NETCONN API 并不如操作文件的 API 那样简单易用。举个例子,调用 f_read 函数读文件时,读到的数据会被放在一个用户指定的数组中,用户操作起来很方便,而 NETCONN API 的读数据 API,就没有那么人性化了。用户获得的不是一个数组,而是一个特殊的数据结构netbuf,用户如果想使用好它,就需要对内核的 pbuf 和 netbuf 结构体有所了解,我们会在后续的章节中对它们进行讲解。NETCONN API 之所以采取这种不人性的设计,是为了避免数据包在内核程序和应用程序之间发生拷贝,从而降低程序运行效率。当然,用户如果不在意数据递交时的效率问题,也可以把 netbuf 中的数据取出来拷贝到一个数组中,然后去处理这个数组。
简单来说,NETCONN API 的优缺点是:
(1)相较于 RAW/Callback API,NETCONN API 简化了编程工作,使用户可以按照操作文件的方式来操作网络连接。但是,内核程序和网络应用程序之间的数据包传递,需要依靠操作系统的信号量和邮箱机制完成,这需要耗费更多的时间和内存,另外还要加上任务切换的时间开销,效率较低。

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



