diff --git a/Board/AP0801.cpp b/Board/AP0801.cpp index 97884501..ce58b620 100644 --- a/Board/AP0801.cpp +++ b/Board/AP0801.cpp @@ -64,6 +64,9 @@ void AP0801::Init(ushort code, cstring name, COM message) WatchDog::Start(); #endif + // 系统休眠时自动进入低功耗 + Power::AttachTimeSleep(); + // Flash最后一块作为配置区 Config::Current = &Config::CreateFlash(); } diff --git a/Board/AP0802.cpp b/Board/AP0802.cpp index 16badfdc..c3ed4b48 100644 --- a/Board/AP0802.cpp +++ b/Board/AP0802.cpp @@ -51,6 +51,9 @@ void AP0802::Init(ushort code, cstring name, COM message) WatchDog::Start(); #endif + // 系统休眠时自动进入低功耗 + Power::AttachTimeSleep(); + // Flash最后一块作为配置区 Config::Current = &Config::CreateFlash(); diff --git a/Board/IOK026X.cpp b/Board/IOK026X.cpp index 4bf9927f..1a9241d9 100644 --- a/Board/IOK026X.cpp +++ b/Board/IOK026X.cpp @@ -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(); } diff --git a/Board/IOK027X.cpp b/Board/IOK027X.cpp index e980477d..2997f6b7 100644 --- a/Board/IOK027X.cpp +++ b/Board/IOK027X.cpp @@ -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(); } diff --git a/Board/IOK0612.cpp b/Board/IOK0612.cpp index c2393d23..de94b522 100644 --- a/Board/IOK0612.cpp +++ b/Board/IOK0612.cpp @@ -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(); } diff --git a/Board/Pandora.cpp b/Board/Pandora.cpp index a9c48d9d..d6e3a321 100644 --- a/Board/Pandora.cpp +++ b/Board/Pandora.cpp @@ -46,6 +46,9 @@ void PA0903::Init(ushort code, cstring name, COM message) Sys.ShowInfo(); #endif + // 系统休眠时自动进入低功耗 + Power::AttachTimeSleep(); + // Flash最后一块作为配置区 Config::Current = &Config::CreateFlash(); } diff --git a/Device/Power.cpp b/Device/Power.cpp index 008bf6c4..7b8e329b 100644 --- a/Device/Power.cpp +++ b/Device/Power.cpp @@ -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; +} diff --git a/Device/Power.h b/Device/Power.h index 5fa5412e..b5fa2932 100644 --- a/Device/Power.h +++ b/Device/Power.h @@ -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 diff --git a/Device/RTC.cpp b/Device/RTC.cpp index 3bdf99b7..365ca317 100644 --- a/Device/RTC.cpp +++ b/Device/RTC.cpp @@ -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) { diff --git a/Device/WatchDog.cpp b/Device/WatchDog.cpp index a3088b57..5af9c4c4 100644 --- a/Device/WatchDog.cpp +++ b/Device/WatchDog.cpp @@ -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); } } diff --git a/Device/WatchDog.h b/Device/WatchDog.h index 70bd7ee8..fdbf116f 100644 --- a/Device/WatchDog.h +++ b/Device/WatchDog.h @@ -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); diff --git a/Kernel/TTime.h b/Kernel/TTime.h index af78d334..8640373a 100644 --- a/Kernel/TTime.h +++ b/Kernel/TTime.h @@ -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; diff --git a/Kernel/Time.cpp b/Kernel/Time.cpp index 029612e5..dece4326 100644 --- a/Kernel/Time.cpp +++ b/Kernel/Time.cpp @@ -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) diff --git a/Platform/GD32F1x0/Power.cpp b/Platform/GD32F1x0/Power.cpp index 9cfaa1eb..4cfe0395 100644 --- a/Platform/GD32F1x0/Power.cpp +++ b/Platform/GD32F1x0/Power.cpp @@ -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(); } diff --git a/Platform/STM32F1/Power.cpp b/Platform/STM32F1/Power.cpp index 9cfaa1eb..4cfe0395 100644 --- a/Platform/STM32F1/Power.cpp +++ b/Platform/STM32F1/Power.cpp @@ -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(); }