一. 概述
常见的 USB 设备如键盘鼠标都需做睡眠唤醒功能,其目的是电源管理降低功耗。实现该功能主要涉及到 USB 挂起(Suspend)、恢复(Resume)、远程唤醒(Remote Wakeup)等。本文将会简要介绍其相关概念,并且基于 NXP LPC5528 Mouse 挂起恢复例程描述其睡眠唤醒关键代码。
二. 设备挂起(Suspend)
在 USB 系统中,正常状态下 hub 或 root hub 会一直周期性地发送 SOF 包(Start Of Frame,全速 USB 每 1ms 发送一个,高速 USB 则 125µs 发送一个)。若 USB 线上一直处于空闲状态超过 3ms,设备则认为这是一个挂起信号,设备需要在 10ms 内进入挂起状态,并把所需的电流大小降到规定的值。当 USB 设备处于挂起状态时,它仍然为其 D+或 D-上拉电阻器供电,以保持空闲状态并保持其内部状态,包括地址和配置。当它被 USB总线上的恢复信号唤醒时,不再需要经过重新枚举过程。如下图为全速设备 Suspend 总线状态。
图 1 全速 USB 设备挂起信号
对于不同速度的 USB 设备,其规定的差分信号线上 J、K、Idle 等状态的电平会有些不同,下表列出了在低速、全速、高速下 USB 状态对应的电平信号。
图 2 USB 状态电平
三. 设备恢复(Resume)
在设备处于 Suspend 的状态下,若需要将设备退出 Suspend 状态,主机 host 需要向设备发送持续时间超过 20ms 的 Resume 信号,并且以 EOP 信号结尾,设备将在 Resume 信号结束后醒过来。在设备醒过来后,host 需要在 3ms 内发送 SOF 信号,以维持正常的通信模式,避免设备重新进入 Suspend 状态。对于全速设备恢复信号是全速段中从数据 J 状态到数据 K 状态的变化。
图 3 全速 USB 设备恢复信号
四. 设备远程唤醒(Remote wakeup)
对于普通的 Resume 唤醒,是由主机 host 唤醒 USB 设备,但同样设备也可以唤醒主机 host,例如电脑休眠时,可以通过 USB 键盘唤醒主机,这种功能称为远程唤醒。使用远程唤醒功能,需要 USB 设备支持远程唤醒功能,并且在配置描述符设置中,将 USB 设备支持远程唤醒能力报告给主机。 通过 USB 设备远程唤醒主机时,USB 设备会生成一个 1ms-15ms 的 Resume 信号,host 在 1ms 内捕获到该信号,并且主机控制器对唤醒操作进行接管,继续产生 Resume 信号直到 20ms,并以 EOP 信号结尾,完成对设备的唤醒。如下图为全速设备 Remote Wakeup 总线状态。
图 4 全速 USB 设备远程唤醒信号
需要注意:
- USB 设备的Remote Wakeup 是可选的,对应配置描述符 bmAttributes 字段的 D5 标识。
- 支持远程唤醒的USB设备必须支持USB的标准请求 CLEAR_FEATURE 和 SET_FEATURE。
- USB 主机通过 SET_FEATURE(DEVICE_REMOTE_WAKEUP)请求使用 USB 设备的远程唤醒功能,其请求的时间在发送设备挂起之前。如果主机并未发送使能远程唤醒特性,设备端不允许执行远程唤醒功能,虽然其支持
五. LPC5528 睡眠唤醒相关编程代码
硬件平台:LPC5528 开发板
参考例程:dev_suspend_resume_hid_mouse_bm
例程功能:枚举为一个鼠标设备, USB suspend 时设备进入低功耗模式,主机可以恢复设备退出低功耗,按动开发板按键设备可以远程唤醒主机。
实现的关键代码:
1. 配置描述符支持远程唤醒功能,USB 设备通过配置描述符 bmAttributes 字段的 D5 标识支持远程唤醒。
图 5 配置描述符代码
2. 加入 LPC5528 SDK USB 代码底层已定义好的 suspend、resume、remotewake 接口函数,底层检测总线状态将会触发对应事件。
图 6 睡眠唤醒接口代码
3. 睡眠唤醒状态机的操作逻辑 USB_DeviceSuspendResumeTask()函数,包含从 Idle、Suspend、Resume 等各个阶段状态对应处理,是实现功能的主要函数。其中芯片进入深度睡眠模式 POWER_EnterDeepSleep( ) 需要重点注意两个参数,一是 APP_EXCLUDE_FROM_DEEPSLEEP 设置睡眠时不需要关闭的模块,二是 APP_DEEPSLEEP_WAKEUP_SOURCE 设置可以从芯片睡眠中唤醒的唤醒源。
图 7 睡眠唤醒状态机代码
图 8 低功耗时仍运行模块及唤醒源
六. 总结
本文介绍挂起、恢复、远程唤醒相关概念,描述 LPC5528 睡眠唤醒功能关键代码,其具体实现代码参考 LPC5528 SDK dev_suspend_resume_hid_mouse_bm 例程。
七. 参考资料
1. USB2.0 协议
2. LPC55xx datasheet