
1 前言 本文将针对 STM32F767 的 USB_OTG_FS 模块工作在 Host 模式下的挂起与恢复以及远程唤醒方面的问题进行讨论。 2 问题描述 客户使用 STM32F767 做项目,使用 USB 作为 Host,客户发现 USB 在进入到挂起状态后通过远程唤醒信号并不能将其唤醒。 3 问题分析与解决 经过与客户邮件电话沟通发现用户是通过操作寄存器 OTG_HPRT 的 PSUSP,与 PRE 位来实 USB 总线的挂起与恢复,发现 USB 总线的挂起与恢复会有问题。 ![]() 为了重现客户的现象,通过 STM32CubMX 工具基于 NUCLEO-F767 板子上新建一个工程,使 USB 工作在HID HOST 模式下。我们希望 HOST 端主动进入挂起状态后使用另外一块实现了鼠标功能的 STM32F407-DISCOVERY 板子可以发送一个远程唤醒信号来使 USB 总线恢复,从而唤醒 USB 主机。由于当前最新 F7 的 HAL 库(V1.9.0)针对HOST 并没有提供挂起与恢复的接口,于是,我们需要自己来实现以下两个功能,并添加到路径下面的中。 于是 HOST 端主动进入挂起的代码实现为:代码操作 HPRT 寄存器的 PSUSP 位,使 USB 进入到挂起状态
下面是 Host 从挂起模式恢复:代码两次操作了 PRES 位,为的是确保操作成功.
那么这样的代码能成功挂起和恢复 USB 总线吗? 经过实际测试,如果 HOST 主动调用 USB_SuspendPort 进入挂起状态是可以正常进入的,如果 HOST 自己主动再次调用 USB_ResumePort 恢复的话也可以正常恢复。但是,如果通过接收到远程唤醒信号后,HOST 端被动地在中断内调用 USB_ResumePort 函数来恢复的话则会失败! 同样的操作,放在 OTG_HS 的话又能够正常,但是客户当前使用的是 OTG_FS 来做产品的,看来两个 USB 外设之间还是存在一定的差异性,针对 OTG_FS 的远程唤醒对寄存器操作还是有一定的要求。 经过一番研究与测试,我们最终通过修改后的代码来实现客户的需求:
此代码最终测试是可以正常挂起和恢复 USB 总线的,不管是 HOST 自己主动挂起与恢复还是由远程唤醒触发被动恢复都是能正常工作的。这里的关键所在是在挂起后,必须将 PHY 的时钟关掉,再操作 HPRT寄存器的 PSUSP 位;然后在唤醒时,先将 PHY 时钟打开后再操作 HPRT 的 PRES 位,按此顺序才能正常。 在结束本篇全速 OTG 作为 USB 主机挂起、唤醒的特殊操作之前,我们看一下这个额外操作的寄存器的描述: ![]() 4 后记 HAL 库并不是一个完整的库,它也在不断的自我更新与完善中,客户需要的有些功能接口可能在库中并没有提供,这个是正常的,这个时候,客户则需要根据情况自己来实现这种接口。 本文所描述的两个接口在当前版本并不存在,但将来 HAL 版本更新时会将它更新。 |
【实战经验】基于STM32F7的网络时间同步例程
STM32硬件结构学习
STM32中BOOT的作用
【STM32F769I-DISC1】开发板刷入Micropython并完成点灯、读取内部温度测试
【STM32F769I-DISC1】测评01:创建STM32cube IDE 工程,点个灯
【STM32F769】创建deepseek本地服务,并实现http请求
汇编浮点库qfplib移植STM32F769I-DISCO开发板与硬件浮点运算性能测试对比
coremark移植到STM32F769I-DISCO开发板的两种方法
【GUI板免费申请活动】【圣诞GUI】使用F746-DISO基于TouchGFX的圣诞树
刘氓兔的杂谈【001】-片上USB 高速PHY