这几天在做产品的休眠模式.在C#应用程序代码中调用
PowerState.Sleep(SleepLevel.DeepSleep, HardwareEvent.GeneralPurpose);
1、发现一旦调用该代码,程序就无法唤醒(当然我是有设置IO外部中断唤醒的).
针对该问题的解决方式:
经过调试发现,由于KEIL4的编译问题,只需在驱动代码出增加一些变量或者打印信息,可以解决.
例如,以下我修改过的代码
void CPU_Sleep( SLEEP_LEVEL level, UINT64 wakeEvents )
{
u32 uCnt = 0xFFF;
NATIVE_PROFILE_HAL_PROCESSOR_POWER();
PWR->CR &= ~(PWR_CR_LPDS | PWR_CR_PDDS); // reset deepsleep bits
switch(level)
{
case SLEEP_LEVEL__DEEP_SLEEP: // stop
hal_printf("CPU_Sleep :: Enter Stop!\r\n");
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
PWR->CR |= PWR_CR_CWUF | PWR_CR_LPDS; // low power deepsleep
break;
case SLEEP_LEVEL__OFF: // standby
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
PWR->CR |= PWR_CR_CWUF | PWR_CR_PDDS; // power down deepsleep
break;
default: // sleep
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // no deepsleep
PWR->CR |= PWR_CR_CWUF;
break;
}
__WFI(); // sleep and wait for interrupt
if(uCnt == 0)
{
hal_printf("CPU_Sleep :: I am Wakeup!!\r\n");
}
}
2、调用发现终于可以停止了,但是又有另外的问题====>没有按任何外部中断,程序会隔1分钟唤醒.
开始以为是用了RTC的闹钟唤醒功能.但经过代码查看及用JLINK调试,发现并不是这么回事。
代码有并没有使用RTC这个东西,而且JLINK中调试发现调用了
PowerState.Sleep(SleepLevel.DeepSleep, HardwareEvent.GeneralPurpose);
并不能够使程序进入休眠。这是一个假象。因为固件还在是在跑,而且周期性地进入CPU_Sleep这个函数。
解决问题的方式是:
不使用这个接口,自己封装一个调用结构给C#调用.也许你会说直接改写CPU_Sleep这个函数就可以了.开始我是这么想的,也是这么试的,结果发现不行.
使用自己封装的接口,确实可以达到进入STOP模式。当进入STOP模式后,你会发现USB在电脑无法识别了(原来的USB”netduion”设备不见了)。这证明是进入休眠了。
按下按键,可以唤醒我的设备.
注意:假如你在唤醒之后使用Debug.Print(“xxxxxx”);这个函数。那么恭喜你,你会发现你的设备无法执行C#的下一个语句.
经分析,因为无法通过USB将与VS通信,导致一直在USB循环中断.
因此,使用.net micro framework做低功耗的要注意一下咯!目前,最好在使用USB的情况下,最好不要使用Debug.Print()这个函数来打印东西。