diff --git a/module-bsp/board/linux/CMakeLists.txt b/module-bsp/board/linux/CMakeLists.txt index 7bd2d8470..40fbacf74 100644 --- a/module-bsp/board/linux/CMakeLists.txt +++ b/module-bsp/board/linux/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(module-bsp keypad_backlight/keypad_backlight.cpp light_sensor/light_sensor.cpp lpm/LinuxLPM.cpp + lpm/PowerProfile.cpp magnetometer/magnetometer.cpp rtc/rtc.cpp torch/torch.cpp diff --git a/module-bsp/board/linux/lpm/PowerProfile.cpp b/module-bsp/board/linux/lpm/PowerProfile.cpp new file mode 100644 index 000000000..c7827e09e --- /dev/null +++ b/module-bsp/board/linux/lpm/PowerProfile.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +namespace bsp +{ + const PowerProfile getPowerProfile() + { + PowerProfile linuxPowerProfile; + + linuxPowerProfile.frequencyShiftLowerThreshold = 40; + linuxPowerProfile.frequencyShiftUpperThreshold = 60; + linuxPowerProfile.maxBelowThresholdCount = 30; + linuxPowerProfile.maxBelowThresholdInRowCount = 10; + linuxPowerProfile.maxAboveThresholdCount = 3; + linuxPowerProfile.minimalFrequency = CpuFrequencyHz::Level_1; + linuxPowerProfile.frequencyIncreaseIntermediateStep = false; + + return linuxPowerProfile; + } +} // namespace bsp diff --git a/module-bsp/board/rt1051/bellpx/CMakeLists.txt b/module-bsp/board/rt1051/bellpx/CMakeLists.txt index 1eb4c3466..52d5b15e5 100644 --- a/module-bsp/board/rt1051/bellpx/CMakeLists.txt +++ b/module-bsp/board/rt1051/bellpx/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources( bsp/bell_temp_sensor/bell_temp_sensor.cpp bsp/battery-charger/battery-charger.cpp bsp/fuel_gauge/fuel_gauge.cpp + bsp/lpm/PowerProfile.cpp pin_mux.c clock_config.cpp irq_gpio.cpp diff --git a/module-bsp/board/rt1051/bellpx/bsp/fuel_gauge/fuel_gauge.cpp b/module-bsp/board/rt1051/bellpx/bsp/fuel_gauge/fuel_gauge.cpp index 260e27f14..b61d03bd0 100644 --- a/module-bsp/board/rt1051/bellpx/bsp/fuel_gauge/fuel_gauge.cpp +++ b/module-bsp/board/rt1051/bellpx/bsp/fuel_gauge/fuel_gauge.cpp @@ -28,7 +28,7 @@ namespace bsp::fuel_gauge (static_cast(FuelGaugeAlertCapacityPercent) << static_cast(CONFIG::shift)) & static_cast(CONFIG::mask); - constexpr auto POLL_INTERVAL_MS = 60U * 1000U; + constexpr auto POLL_INTERVAL_MS = 5U * 60U * 1000U; enum class CW201xRetCode : int { diff --git a/module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp b/module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp new file mode 100644 index 000000000..7bd05ef1d --- /dev/null +++ b/module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +namespace bsp +{ + const PowerProfile getPowerProfile() + { + PowerProfile bellPowerProfile; + + bellPowerProfile.frequencyShiftLowerThreshold = 50; + bellPowerProfile.frequencyShiftUpperThreshold = 90; + bellPowerProfile.maxBelowThresholdCount = 10; + bellPowerProfile.maxBelowThresholdInRowCount = 5; + bellPowerProfile.maxAboveThresholdCount = 3; + bellPowerProfile.minimalFrequency = CpuFrequencyHz::Level_0; + bellPowerProfile.frequencyIncreaseIntermediateStep = true; + + return bellPowerProfile; + } +} // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp index c74ad290f..eb88426ef 100644 --- a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp @@ -15,6 +15,14 @@ namespace bsp DCDC_AdjustTargetVoltage(DCDC, VDDRun_1275_mV, VDDStandby_925_mV); switch (freq) { + case CpuClock::CpuClock_Osc_4_Mhz: + /* Set PERIPH_CLK2_PODF. */ + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 2); + /* Set AHB_PODF. */ + CLOCK_SetDiv(kCLOCK_AhbDiv, 1); // CBCDR + + DCDC_AdjustTargetVoltage(DCDC, VDDRun_900_mV, VDDStandby_925_mV); + break; case CpuClock::CpuClock_Osc_12_Mhz: /* Set PERIPH_CLK2_PODF. */ CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); @@ -53,7 +61,8 @@ namespace bsp break; } - if (freq == CpuClock::CpuClock_Osc_12_Mhz || freq == CpuClock::CpuClock_Osc_24_Mhz) { + if (freq == CpuClock::CpuClock_Osc_4_Mhz || freq == CpuClock::CpuClock_Osc_12_Mhz || + freq == CpuClock::CpuClock_Osc_24_Mhz) { /* Set periph clock source. */ CLOCK_SetMux(kCLOCK_PeriphMux, 1); } diff --git a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp index a94bd0398..4d8d13d2f 100644 --- a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp +++ b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp @@ -23,6 +23,7 @@ namespace bsp public: enum class CpuClock { + CpuClock_Osc_4_Mhz, CpuClock_Osc_12_Mhz, CpuClock_Osc_24_Mhz, CpuClock_Pll2_66_Mhz, diff --git a/module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp b/module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp index c3bc2e42f..d083a74f9 100644 --- a/module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp @@ -72,6 +72,9 @@ namespace bsp { currentFrequency = freq; switch (freq) { + case bsp::CpuFrequencyHz::Level_0: + CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_4_Mhz); + break; case bsp::CpuFrequencyHz::Level_1: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_12_Mhz); break; diff --git a/module-bsp/board/rt1051/puretx/CMakeLists.txt b/module-bsp/board/rt1051/puretx/CMakeLists.txt index 0ec93a160..0c01050ff 100644 --- a/module-bsp/board/rt1051/puretx/CMakeLists.txt +++ b/module-bsp/board/rt1051/puretx/CMakeLists.txt @@ -15,6 +15,7 @@ target_sources( bsp/battery_charger/battery_charger.cpp bsp/eink/eink_pin_config.cpp bsp/keyboard/keyboard.cpp + bsp/lpm/PowerProfile.cpp pin_mux.c clock_config.cpp irq_gpio.cpp diff --git a/module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp b/module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp new file mode 100644 index 000000000..89b61797d --- /dev/null +++ b/module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +namespace bsp +{ + const PowerProfile getPowerProfile() + { + PowerProfile purePowerProfile; + + purePowerProfile.frequencyShiftLowerThreshold = 40; + purePowerProfile.frequencyShiftUpperThreshold = 60; + purePowerProfile.maxBelowThresholdCount = 30; + purePowerProfile.maxBelowThresholdInRowCount = 10; + purePowerProfile.maxAboveThresholdCount = 3; + purePowerProfile.minimalFrequency = CpuFrequencyHz::Level_1; + purePowerProfile.frequencyIncreaseIntermediateStep = false; + + return purePowerProfile; + } +} // namespace bsp diff --git a/module-bsp/bsp/common.hpp b/module-bsp/bsp/common.hpp index c410b178e..c4a6039fe 100644 --- a/module-bsp/bsp/common.hpp +++ b/module-bsp/bsp/common.hpp @@ -15,6 +15,7 @@ namespace bsp /// Only a few thresholds are available in the current configuration enum class CpuFrequencyHz { + Level_0 = 4000000, Level_1 = 12000000, Level_2 = 24000000, Level_3 = 66000000, diff --git a/module-bsp/bsp/lpm/PowerProfile.hpp b/module-bsp/bsp/lpm/PowerProfile.hpp new file mode 100644 index 000000000..c2987358f --- /dev/null +++ b/module-bsp/bsp/lpm/PowerProfile.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include + +namespace bsp +{ + struct PowerProfile + { + std::uint32_t frequencyShiftLowerThreshold; + std::uint32_t frequencyShiftUpperThreshold; + std::uint32_t maxBelowThresholdCount; + std::uint32_t maxBelowThresholdInRowCount; + std::uint32_t maxAboveThresholdCount; + CpuFrequencyHz minimalFrequency; + bool frequencyIncreaseIntermediateStep; + }; + + const PowerProfile getPowerProfile(); +} // namespace bsp diff --git a/module-sys/SystemManager/CpuGovernor.cpp b/module-sys/SystemManager/CpuGovernor.cpp index 05a6983c0..66be6aa5d 100644 --- a/module-sys/SystemManager/CpuGovernor.cpp +++ b/module-sys/SystemManager/CpuGovernor.cpp @@ -9,7 +9,7 @@ namespace sys { GovernorSentinel::GovernorSentinel(std::shared_ptr newSentinel) - : sentinelPtr(newSentinel), requestedFrequency(bsp::CpuFrequencyHz::Level_1) + : sentinelPtr(newSentinel), requestedFrequency(bsp::CpuFrequencyHz::Level_0) {} [[nodiscard]] auto GovernorSentinel::GetSentinel() const noexcept -> SentinelPointer @@ -77,12 +77,12 @@ namespace sys void CpuGovernor::ResetCpuFrequencyRequest(std::string sentinelName) { - SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyHz::Level_1); + SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyHz::Level_0); } [[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() const noexcept -> bsp::CpuFrequencyHz { - bsp::CpuFrequencyHz minFrequency = bsp::CpuFrequencyHz::Level_1; + bsp::CpuFrequencyHz minFrequency = bsp::CpuFrequencyHz::Level_0; for (auto &sentinel : sentinels) { const auto sentinelFrequency = sentinel->GetRequestedFrequency(); diff --git a/module-sys/SystemManager/CpuSentinel.cpp b/module-sys/SystemManager/CpuSentinel.cpp index 70153f857..b0b7ff52a 100644 --- a/module-sys/SystemManager/CpuSentinel.cpp +++ b/module-sys/SystemManager/CpuSentinel.cpp @@ -29,10 +29,10 @@ namespace sys void CpuSentinel::ReleaseMinimumFrequency() { - if (currentFrequencyToHold != bsp::CpuFrequencyHz::Level_1) { + if (currentFrequencyToHold != bsp::CpuFrequencyHz::Level_0) { auto msg = std::make_shared(GetName()); owner->bus.sendUnicast(std::move(msg), service::name::system_manager); - currentFrequencyToHold = bsp::CpuFrequencyHz::Level_1; + currentFrequencyToHold = bsp::CpuFrequencyHz::Level_0; } } diff --git a/module-sys/SystemManager/PowerManager.cpp b/module-sys/SystemManager/PowerManager.cpp index 15a7e2e75..bb7f9b5b4 100644 --- a/module-sys/SystemManager/PowerManager.cpp +++ b/module-sys/SystemManager/PowerManager.cpp @@ -9,11 +9,6 @@ namespace sys { namespace { - inline constexpr uint32_t frequencyShiftLowerThreshold{40}; - inline constexpr uint32_t frequencyShiftUpperThreshold{60}; - inline constexpr uint32_t maxBelowThresholdCount{30}; - inline constexpr uint32_t maxBelowThresholdInRowCount{10}; - inline constexpr uint32_t maxAboveThresholdCount{3}; constexpr auto lowestLevelName{"lowestCpuFrequency"}; constexpr auto middleLevelName{"middleCpuFrequency"}; constexpr auto highestLevelName{"highestCpuFrequency"}; @@ -38,7 +33,7 @@ namespace sys totalTicksCount += ticks; } - PowerManager::PowerManager() + PowerManager::PowerManager() : powerProfile{bsp::getPowerProfile()} { lowPowerControl = bsp::LowPowerMode::Create().value_or(nullptr); driverSEMC = drivers::DriverSEMC::Create("ExternalRAM"); @@ -81,11 +76,12 @@ namespace sys const auto currentCpuFreq = lowPowerControl->GetCurrentFrequencyLevel(); const auto minFrequencyRequested = cpuGovernor->GetMinimumFrequencyRequested(); - if (cpuLoad > frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyHz::Level_6) { + if (cpuLoad > powerProfile.frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyHz::Level_6) { aboveThresholdCounter++; belowThresholdCounter = 0; } - else if (cpuLoad < frequencyShiftLowerThreshold && currentCpuFreq > bsp::CpuFrequencyHz::Level_1) { + else if (cpuLoad < powerProfile.frequencyShiftLowerThreshold && + currentCpuFreq > powerProfile.minimalFrequency) { belowThresholdCounter++; aboveThresholdCounter = 0; } @@ -101,13 +97,19 @@ namespace sys ResetFrequencyShiftCounter(); IncreaseCpuFrequency(minFrequencyRequested); } - else if (aboveThresholdCounter >= maxAboveThresholdCount) { - ResetFrequencyShiftCounter(); - IncreaseCpuFrequency(bsp::CpuFrequencyHz::Level_6); + else if (aboveThresholdCounter >= powerProfile.maxAboveThresholdCount) { + if (powerProfile.frequencyIncreaseIntermediateStep && currentCpuFreq < bsp::CpuFrequencyHz::Level_4) { + ResetFrequencyShiftCounter(); + IncreaseCpuFrequency(bsp::CpuFrequencyHz::Level_4); + } + else { + ResetFrequencyShiftCounter(); + IncreaseCpuFrequency(bsp::CpuFrequencyHz::Level_6); + } } else { - if (belowThresholdCounter >= - (isFrequencyLoweringInProgress ? maxBelowThresholdInRowCount : maxBelowThresholdCount) && + if (belowThresholdCounter >= (isFrequencyLoweringInProgress ? powerProfile.maxBelowThresholdInRowCount + : powerProfile.maxBelowThresholdCount) && currentCpuFreq > minFrequencyRequested) { ResetFrequencyShiftCounter(); DecreaseCpuFrequency(); @@ -119,7 +121,7 @@ namespace sys { const auto freq = lowPowerControl->GetCurrentFrequencyLevel(); - if (freq == bsp::CpuFrequencyHz::Level_1) { + if ((freq <= bsp::CpuFrequencyHz::Level_1) && (newFrequency > bsp::CpuFrequencyHz::Level_1)) { // connect internal the load resistor lowPowerControl->ConnectInternalLoadResistor(); // turn off power save mode for DCDC inverter @@ -148,7 +150,7 @@ namespace sys void PowerManager::DecreaseCpuFrequency() { const auto freq = lowPowerControl->GetCurrentFrequencyLevel(); - auto level = bsp::CpuFrequencyHz::Level_1; + auto level = powerProfile.minimalFrequency; switch (freq) { case bsp::CpuFrequencyHz::Level_6: @@ -164,9 +166,11 @@ namespace sys level = bsp::CpuFrequencyHz::Level_2; break; case bsp::CpuFrequencyHz::Level_2: - level = bsp::CpuFrequencyHz::Level_1; + level = powerProfile.minimalFrequency; break; case bsp::CpuFrequencyHz::Level_1: + [[fallthrough]]; + case bsp::CpuFrequencyHz::Level_0: break; } @@ -175,7 +179,7 @@ namespace sys SetCpuFrequency(level); } - if (level == bsp::CpuFrequencyHz::Level_1) { + if (level <= bsp::CpuFrequencyHz::Level_1) { // Enable weak 2P5 and 1P1 LDO and Turn off regular 2P5 and 1P1 LDO lowPowerControl->SwitchToLowPowerModeLDO(); @@ -233,7 +237,7 @@ namespace sys void PowerManager::UpdateCpuFrequencyMonitor(bsp::CpuFrequencyHz currentFreq) { auto ticks = xTaskGetTickCount(); - auto levelName = currentFreq == bsp::CpuFrequencyHz::Level_1 + auto levelName = currentFreq == powerProfile.minimalFrequency ? lowestLevelName : (currentFreq == bsp::CpuFrequencyHz::Level_6 ? highestLevelName : middleLevelName); diff --git a/module-sys/SystemManager/SystemManagerCommon.cpp b/module-sys/SystemManager/SystemManagerCommon.cpp index 1cdb92e1e..4ee76e2b9 100644 --- a/module-sys/SystemManager/SystemManagerCommon.cpp +++ b/module-sys/SystemManager/SystemManagerCommon.cpp @@ -670,7 +670,7 @@ namespace sys void SystemManagerCommon::UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency) { - if (newFrequency == bsp::CpuFrequencyHz::Level_1) { + if (newFrequency <= bsp::CpuFrequencyHz::Level_1) { purefs::subsystem::disk_mgr()->pm_control(purefs::blkdev::pm_state::suspend); } else { diff --git a/module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp b/module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp index 6fa5d99dc..3f5908703 100644 --- a/module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp +++ b/module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp @@ -31,7 +31,7 @@ namespace sys protected: const std::string name; - bsp::CpuFrequencyHz currentFrequencyToHold{bsp::CpuFrequencyHz::Level_1}; + bsp::CpuFrequencyHz currentFrequencyToHold{bsp::CpuFrequencyHz::Level_0}; sys::Service *owner{nullptr}; /// function called from the PowerManager context diff --git a/module-sys/SystemManager/include/SystemManager/PowerManager.hpp b/module-sys/SystemManager/include/SystemManager/PowerManager.hpp index 559f965ee..e22572eb4 100644 --- a/module-sys/SystemManager/include/SystemManager/PowerManager.hpp +++ b/module-sys/SystemManager/include/SystemManager/PowerManager.hpp @@ -9,6 +9,7 @@ #include "bsp/lpm/bsp_lpm.hpp" #include "drivers/semc/DriverSEMC.hpp" #include "CpuGovernor.hpp" +#include #include namespace sys @@ -78,6 +79,7 @@ namespace sys std::unique_ptr lowPowerControl; std::shared_ptr driverSEMC; std::unique_ptr cpuGovernor; + const bsp::PowerProfile powerProfile; }; } // namespace sys diff --git a/module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp b/module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp index 93a25638a..ffb009287 100644 --- a/module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp +++ b/module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp @@ -39,7 +39,7 @@ TEST_CASE("Power Manager CPU sentinels governor test") governor->RegisterNewSentinel(testSentinel_1); governor->RegisterNewSentinel(testSentinel_2); - REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_1); + REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_0); governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyHz::Level_4); REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_4); @@ -56,7 +56,10 @@ TEST_CASE("Power Manager CPU sentinels governor test") governor->SetCpuFrequencyRequest("bedNameSentinel", bsp::CpuFrequencyHz::Level_6); REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_2); - governor->ResetCpuFrequencyRequest("testSentinel_1"); + governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyHz::Level_1); REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_1); + + governor->ResetCpuFrequencyRequest("testSentinel_1"); + REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_0); } } diff --git a/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp b/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp index b6024a4d4..e1b50b6cd 100644 --- a/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp +++ b/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp @@ -29,7 +29,7 @@ namespace sys private: std::string sentinelName; - bsp::CpuFrequencyHz frequencyRequested = bsp::CpuFrequencyHz::Level_1; + bsp::CpuFrequencyHz frequencyRequested = bsp::CpuFrequencyHz::Level_0; }; class ReleaseCpuFrequencyMessage : public sys::DataMessage diff --git a/products/BellHybrid/EinkSentinelBell.cpp b/products/BellHybrid/EinkSentinelBell.cpp index c87b29a35..64739cd4e 100644 --- a/products/BellHybrid/EinkSentinelBell.cpp +++ b/products/BellHybrid/EinkSentinelBell.cpp @@ -9,7 +9,7 @@ namespace service::eink { namespace { - constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyHz::Level_6; + constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyHz::Level_5; } // namespace EinkSentinel::EinkSentinel(std::string name, sys::Service *service) : sys::CpuSentinel(name, service)