[STM32H7] 长时间空闲之后 UDP 数据包无法发送

[复制链接]
85|32
onlycook 发表于 2026-10-5 21:42 | 显示全部楼层
一个值得怀疑的点是:tcpip_thread 在长时间空闲后,是否因为某些超时处理进入了某种阻塞等待状态,导致邮箱消息处理被延后。
一点点0321 发表于 2026-10-5 21:58 | 显示全部楼层
这个问题在 H7 上太经典了,90% 是 Cache 一致性没处理好。虽然你说关了 Cache,但如果是通过 MPU 配置的,必须确认 LwIP 的 RX/TX 描述符和缓冲区真的被映射成了 Non-cacheable 区域,否则 CPU 改了 OWN 位但 DMA 看不到,或者 DMA 写了数据 CPU 读不到旧值
powerantone 发表于 2026-10-5 22:32 | 显示全部楼层
LwIP 的消息邮箱在 FreeRTOS 下如果由 sys_mbox_fetch 封装,可能存在超时参数设置问题。若 mbox 等待超时时间过长,且没有新的中断唤醒机制,消息会一直滞留。
合同圣诞节fy 发表于 2026-10-6 08:16 | 显示全部楼层
检查一下 ETH 驱动里的 HAL_ETH_Transmit 函数实现。H7 的 HAL 库有些版本在处理空闲队列时,如果长时间不发送,可能会漏掉唤醒 MAC 发送引擎的操作。试着在 sendto 之后手动调用一下 HAL_ETH_StartTransmission,看看能不能把数据“推”出去
喂什么玩意 发表于 2026-10-6 08:18 | 显示全部楼层
检查一下 ETH 驱动里的 HAL_ETH_Transmit 实现。H7 的 HAL 库有些老版本在处理空闲队列时,如果长时间不发送,可能会漏掉唤醒 MAC 发送引擎的操作。试着在 sendto 之后手动调用一下 HAL_ETH_StartTransmission,看看能不能把数据“推”出去
probedog 发表于 2026-10-6 10:43 | 显示全部楼层
STM32H7 的 ETH 中断虽然能触发,但中断服务程序里可能只处理了接收或错误标志,并没有主动调用 sys_check_timeouts() 或向 tcpip_thread 发送唤醒信号,这属于 CubeMX 默认生成的 lwIP 移植层常见缺口。
solty 发表于 2026-10-6 11:39 | 显示全部楼层
你说 DMA 描述符 OWN 位为 0,这意味着 DMA 没有占用描述符。但这通常是因为 tcpip_thread 还没来得及把 pbuf 转换成 DMA 可读的帧格式并置位 OWN,而不是 DMA 层面的问题。
spicy 发表于 2026-10-6 12:58 | 显示全部楼层
在 CubeMX 生成的工程中,ethernetif_input 通常负责将接收到的数据投递到 tcpip_thread。如果长时间没有接收中断,tcpip_thread 可能完全处于休眠,不会主动轮询发送队列。
stormwind123 发表于 2026-10-6 14:08 | 显示全部楼层
如果 sendto 内部调用了 netconn_send 或类似接口,且返回了 ERR_OK,说明 LwIP 协议栈的 API 层已经接受了这个请求。问题出在内核线程未能及时消费这个请求。
七毛钱 发表于 2026-10-6 15:45 | 显示全部楼层
检查一下 tcpip_thread 是否在等待一个长期未触发的 sys_timeout。例如,如果某个超时事件的时间戳因为时钟回绕或计算问题导致下一次触发时间被推得很远,线程会一直等待。
内政奇才 发表于 2026-10-6 17:10 | 显示全部楼层
另一种符合“不修改协议栈”约束的思路是:在 CubeMX 的 lwIP 配置中调整 TCPIP_THREAD_STACKSIZE 或邮箱大小,并确保在 ethernetif 的接收中断中正确调用 sys_check_timeouts 或发出信号量唤醒 tcpip_thread,这属于配置层面而非源码修改。
又见江南雨 发表于 2026-10-6 18:23 | 显示全部楼层
如果系统支持,可以尝试在空闲任务钩子或低优先级任务中周期性调用 sys_check_timeouts(),虽然你说手动调用无效,但持续调用与单次调用效果可能不同,值得验证。
故里说长安 发表于 2026-10-6 18:47 | 显示全部楼层
现象里最关键的一点是 sendto 返回成功并不等于网卡已经发出数据,它只说明 LwIP 的 API 层接受了这个请求,后面还要靠 tcpip_thread 把数据真正推到驱动层。
海滨消消 发表于 2026-10-6 19:08 | 显示全部楼层
空闲十秒后出问题,说明系统里某个周期性唤醒机制失效了,tcpip_thread 很可能一直阻塞在邮箱等待上,没有机会去处理新投递进来的发送消息。
甜心puppy 发表于 2026-10-6 20:35 | 显示全部楼层
应用任务跑在空闲优先级这件事值得注意,因为空闲优先级任务在 FreeRTOS 里随时会被抢占,它调用 sendto 的时机和内部加锁行为可能被高优先级线程打断得很不规律。
豌豆爹 发表于 2026-10-6 20:45 | 显示全部楼层
CubeMX 生成的 lwIP 移植层里,ethernetif_input 通常只负责接收路径的投递,发送路径的推进完全依赖 tcpip_thread 主动运行,空闲久了就容易暴露唤醒缺失。
等凌晨日出 发表于 2026-10-6 20:52 | 显示全部楼层
tcpip_thread 优先级很高,按理说应该能及时处理消息,但如果它自己卡在某个超时等待或者信号量上,优先级再高也没用,因为它根本没在运行。
茉璃夏 发表于 2026-10-6 21:39 | 显示全部楼层
手动调用 sys_check_timeouts 没有效果,基本可以排除 TCP 重传、ARP 老化这类超时逻辑的问题,矛头应该指向 tcpip_thread 本身没有被唤醒。
进入猫次元 发表于 2026-10-6 22:49 | 显示全部楼层
如果 lwipopts.h 里没有开启 LWIP_TCPIP_CORE_LOCKING,所有 socket API 调用都会变成向 tcpip_thread 投递消息,一旦线程不醒,消息就***躺在邮箱里。
进入猫次元 发表于 2026-10-6 22:49 | 显示全部楼层
如果 lwipopts.h 里没有开启 LWIP_TCPIP_CORE_LOCKING,所有 socket API 调用都会变成向 tcpip_thread 投递消息,一旦线程不醒,消息就***躺在邮箱里。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部