加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 1 USB遠(yuǎn)程睡眠喚醒要注意的幾個(gè)點(diǎn)
    • 2 MCU喚醒之后引起USB異常的幾個(gè)點(diǎn)
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

踩坑記錄——USB鍵盤睡眠喚醒

07/18 13:23
2820
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

前段時(shí)間我用一個(gè)國產(chǎn)MCU實(shí)現(xiàn)了雷蛇鍵盤的效果,按鍵支持十鍵無沖,RGB燈支持單控任意一個(gè)燈任意一種顏色,但是這個(gè)過程還是比較曲折的,原本以為鍵盤功能是最難搞的,低功耗處理是最簡單的,沒想到前面這么順利,最后才翻車了,所以特意出一期記錄一下我踩過的坑。

1 USB遠(yuǎn)程睡眠喚醒要注意的幾個(gè)點(diǎn)

1、配置描述符(Configuration Descriptor)要打開遠(yuǎn)程喚醒(Remote Wakeup)功能。

Configuration Descriptor

Offset Field Size Value Description remark
0 bLength 1 Number 以字節(jié)為單位的描述符大小 bLength以字節(jié)為單位的描述符大小(0x09)
1 bDescriptorType 1 Constant 配置描述符類型 一般為CONFIGURATION (0x02)
2 wTotalLength 2 Number 配置返回的數(shù)據(jù)總長度 包括該配置返回的所有描述符(配置、接口、端點(diǎn)、和專用的類型或者專用的廠商描述符)的總長度
3 bNumInterfaces 1 Number 配置支持的接口數(shù)量 最小值為0x01
4 bConfigurationValue 1 Number Get Configuration 和Set Configuration請求的配置值 必須為0x01或者更高值。取值為0的Set Configuration請求會(huì)使設(shè)備進(jìn)入未配置狀態(tài)(Not Configured state)
5 iConfiguration 1 Index 字符串描述符索引 若沒有字符串描述符,這個(gè)字段的值為0
6 bmAttributes 1 Bitmap 配置特性 Bit7: USB1.0協(xié)議中表示總線供電(Bus Powered),設(shè)置bit7=1表示由總線供電(Bus Powered),其他協(xié)議該位保留(Reserved),必須設(shè)置為1
Bit6: 自供電(Self-powered),bits6=1時(shí),設(shè)備自供電(Self-powered)
Bit5: 遠(yuǎn)程喚醒(Remote Wakeup),bit5=1時(shí),設(shè)備支持遠(yuǎn)程喚醒
Bit4…0: 未使用,保留,必須為0
7 bMaxPower 1 mA 設(shè)備從總線獲取的最大功耗 當(dāng)設(shè)備完全運(yùn)行時(shí),特定配置的USB設(shè)備從總線取得的最大功耗

bmAttributes屬性的Bit5要置1,這樣才能打開遠(yuǎn)程喚醒(Remote Wakeup)功能,另外PC端也要在相應(yīng)的USB設(shè)備上打開“允許此設(shè)備喚醒計(jì)算機(jī)(O)”

在這里插入圖片描述

Configuration Descriptor 部分配置參考示例:

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

2、USB的時(shí)鐘頻率不能低于48MHz且必須是48的倍數(shù)。

時(shí)鐘頻率要設(shè)對,否則會(huì)導(dǎo)致通訊異常。這個(gè)點(diǎn)原本我是知道的,但沒想到的是MCU在進(jìn)入休眠之后自動(dòng)切換到了內(nèi)部時(shí)鐘,而且在喚醒之后沒有切換回來,因此導(dǎo)致喚醒之后USB通訊異常。

所以,在上電初始化的時(shí)候以及休眠喚醒之后都需要配置好系統(tǒng)時(shí)鐘。

3、USB Device喚醒PC需要發(fā)送喚醒序列。

PC在進(jìn)入睡眠之后會(huì)主動(dòng)發(fā)送SetDeviceFeature,設(shè)備端收到以后進(jìn)入掛起狀態(tài)(SUSPend)并且USB進(jìn)入低功耗模式,如果設(shè)備需要喚醒PC的話則需要發(fā)送喚醒序列,先使用RESUME_INTERNAL喚醒設(shè)備本身,然后進(jìn)入遠(yuǎn)程喚醒狀態(tài)RESUME_START,遠(yuǎn)程喚醒的操作就是把USB控制寄存器的第4位置1,然后等待10ms把USB控制寄存器的第4位置為0,最后進(jìn)入RESUME_OFF狀態(tài),設(shè)備的一次遠(yuǎn)程喚醒請求完成。

注:USB總線由SUSPend狀態(tài)切換回CONFIGURED狀態(tài)實(shí)際上是由Host決定的,Device只能發(fā)送喚醒序列,然后等Host返回ClearFeature之后才能真正的喚醒USB,回到正常的CONFIGURED狀態(tài)。

RESUME函數(shù)參考示例:

/*******************************************************************************
 * @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異常的幾個(gè)點(diǎn)

我在調(diào)試好鍵盤功能之后就開始著手做MCU的休眠,但是在調(diào)試的過程中發(fā)現(xiàn)了一些新的問題。

注:我用的MCU是ch32v203,這個(gè)MCU是一款國產(chǎn)IC,應(yīng)該是參考了stm32設(shè)計(jì)的,無論是硬件還是軟件都極其相似,因此,如果改用stm32或者其他stm32的替代方案可能也會(huì)有類似的問題。

1、不能在USB中斷服務(wù)函數(shù)里面讓MCU進(jìn)入休眠。

收到PC端傳過來的休眠信號之后,會(huì)進(jìn)USB中斷,然后進(jìn)入掛起狀態(tài)(SUSPend),我測試的時(shí)候圖方便直接在中斷里面讓MCU進(jìn)入了停機(jī)模式,結(jié)果MCU喚不醒了,可能是因?yàn)閱拘阎笠獜乃吣切写a繼續(xù)往后跑,但是因?yàn)樗呤窃谥袛喾?wù)函數(shù)里面的,喚醒之后進(jìn)不了這個(gè)中斷了,也就沒法繼續(xù)往下跑了。

2、睡眠之前要失能窗口看門狗。

這個(gè)問題有點(diǎn)莫名其妙,窗口看門狗是掛在APB1時(shí)鐘上面的,MCU進(jìn)入休眠的時(shí)候會(huì)關(guān)閉APB1時(shí)鐘,所以看門狗是不會(huì)影響休眠和喚醒的,實(shí)際上也是MCU休眠和喚醒的功能也是正常的,休眠之前USB和看門狗也是正常的,但是如果休眠時(shí)不先關(guān)閉看門狗時(shí)鐘,喚醒之后就會(huì)出現(xiàn)USB通訊異常的情況,我一時(shí)間也沒搞懂是什么原因,唯一有關(guān)聯(lián)的是USB和看門狗都是掛在APB1下面的,有大神可以解答一下我的疑惑嗎?

3、MCU休眠只能選擇WFE,選擇WFI的話USB無法喚醒MCU。

普通外部中斷喚醒(EXTI0-15)不管用WFI還是WFE都是可以正常使用的,USB中斷(EXTI18)在MCU休眠之前也是可以正常使用,但是一旦MCU通過WFI進(jìn)入休眠之后,就無法通過USB中斷喚醒了,這個(gè)時(shí)候哪怕通過其他外部中斷喚醒了MCU,USB也還是無法恢復(fù)正常通訊。

如果是用WFE則沒有這個(gè)問題,這就很奇怪了,中斷配置我也檢查過很多次了,并沒有發(fā)現(xiàn)什么問題,最后沒辦法就只能用WFE了。

結(jié)束語

關(guān)于USB遠(yuǎn)程睡眠喚醒的坑就講到這,這里其實(shí)只是列舉了一部分,因?yàn)檫@只是總結(jié)我遇到的新坑,有些以前踩過的坑這里就沒寫了,我也是第一次做USB的低功耗,沒想到會(huì)遇到這么多奇怪的問題。雖然最后問題都解決了,但是有些疑惑還是沒想明白,有大神知道的話還望不吝賜教!

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險(xiǎn)等級 參考價(jià)格 更多信息
LAN8710AI-EZK-TR 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER, QCC32, 5 X 5 MM, 0.90 MM HEIGHT, ROHS COMPLIANT, QFN-32

ECAD模型

下載ECAD模型
$1.56 查看
TJA1040T/CM,118 1 NXP Semiconductors TJA1040 - High-speed CAN transceiver with standby mode SOIC 8-Pin

ECAD模型

下載ECAD模型
$2.24 查看
VOD217T 1 Vishay Intertechnologies VOD205T, VOD206T, VOD207T, VOD211T, VOD213T, VOD217T Optocoupler, Phototransistor Output, Dual Channel, SOIC-8 Package

ECAD模型

下載ECAD模型
$0.76 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜