追踪研读法破解EZ-USB的“远程唤醒”

  
  一直没搞明白EZ-USB的远程唤醒到底是个什么鬼,今天就集中极力搞一搞。我不明白的主要集中在以下两点:
  (1)、远程唤醒是由谁发起的?既然是叫“远程”,那么这个远程唤醒是由谁发起的呢?是Host吗?还是EZ-USB得WAKEUP / WU2引脚引起的中断吗?
  (2)、远程唤醒的一整套的响应机制是怎样的呢?
  同样,我才用的依然是“追踪研读法”,就是在固件源代码和芯片手册中搜索相关的关键字,详细的研读,追踪每一个细节,不放过能够捕捉到的任何蛛丝马迹。没办法,谁叫俺笨呢?哈哈,这就是笨人的本方法。
  在这里,我将追踪“remote wakeup”、“WU2”等关键词。



远程唤醒在固件源码中的体现

  固件源码中与远程唤醒有关的,是一个Rwuen变量,搜索到有8处这个变量的痕迹:
这里写图片描述

(1)声明Rwuen为BOOL类型的变量:

BOOL      Rwuen;

(2)在main函数的刚开始先关闭远程唤醒:

Rwuen = FALSE;               // Disable remote wakeup

(3)在主函数中处理睡眠状态时,用于判断远程唤醒是不是被使能了:

while(!Rwuen && EZUSB_EXTWAKEUP());
            // above.  Must continue to go back into suspend if the host has disabled remote wakeup
            // *and* the wakeup was caused by the external wakeup pin.

(4)在设备请求的解析函数SetupCommand中,用于返回给Host设备状态:远程唤醒和自供电。

case SC_GET_STATUS:                  // *** Get Status
   if(DR_GetStatus())
      switch(SETUPDAT[0])
      {
         case GS_DEVICE:            // Device
            EP0BUF[0] = ((BYTE)Rwuen << 1) | (BYTE)Selfpwr;
            EP0BUF[1] = 0;
            EP0BCH = 0;
            EP0BCL = 2;
            break;

(5)在设备请求的解析函数SetupCommand中,用于响应清除特性的请求:

case SC_CLEAR_FEATURE:                  // *** Clear Feature
if(DR_ClearFeature())
  switch(SETUPDAT[0])
  {
     case FT_DEVICE:            // Device
        if(SETUPDAT[2] == 1)
           Rwuen = FALSE;       // Disable Remote Wakeup
        else
           EZUSB_STALL_EP0();   // Stall End Point 0
        break;
     case FT_ENDPOINT:         // End Point
        if(SETUPDAT[2] == 0)
        {
           *(BYTE xdata *) epcs(SETUPDAT[4]) &= ~bmEPSTALL;
           EZUSB_RESET_DATA_TOGGLE( SETUPDAT[4] );
        }
        else
           EZUSB_STALL_EP0();   // Stall End Point 0
        break;
  }
break;

(6)在设备请求的解析函数SetupCommand中,用于响应设置特性的请求:

 case SC_SET_FEATURE:                  // *** Set Feature
    if(DR_SetFeature())
       switch(SETUPDAT[0])
       {
          case FT_DEVICE:            // Device
             if(SETUPDAT[2] == 1)
                Rwuen = TRUE;      // Enable Remote Wakeup
             else if(SETUPDAT[2] == 2)
                // Set Feature Test Mode.  The core handles this request.  However, it is
                // necessary for the firmware to complete the handshake phase of the
                // control transfer before the chip will enter test mode.  It is also
                // necessary for FX2 to be physically disconnected (D+ and D-)
                // from the host before it will enter test mode.
                break;
             else
                EZUSB_STALL_EP0();   // Stall End Point 0
             break;
          case FT_ENDPOINT:         // End Point
             *(BYTE xdata *) epcs(SETUPDAT[4]) |= bmEPSTALL;
             break;
          default:
             EZUSB_STALL_EP0();      // Stall End Point 0
       }
    break;

(7)变量的声明:

extern BOOL   Rwuen;

(8)在初始化程序中使能远程唤醒:

void TD_Init(void)             // Called once at startup
{
   BREAKPT &= ~bmBPEN;      
   Rwuen = TRUE;            // 使能远程唤醒

  那么问题来了:
  Rwuen只是一个声明的变量,单纯的变量而已,并没有牵涉到芯片的寄存器,上述固件源码中只看到判断Ruwen的状态,而没有看到响应寄存器的设置,那是怎么直到有“远程唤醒”事件的发生呢?也就是说没有看到类似中断服务程序。
  我想这个问题只能到文档中去寻找相关的描述了吧!那么,下面继续:
  



文档中的相关描述,关键词remote wakeup

这里写图片描述
  ↑这里说到:USB总线上所有的数据传输都是有Host发起的,但是只有一种情况是例外的,即当Host将USB Device设置成挂起模式进入低功耗状态后,USB设备可以发起一个“remote wakeup ”信号。
  起码明白了一点:远程唤醒信号是由USB设备发送给Host。
  那么问题又来了
  (1)固件源码中并没有相应的体现啊!!!即固件源码中并没有发送远程唤醒信号给Host的部分;
  (2)设备是怎样知道啥时候该发送这个信号呢???固件源码中也没有说。
  继续追踪:
这里写图片描述
  ↑ 这里提到:USB设备要想发起恢复信号,则他必须在枚举阶段在配置描述符里表明其具备远程唤醒能力,并且Host使能了该设备的远程唤醒能力。
  继续追踪:
这里写图片描述
  ↑谢天谢地,这里详细介绍了远程唤醒,其实就是恢复/重新启动。
  这段说到,固件通过设置USBCS寄存器的SIGRSUME位,来向Host发送远程唤醒请求,总算解决了一个疑问,那么Host收到远程唤醒请求(即Resume,后面说成恢复)之后,怎样将USB设备恢复呢???从下图里可以看到,8051只需要做到设置USBCS寄存器的SIGRSUME位即可,其他的应该是有Host和USB设备的硬件来做吧:
这里写图片描述
  当然,还有一些细节要注意:固件在收到唤醒中断5ms之后才能设置USBCS寄存器的SIGRSUME位,然后再过10-15ms清除之。现在又多了一个问题:我咋没有看见固件中的唤醒中断呢??
这里写图片描述
  ↑这一段又可耻的说了一通恢复程序中应该注意的问题,看来他要吊我的胃口了,就是不肯说这个唤醒中断在哪里,还有Host收到恢复请求之后是怎样告诉USB设备可以恢复了。
  在设置USBCS寄存器的SIGRSUME位之前,固件必须检查唤醒源是否来自WAKEUP / WU2引脚,如果两个引脚都没有不是唤醒源,那么唤醒事件来自USB总线被激活,这种情况下就不能通过设置USBCS寄存器的SIGRSUME位来恢复。
这里写图片描述
  ↑继续东拉西扯转移话题,WU2/PA3是同时激活状态,只不过WU2只有在设置WU2EN位为1的前提下才有效,这是还需要将PA3设置成输入。
  没办法,只得继续追踪了,可奈何文档里关于这个关键词也就这么多内容了。

文档中的相关描述,关键词WU2

  之所以选择WU2这个关键词,是因为WU2是芯片的唤醒信号的其中一个引脚。我怀疑远程唤醒是WAKEUP / WU2引脚引起的。
这里写图片描述  
  ↑ 在这张表中可以看到,Resume的中断优先级是0,是最高的。
这里写图片描述
  ↑说到,唤醒中断的标志位(哈哈哈,终于到重点了),RESI = 1 表明有Resume中断发生,中断源可能来自 WAKEUP或WU2引脚,或者USB总线从挂起状态恢复了。
  我也终于在fw.c中找到了一段关于RESI 的代码,唤醒中断处理:
  

// Wake-up interrupt handler
void resume_isr(void) interrupt WKUP_VECT
{
   EZUSB_CLEAR_RSMIRQ();
}

  ↑在这个中断服务程序里,也仅仅是清除了中断标志位,没有对变量Resume处理。还有,这里的WKUP_VECT为啥是6啊???不是应该是0吗???

#define EZUSB_ENABLE_RSMIRQ()      (EICON |= 0x20)      
// Enable Resume Interrupt (EPFI_)
#define EZUSB_DISABLE_RSMIRQ()      (EICON &= ~0x20)   
// Disable Resume Interrupt (EPFI_)
#define EZUSB_CLEAR_RSMIRQ()      (EICON &= ~0x10)   
// Clear Resume Interrupt Flag (PFI_)

这里写图片描述
  ↑上面这段话可以比较含混的证明使芯片唤醒的就是WAKEUP或WU2引脚,或者USB总线从挂起状态恢复这三个条件,但并没有明确说明远程唤醒来自这三个货。唉,为啥就不能明明白白的说明呢!!!
这里写图片描述
  ↑这里又有说明这三个唤醒源可以分别使能,也可以在这里设置WU和WU2的有效极性。也可以进一步查询是哪个引脚引起的唤醒中断。
  
  

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值