- UID
- 1029342
- 性别
- 男
|
这段时间做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了。 |
|