改进电源管理,系统空闲时自动进入低功耗睡眠
This commit is contained in:
parent
f7768ec184
commit
f2dee255c1
|
@ -64,6 +64,9 @@ void AP0801::Init(ushort code, cstring name, COM message)
|
|||
WatchDog::Start();
|
||||
#endif
|
||||
|
||||
// 系统休眠时自动进入低功耗
|
||||
Power::AttachTimeSleep();
|
||||
|
||||
// Flash最后一块作为配置区
|
||||
Config::Current = &Config::CreateFlash();
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ void AP0802::Init(ushort code, cstring name, COM message)
|
|||
WatchDog::Start();
|
||||
#endif
|
||||
|
||||
// 系统休眠时自动进入低功耗
|
||||
Power::AttachTimeSleep();
|
||||
|
||||
// Flash最后一块作为配置区
|
||||
Config::Current = &Config::CreateFlash();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ void PA0903::Init(ushort code, cstring name, COM message)
|
|||
Sys.ShowInfo();
|
||||
#endif
|
||||
|
||||
// 系统休眠时自动进入低功耗
|
||||
Power::AttachTimeSleep();
|
||||
|
||||
// Flash最后一块作为配置区
|
||||
Config::Current = &Config::CreateFlash();
|
||||
}
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
@ -43,10 +41,10 @@ void Power::Standby(uint msTime)
|
|||
}
|
||||
}
|
||||
|
||||
if(!msTime) msTime = 0xFFFF;
|
||||
WatchDog::Start(msTime);
|
||||
/*if(!msTime) msTime = 0xFFFF;
|
||||
WatchDog::Start(msTime);*/
|
||||
|
||||
OnStandby();
|
||||
OnStandby(msTime);
|
||||
}
|
||||
|
||||
// 各模块向系统注册低功耗句柄,供系统进入低功耗前调用
|
||||
|
@ -56,3 +54,16 @@ void Power::AddPower(Power* power)
|
|||
|
||||
_powers.Add(power);
|
||||
}
|
||||
|
||||
void OnTimeSleep(int ms)
|
||||
{
|
||||
Power::Sleep(ms);
|
||||
}
|
||||
|
||||
// 附加到系统时钟,睡眠时进入低功耗
|
||||
bool Power::AttachTimeSleep()
|
||||
{
|
||||
((TTime&)Time).OnSleep = OnTimeSleep;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -1,64 +1,17 @@
|
|||
#include "WatchDog.h"
|
||||
|
||||
/*
|
||||
独立看门狗IWDG——有独立时钟(内部低速时钟LSI---40KHz),所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。
|
||||
窗口看门狗WWDG——时钟与系统相同。如果系统时钟不走了,这个狗也就失去作用了,主要用于监视软件错误。
|
||||
|
||||
独立看门狗
|
||||
看门狗定时时限=IWDG_SetReload()的值 / 看门狗时钟频率
|
||||
看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数
|
||||
|
||||
独立看门狗(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue