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

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(); WatchDog::Start();
#endif #endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区 // Flash最后一块作为配置区
Config::Current = &Config::CreateFlash(); Config::Current = &Config::CreateFlash();
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -46,6 +46,9 @@ void PA0903::Init(ushort code, cstring name, COM message)
Sys.ShowInfo(); Sys.ShowInfo();
#endif #endif
// 系统休眠时自动进入低功耗
Power::AttachTimeSleep();
// Flash最后一块作为配置区 // Flash最后一块作为配置区
Config::Current = &Config::CreateFlash(); 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" #include "Device\WatchDog.h"
// 低功耗处理器 // 低功耗处理器
@ -12,26 +13,23 @@ void Power::SetPower()
void Power::ChangePower(int level) { } 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; OnSleep(msTime);
WatchDog::Start(msTime);
OnStop();
} }
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++) for(int i=0; i<_powers.Count(); i++)
{ {
@ -42,17 +40,30 @@ void Power::Standby(uint msTime)
pwr->ChangePower(msTime); pwr->ChangePower(msTime);
} }
} }
if(!msTime) msTime = 0xFFFF; /*if(!msTime) msTime = 0xFFFF;
WatchDog::Start(msTime); WatchDog::Start(msTime);*/
OnStandby(); OnStandby(msTime);
} }
// 各模块向系统注册低功耗句柄,供系统进入低功耗前调用 // 各模块向系统注册低功耗句柄,供系统进入低功耗前调用
void Power::AddPower(Power* power) void Power::AddPower(Power* power)
{ {
debug_printf("Power::AddPower 0x%p\r\n", power); debug_printf("Power::AddPower 0x%p\r\n", power);
_powers.Add(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); virtual void ChangePower(int level);
// 低功耗相关 // 低功耗相关
static void Stop(uint msTime = 0); static void Sleep(int msTime = 0);
static void DeepSleep(uint msTime = 0); static void Stop(int msTime = 0);
static void Standby(uint msTime = 0); static void Standby(int msTime = 0);
// 各模块向系统注册低功耗句柄,供系统进入低功耗前调用 // 各模块向系统注册低功耗句柄,供系统进入低功耗前调用
static void AddPower(Power* power); static void AddPower(Power* power);
// 附加到系统时钟,睡眠时进入低功耗
static bool AttachTimeSleep();
private: private:
static void OnStop(); static void OnSleep(int msTime);
static void OnDeepSleep(); static void OnStop(int msTime);
static void OnStandby(); static void OnStandby(int msTime);
}; };
#endif #endif

View File

@ -19,7 +19,7 @@ HardRTC* HardRTC::Instance()
void FuncLoadTime() { HardRTC::Instance()->LoadTime(); } void FuncLoadTime() { HardRTC::Instance()->LoadTime(); }
void FuncSaveTime() { HardRTC::Instance()->SaveTime(); } 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) void HardRTC::Start(bool lowpower, bool external)
{ {

View File

@ -1,64 +1,17 @@
#include "WatchDog.h" #include "WatchDog.h"
/* WatchDog::WatchDog() { }
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(); ConfigMax();
} }
WatchDog& WatchDog::Current()
{
static WatchDog dog;
return dog;
}
void WatchDog::FeedDogTask(void* param) void WatchDog::FeedDogTask(void* param)
{ {
WatchDog* dog = (WatchDog*)param; WatchDog* dog = (WatchDog*)param;
@ -67,18 +20,27 @@ void WatchDog::FeedDogTask(void* param)
void WatchDog::Start(uint ms, uint msFeed) void WatchDog::Start(uint ms, uint msFeed)
{ {
static WatchDog dog;
static uint tid = 0; static uint tid = 0;
auto& dog = Current();
if(ms > 20000) if(ms > 20000)
dog.ConfigMax();
else
dog.Config(ms);
if(!tid && msFeed > 0 && msFeed <= 26000)
{ {
debug_printf("WatchDog::Start "); dog.ConfigMax();
// 首次调度为0ms让调度系统计算得到其平均耗时其它任务Sleep时也可以喂狗
tid = Sys.AddTask(WatchDog::FeedDogTask, &dog, 0, msFeed, "看门狗"); 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 class WatchDog
{ {
private: private:
WatchDog();
public: public:
//WatchDog(uint ms = 3000); //WatchDog(uint ms = 3000);
@ -18,6 +19,7 @@ public:
void ConfigMax(); // 看门狗无法关闭,只能设置一个最大值 void ConfigMax(); // 看门狗无法关闭,只能设置一个最大值
void Feed(); // 喂狗 void Feed(); // 喂狗
static WatchDog& Current();
static void FeedDogTask(void* param); static void FeedDogTask(void* param);
// 打开看门狗。最长喂狗时间26208ms默认2000ms // 打开看门狗。最长喂狗时间26208ms默认2000ms
static void Start(uint msTimeout = 2000, uint msFeed = 500); static void Start(uint msTimeout = 2000, uint msFeed = 500);

View File

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

View File

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

View File

@ -4,19 +4,22 @@
#include "Platform\stm32.h" #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 #ifdef STM32F0
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI); PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
#endif #endif
} }
void Power::OnStandby() void Power::OnStandby(int msTime)
{ {
if(!msTime) msTime = 20000;
WatchDog::Start(msTime);
PWR_EnterSTANDBYMode(); PWR_EnterSTANDBYMode();
} }

View File

@ -4,19 +4,22 @@
#include "Platform\stm32.h" #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 #ifdef STM32F0
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI); PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
#endif #endif
} }
void Power::OnStandby() void Power::OnStandby(int msTime)
{ {
if(!msTime) msTime = 20000;
WatchDog::Start(msTime);
PWR_EnterSTANDBYMode(); PWR_EnterSTANDBYMode();
} }