改进电源管理,系统空闲时自动进入低功耗睡眠

This commit is contained in:
大石头X2 2016-12-28 16:54:48 +08:00
parent f7768ec184
commit f2dee255c1
15 changed files with 121 additions and 114 deletions

View File

@ -64,6 +64,9 @@ void AP0801::Init(ushort code, cstring name, COM message)
WatchDog::Start();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();
}

View File

@ -51,6 +51,9 @@ void AP0802::Init(ushort code, cstring name, COM message)
WatchDog::Start();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();

View File

@ -2,6 +2,7 @@
#include "Kernel\Task.h"
#include "Device\Power.h"
#include "Device\WatchDog.h"
#include "Config.h"
@ -51,6 +52,9 @@ void IOK026X::Init(ushort code, cstring name, COM message)
WatchDog::Start();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();
}

View File

@ -2,6 +2,7 @@
#include "Kernel\Task.h"
#include "Device\Power.h"
#include "Device\WatchDog.h"
#include "Config.h"
#include "Drivers\Esp8266\Esp8266.h"
@ -50,6 +51,9 @@ void IOK027X::Init(ushort code, cstring name, COM message)
WatchDog::Start();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();
}

View File

@ -2,6 +2,7 @@
#include "Kernel\Task.h"
#include "Device\Power.h"
#include "Device\WatchDog.h"
#include "Config.h"
@ -52,6 +53,9 @@ void IOK0612::Init(ushort code, cstring name, COM message)
WatchDog::Start();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();
}

View File

@ -46,6 +46,9 @@ void PA0903::Init(ushort code, cstring name, COM message)
Sys.ShowInfo();
#endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区
Config::Current = &Config::CreateFlash();
}

View File

@ -1,5 +1,6 @@
#include "Device\Power.h"
#include "Kernel\TTime.h"
#include "Device\Power.h"
#include "Device\WatchDog.h"
// 低功耗处理器
@ -12,26 +13,23 @@ void Power::SetPower()
void Power::ChangePower(int level) { }
void Power::Stop(uint msTime)
void Power::Sleep(int msTime)
{
debug_printf("Power::Stop Time=%d \r\n", msTime);
//debug_printf("Power::Sleep Time=%d 仅关闭内核,各外设不变,定时唤醒后继续执行 \r\n", msTime);
if(!msTime) msTime = 0xFFFF;
WatchDog::Start(msTime);
OnStop();
OnSleep(msTime);
}
void Power::DeepSleep(uint msTime)
void Power::Stop(int msTime)
{
debug_printf("Power::DeepSleep Time=%d \r\n", msTime);
debug_printf("Power::Stop Time=%d 关闭内核和外设,靠外部中断唤醒,然后继续执行 \r\n", msTime);
OnDeepSleep();
OnStop(msTime);
}
void Power::Standby(uint msTime)
void Power::Standby(int msTime)
{
debug_printf("Power::Standby Time=%d \r\n", msTime);
debug_printf("Power::Standby Time=%d 全停,只能等专门的引脚或看门狗来唤醒,重新启动 \r\n", msTime);
for(int i=0; i<_powers.Count(); i++)
{
@ -42,17 +40,30 @@ void Power::Standby(uint msTime)
pwr->ChangePower(msTime);
}
}
if(!msTime) msTime = 0xFFFF;
WatchDog::Start(msTime);
OnStandby();
/*if(!msTime) msTime = 0xFFFF;
WatchDog::Start(msTime);*/
OnStandby(msTime);
}
// 各模块向系统注册低功耗句柄,供系统进入低功耗前调用
void Power::AddPower(Power* power)
{
debug_printf("Power::AddPower 0x%p\r\n", power);
_powers.Add(power);
}
void OnTimeSleep(int ms)
{
Power::Sleep(ms);
}
// 附加到系统时钟,睡眠时进入低功耗
bool Power::AttachTimeSleep()
{
((TTime&)Time).OnSleep = OnTimeSleep;
return true;
}

View File

@ -13,17 +13,20 @@ public:
virtual void ChangePower(int level);
// 低功耗相关
static void Stop(uint msTime = 0);
static void DeepSleep(uint msTime = 0);
static void Standby(uint msTime = 0);
static void Sleep(int msTime = 0);
static void Stop(int msTime = 0);
static void Standby(int msTime = 0);
// 各模块向系统注册低功耗句柄,供系统进入低功耗前调用
static void AddPower(Power* power);
// 附加到系统时钟,睡眠时进入低功耗
static bool AttachTimeSleep();
private:
static void OnStop();
static void OnDeepSleep();
static void OnStandby();
static void OnSleep(int msTime);
static void OnStop(int msTime);
static void OnStandby(int msTime);
};
#endif

View File

@ -19,7 +19,7 @@ HardRTC* HardRTC::Instance()
void FuncLoadTime() { HardRTC::Instance()->LoadTime(); }
void FuncSaveTime() { HardRTC::Instance()->SaveTime(); }
int FuncSleep(int ms) { return HardRTC::Instance()->Sleep(ms); }
void FuncSleep(int ms) { HardRTC::Instance()->Sleep(ms); }
void HardRTC::Start(bool lowpower, bool external)
{

View File

@ -1,64 +1,17 @@
#include "WatchDog.h"
/*
IWDGLSI---40KHz 
WWDG 
=IWDG_SetReload() /
=LSI40KHz/ 
(IWDG)40kHz的低速时钟为驱动使
APB1时钟分频后得到的时钟驱动
IWDG_SetPrescaler() 4~256
IWDG_SetReload() 12 0~0x0FFF
IWDG_ReloadCounter() 1
IWDG_PR和IWDG_RLR寄存器具有写保护功能IWDG_KR寄存器中写入0x5555
(0xAAAA)
#define IWDG_WriteAccess_Enable ((uint16_t)0x5555)
#define IWDG_WriteAccess_Disable ((uint16_t)0x0000)
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
{
assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));
IWDG->KR = IWDG_WriteAccess;
}
void IWDG_ReloadCounter(void)
{
IWDG->KR = KR_KEY_Reload;
}
void IWDG_Enable(void)
{
IWDG->KR = KR_KEY_Enable;
}
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
{
assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));
IWDG->PR = IWDG_Prescaler;
}
void IWDG_SetReload(uint16_t Reload)
{
assert_param(IS_IWDG_RELOAD(Reload));
IWDG->RLR = Reload;
}
*/
/*WatchDog::WatchDog(uint ms)
{
Timeout = ms;
Config(ms);
}*/
WatchDog::WatchDog() { }
WatchDog::~WatchDog()
{
ConfigMax();
}
WatchDog& WatchDog::Current()
{
static WatchDog dog;
return dog;
}
void WatchDog::FeedDogTask(void* param)
{
WatchDog* dog = (WatchDog*)param;
@ -67,18 +20,27 @@ void WatchDog::FeedDogTask(void* param)
void WatchDog::Start(uint ms, uint msFeed)
{
static WatchDog dog;
static uint tid = 0;
auto& dog = Current();
if(ms > 20000)
dog.ConfigMax();
else
dog.Config(ms);
if(!tid && msFeed > 0 && msFeed <= 26000)
{
debug_printf("WatchDog::Start ");
// 首次调度为0ms让调度系统计算得到其平均耗时其它任务Sleep时也可以喂狗
tid = Sys.AddTask(WatchDog::FeedDogTask, &dog, 0, msFeed, "看门狗");
dog.ConfigMax();
if(tid) Sys.RemoveTask(tid);
}
else
{
dog.Config(ms);
dog.Feed();
if(!tid && msFeed > 0 && msFeed <= 26000)
{
debug_printf("WatchDog::Start ");
// 首次调度为0ms让调度系统计算得到其平均耗时其它任务Sleep时也可以喂狗
tid = Sys.AddTask(WatchDog::FeedDogTask, &dog, 0, msFeed, "看门狗");
}
else
debug_printf("WatchDog::Config %dms Feed=%dms \r\n", ms, msFeed);
}
}

View File

@ -7,6 +7,7 @@
class WatchDog
{
private:
WatchDog();
public:
//WatchDog(uint ms = 3000);
@ -18,6 +19,7 @@ public:
void ConfigMax(); // 看门狗无法关闭,只能设置一个最大值
void Feed(); // 喂狗
static WatchDog& Current();
static void FeedDogTask(void* param);
// 打开看门狗。最长喂狗时间26208ms默认2000ms
static void Start(uint msTimeout = 2000, uint msFeed = 500);

View File

@ -24,7 +24,7 @@ public:
Func OnInit;
Func OnLoad;
Func OnSave;
typedef int (*FuncInt)(int);
typedef void (*FuncInt)(int);
FuncInt OnSleep;
TTime();
@ -36,8 +36,8 @@ public:
UInt64 Current() const; // 当前毫秒数
void SetTime(UInt64 seconds); // 设置时间
void Sleep(uint ms, bool* running = nullptr) const;
void Delay(uint us) const; // 微秒级延迟
void Sleep(int ms, bool* running = nullptr) const;
void Delay(int us) const; // 微秒级延迟
uint TicksToUs(uint ticks) const;
uint UsToTicks(uint us) const;

View File

@ -64,41 +64,43 @@ void TTime::SetTime(UInt64 sec)
#endif
#endif
void TTime::Sleep(uint ms, bool* running) const
void TTime::Sleep(int ms, bool* running) const
{
// 睡眠时间太短
if(!ms) return;
if(ms <= 0) return;
// 结束时间
Int64 end = Current() + ms;
// 较大的睡眠时间直接让CPU停下来
if(OnSleep && ms >= 10)
{
uint ms2 = ms;
if(OnSleep(ms2) == 0)
while(ms >= 10)
{
// CPU睡眠是秒级还有剩余量
if(ms >= ms2)
ms -= ms2;
else
ms = 0;
OnSleep(ms);
// 判断是否需要继续
if(running != nullptr && !*running) break;
// 重新计算剩下的时间
ms = (int)(end - Current());
}
}
// 睡眠时间太短
if(!ms || (running && !*running)) return;
uint me = Current() + ms;
// 空转
while(true)
{
if(Current() >= me) break;
if(Current() >= end) break;
if(running != nullptr && !*running) break;
}
}
void TTime::Delay(uint us) const
void TTime::Delay(int us) const
{
// 睡眠时间太短
if(!us) return;
if(us <= 0) return;
// 较大的时间,按毫秒休眠
if(us >= 1000)

View File

@ -4,19 +4,22 @@
#include "Platform\stm32.h"
void Power::OnStop()
void Power::OnSleep(int msTime)
{
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}
void Power::OnDeepSleep()
void Power::OnStop(int msTime)
{
#ifdef STM32F0
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
#endif
}
void Power::OnStandby()
void Power::OnStandby(int msTime)
{
if(!msTime) msTime = 20000;
WatchDog::Start(msTime);
PWR_EnterSTANDBYMode();
}

View File

@ -4,19 +4,22 @@
#include "Platform\stm32.h"
void Power::OnStop()
void Power::OnSleep(int msTime)
{
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}
void Power::OnDeepSleep()
void Power::OnStop(int msTime)
{
#ifdef STM32F0
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
#endif
}
void Power::OnStandby()
void Power::OnStandby(int msTime)
{
if(!msTime) msTime = 20000;
WatchDog::Start(msTime);
PWR_EnterSTANDBYMode();
}