目录

1.USB Resume信号

2.USB远程唤醒的方式

3.J状态和K状态

4.STM32 USB设备远程唤醒机制详解

5.主机对设备远程唤醒功能状态的获取、清除和设置


1.USB Resume信号

USB设备进入挂起状态之后,将由Resume信号进行唤醒。Resume信号可以由USB主机发起,也可以由USB设备本身触发,但是只有USB主机可以结束Resume信号

(1)主机在挂起设备后可通过翻转数据线上的极性并保持20ms来唤醒设备,并以低速EOP信号结尾。

(2)如果设备支持远程唤醒,设备可向主机发起远程唤醒请求,前提是设备已进入idle状态至少5ms,设备会驱动总线进入K状态,如下图,K状态必须维持1ms-15ms之内,此信号会在1ms内被主机接管,主机会继续驱动唤醒信号直到20ms,并以低速EOP信号结尾。

2.USB远程唤醒的方式

当主机控制器进入挂起后,所有设备是没办法向主机提交数据的,那主机是怎样知道设备的唤醒请求呢?答案是通过电信号。如下图(usb_20.pdf Page-333),设备需要生成一个1ms-15ms的K状态电信号(这里例子为10ms)hub会在1ms内捕获到该信号(此时设备其实就可以停止驱动K状态了),hub会进行和设备相同的操作把此信号传递给主机控制器,主机控制器对唤醒操作进行接管,主机会继续驱动唤醒信号直到20ms,并以低速EOP信号结尾,完成对设备的唤醒操作。如果是一个鼠标设备的话,休眠的系统有时会被恢复,其实这里大家可以看做是设备给主机系统发送一个IO中断信号,主机系统检测到后可以实现一系列的后续操作。

3.J状态和K状态

J状态 LS(低速) 差分0
FS(全速) 差分1
K状态 LS(低速) 差分1
FS(全速) 差分0

4.STM32 USB设备远程唤醒机制详解

首先我们以我自己设计的STM32 USB鼠标例子来分析。

1.USB外设需支持远程唤醒操作

USB外设必须支持远程唤醒功能,当然STM32F103 USB外设符合USB2.0全速设备的技术规范,所以支持远程唤醒的功能。

2.USB设备描述符设置远程唤醒

USB设备配置描述符设备属性中必须Bit5必须为1(remote wake-up)。

STM32F103鼠标设备配置描述符源代码如下,从0数第7个字节0xE0(1110000b),标识设备是自供电且具有远程唤醒功能。

    0x09, /* bLength: Configuation Descriptor size */USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */JOYSTICK_SIZ_CONFIG_DESC,/* wTotalLength: Bytes returned */0x00,0x01,         /*bNumInterfaces: 1 interface*/0x01,         /*bConfigurationValue: Configuration value*/0x00,         /*iConfiguration: Index of string descriptor describingthe configuration*/0xE0,         /*bmAttributes: bus powered and support Remote wake-up */0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

3.STM32 USB设备远程唤醒代码剖析

实现的功能就是STM32按下一个按键后,STM32 USB设备发送一次远程唤醒请求。进入按键中断后代码如下,首先会判断设备是否存在远程唤醒功能,pInformation->Current_Feature = ConfigDescriptor[7];这句代码在USB初始化调用,如果我们配置描述符ConfigDescriptor[7]的Bit5设置为0,此分支不会进入,USB设备当然也就不会进行远程唤醒主机。一旦被设置为1,则会调用Resume(RESUME_INTERNAL);发送远程唤醒请求。

void EXTI9_5_IRQHandler(void)
{if (EXTI_GetITStatus(GPIO_KEY_EXTI_Line) != RESET){if (pInformation->Current_Feature & 0x20) //Remote wake-up enabled{Resume(RESUME_INTERNAL);}/* Clear the EXTI line 9 pending bit */EXTI_ClearITPendingBit(GPIO_KEY_EXTI_Line);}
}

Resume函数函数根据参数RESUME_INTERNAL会先使用Resume_Init唤醒自己然后进入远程唤醒状态RESUME_START,远程唤醒的操作就是把USB控制寄存器的第4位置1,然后等待10ms把USB控制寄存器的第4位置为0,最后进入RESUME_OFF状态,设备的一次远程唤醒请求完成。下图为Resume函数原理和USB控制寄存器Resume位的含义。

大家可以看到,Resume函数竟然具有时间计数功能,这是因为每一个ESOF(帧结束包)中断都会调用一次Resume(RESUME_ESOF);函数,而我们知道对于全速设备ESOF(帧结束包)中断是1ms一次的,Resume函数原型上面已经给出,大家深入理解。下面为USB外设中断处理函数,它会处理USB外设所有的中断,我们这里只列举ESOF中断,而ESOF中断调用了Resume函数。

/*******************************************************************************
* Function Name  : USB_Istr
* Description    : STR events interrupt service routine
* Input          :
* Output         :
* Return         :
*******************************************************************************/
void USB_Istr(void)
{wIstr = _GetISTR();..../*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_ESOF)if (wIstr & ISTR_ESOF & wInterrupt_Mask){_SetISTR((uint16_t)CLR_ESOF);/* resume handling timing is made with ESOFs */Resume(RESUME_ESOF); /* request without change of the machine state */#ifdef ESOF_CALLBACKESOF_Callback();
#endif}
#endif....
} /* USB_Istr */

紧接着设备会被主机唤醒,设备如果唤醒中断使能,则会进入USB唤醒中断处理程序,中断中首先会退出低功耗然后清除控制寄存器的FSUSP位,代码如下。

/*******************************************************************************
* Function Name  : USB_Istr
* Description    : ISTR events interrupt service routine
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void USB_Istr(void)
{wIstr = _GetISTR();.../*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_WKUP)if (wIstr & ISTR_WKUP & wInterrupt_Mask){_SetISTR((uint16_t)CLR_WKUP);Resume(RESUME_EXTERNAL);}
#endif...} /* USB_Istr */// 核心Resume(RESUME_EXTERNAL);--->Resume_Init/*******************************************************************************
* Function Name  : Resume_Init
* Description    : Handles wake-up restoring normal operations
* Input          : None.
* Output         : None.
* Return         : USB_SUCCESS.
*******************************************************************************/
void Resume_Init(void)
{uint16_t wCNTR;/* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- *//* restart the clocks *//* ...  *//* CNTR_LPMODE = 0 */wCNTR = _GetCNTR();wCNTR &= (~CNTR_LPMODE);_SetCNTR(wCNTR);/* restore full power *//* ... on connected devices */Leave_LowPowerMode();/* reset FSUSP bit */_SetCNTR(IMR_MSK);/* reverse suspend preparation *//* ... */}

上面唤醒中断里面调用了Resume(RESUME_EXTERNAL);函数,其实会把USB_CNTR寄存器的LP_MODE位置为’0’,先退出低功耗,紧接着会把CNTR_FSUSP清零。挂起的时候第①就是设备会先进行强制挂起,第②就是让设备进入低功耗完成挂起例程的处理,当然我们在唤醒的时候不但要退出低功耗,而且还要清除CNTR_FSUSP位,挂起处理程序如下图所示。

void Suspend(void)
{u16 wCNTR;/* macrocell enters suspend mode */// 强制挂起wCNTR = _GetCNTR();wCNTR |= CNTR_FSUSP;_SetCNTR(wCNTR);/* force low-power mode in the macrocell */// 进入低功耗wCNTR = _GetCNTR();wCNTR |= CNTR_LPMODE;_SetCNTR(wCNTR);/* switch-off the clocks *//* ... */Enter_LowPowerMode();}

5.主机对设备远程唤醒功能状态的获取、清除和设置

1.主机可使用GetStatus请求USB设备的状态。

请求格式如下图(我们这里获取设备状态):

返回数据格式如下:

2.主机可使用ClearFeature请求清除设备的远程唤醒功能,当然这需要设备实现对ClearFeature请求的处理。

3.主机可使用SetFeature请求设置设备的远程唤醒功能,当然这需要设备实现对SetFeature请求的处理。


1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除;

2.未经原作者允许不得转载本文内容,否则将视为侵权;

3.转载或者引用本文内容请注明来源及原作者;

4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

下面是我的个人微信公众号,关注【一个早起的程序员】精彩系列文章每天不断。

STM32 USB设备远程唤醒机制详解相关推荐

  1. Android设备扫描机制详解

    Android设备扫描机制详解 本文基于Android pie,对Android的设备扫描机制做一个全面的解析,由于本人掌握的知识有限,如有讲错的地方还请大家指出来. Android提供了一套扫描机制 ...

  2. STM32芯片IAP升级机制详解

    一.先了解ICP和ISP.IAP之间的区别: 1. ISP(In System Programing 在系统编程)的实现相对要简单一些,一般通用做法是内部的存储器可以由上位机的软件通过串口来进行改写. ...

  3. 《Linux 设备驱动开发详解(第2版)》——1.4 Linux设备驱动

    本节书摘来自异步社区<Linux 设备驱动开发详解(第2版)>一书中的第1章,第1.1节,作者:宋宝华著,更多章节内容可以访问云栖社区"异步社区"公众号查看 1.4 L ...

  4. linux 设备驱动 ppt,linux设备驱动开发详解讲座ppt

    PPT内容 这是linux设备驱动开发详解讲座ppt下载,主要介绍了设备驱动简介:建立和运行模块:字符驱动:调试技术:并发和竞争:分配内存:硬件通讯:中断处理:块设备驱动,欢迎点击下载. 嵌入式Lin ...

  5. 《Linux设备驱动开发详解(第2版)》隆重出版

    Linux设备驱动开发详解(第2版)(前一版狂销3万册,畅销书最新升级) [新品] 点击看大图     基本信息 * 作者: 宋宝华       * 出版社:人民邮电出版社     * ISBN:97 ...

  6. 《linux设备驱动开发详解》笔记——15 linux i2c驱动

    <linux设备驱动开发详解>笔记--15 linux i2c驱动 15.1 总体结构 如下图,i2c驱动分为如下几个重要模块 核心层core,完成i2c总线.设备.驱动模型,对用户提供s ...

  7. STM32接口FSMC/FMC难点详解

    STM32接口FSMC/FMC难点详解 转载   http://blog.sina.com.cn/s/blog_808bca130102x94k.html STM32F767的FMC将外部存储器划分为 ...

  8. 《Linux设备驱动开发详解 A》一一2.3 接口与总线

    本节书摘来华章计算机出版社<Linux设备驱动开发详解 A>一书中的第2章,第2.3节,作者:宋宝华 更多章节内容可以访问云栖社区"华章计算机"公众号查看.1 2.3 ...

  9. SSL / TLS 协议运行机制详解

    转载自  SSL / TLS 协议运行机制详解 互联网的通信安全,建立在SSL/TLS协议之上. 本文简要介绍SSL/TLS协议的运行机制.文章的重点是设计思想和运行过程,不涉及具体的实现细节.如果想 ...

最新文章

  1. android5多窗口,教程 开启 Nexus5 Android M 的多窗口模式。
  2. 科研超级神器,摘要页一键链接关联论文
  3. 是谁卖了我的信息资料?
  4. tensorflow教程 学习笔记 之 Eager execution 急切执行
  5. oracle顺序读发散读,Oracle 拼音排序
  6. asp.net面试的题目
  7. js事件冒泡和事件委托
  8. HDU 1253 胜利大逃亡 题解
  9. ssh公钥免密码登录
  10. 【Breadth-first Search 】279. Perfect Squares
  11. python php 序列化,序列化和反序列化的详细介绍
  12. mysql删除表外键_MySQL删除所有表的外键约束、禁用外键约束
  13. NSString 和 NSMutableString
  14. java web相关试卷_JavaWeb试卷四
  15. 大数据分析常见的犯错问题
  16. PHP spl_autoload_register()函数的一些见解
  17. redis通用key操作
  18. 作业二在校大学生零食消费调查问卷
  19. 云钉一体,支撑5亿用户1900万企业背后的技术复盘
  20. H5 js方式实现前端视频压缩

热门文章

  1. input金额失焦自动补零和千分位格式化
  2. CC00296.CloudKubernetes——|KuberNetes运维.V17|——|监控.v03|部署ingress.helm方式|
  3. 那些编程语言中的“后浪”都怎么样了:Swift 成功把“前浪”拍在沙滩上
  4. Java Object
  5. win2012文件服务器添加角色,win2012系统无法添加角色处理教程
  6. 数据治理:数据血缘关系
  7. 判断 jdk8是否为jce限制版本
  8. 系统编程04-消息队列(ftok、msgget、msgsnd、msgrcv、msgctl、shmget、shmat、shmdt、shmctl、semget、semctl、semop)
  9. python期货自动化交易_python程序化交易神器——tushare
  10. 论文分享 - Machine Comprehension Using Match-LSTM and Answer Pointe