你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

USB_WritePacket 陷入无限循环

[复制链接]
patch1582 提问时间:2026-8-14 18:42 / 未解决

我在 STM32F407 上搞了一套 USB DFU 主机类驱动。硬件上我把 USB‑C 线直接焊接到 D+、D‑、5V、GND 引脚。

小于等于 128 字节的传输,协议栈工作完全正常。但是当phost->Control.setup.b.wLength.w > 128例如 192 字节,调用USBH_CtlReq之后,代码会在USB_WritePacket函数内部死循环。

我跟踪代码发现 HCTSIZ 寄存器的两个关键字段:sizecnt。 下面对比128 字节正常传输与192 字节失败传输的寄存器跟踪日志。

  1. 正常场景:传输 128 字节 初始状态:size = 128,cnt = 2

循环第 1 轮: i=15:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 2 i=31:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 1

循环第 2 轮: 初始状态:size = 128,cnt = 2 i=15:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 1 i=31:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 0

结果:传输完成,执行成功。

  1. 失败场景:传输 192 字节 初始状态:size = 192,cnt = 3

循环第 1 轮: i=15:写入 USBx_DFIFO;寄存器更新:size = 128,cnt = 3 i=31:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 2 i=47:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 1

循环第 2 轮(异常开始): 初始状态:size = 128,cnt = 2 i=15:写入 USBx_DFIFO;寄存器更新:size = 128,cnt = 2 i=31:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 1 i=47:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 1

最后一次写完数据包,cnt 没有发生变化。

循环第 3 轮(状态错乱,进入死循环): 传输被重新初始化为:size = 128,cnt = 3

cnt 被莫名重新设置为 3

i=15:写入 USBx_DFIFO;寄存器更新:size = 128,cnt = 3 i=31:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 3

cnt 锁死固定等于 3,不再递减 i=47:写入 USBx_DFIFO;寄存器更新:size = 64,cnt = 3

我把同一套 DFU 主机上层代码移植到 STM32G0C1CEU6,大数据包传输一切正常。应用层代码完全不变;二者最大硬件差异:F4 使用 FIFO 架构,G0 使用 PMA 内存架构,底层硬件驱动不同。

收藏 评论1 发布时间:2026-8-14 18:42

举报

1个回答
xmshao 回答时间:2026-8-18 10:33:12

可能是发生NAK 后,软件错误地把整个192B 传输重新提交了。这会引出两个现象:

1、HCTSIZ / PKTCNT 被重新写。

这时会看到,本来还剩一部分没发完,结果 PKTCNT 又回到 3。

2、NPTX FIFO 被重复灌数据。

因为同一段 192B 又被重新塞进FIFO,最后可能卡在 USB_WritePacket()。

原因很可能是控制 OUT 的NAK 重试逻辑有问题。

你要确认下,设备回了 NAK 之后,主机是不是把整段192B 又从头提交了一遍。

具体来说,就是观察在出错或被 NAK 后再次发送时,是否简单地再次SubmitRequest(192),并把 xfer_count 清零。

正常情况下,主机只应重试还没成功发送的那一包,而不是不管前面已经发出去多少,又把整段数据重新发一遍。

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版