踩坑记录——USB键盘睡眠唤醒

这篇具有很好参考价值的文章主要介绍了踩坑记录——USB键盘睡眠唤醒。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

踩坑记录——USB键盘睡眠唤醒

前言

前段时间我用一个国产MCU实现了雷蛇键盘的效果,按键支持十键无冲,RGB灯支持单控任意一个灯任意一种颜色,但是这个过程还是比较曲折的,原本以为键盘功能是最难搞的,低功耗处理是最简单的,没想到前面这么顺利,最后才翻车了,所以特意出一期记录一下我踩过的坑。

1 USB远程睡眠唤醒要注意的几个点

1、配置描述符(Configuration Descriptor)要打开远程唤醒(Remote Wakeup)功能。

Configuration Descriptor

Offset Field Size Value Description remark
0 bLength 1 Number 以字节为单位的描述符大小 bLength以字节为单位的描述符大小(0x09)
1 bDescriptorType 1 Constant 配置描述符类型 一般为CONFIGURATION (0x02)
2 wTotalLength 2 Number 配置返回的数据总长度 包括该配置返回的所有描述符(配置、接口、端点、和专用的类型或者专用的厂商描述符)的总长度
3 bNumInterfaces 1 Number 配置支持的接口数量 最小值为0x01
4 bConfigurationValue 1 Number Get Configuration 和Set Configuration请求的配置值 必须为0x01或者更高值。取值为0的Set Configuration请求会使设备进入未配置状态(Not Configured state)
5 iConfiguration 1 Index 字符串描述符索引 若没有字符串描述符,这个字段的值为0
6 bmAttributes 1 Bitmap 配置特性 Bit7: USB1.0协议中表示总线供电(Bus Powered),设置bit7=1表示由总线供电(Bus Powered),其他协议该位保留(Reserved),必须设置为1
Bit6: 自供电(Self-powered),bits6=1时,设备自供电(Self-powered)
Bit5: 远程唤醒(Remote Wakeup),bit5=1时,设备支持远程唤醒
Bit4…0: 未使用,保留,必须为0
7 bMaxPower 1 mA 设备从总线获取的最大功耗 当设备完全运行时,特定配置的USB设备从总线取得的最大功耗

bmAttributes属性的Bit5要置1,这样才能打开远程唤醒(Remote Wakeup)功能,另外PC端也要在相应的USB设备上打开“允许此设备唤醒计算机(O)”

踩坑记录——USB键盘睡眠唤醒

Configuration Descriptor 部分配置参考示例:

0x09,                   //bLength(9);               配置描述符
0x02,                   //bDescriptorType(Configuration);
0x29,0x00,              //wTotalLength(41);
0x01,                   //bNumInterfaces(1);
0x01,                   //bConfigurationValue(1);
0x00,                   //iConfiguration(0);
0xA0,                   //bmAttributes(BUSPower); //支持远程唤醒
0x32,                   //MaxPower(100mA);

2、USB的时钟频率不能低于48MHz且必须是48的倍数。
时钟频率要设对,否则会导致通讯异常。这个点原本我是知道的,但没想到的是MCU在进入休眠之后自动切换到了内部时钟,而且在唤醒之后没有切换回来,因此导致唤醒之后USB通讯异常。
所以,在上电初始化的时候以及休眠唤醒之后都需要配置好系统时钟。

3、USB Device唤醒PC需要发送唤醒序列。
PC在进入睡眠之后会主动发送SetDeviceFeature,设备端收到以后进入挂起状态(SUSPend)并且USB进入低功耗模式,如果设备需要唤醒PC的话则需要发送唤醒序列,先使用RESUME_INTERNAL唤醒设备本身,然后进入远程唤醒状态RESUME_START,远程唤醒的操作就是把USB控制寄存器的第4位置1,然后等待10ms把USB控制寄存器的第4位置为0,最后进入RESUME_OFF状态,设备的一次远程唤醒请求完成。
注:USB总线由SUSPend状态切换回CONFIGURED状态实际上是由Host决定的,Device只能发送唤醒序列,然后等Host返回ClearFeature之后才能真正的唤醒USB,回到正常的CONFIGURED状态

RESUME函数参考示例:

/*******************************************************************************
 * @fn       Resume
 *
 * @brief    This is the state machine handling resume operations and
 *                 timing sequence. The control is based on the Resume structure
 *                 variables and on the ESOF interrupt calling this subroutine
 *                 without changing machine state.
 *
 * @param    a state machine value (RESUME_STATE)
 *                  RESUME_ESOF doesn't change ResumeS.eState allowing
 *                  decrementing of the ESOF counter in different states.
 *
 * @return  None.
 */
void Resume(RESUME_STATE eResumeSetVal)
{
  uint16_t wCNTR;

  if (eResumeSetVal != RESUME_ESOF)
	{
   ResumeS.eState = eResumeSetVal;
	}
	
  switch (ResumeS.eState)
  {
    case RESUME_EXTERNAL:
      if (remotewakeupon ==0)
      {
        Resume_Init();
        ResumeS.eState = RESUME_OFF;
      }
      else 
      {
        ResumeS.eState = RESUME_ON;
      }
      break;
			
    case RESUME_INTERNAL:
      Resume_Init();
      ResumeS.eState = RESUME_START;
      remotewakeupon = 1;
      break;
		
    case RESUME_LATER:
      ResumeS.bESOFcnt = 2;
      ResumeS.eState = RESUME_WAIT;
      break;
		
    case RESUME_WAIT:
      ResumeS.bESOFcnt--;
      if (ResumeS.bESOFcnt == 0)
        ResumeS.eState = RESUME_START;
      break;
			
    case RESUME_START:
      wCNTR = _GetCNTR();
      wCNTR |= CNTR_RESUME;
      _SetCNTR(wCNTR);
      ResumeS.eState = RESUME_ON;
      ResumeS.bESOFcnt = 10;
      break;
		
    case RESUME_ON:    
      ResumeS.bESOFcnt--;
      if (ResumeS.bESOFcnt == 0)
      {
        wCNTR = _GetCNTR();
        wCNTR &= (~CNTR_RESUME);
        _SetCNTR(wCNTR);
        ResumeS.eState = RESUME_OFF;
        remotewakeupon = 0;
      }
      break;
			
    case RESUME_OFF:
			
    case RESUME_ESOF:
			
    default:
      ResumeS.eState = RESUME_OFF;
      break;
  }
}

2 MCU唤醒之后引起USB异常的几个点

我在调试好键盘功能之后就开始着手做MCU的休眠,但是在调试的过程中发现了一些新的问题。
注:我用的MCU是ch32v203,这个MCU是一款国产IC,应该是参考了stm32设计的,无论是硬件还是软件都极其相似,因此,如果改用stm32或者其他stm32的替代方案可能也会有类似的问题。

1、不能在USB中断服务函数里面让MCU进入休眠。
收到PC端传过来的休眠信号之后,会进USB中断,然后进入挂起状态(SUSPend),我测试的时候图方便直接在中断里面让MCU进入了停机模式,结果MCU唤不醒了,可能是因为唤醒之后要从睡眠那行代码继续往后跑,但是因为睡眠是在中断服务函数里面的,唤醒之后进不了这个中断了,也就没法继续往下跑了。

2、睡眠之前要失能窗口看门狗。
这个问题有点莫名其妙,窗口看门狗是挂在APB1时钟上面的,MCU进入休眠的时候会关闭APB1时钟,所以看门狗是不会影响休眠和唤醒的,实际上也是MCU休眠和唤醒的功能也是正常的,休眠之前USB和看门狗也是正常的,但是如果休眠时不先关闭看门狗时钟,唤醒之后就会出现USB通讯异常的情况,我一时间也没搞懂是什么原因,唯一有关联的是USB和看门狗都是挂在APB1下面的,有大神可以解答一下我的疑惑吗?

3、MCU休眠只能选择WFE,选择WFI的话USB无法唤醒MCU。
普通外部中断唤醒(EXTI0-15)不管用WFI还是WFE都是可以正常使用的,USB中断(EXTI18)在MCU休眠之前也是可以正常使用,但是一旦MCU通过WFI进入休眠之后,就无法通过USB中断唤醒了,这个时候哪怕通过其他外部中断唤醒了MCU,USB也还是无法恢复正常通讯。
如果是用WFE则没有这个问题,这就很奇怪了,中断配置我也检查过很多次了,并没有发现什么问题,最后没办法就只能用WFE了。

结束语

关于USB远程睡眠唤醒的坑就讲到这,这里其实只是列举了一部分,因为这只是总结我遇到的新坑,有些以前踩过的坑这里就没写了,我也是第一次做USB的低功耗,没想到会遇到这么多奇怪的问题。虽然最后问题都解决了,但是有些疑惑还是没想明白,有大神知道的话还望不吝赐教!文章来源地址https://www.toymoban.com/news/detail-489238.html

到了这里,关于踩坑记录——USB键盘睡眠唤醒的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 联想小新 Pro 16 2022 锐龙版开启S3睡眠模式方法,解决S0睡眠发热耗电容易唤醒等烦恼

    联想小新 Pro 16 2022 锐龙版,CPU为AMD Ryzen 7 6800H  默认为S0睡眠模式,经常发热睡死过去,并且无法禁止鼠标唤醒电脑 本文借助“Universal AMD Form Browser”软件,在固件层面修改笔记本的睡眠方式。 本文所用到的软件Universal AMD Form Browser下载地址:https://download.csdn.net/download/nanj/

    2024年02月09日
    浏览(42)
  • Mac book pro 睡眠唤醒之后,外接显示器再也无法点亮,只能重启,怎么解决?

    问题描述 mac book合上盖子外接显示器,锁屏后过一段时间,再尝试唤醒的时候,显示器上没反应。 只能拔下HDMI的线再重新插,显示器才能有信号。 于是上网找解决办法 方法1 (hp显示器)打开input control ,进入dp hot-plug detection,更改模式位low power 到 always active 可惜俺是DELL显

    2024年02月05日
    浏览(58)
  • 【ROG】关闭睡眠时键盘背光

    ROG 幻系列笔记本,在睡眠时(注意不是休眠时)键盘背光默认会一闪一闪 感觉这和睡眠的本质不符 为了让键盘背光获得更好的睡眠效果,现希望关闭ROG笔记本的键盘背光 按下ROG键

    2024年02月11日
    浏览(33)
  • 银河麒麟桌面V10SP1版本系统休眠唤醒鼠标键盘失效解决方法

    使用银河麒麟桌面系统有时会出现系统休眠后再唤醒,鼠标键盘失效的问题,可尝试以下方法解决。 1.检查是否安装 laptop-mode-tools 工具 执行命令: 如果执行命令无结果输出,表示未安装(如果已安装,忽略第2步) 2.安装 laptop-mode-tools 包 执行命令: 安装完成后查看结果 3.判断

    2024年02月12日
    浏览(114)
  • Android 9.0 禁止usb键盘和usb鼠标挂载

    在9.0的系统产品开发中,对于系统中usb鼠标和usb键盘的等外设输入设备挂载处理,系统是在inputflinger模块中处理的,在产品的需求中对于外设输入设备的usb鼠标和usb键盘的挂载是禁用的,所以需要从挂载入手,禁止挂载usb鼠标和usb键盘 在android系统中是由各个子系统分工协作

    2024年02月09日
    浏览(45)
  • USB(键盘)流量分析

    hws2023的一道misc,没接触过,写一份博客,稍微带一点鼠标流量,自己做题收获,可能在某些情况仅适用本题 网上大部分讲USB协议数据在 Leftover Capture Data域 中,就这道题,以及目前已知少量博客显示, HID Data 域中也具有价值(USB URB里找有没有数据就行)。鼠标流量数据长度

    2024年02月06日
    浏览(37)
  • 记录--终于搞懂了网盘网页是怎么唤醒本地应用了

    用百度网盘举例,可以通过页面打开本机的百度网盘软件,很多软件的网站页面都有这个功能。这个事情一直令我比较好奇,这次终于有空抽时间来研究研究了,本篇讲的是Windows的,mac的原理与之类似,Mac文章已发布:(Mac版)终于搞懂了浏览器是怎么唤醒本地应用了。 本身单

    2024年01月16日
    浏览(42)
  • Android 12.0 通过驱动实现禁用usb鼠标和usb键盘功能

    在12.0的系统产品定制化开发中,在进行定制中有关于usb键盘和usb鼠标的需求中,产品要求禁止usb口挂载usb鼠标和usb键盘,所以需要要求在usb挂载类型的时候 判断如果是usb鼠标和usb键盘就不让挂载,这就需要从驱动方面入手来解决这个问题,接下来看下驱动的某些挂载usb的相

    2024年02月08日
    浏览(106)
  • Android 13.0 通过驱动实现禁用usb鼠标和usb键盘功能

    在13.0的系统产品定制化开发中,在进行定制中有关于usb键盘和usb鼠标的需求中,产品要求禁止usb口挂载usb鼠标和usb键盘,所以需要要求在usb挂载类型的时候 判断如果是usb鼠标和usb键盘就不让挂载,这就需要从驱动方面入手来解决这个问题,接下来看下驱动的某些挂载usb的相

    2024年02月08日
    浏览(57)
  • 基于STM32的USB键盘

    1、选择相应芯片(本文使用STM32F070F6P6) 2、RCC时钟配置和Debug设置 注:这里的PA9/10要重映射为PA11/12供USB接口使用(大部分芯片是分开的不用设置) 3、配置USB 注:这里的PID和VID默认就可以了(多设备时可以更改) 4、时钟配置 ①、修改USBD_HID_CfgFSDesc参数 首先长度,跳转至定义修改为

    2024年02月03日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包