ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32H7 LAN8720A LWIP Ping不通?CubeMX配置与排查实战

STM32H7 LAN8720A LWIP Ping不通?CubeMX配置与排查实战 1. 项目缘起与整体设计思路STM32H7 系列 MCU 主频能跑到 480MHz带 Ethernet MAC 控制器配合 LAN8720A 这颗经典 PHY 芯片做以太网通信在工业控制、数据采集、边缘网关这类场景里非常常见。但真正上手做的时候很多人会卡在同一个地方CubeMX 里 LWIP 配置看起来没问题代码也编译通过了网线插上电脑就是 ping 不通。我前后做过四五个基于 H7 的以太网项目从 H743 到 H723 都碰过这个问题几乎每次都会以不同面貌出现。这篇内容就是把我踩过的坑、验证过的配置、以及最终稳定跑通的方案完整梳理出来。核心关键词围绕STM32H7、LAN8720A、LWIP、Ping、CubeMX展开适合正在用 H7 做以太网通信的嵌入式开发者尤其是那些 CubeMX 配置完发现 ping 不通、或者 ping 通了但丢包严重的朋友。我会从硬件接口、时钟树、CubeMX 参数、LWIP 协议栈配置、PHY 地址与自协商、中断与缓存一致性这几个维度逐一拆解每个环节都给出可复现的操作和判断依据。先说整体思路。STM32H7 的以太网外设和 F4/F7 有本质区别它用的是新版 Ethernet MAC配合 DMA 描述符支持多队列和更复杂的缓存管理。LAN8720A 是一颗 10/100M 自协商 PHY通过 RMII 接口和 MAC 连接需要外部 50MHz 时钟源。LWIP 作为轻量级 TCP/IP 协议栈在 H7 上跑的时候内存池大小、PBUF 分配、checksum 卸载这些参数如果配错表现就是能收不能发或者 ARP 能通但 ICMP 不回。我选择 RMII 而不是 MII原因是 RMII 引脚少、PCB 布线简单LAN8720A 原生支持 RMII50MHz 时钟可以由外部晶振提供也可以从 MCU 的 MCO 输出。实际项目里我倾向于用外部 25MHz 晶振给 LAN8720A然后 LAN8720A 的 REF_CLK 输出 50MHz 给 STM32H7 的 ETH_RMII_REF_CLK这样时钟抖动小自协商更稳。这个选择直接决定了后面 CubeMX 里时钟树的配置方式也是很多人 ping 不通的根源之一。LWIP 版本我一般用 ST 官方 CubeMX 里集成的 2.1.2 或 2.1.3配合 FreeRTOS 跑。裸机也能跑但 H7 资源丰富上 RTOS 后网络任务和业务任务分离调试起来清晰得多。下面按实际工程顺序从硬件确认到软件配置再到问题排查一步步展开。2. 硬件接口与时钟配置的关键细节2.1 LAN8720A 的 RMII 连接与 PHY 地址LAN8720A 的 PHY 地址由 PHYAD0 引脚决定这个引脚在复位时被采样。很多开发板把这个引脚悬空或者接地导致地址是 0 或 1。CubeMX 里 ETH 配置的 PHY Address 必须和硬件一致否则 LWIP 初始化时读不到 PHY 寄存器表现就是ethernet_link_check一直失败ping 自然不通。我习惯在原理图阶段就把 PHYAD0 通过 4.7k 电阻下拉到地地址固定为 0。这样软件里 PHY Address 填 0不用猜。如果你用的是现成开发板先拿万用表量一下 PHYAD0 引脚在复位后的电平或者直接看原理图。这个细节看起来小但我见过至少三次因为地址填错导致调了一整天的情况。RMII 接口的引脚连接如下表这是 H7 和 LAN8720A 之间的标准接法STM32H7 引脚LAN8720A 引脚说明PA1REF_CLK50MHz 参考时钟PA2MDIO管理数据PA7CRS_DV载波侦听PC1MDC管理时钟PC4RXD0接收数据0PC5RXD1接收数据1PB11TX_EN发送使能PB12TXD0发送数据0PB13TXD1发送数据1注意 PA1 是 ETH_RMII_REF_CLK在 H7 上这个引脚必须配置为复用功能并且时钟来源要选对。如果 LAN8720A 提供 50MHz那 PA1 就是输入如果用 MCU 的 MCO 输出那就要另外配置。我推荐前者因为 LAN8720A 的 REF_CLK 输出经过内部 PLL稳定性比 MCO 分频好。2.2 时钟树配置与 50MHz 参考时钟STM32H7 的 ETH 外设需要 50MHz 时钟这个时钟可以来自 PLL1Q、PLL2Q 或者外部引脚。用 RMII 且 LAN8720A 提供 REF_CLK 时CubeMX 里 ETH 的 Clock Source 要选External PHY clock也就是从 PA1 输入。这时候 PLL 不用给 ETH 供时钟但要注意 PA1 的复用功能要正确。如果 LAN8720A 没有输出 50MHz而是用 MCU 的 MCO1 输出 50MHz 给 PHY那 CubeMX 里 ETH Clock Source 选PLL1Q或PLL2Q同时配置 MCO1 输出。这种情况下PLL 的配置要保证输出正好 50MHz。比如 H743 的 PLL1 配置成 400MHzQ 分频 8 得到 50MHz。这个计算过程要仔细差一点自协商就会失败。我实测下来外部 PHY 提供时钟的方案在 H7 上更省心因为不用纠结 PLL 分频。但前提是 LAN8720A 的 25MHz 晶振要选质量好的负载电容匹配对。晶振起振不良会导致 REF_CLK 频率偏移PHY 自协商能过但通信丢包。2.3 复位电路与电源去耦LAN8720A 的 nRST 引脚不能悬空必须由 MCU 或 RC 电路控制。我一般用 MCU 的一个 GPIO 控制复位上电后拉低至少 100us 再拉高确保 PHY 内部寄存器复位完成。如果 nRST 一直拉高PHY 可能处于不确定状态MDIO 读写会失败。电源方面LAN8720A 需要 3.3V 和 1.2V内部稳压输出。1.2V 由内部 LDO 产生外部要接 10uF 和 0.1uF 去耦。我遇到过因为 1.2V 去耦不足导致 PHY 工作不稳定的情况ping 大包时丢包小包正常。后来在 1.2V 引脚旁边补了 10uF 钽电容问题消失。这个经验在数据手册里不会重点强调但实际布线时很关键。3. CubeMX 中 ETH 与 LWIP 的配置实操3.1 ETH 外设参数逐项说明打开 CubeMX在 Connectivity 里选 ETH。Mode 选 RMII下面几个参数要重点看PHY Address填 0和硬件 PHYAD0 一致。Auto Negotiation勾上让 PHY 自己协商 10/100M 和全双工。Carrier Sense使能。Receive Own使能。Loopback Mode不勾。Checksum Offload这个我建议先不勾等基础通信通了再开。因为 H7 的 checksum 卸载和 LWIP 的配置要配合配错会导致包被丢弃。Advanced Parameters 里Rx Buffer Length默认 1524 够用Rx Buffers和Tx Buffers我一般设 4 和 4。H7 的 DMA 描述符数量影响吞吐但 ping 场景下 4 个足够。Rx Descriptor和Tx Descriptor保持默认。中断方面ETH 全局中断要开优先级设成比 FreeRTOS 的 configMAX_SYSCALL_INTERRUPT_PRIORITY 低数值大。我一般设 5 或 6确保中断里能调用 FreeRTOS 的 API。3.2 LWIP 协议栈配置要点LWIP 在 CubeMX 里是 Middleware 下的组件。先使能 LWIP然后几个关键参数LWIP_DHCP调试阶段建议先关用静态 IP。DHCP 会引入额外变量ping 不通时不好判断是 DHCP 没拿到地址还是链路问题。IP 地址设成和电脑同网段比如电脑是 192.168.1.100板子设 192.168.1.200掩码 255.255.255.0网关 192.168.1.1。MEM_SIZE默认 1600 偏小我设成 4096 或 8192。H7 内存大不用省。PBUF_POOL_SIZE设 8 或 16每个 PBUF 大小 1524。TCP 相关ping 用不到 TCP但 LWIP 初始化会分配保持默认即可。还有一个容易忽略的LWIP_NETIF_HOSTNAME和LWIP_NETIF_STATUS_CALLBACK。后者在链路状态变化时回调调试时可以在回调里打印 PHY 状态方便判断链路是否 up。3.3 FreeRTOS 任务划分与优先级如果跑 FreeRTOSLWIP 需要一个任务处理超时和接收。CubeMX 生成的代码里MX_LWIP_Init会创建tcpip_thread。我一般再创建一个ethernetif_input任务优先级比 tcpip_thread 低一级专门处理接收。任务优先级安排任务优先级说明tcpip_thread3LWIP 核心处理协议栈ethernetif_input2从 DMA 取包投递给 LWIP业务任务1用户逻辑堆栈大小tcpip_thread 给 1024 字ethernetif_input 给 512 字。H7 的 RAM 充足不用抠。4. Ping 不通问题的系统化排查4.1 从 PHY 寄存器读起ping 不通时第一步不是改代码而是读 PHY 寄存器。在MX_LWIP_Init之后加一段代码读 LAN8720A 的 BCR地址 0和 BSR地址 1。BCR 的 bit15 是复位bit12 是自协商使能。BSR 的 bit2 是链路状态bit5 是自协商完成。如果 BSR 的 bit2 是 0说明链路没 up。这时候检查网线是否插好换一根试试。电脑网口是否正常工作换个口。LAN8720A 的 25MHz 晶振是否起振用示波器看 REF_CLK 是否有 50MHz。PHY 地址是否填对。如果 bit2 是 1 但 ping 不通说明链路 up 了问题在 MAC 或 LWIP 层。这时候读 MAC 的寄存器看发送和接收计数器有没有增长。4.2 缓存一致性问题H7 有 D-CacheETH DMA 访问的内存如果被 Cache 缓存会出现数据不一致。具体表现是发送时 DMA 读到的数据是旧的接收时 CPU 读到的数据没更新。ping 不通或者 ping 通但数据错乱很多时候是这个原因。解决办法有两种把 ETH 描述符和缓冲区放在非缓存区域通过 MPU 配置。在发送前和接收后调用SCB_CleanDCache_by_Addr和SCB_InvalidateDCache_by_Addr。我推荐第一种一劳永逸。在main.c里配置 MPU把 ETH 使用的 RAM 区域设成MPU_ACCESS_NOT_CACHEABLE。具体地址要看链接脚本里 ETH 缓冲区的分配。CubeMX 生成的代码里ETH 描述符在0x30000000开始的区域这个区域默认是 AXI SRAM可以配成非缓存。如果不想动 MPU就在ethernetif.c的low_level_output里加 clean cache在low_level_input里加 invalidate cache。注意地址要 32 字节对齐长度要按 cache line 对齐。4.3 中断与 DMA 描述符配置H7 的 ETH DMA 描述符有所有权位CPU 和 DMA 交替持有。如果描述符配置错误DMA 会停止工作。常见问题是描述符地址没有 32 字节对齐。描述符的 OWN 位没有正确翻转。接收描述符的 buffer 地址没有对齐。CubeMX 生成的代码一般没问题但如果你手动改过链接脚本或者内存分配要检查这些。我遇到过因为把 ETH 描述符放到 DTCM 导致 DMA 无法访问的情况。DTCM 是紧耦合内存DMA 访问不了必须放在 AXI SRAM 或 SRAM1/2/3。4.4 常见问题速查表现象可能原因排查方法PHY 寄存器读不到PHY 地址错、MDIO 引脚配置错量 PHYAD0 电平检查 PA2/PC1 复用链路不 up晶振不起振、网线问题、自协商失败示波器看 REF_CLK换网线读 BSR链路 up 但 ping 不通缓存不一致、IP 冲突、防火墙关 D-Cache 测试换 IP关电脑防火墙ping 通但丢包去耦不足、时钟抖动、缓冲区太小补电容换晶振加大 PBUF_POOL_SIZE大包不通小包通MTU 配置、缓存对齐检查 LWIP MTU检查 cache line 对齐5. 实操验证与稳定性优化5.1 分阶段验证方法我习惯分三步验证第一步不跑 LWIP直接读 PHY 寄存器确认 MDIO 通信正常。这一步通了说明硬件接口没问题。第二步跑 LWIP 但不跑 FreeRTOS用裸机轮询方式 ping。这一步通了说明 MAC 和 LWIP 配置没问题。第三步加上 FreeRTOS用中断方式 ping。这一步通了说明任务划分和中断优先级没问题。每一步都确认稳定后再进下一步出问题时范围小好定位。5.2 长时间 ping 测试与统计基础 ping 通之后用ping -t跑至少 10 分钟看丢包率。理想情况是 0% 丢包延迟稳定在 1ms 以内。如果丢包看是规律性丢包还是随机丢包。规律性丢包通常是缓冲区不够或者任务优先级问题。随机丢包多半是硬件信号完整性问题比如 REF_CLK 走线太长、没有阻抗匹配。我在一个项目里遇到过每 ping 几百次丢一个包最后发现是 REF_CLK 走线经过了一个电源平面分割区重新布线后解决。5.3 性能优化参数ping 通了之后如果要做 TCP 传输还要调这些TCP_MSS设成 1460配合 MTU 1500。TCP_WND设成 4 倍 MSS提高吞吐。TCP_SND_BUF设成 2 倍 MSS。MEM_SIZE加大到 16KB 以上。H7 的 ETH 支持 checksum 卸载开启后 CPU 占用降低。在 CubeMX 里勾上 Checksum Offload然后在 LWIP 里定义CHECKSUM_BY_HARDWARE。注意收发都要配只配一个会导致包被丢弃。6. 个人经验与后续扩展我在 H7 上做以太网最大的体会是硬件问题占七成软件问题占三成。很多人一上来就改 LWIP 参数其实先量一下 REF_CLK、读一下 PHY 寄存器能省很多时间。LAN8720A 这颗 PHY 很成熟只要时钟和复位对了自协商基本不会出问题。另一个经验是缓存一致性。H7 的 D-Cache 在跑网络时一定要处理好要么配 MPU 非缓存要么手动 clean/invalidate。我见过有人 ping 通但 TCP 传文件校验失败查了两天最后发现是 cache 没处理。后续如果要扩展可以在这个基础上加 HTTP 服务器或者 MQTT 客户端。LWIP 的 raw API 和 netconn API 都支持H7 的性能跑这些绰绰有余。我下一个项目准备试试在 H723 上跑 LWIP 加 TLS到时候再分享。
返回列表