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

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 回答时间:5 天前

可能是发生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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版