????前兩天在研究FreeRTOS的Tickless低功耗管理,使用的是CH582的板子,一直卡在portSUPPRESS_TICKS_AND_SLEEP()宏的實現(xiàn)上面。具體問題如下:
????使用LowPower_Halt休眠沒有問題,使用LowPower_Sleep休眠時,系統(tǒng)在切換任務時就直接卡B了。
????非常郁悶,嘗試了各種方法都不行,直到我看到這個:
????
????也就是說CH58X系列的systick在休眠后是會復位配置和計數(shù)的,這不坑爹嘛!
????廢話不多少,上代碼。以下是portSUPPRESS_TICKS_AND_SLEEP()宏的具體實現(xiàn):
/*?Define?the?function?that?is?called?by?portSUPPRESS_TICKS_AND_SLEEP().?*/ void?vApplicationSleep(?uint32_t?xExpectedIdleTime?)?{ #if(defined(HAL_SLEEP))?&&?(HAL_SLEEP?==?TRUE) ????unsigned?long?ulLowPowerTimeBeforeSleep,?ulLowPowerTimeAfterSleep,?ulLowPowerTimeTotalSleep,?irq_status; ????eSleepModeStatus?eSleepStatus; ????uint32_t?time_sleep,?time_curr,?time; ????/*?Stop?the?timer?that?is?generating?the?tick?interrupt.?*/ ????PFIC_DisableIRQ(RTC_IRQn); ????PFIC_DisableIRQ(SysTick_IRQn); ????SYS_DisableAllIrq(&irq_status); ????ulLowPowerTimeBeforeSleep?=?RTC_GetCycle32k(); ????time?=?xExpectedIdleTime?*?32.768?+?ulLowPowerTimeBeforeSleep; ????if?(time?>=?RTC_TIMER_MAX_VALUE)?{ ????????time?-=?RTC_TIMER_MAX_VALUE; ????} ????if?(time?<?WAKE_UP_RTC_MAX_TIME?+?32)?{ ????????PFIC_EnableIRQ(SysTick_IRQn); ????????SYS_RecoverIrq(irq_status); ????????return; ????} ????time?-=?(WAKE_UP_RTC_MAX_TIME?+?32); ????time_curr?=?RTC_GetCycle32k(); ????//?檢測睡眠時間 ????if?(time?<?time_curr)?{ ????????time_sleep?=?time?+?(RTC_TIMER_MAX_VALUE?-?time_curr); ????}?else?{ ????????time_sleep?=?time?-?time_curr; ????} ????if?(time_sleep?>?(RTC_TIMER_MAX_VALUE?-?TMOS_TIME_VALID))?{ ????????PFIC_EnableIRQ(SysTick_IRQn); ????????SYS_RecoverIrq(irq_status); ????????return; ????} ????/*?Ensure?it?is?still?ok?to?enter?the?sleep?mode.?*/ ????eSleepStatus?=?eTaskConfirmSleepModeStatus(); ????if(?eSleepStatus?==?eAbortSleep?)?{ ????????PFIC_EnableIRQ(SysTick_IRQn); ????????SYS_RecoverIrq(irq_status); ????} ????else?{ ????????if(?eSleepStatus?==?eNoTasksWaitingTimeout?)?{ ????????????LowPower_Shutdown(0); ????????} ????????else?{ ????????????RTC_SetTignTime(time); ????????????//PFIC_EnableIRQ(RTC_IRQn); #if(DEBUG?==?Debug_UART1)?//?使用其他串口輸出打印信息需要修改這行代碼 ??????????????while((R8_UART1_LSR?&?RB_LSR_TX_ALL_EMP)?==?0)?{ ??????????????????__nop(); ??????????????} #endif ????????????//?LOW?POWER-sleep模式 ????????????if(!(R8_RTC_FLAG_CTRL?&?RB_RTC_TRIG_FLAG))?{ ????????????????LowPower_Sleep_Event(RB_PWR_RAM2K?|?RB_PWR_RAM30K?|?RB_PWR_XROM?|?RB_PWR_EXTEND?|?RB_PWR_CORE); ????????????????if(R8_RTC_FLAG_CTRL?&?RB_RTC_TRIG_FLAG)?{?//?注意如果使用了RTC以外的喚醒方式,需要注意此時32M晶振未穩(wěn)定 ????????????????????R8_RTC_FLAG_CTRL?=?RB_RTC_TRIG_CLR; ????????????????????time?+=?WAKE_UP_RTC_MAX_TIME; ????????????????????if(time?>?0xA8C00000)?{ ????????????????????????time?-=?0xA8C00000; ????????????????????} ????????????????????RTC_SetTignTime(time); ????????????????????LowPower_Idle_Event(); ????????????????????R8_RTC_FLAG_CTRL?=?RB_RTC_TRIG_CLR; ????????????????} ????????????????HSECFG_Current(HSE_RCur_100);?//?降為額定電流(低功耗函數(shù)中提升了HSE偏置電流) ????????????????vPortSetupTimerInterrupt();???//?恢復SysTick配置 ????????????} ????????????ulLowPowerTimeAfterSleep?=?RTC_GetCycle32k(); ????????????if?(ulLowPowerTimeAfterSleep?<?ulLowPowerTimeBeforeSleep)?{ ????????????????ulLowPowerTimeTotalSleep?=?ulLowPowerTimeAfterSleep?+?(RTC_TIMER_MAX_VALUE?-?ulLowPowerTimeBeforeSleep); ????????????} ????????????else?{ ????????????????ulLowPowerTimeTotalSleep?=?ulLowPowerTimeAfterSleep?-?ulLowPowerTimeBeforeSleep; ????????????} ????????????ulLowPowerTimeTotalSleep?=?ulLowPowerTimeTotalSleep?*?1000?/?32768; ????????????vTaskStepTick(?ulLowPowerTimeTotalSleep?); ????????????//PRINT("ulLowPowerTimeTotalSleep?=?%d??xExpectedIdleTime=%d\n",?ulLowPowerTimeTotalSleep,?xExpectedIdleTime); ????????????//PRINT("xTickCount?=?%d\n",?xTaskGetTickCount()); ????????} ????????SYS_RecoverIrq(irq_status); ????????PFIC_EnableIRQ(SysTick_IRQn); ????} #endif }
重點是休眠喚醒后,需要調用vPortSetupTimerInterrupt()恢復SysTick配置。
熱門產品 :
CH397: 高集成度、低功耗USB網卡芯片