• 【STM32】标准库-以太网外设


    TCP/IP模型

    TCP/IP 只有四个分层,分别为应用层、传输层、网络层以及网络访问层(物理层)

    实际上,还有一个 TCP/IP 混合模型,分为五个层。它实际与 TCP/IP四层模型是相通的,只是把网络访问层拆成数据链路层和物理层。这种分层方法对我们学习理解更容易。
    在这里插入图片描述
    在 TCP/IP 混合参考模型中,数据链路层又被分为 LLC 层 (逻辑链路层) 和 MAC 层 (媒体介质访问层)。
    目前,对于普通的接入网络终端的设备,LLC 层和 MAC 层是软、硬件的分界线。
    如 PC的网卡主要负责实现参考模型中的 MAC 子层和物理层;在 PC 的软件系统中则有一套庞大程序
    实现了 LLC 层及以上的所有网络层次的协议。

    各层的功能

    • LLC 层:
      处理传输错误;调节数据流,协调收发数据双方速度,防止发送方发送得太快而接收方丢失数据。主要使用数据链路协议。

    • 网络层:
      本层也被称为 IP 层。LLC 层负责把数据从线的一端传输到另一端,但很多时候不同的设备位于不同的网络中 (并不是简单的网线的两头)。此时就需要网络层来解决子网路由拓扑问

    • 传输层:
      由网络层处理好了网络传输的路径问题后,端到端的路径就建立起来了。传输层就负责处理端到端的通讯。在这一层中主要有 TCP、UDP 协议

    • 应用层:
      经过前面三层的处理,通讯完全建立。应用层可以通过调用传输层的接口来编写特定的应用程序。而 TCP/IP 协议一般也会包含一些简单的应用程序如 Telnet 远程登录、FTP 文件传输、SMTP 邮件传输协议。

    实际上,在发送数据时,经过网络协议栈的每一层,都会给来自上层的数据添加上一个数据包的头,再传递给下一层。
    在接收方收到数据时,一层层地把所在层的数据包的头去掉,向上层递交数据

    在这里插入图片描述

    以太网(数据链路层中的MAC层)

    以太网 (Ethernet) 是互联网技术的一种,由于它是在组网技术中占的比例最高,很多人直接把以太网理解为互联网。

    以太网是指遵守 IEEE 802.3 标准组成的局域网,由 IEEE802.3 标准规定的主要是位于参考模型的
    物理层 (PHY) 和数据链路层中的介质访问控制子层 (MAC)。

    功能

    MAC 子层是属于数据链路层的下半部分,它主要负责与物理层进行数据交接如是否可以发送
    数据,发送的数据是否正确,对数据流进行控制等

    发送时候:它自动对来自上层的数据包加上一些控制信号,交给物理层。
    接受时候:接收方得到正常数据时,自动去除 MAC 控制信号,把该数据包交给上层。

    数据包格式

    在这里插入图片描述

    • 前导字段(报头)
      这是一段方波,用于使收发节点的时钟同步内容为连续 7 个字节的 0x55。
    • 帧起始定界符 (SFD)
      用于区分前导段与数据段的,内容为 0xD5。
    • MAC 地址(DA/SA)
      MAC 地址由 48 位数字组成,它是网卡的物理地址,在以太网传输的最底层,就是根据 MAC 地址来收发数据的。部分 MAC 地址用于广播和多播,在同一个网络里不能有两个相同的 MAC 地址。MSb

    数据包中的 DA 是目标地址,SA 是源地址。

    网卡:TCP/IP中的数据链路层中的MAC层与物理层(PHY)

    • 数据包类型
      本区域可以用来描述本 MAC 数据包是属于 TCP/IP 协议层的 IP 包、ARP 包还是 SNMP 包,也可以用来描述本 MAC 数据包数据段的长度。

    如果该值被设置大于 0x0600(1536),不用于长度描述,而是用于类型描述功能,表示与以太网帧相关的 MAC 客户端协议的种类。

    • 数据段
      数据段是 MAC 包的核心内容,它包含的数据来自 MAC 的上层。其长度可以从0~1500 字节间变化。

    • 填充域
      由于协议要求整个 MAC 数据包的长度至少为 64 字节 (接收到的数据包如果少于64 字节会被认为发生冲突,数据包被自动丢弃),当数据段的字节少于 46 字节时,在填充域会自动填上无效数据,以使数据包符合长度要求。

    • 校验和域
      MAC 数据包的尾部是校验和域,它保存了 CRC 校验序列,用于检错。MSb

    • 单播 MAC 地址是指第一个字节的最低位是 0 的 MAC 地址。

    • 组播 MAC 地址是指第一个字节的最低位是 1 的 MAC 地址(第40位bit)。

    • 广播 MAC 地址是指每个比特都是 1 的 MAC 地址。广播 MAC 地址是组播 MAC 地址的一个特例。

    物理层(PHY层)

    在物理层,由 IEEE 802.3 标准规定了以太网使用的传输介质、传输速度、数据编码方式和冲突检
    测机制
    物理层一般是通过一个 PHY 芯片实现其功能的

    • 传输介质
      传输介质包括同轴电缆、双绞线 (水晶头网线是一种双绞线)、光纤。根据不同的传输速度和距离要
      求,基于这三类介质的信号线又衍生出很多不同的种类,超五类网线
      六类网线等

    • 传输速度
      100MBPS、10MPS、1GBPS

    • 编码方式
      为了让接收方在没有外部时钟参考的情况也能确定每一位的起始、结束和中间位置,在传输信号
      时不直接采用二进制编码。在 10BASE-T 的传输方式中采用曼彻斯特编码,在 100BASE-T 中则采
      用 4B/5B 编码。

    a. 曼彻斯特编码把每一个二进制位的周期分为两个间隔,在表示“1”时,以前半个周期为高电平,
    后半个周期为低电平。

    在这里插入图片描述
    采用曼彻斯特码在每个位周期都有电压变化,便于同步。但这样的编码方式效率太低,只有 50%。

    b. 在 100BASE-T 采用的 4B/5B 编码是把待发送数据位流的每 4 位分为一组,以特定的 5 位编码来
    表示,这些特定的 5 位编码能使数据流有足够多的跳变,达到同步的目的,而且效率也从曼彻斯
    特编码的 50% 提高到了 80%。

    • 冲突检测机制
      早期的以太网大多是多个节点连接到同一条网络总线上 (总线型网络),存在信道竞争问题,因而
      每个连接到以太网上的节点都必须具备冲突检测功能。

    如果多个节点同时利用同一条总线发送数据,则会产生冲突,总线上的节点可通过接收到的信号与
    原始发送的信号的比较检测是否存在冲突,若存在冲突则停止发送数据,随机等待一段时间再重
    传。

    现在大多数局域网组建的时候很少采用总线型网络,大多是一个设备接入到一个独立的路由或交换机接口,组成星型网络,不会产生冲突。但为了兼容,新出的产品还是带有冲突检测机制。

    STM32以太网外设

    STM32F42x 系列控制器内部集成了一个以太网外设,它实际是一个通过 DMA 控制器进行介质访问控制 (MAC),它的功能就是实现 MAC 层的任务。

    借助以太网外设,STM32F42x 控制器可以通过 ETH 外设按照 IEEE 802.3-2002 标准发送和接收 MAC 数据包。ETH 内部自带专用的 DMA控制器用于 MAC

    在这里插入图片描述

    • ETH 支持两个工业标准接口介质独立接口 (MII) 和简化介质独立接口 (RMII)用于与外部 PHY 芯片连接。MII 和 RMII 接口用于 MAC 数据包传输

    • ETH 还集成了站管理接口(SMI) 接口专门用于与外部 PHY 通信,用于访问 PHY 芯片寄存器

    • ETH 有专用的 DMA 控制器,它通过 AHB 主从接口与内核和存储器相连,AHB 主接口用于控制数据传输,而 AHB 从接口用于访问STM32以太网外设“控制与状态寄存器”(CSR) 空间

    数据收发

    • 在进行数据发送时,先将数据有存储器以 DMA 传输到发送 TX FIFO 进行缓冲,然后由 MAC 内核发送
    • 接收数据时,RXFIFO 先接收以太网数据帧,再由 DMA 传输至存储器

    SMI接口

    SMI 是 MAC 内核访问 PHY 寄存器标志接口,它由两根线组成,数据线 MDIO 和时钟线 MDC。

    • MDC:周期性时钟,提供以最大频率 2.5 MHz 传输数据时的参考时序。MDC 的最短高 电平时间和最短低电平时间必须均为 160 ns。MDC 的最小周期必须为 400 ns。在空闲 状态下,SMI 管理接口将 MDC 时钟信号驱动为低电平。
    • MDIO:数据输入/输出比特流,用于通过 MDC 时钟信号向/从 PHY 设备同步传输状态 信息。

    SMI 支持访问 32 个 PHY

    PHY 芯片内部一般都有 32 个 16 位的寄存器,用于配置 PHY 芯片属性、工作环境、状态指示等

    MAC 内核就是通过 SMI 向 PHY 的寄存器写入数据或从 PHY 寄存器读取 PHY 状态,一次只能对一个 PHY 的其中一个寄存器进行访问。SMI 最大通信频率为 2.5MHz

    SMI 是通过数据帧方式与 PHY 通信的

    数据帧格式如下:
    在这里插入图片描述
    在这里插入图片描述
    SMI写时序图
    在这里插入图片描述
    SMI读时序图
    在这里插入图片描述

    SMI时钟来源与时钟频率选择
    以太网 MAC MII 地址寄存器 (ETH_MACMIIAR)的CR:时钟范围 (Clock range)位
    在这里插入图片描述

    MII 和 RMII 接口

    介质独立接口 (MII) 用于连接 MAC 控制器和 PHY 芯片,提供数据传输路径。RMII 接口是 MII 接口的简化版本,
    MII 需要 16 根通信线,RMII 只需 7 根通信,在功能上是相同的。
    在这里插入图片描述
    TX_CLK:数据发送时钟线。标称速率为 10Mbit/s 时为 2.5MHz;速率为 100Mbit/s 时为25MHz。RMII 接口没有该线。

    RX_CLK:数据接收时钟线。标称速率为 10Mbit/s 时为 2.5MHz;速率为 100Mbit/s 时为25MHz。RMII 接口没有该线。

    TX_EN:数据发送使能。在整个数据发送过程保存有效电平。

    TXD[3:0] 或 TXD[1:0]:数据发送数据线。对于 MII 有 4 位,RMII 只有 2 位。只有在 TX_EN处于有效电平数据线才有效。

    CRS:载波侦听信号,由 PHY 芯片负责驱动,当发送或接收介质处于非空闲状态时使能该信号。在全双工模式该信号线无效。

    COL:冲突检测信号,由 PHY 芯片负责驱动,检测到介质上存在冲突后该线被使能,并且保持至冲突解除。在全双工模式该信号线无效。

    RXD[3:0] 或 RXD[1:0]:数据接收数据线,由 PHY 芯片负责驱动。对于 MII 有 4 位,RMII只有 2 位。在 MII 模式,当 RX_DV 禁止、RX_ER 使能时,特定的 RXD[3:0] 值用于传输来自 PHY 的特定信息。

    RX_DV:接收数据有效信号,功能类似 TX_EN,只不过用于数据接收,由 PHY 芯片负责驱动。对于 RMII 接口,是把 CRS 和 RX_DV 整合成 CRS_DV 信号线,当介质处于不同状态时会自切换该信号状态。

    RX_ER:接收错误信号线,由 PHY 驱动,向 MAC 控制器报告在帧某处检测到错误。

    REF_CLK:仅用于 RMII 接口,由外部时钟源提供 50MHz 参考时钟。

    MII和RMII的时钟源

    因为要达到 100Mbit/s 传输速度,MII 和 RMII 数据线数量不同,使用 MII 和 RMII 在时钟线的设计是完全不同的。

    • 对于 MII 接口,一般是外部为 PHY 提供 25MHz 时钟源,再由 PHY 提供 TX_CLK 和 RX_CLK 时钟。
      在这里插入图片描述

    • 对于 RMII 接口,一般需要外部直接提供 50MHz 时钟源,同时接入 MAC 和 PHY。
      在这里插入图片描述
      MII/RMII 选择
      使用 SYSCFG_PMC 寄存器中的配置位 23 MII_RMII_SEL 选择 MII 或 RMII 模式。
      以太网控 制器处于复位模式或使能时钟前,应用程序必须设置 MII/RMII 模式。

    MAC数据帧的发送

    MAC 数据帧发送全部由 DMA 控制,从系统存储器(RAM中)读取的以太网帧由 DMA 推入 FIFO,ETH 外设自动填充完成 MAC 数据包封装,然后将帧弹出并传输到 MAC 内核。

    检测到 SOF (开始传输帧命令)时,MAC 接受数据并开始向 MII 发送。
    检测到EOF(完成传输帧) 传输到 MAC 内核后,内核将完成正常的发送,然后将发送 的状态返回给 DMA。

    以太网数据帧是先存在DMA FIFO中,检测到SOF事件后,将数据弹到MAC内核中,MAC内核通过MII/RMII接口将数据传输到PHY芯片,传输结束后,产生EOF事件,MAC内核通知DMA,注意:该DMA为以太网内部专用的DMA

    何时产生SOF事件呢?
    SOF事件来源有2个种方式,(向 MAC 内核弹出数据有两种操作模式):

    • 在阈值(直通)模式下,只要 FIFO 中的字节数超过配置的阈值(或在超过阈值前写入帧结束), 数据就准备好弹出并转发到 MAC 内核。使用 ETH_DMABMR 的 TTC 位配置阈值。
    • 在存储转发模式下,仅当在 FIFO 中存储完整的帧后,才会向 MAC 内核弹出帧。如果 Tx FIFO 的大小小于要发送的以太网帧,则在 Tx FIFO 接近填满时向 MAC 内核弹 出帧。

    DMA -FIFO手动清空,复位FIFO指针
    可通过将 FTF 位(ETH_DMAOMR 寄存器 [20])置 1 来清空发送 FIFO 的所有内容。 此位自行清零,并将 FIFO 指针初始化为默认状态。如果向 MAC 内核传输帧时将 FTF 位置 1,则传输将停止,因为此时 FIFO 被视为空。

    自动 CRC 和 pad 生成功能
    以太网数据帧有最短长度要求,当传输的数据小于该要求则需要补足

    当从应用程序接收的字节数少于 60(DA+SA+LT+数据)时,会向发送帧附加零,使数据长 度正好为 46 字节
    在这里插入图片描述

    对于半双工模式下发送以太网数据帧:
    当请求发送新的帧时,MAC 将发送报头和 SFD,紧接着发送数据,如果在开始传输帧到 CRC 字段结束之间的任何时间发生冲突(冲突检测窗口为512位时间),MAC 将在 MII 上发送 0x5555 5555 的 32 位阻塞信号,如果在报头发送 阶段发生冲突,MAC 将完成报头和 SFD 的发送,然后发送阻塞信号。。阻塞信号生成仅适用于半双工模式,不适用于全双工模式。

    系统使用一个 jabber 定时器,用于在传输的字节超过 2048 字节(默认值)时切断以太网帧 的发送。以太网数据帧有最短和最长数据帧长度要求

    可以控制2个以太网数据帧发送之间的间隔
    两个 发送帧之间的空闲期段,即配置的帧间隔(ETH_MACCR 寄存器中的 IFG 位)
    在这里插入图片描述

    发送流量控制(发送控制)
    在全双工模式下,当发送流量控制使能位(ETH_MACFCR 中的 TFE 位)置 1 时,MAC 将 生成暂停帧并根据需要发送暂停帧。暂停帧:通知发送方停止发送数据,全双工模式下,假如接收FIFO满了,则发送暂停帧

    可以通过 两种方式启动暂停帧的生成。

    • 当应用程序将 ETH_MACFCR 寄存器中的 FCB 位置 1 (手动)
      通过将 ETH_MACFCR 寄存器中的 FCB 位置 1 来请求流量控制,则 MAC 将生成并发送单个暂停帧。
    • 接收 FIFO 已满(数据包缓冲区)时,将发送暂停帧。

    生成的帧中的暂停时间值为 ETH_MACFCR 中编程的 暂停时间值。
    在这里插入图片描述

    单数据包发送操作
    发送操作的常规事件序列如下:

    1. 如果系统有要传输的数据,则 DMA 控制器将通过 AHB 主接口从存储器中获取这些数据 并将其转发给 FIFO。它将继续接收数据直到传输帧结束。
    2. 当超过阈值(接收的数据超过设置的阈值)或 **FIFO 接收到完整的数据包(从AHB主接口中接收到数据(需要发送的数据))**时,直到将完整的数据包传输到 MAC 为止。 DMA 继续从 FIFO 传输数据,数据会被弹出并被传输到 MAC 内核。帧传输完成后,来 自 MAC 的状态将通知 DMA 控制器。

    发送操作––缓冲区中有两个数据帧(发一个数据帧的同时,从AHB主接口接收下一个数据帧)
    由于 DMA 必须先更新描述符状态才能将其释放给主机,因此一个发送 FIFO 内最多只能 有两个帧。仅当 OSF(对第二个帧起作用)位置 1 时,DMA 才会获取第二个帧并将其 置于 FIFO 中。

    • 如果此位未置 1,则仅当 MAC 完全处理该帧且 DMA 已释放描述符后, DMA 才会从存储器获取下一帧。
    • 如果 OSF 已置 1,则 DMA 将第一个帧传输到 FIFO 后将立即开始获取第二个帧。不会 等待状态更新。

    冲突期间的重新发送(仅在半双工模式下该功能有效)
    在半双工模式下,向 MAC 传输帧时,可能在 MAC 线接口上发生冲突事件。MAC 甚至会在 接收到帧结束之前就给出状态来指示重试。然后将使能重新发送并再次将帧从 FIFO 中弹 出。当超过 96 个字节弹向 MAC 内核后,FIFO 控制器将释放该空间,使 DMA 可推入更多 数据。这意味着超过阈值后或 MAC 内核指示延迟冲突事件时,无法重新发送。

    发送校验和减荷
    通信协议(例如 TCP 和 UDP)将实施校验和字段,这有助于确定通过网络发送的数据的完 整性。由于以太网最广泛的用途是通过 IP 数据报封装 TCP 和 UDP,因此以太网控制器具有 发送校验和减荷功能,该功能支持校验和计算、发送路径中的校验和插入以及接收路径中的错误检测。
    检验以太网数据帧中有效载荷的IP 数据报封装 TCP 和 UDP

    通过完整的帧来计算 TCP、UDP 或 ICMP 的校验和,然后将其插入相应的报头字段。由于此要求,仅当发送 FIFO 配置为存储转发模式(即,ETH_ETH_DMAOMR 寄存器中的 TSF 位 置 1)时,才使能此功能。如果内核配置为阈值(直通)模式,则将绕过发送校验和减荷。

    MAC 数据包的接收

    在检测到有 MAC 数据包需要接收时,ETH 外设控制数据接收,并解包MAC 数据包得到解包后的数据通过 DMA 传输到系统寄存器内。

    MAC接收也有2种方式

    • 在阈值(直通)模式下,当 FIFO 接收到 64 个字节 (使用 ETH_DMAOMR 寄存器中的 RTC 位配置) 或完整的数据包时,数据将弹出,

    • 在 Rx FIFO 存储转发模式(通过 ETH_DMAOMR 寄存器中的 RSF 位置)下,仅在帧完全 写入接收 FIFO 后才可读出帧。

    去除接收的帧的报头和 SFD。检测到 SFD 后,MAC 开始向接收 FIFO 发送以太网帧数据, 从 SFD 后面的第一个字节(目标地址)开始发送。

    如果接收的帧长度/类型字段小于 0x600 并且为 MAC 编程了自动去除 CRC/pad 选项,则 MAC 将向接收 FIFO 发送帧数据(数据量不超过长度/类型字段中指定的数量),然后开始 丢弃字节(包括 FCS 字段)。如果长度/类型字段大于或等于 0x600,则不管编程的自动 CRC 去除选项的值如何,MAC 都会向 Rx FIFO 发送所有接收到的以太网帧数据

    默认情况 下,使能 MAC 看门狗定时器,即,超过 2048 个字节的帧会被切断。可通过对 MAC 配置寄存器中的看门狗禁止 (WD) 位编程来禁止此功能。

    接收 CRC:自动 CRC 和 pad 去除
    MAC 将检查接收帧中的任何 CRC 错误。它将计算接收的帧(包括目标地址字段到 FCS 字 段)的 32 位 CRC。

    在这里插入图片描述

    接收校验和减荷
    对接收的以太网帧中的 IPv4 和 IPv6 帧进行检测和处理,以确保数据完整性。可通过将 ETH_MACCR 寄存器中的 IPCO 位置 1 来使能接收校验和减荷。

    接收帧控制器(过滤)
    如果复位 MAC CSR 帧过滤寄存器中的 RA 位,则 MAC 将根据目标/源地址执行帧过滤
    检测到过滤失败时,帧将被丢弃且不会传输到应用程序

    接收流量控制(全双工模式)
    MAC 将检测接收暂停帧并暂停帧发送,暂停时间为接收的暂停帧内指定的延迟(仅限全双 工模式)。
    可通过 ETH_MACFCR 中的 RFCE 位使能或禁止暂停帧检测功能
    使能接收流 量控制后,将开始监视接收帧的目标地址是否与控制帧的多播地址 (0x0180 C200 0001) 匹 配。
    如果检测到匹配(接收的帧的目标地址与保留的控制帧的目标地址匹配),MAC 将根 据 ETH_MACFFR 中的 PCF 位来决定是否将接收的控制帧(如暂停帧)传输到应用程序
    对于具有单播目标地址的暂停帧,MAC 将根据 DA 是否与 MAC 地址 0 寄存器的内容匹配以 及 ETH_MACFCR 中的 UPDF 位是否置 1(检测具有单播目标地址的暂停帧)来进行过滤。
    在这里插入图片描述

    MAC过滤

    MAC 过滤功能可以选择性的过滤设定目标地址或源地址的 MAC 帧。它将检查所有接收到的数据帧的目标地址和源地址,根据过滤选择设定情况,检测后报告过滤状态。
    针对目标地址过滤可以有三种,分别是单播、多播和广播目标地址过滤;
    针对源地址过滤就只有单播源地址过滤。

    • 单播目标地址过滤是将接收的相应 DA 字段与预设的以太网 MAC 地址寄存器内容比较,最高可预设 4 个过滤 MAC 地址。
    • 多播目标地址过滤是根据帧过滤寄存器中的 HM 位执行对多播地址的过滤,是对 MAC 地址寄存器进行比较来实现的。单播和多播目标地址过滤都还支持 Hash 过滤模式。
      • 广播目标地址过滤通过将帧过滤寄存器的 BFD 位置 1 使能,这使得 MAC 丢弃所有广播帧。

    单播源地址过滤是将接收的 SA 字段与 SA 寄存器内容进行比较过滤。

    MAC 过滤还具备反向过滤操作功能,即让过滤结构求补集。

    MAC 回送模式模式

    MAC 支持对发送到其接收器的帧进行回送。默认情况下,禁止 MAC 回送功能,可通过编程 MAC ETH_MACCR 寄存器中的 Loopback 位使能该功能

    移植官方以太网驱动(无操作系统)

    官方文件stsw-stm32070.rar
    在其文件目录 (…STM32F4x7_ETH_LwIP_V1.1.1LibrariesSTM32F4x7_ETH_Driver) 下可找到 stm32f4x7_eth.c、stm32f4x7_eth.h 和 stm32f4x7_eth_conf_template.h 三个文件,其中的 stm32f4x7_eth.c 和 stm32f4x7_eth.h 就是类似 stm32f4xx_adc.c 是关于 ETH 外设的驱动。

    移植步骤

    • 在 stsw-stm32070 文件夹找到 port 文件夹 (路径:… \Utilities\Third_Party\lwip-1.4.1\port),把整个port 文件夹拷贝 lwip-1.4.1 文件夹中,在 port 文件夹下的 STM32F4x7 文件中把 arch 和 Standalone两个文件夹直接剪切到 port 文件夹中,即此时 port 文件夹有三个 STM32F4x7、 arch 和 Standalone文件夹,最后把 STM32F4x7 文件夹删除,arch 存放与开发平台相关头文件, Standalone 文件夹是无操作系统移植时 ETH 外设与 LwIP 连接的底层驱动函数,其调用STM32的ETH外设进行收发数据
      在这里插入图片描述
    • ETH 外设驱动文件,在 stsw-stm32070 文件夹中找到 stm32f4x7_eth.h 和stm32f4x7_eth.c 两个文件 (路径:… \Libraries\STM32F4x7_ETH_Driver),将这两个文件拷贝出来,这两个文件是 ETH 驱动文件,类似标准库中外设驱动代码实现文件,在移植过程中我们几乎不过文件的内容。
      在这里插入图片描述
    • 相关 GPIO 初始化、 ETH 外设初始化、 PHY 状态获取等等函数的实现,在 stsw-stm32070 文件夹中找到 stm32f4x7_eth_bsp.c、 stm32f4x7_eth_bsp.h 和 stm32f4x7_eth_conf.h三个文件 (路径:… \Project\Standalone\tcp_echo_client),将这三个文件拷贝出来。因为 ST 官方 LwIP 测试平台使用的 PHY 型号不是使用 LAN8720A,所以这三个文件需要我们进行修改。
      在这里插入图片描述
    • 在 stsw-stm32070 文件夹中找到 netconf.c、 tcp_echoclient.c、 lwipopts.h、 netconf.h 和 tcp_echoclient.h 五个文件 (路径:…
      \Project\Standalone\tcp_echo_client),直接拷贝到 App 文件夹 (自己新建) 中, netconf.c 文件代码实现 LwIP 初始化函数、周期调用函数、 DHCP 功能函数等等, tcp_echoclient.c 文件实现 TCP 通信参数代码, lwipopts.h 包含 LwIP 功能选项。
      在这里插入图片描述
    • 拷贝lwip文件到工程文件夹下
      在这里插入图片描述
      在这里插入图片描述
    • 在工程中添加文件
      在这里插入图片描述
      在这里插入图片描述
    • 设置头文件路径
      在这里插入图片描述

    ethernetif.c 文件是无操作系统时网络接口函数,该文件在移植是只需修改相关头文件名,函数实现部分无需修改。该文件主要有三个部分函数,一个是 low_level_init,用于初始化 MAC 相关工作环境、初始化 DMA 描述符链表,并使能 MAC 和 DMA;一个是 low_level_output,它是最底层发送一帧数据函数;最后一个是 low_level_input,它是最底层接收一帧数据函数。

    stm32f4x7_eth.h 和stm32f4x7_eth.c 两个文件用于 ETH 驱动函数实现,它是通过直接操作寄存器方式实现,这两个文件我们无需修改。

    需要修改的文件如下

    • stm32f4x7_eth_conf.h
    • stm32f4x7_eth_bsp.h
    • stm32f4x7_eth_bsp.c
    • netconf.h
    • netconf.c

    stm32f4x7_eth_conf.h头文件的修改
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    stm32f4x7_eth_bsp.h文件修改
    在这里插入图片描述
    stm32f4x7_eth_bsp.c文件修改

    ETH_BSP_Config()函数
    在这里插入图片描述
    在这里插入图片描述
    ETH_MACDMA_Config()函数
    在这里插入图片描述
    在这里插入图片描述
    ETH_GPIO_Config()函数
    在这里插入图片描述
    在这里插入图片描述
    netconf.h文件修改

    /**
      ******************************************************************************
      * @file    netconf.h
      * @author  MCD Application Team
      * @version V1.1.0
      * @date    31-July-2013 
      * @brief   This file contains all the functions prototypes for the netconf.c 
      *          file.
      ******************************************************************************
      * @attention
      *
      * 

    © COPYRIGHT 2013 STMicroelectronics

    * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */
    /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __NETCONF_H #define __NETCONF_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Exported types ------------------------------------------------------------*/ #define DHCP_START 1 #define DHCP_WAIT_ADDRESS 2 #define DHCP_ADDRESS_ASSIGNED 3 #define DHCP_TIMEOUT 4 #define DHCP_LINK_DOWN 5 //#define USE_DHCP /* enable DHCP, if disabled static address is used */ /* Uncomment SERIAL_DEBUG to enables retarget of printf to serial port (COM1 on STM32 evalboard) for debug purpose */ #define SERIAL_DEBUG #define DEST_IP_ADDR0 192 /* 服务器IP */ #define DEST_IP_ADDR1 168 #define DEST_IP_ADDR2 1 #define DEST_IP_ADDR3 100 #define DEST_PORT 6000 /* 服务器端口 */ #define UDP_SERVER_PORT 5000 /* define the UDP local connection port */ #define UDP_CLIENT_PORT 5000 /* define the UDP remote connection port */ /* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ #define MAC_ADDR0 2 /* 网卡MAC */ #define MAC_ADDR1 0 #define MAC_ADDR2 0 #define MAC_ADDR3 0 #define MAC_ADDR4 0 #define MAC_ADDR5 0 /*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ #define IP_ADDR0 192 /* 本机IP */ #define IP_ADDR1 168 #define IP_ADDR2 1 #define IP_ADDR3 122 /*NETMASK*/ #define NETMASK_ADDR0 255 /* 子网掩码 */ #define NETMASK_ADDR1 255 #define NETMASK_ADDR2 255 #define NETMASK_ADDR3 0 /*Gateway Address*/ #define GW_ADDR0 192 /* 网关IP */ #define GW_ADDR1 168 #define GW_ADDR2 1 #define GW_ADDR3 1 /** * @brief Number of milliseconds when to check for link status from PHY */ #ifndef LINK_TIMER_INTERVAL #define LINK_TIMER_INTERVAL 1000 #endif /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ #define printf USART1Printf /* Exported functions ------------------------------------------------------- */ void LwIP_Init(void); void LwIP_Pkt_Handle(void); void LwIP_Periodic_Handle(__IO uint32_t localtime); #ifdef __cplusplus } #endif #endif /* __NETCONF_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    netconf.c文件修改
    LwIP_Init()函数
    调试信息的修改
    在这里插入图片描述
    tcp_echoclient.h修改
    在这里插入图片描述
    tcp_echoclient.c修改
    在这里插入图片描述

    还有一些其他的修改,比如源代码缺少头文件,直接补上就可以了;调试信息接口的修改,使用LCD还是串口等;工作指示灯LED

    lwipopts.h 文件存放一些宏定义,用于剪切 LwIP 功能,比如有无操作系统、内存空间分配、存储池分配、 TCP 功能、 DHCP 功能、 UDP 功能选择等等。

    LwIP_Periodic_Handle 函数是一个必须被无限循环调用的 LwIP 支持函数,一般在 main 函数的无限循环中调用,主要功能是为 LwIP 各个模块提供时间并查询链路状态,该函数有一个形参,用于指示当前时间,单位为 ms。

    LwIP_Pkt_Handle 函数用于从以太网存储器读取一个以太网帧并将其发送给 LwIP,它在接收到以太网帧时被调用,它是直接调用 ethernetif_input 函数实现的,该函数定义在 ethernetif.c 文件中。

    LwIP 为使用者提供了两种应用程序接口 (API 函数) 来实现 TCP/IP 协议栈,

    • 一种是低水平、基于回调函数的 API,称为 RAW API,
    • 另外一种是高水平、连续的 API,称为 sequential API, sequentialAPI
      又有两种函数结构,一种是 Netconn,一种是 Socket,它与在电脑端使用的 BSD 标准的 Socket API结构和原理是非常相似的。

    测试

    使用网线连接开发板和PC,更改PC的IP使其与开发板同一的局域网下

    LwIP_Periodic_Handle 函数执行 LwIP 需要周期性执行函数,该所以我们需要为该函数提高一个时间基准,这里使用 TIM 产生这个基准,初始化配置 TIM 每 10ms 中断一次,在其中断服务函数中递增 LocalTime 变量值。

    在这里插入图片描述
    在这里插入图片描述
    主函数
    调用初始化函数
    在这里插入图片描述
    设置开发板IP与服务器地址等

    /**
      ******************************************************************************
      * @file    netconf.h
      * @author  MCD Application Team
      * @version V1.1.0
      * @date    31-July-2013 
      * @brief   This file contains all the functions prototypes for the netconf.c 
      *          file.
      ******************************************************************************
      * @attention
      *
      * 

    © COPYRIGHT 2013 STMicroelectronics

    * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */
    /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __NETCONF_H #define __NETCONF_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Exported types ------------------------------------------------------------*/ #define DHCP_START 1 #define DHCP_WAIT_ADDRESS 2 #define DHCP_ADDRESS_ASSIGNED 3 #define DHCP_TIMEOUT 4 #define DHCP_LINK_DOWN 5 //#define USE_DHCP /* enable DHCP, if disabled static address is used */ /* Uncomment SERIAL_DEBUG to enables retarget of printf to serial port (COM1 on STM32 evalboard) for debug purpose */ #define SERIAL_DEBUG #define DEST_IP_ADDR0 192 /* 服务器IP */ #define DEST_IP_ADDR1 168 #define DEST_IP_ADDR2 1 #define DEST_IP_ADDR3 100 #define DEST_PORT 6000 /* 服务器端口 */ #define UDP_SERVER_PORT 5000 /* define the UDP local connection port */ #define UDP_CLIENT_PORT 5000 /* define the UDP remote connection port */ /* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ #define MAC_ADDR0 2 /* 网卡MAC */ #define MAC_ADDR1 0 #define MAC_ADDR2 0 #define MAC_ADDR3 0 #define MAC_ADDR4 0 #define MAC_ADDR5 0 /*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ #define IP_ADDR0 192 /* 本机IP */ #define IP_ADDR1 168 #define IP_ADDR2 1 #define IP_ADDR3 122 /*NETMASK*/ #define NETMASK_ADDR0 255 /* 子网掩码 */ #define NETMASK_ADDR1 255 #define NETMASK_ADDR2 255 #define NETMASK_ADDR3 0 /*Gateway Address*/ #define GW_ADDR0 192 /* 网关IP */ #define GW_ADDR1 168 #define GW_ADDR2 1 #define GW_ADDR3 1 /** * @brief Number of milliseconds when to check for link status from PHY */ #ifndef LINK_TIMER_INTERVAL #define LINK_TIMER_INTERVAL 1000 #endif /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ #define printf USART1Printf /* Exported functions ------------------------------------------------------- */ void LwIP_Init(void); void LwIP_Pkt_Handle(void); void LwIP_Periodic_Handle(__IO uint32_t localtime); #ifdef __cplusplus } #endif #endif /* __NETCONF_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    更改PC机IP地址
    在这里插入图片描述
    PC ping 开发板
    在这里插入图片描述
    开发板作为TCP client 连接TCP服务器
    开发板有2个按键,KEY1按下则连接TCP服务器
    KEY2按下则断开连接

    需要2个文件
    tcp_echoclient.c与tcp_echoclient.h
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    工程文件下载链接

  • 相关阅读:
    virsh 保护命令 virtual protect rebase
    springboot项目基于jdk17、分布式事务seata-server-1.7.1、分库分表shardingSphere5.2.1开发过程中出现的问题
    如何防止重复提交订单
    Swift 中的Getter 和 Setter
    visual studio开发过程中常见操作
    点亮三盏灯
    2. 在STM32CubeMX建立的Keil5工程中添加自定义的相关文件
    Flink CDC 新一代数据集成框架
    多线程案例
    Spring创建Bean的过程大概记录
  • 原文地址:https://blog.csdn.net/qq_45607873/article/details/126195782