首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

STM32 USB断开连接代码停止运行 (转)

STM32 USB断开连接代码停止运行 (转)

这段时间做USB固件升级,使用ST官方固件,最开始按照ST的做法通过检测按键进入DFU模式。后来由于别人觉得这种方式做不好,要改成检测USB的而不是检测按键的。但是当我改好了测试的时候却发现当我把USB初始化之后断开了USB连接程序停止了运行,接上USB程序才会继续跑。连使用Jlink调试都没用了。然而根据打印调试,USB接上的时候MCU并没有复位,硬件出错其实也不太像,总之觉得一切很诡异。至少在当时我根本就没办法解释我所观察到的这个现象。百度也没有结果,大多数情况下百度其实很废但是没办法。
        想了很久我觉得是不是MCU休眠去了?带着这样的猜测到初始化过程中去找相关初始化,因为在我印象当中,睡眠模式也是需要初始化寄存器的,只可惜找了好久没有找到。不过我觉得打印调试在大多数时候还是好用的。于是我就通过printf一个个捕捉中断,试图搞清楚在拔出USB的那一刻到底去哪里执行代码了。几经调试,最后才发现在USB_Istr函数中有这样一段代码:#if (IMR_MSK & ISTR_SUSP)
  if (wIstr & ISTR_SUSP & wInterrupt_Mask)
  {

    /* check if SUSPEND is possible */
    if (fSuspendEnabled)
    {
      Suspend();
    }
    else
    {
      /* if not possible then resume after xx ms */
      Resume(RESUME_LATER);
    }
    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
    _SetISTR((uint16_t)CLR_SUSP);
#ifdef SUSP_CALLBACK
    SUSP_Callback();
#endif
  }
#endif
问题就出在Suspend()函数:        /* enter system in STOP mode, only when wakeup flag in not set */
        if((_GetISTR()&ISTR_WKUP)==0)
        {
                __WFI();
                /* Reset SLEEPDEEP bit of Cortex System Control Register */
#if defined (STM32F30X) || defined (STM32F37X)
                SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
#else
                SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
#endif
        }
这里的__WFI()指令就是导致代码停止运行的罪魁祸首。从数据手册中可以查到这是一条进入睡眠状态的指令,令我以外的是STM32进入睡眠低功耗模式连初始化都不需要(我确实没有找到相关初始化代码)直接一条指令就搞定。这也可以算的是我墨守成规的一个教训吧。所以最后只需把这条__WFI()指令屏蔽掉就OK了。
继承事业,薪火相传
返回列表