From 3cbbeff551230786ae13c23a7bf4fa8c50099896 Mon Sep 17 00:00:00 2001 From: Lefucjusz Date: Thu, 7 Sep 2023 14:27:00 +0200 Subject: [PATCH] [MOS-1011] Fix frequency switching stability Multiple fixes of clock switching related stability issues: * added RC oscillator hysteresis as in NXP example; * changed DCDC converter config; * configure PLL2 to be able to run on any CPU frequency level; * added switching to 1.275V (overdrive) voltage when applying any clock change above 12MHz as well as LDO or bandgap switching, as done in Mbed OS' lpm.c for RT1050; * changed BMCR AXI queues weighs for SDRAM in JLink scripts to disable operations reordering, as it is known to cause data integrity issues; * extracted some code to separate files; * smaller or bigger code cleanups. --- evkbimxrt1050_sdram_init.jlinkscript | 4 +- evkbimxrt1050_sdram_init_T6.jlinkscript | 24 ++-- harmony_changelog.md | 1 + .../windows/advanced/CPUModeTestWindow.cpp | 10 +- module-bsp/board/linux/lpm/LinuxLPM.cpp | 22 +--- module-bsp/board/linux/lpm/LinuxLPM.h | 16 +-- module-bsp/board/rt1051/CMakeLists.txt | 5 +- .../board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp | 15 --- .../board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp | 5 +- module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp | 11 +- .../board/rt1051/bsp/lpm/CpuFreqLPM.cpp | 2 +- .../board/rt1051/bsp/lpm/CpuFreqLPM.hpp | 1 + module-bsp/board/rt1051/bsp/lpm/DCDC.cpp | 48 +++++++ module-bsp/board/rt1051/bsp/lpm/DCDC.hpp | 11 ++ module-bsp/board/rt1051/bsp/lpm/LDO.cpp | 62 +++++++++ module-bsp/board/rt1051/bsp/lpm/LDO.hpp | 10 ++ .../board/rt1051/bsp/lpm/Oscillator.cpp | 71 ++++++---- .../board/rt1051/bsp/lpm/Oscillator.hpp | 6 +- .../board/rt1051/bsp/lpm/RT1051LPMCommon.cpp | 122 +++++++----------- .../board/rt1051/bsp/lpm/RT1051LPMCommon.hpp | 14 +- module-bsp/board/rt1051/common/board.cpp | 6 - .../rt1051/drivers/RT1051DriverOscillator.cpp | 4 +- .../board/rt1051/drivers/RT1051DriverPLL2.cpp | 49 +++++-- .../board/rt1051/drivers/RT1051DriverPLL2.hpp | 10 +- .../board/rt1051/drivers/RT1051DriverPWM.cpp | 6 +- .../board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp | 41 +++--- .../board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp | 4 - module-bsp/bsp/common.cpp | 54 ++++---- module-bsp/bsp/common.hpp | 22 ++-- module-bsp/bsp/lpm/bsp_lpm.hpp | 11 +- module-sys/SystemManager/PowerManager.cpp | 8 +- .../SystemManager/SystemManagerCommon.cpp | 14 +- .../cpu/algorithm/FrequencyStepping.cpp | 4 +- .../include/SystemManager/PowerManager.hpp | 8 +- .../messages/RequestCpuFrequencyMessage.hpp | 14 +- pure_changelog.md | 1 + 36 files changed, 399 insertions(+), 317 deletions(-) create mode 100644 module-bsp/board/rt1051/bsp/lpm/DCDC.cpp create mode 100644 module-bsp/board/rt1051/bsp/lpm/DCDC.hpp create mode 100644 module-bsp/board/rt1051/bsp/lpm/LDO.cpp create mode 100644 module-bsp/board/rt1051/bsp/lpm/LDO.hpp diff --git a/evkbimxrt1050_sdram_init.jlinkscript b/evkbimxrt1050_sdram_init.jlinkscript index ce4dc6cb88e32de0755bd3bb8f0edc8441dfae28..7a4c70812729789c73f24937c791ae548055dfdb 100644 --- a/evkbimxrt1050_sdram_init.jlinkscript +++ b/evkbimxrt1050_sdram_init.jlinkscript @@ -187,8 +187,8 @@ void SDRAM_Init() { // Config SDR Controller Registers/ MEM_WriteU32(0x402F0000,0x10000004); // MCR - MEM_WriteU32(0x402F0008,0x20200E44); // BMCR0 - MEM_WriteU32(0x402F000C,0x20200E40); // BMCR1 + MEM_WriteU32(0x402F0008,0x00000081); // BMCR0 + MEM_WriteU32(0x402F000C,0x00000081); // BMCR1 MEM_WriteU32(0x402F0010,0x8000001D); // BR0, 64MB OK MEM_WriteU32(0x402F0040,0x00000E31); // SDRAMCR0 OK MEM_WriteU32(0x402F0044,0x00774D22); // SDRAMCR1 diff --git a/evkbimxrt1050_sdram_init_T6.jlinkscript b/evkbimxrt1050_sdram_init_T6.jlinkscript index c9f0aaae9a12e47a318e6dbe939782b9050f3581..43cba99c92effd698d49d8732c44200ae52f0053 100644 --- a/evkbimxrt1050_sdram_init_T6.jlinkscript +++ b/evkbimxrt1050_sdram_init_T6.jlinkscript @@ -239,21 +239,21 @@ void SDRAM_SEMC_Init(void) reg_val |= 0x00000002; MEM_WriteU32(SEMC_MCR, reg_val); - /* Configure queues for AXI bus: + /* Configure queues for AXI bus as suggested in https://community.nxp.com/t5/i-MX-RT/i-MXRT1060-SEMC-SDRAM-Data-Corruption/m-p/11696908: * Queue A: - * WQOS = 4; - * WAGE = 2; - * WSH = 3; - * WRWS = 5 */ - MEM_WriteU32(SEMC_BMCR0, 0x00030524); + * WQOS = 1; + * WAGE = 8; + * WSH = 0; + * WRWS = 0 */ + MEM_WriteU32(SEMC_BMCR0, 0x00000081); /* Queue B: - * WQOS = 4; - * WAGE = 2; - * WPH = 3; - * WRWS = 5; - * WBR = 6 */ - MEM_WriteU32(SEMC_BMCR1, 0x06050324); + * WQOS = 1; + * WAGE = 8; + * WPH = 0; + * WRWS = 0; + * WBR = 0 */ + MEM_WriteU32(SEMC_BMCR1, 0x00000081); /* Configure MCR: * set bus timeout cycles to 0x10; diff --git a/harmony_changelog.md b/harmony_changelog.md index c155e316c534ace51d6d9e63bf07880bf8ae9648..8ec9657767f7fd79771048d014796ffa4d79111c 100644 --- a/harmony_changelog.md +++ b/harmony_changelog.md @@ -52,6 +52,7 @@ * General improvement in Eink display and error handling * Changed the "Turn off Harmony" popup display time to 10 seconds * The default year has been updated to 2023 +* Improved device stability related to frequency scaling ## [2.0.0 2023-06-29] diff --git a/module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp b/module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp index bfd157dd1fa0732733bf37a065b21b8445f9b9b2..15e9bc22b91c0f3c60b9da46a639e9b7aa8153d8 100644 --- a/module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp +++ b/module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "CPUModeTestWindow.hpp" @@ -134,9 +134,9 @@ namespace gui permanentFreqSpinner = new gui::TextSpinnerBox(permanentFreqBody, {"OFF", "ON"}, Boundaries::Continuous); permanentFreqSpinner->setMinimumSize(100, 30); auto ret = - application->async_call(service::name::system_manager); + application->async_call(service::name::system_manager); application->sync(ret); - permanentFreqSpinner->setCurrentValue(ret.getResult().pernament ? "ON" : "OFF"); + permanentFreqSpinner->setCurrentValue(ret.getResult().permanent ? "ON" : "OFF"); permanentFreqBody->inputCallback = [&](Item &item, const InputEvent &event) { auto ret = permanentFreqSpinner->onInput(event); @@ -193,10 +193,10 @@ namespace gui newFreqBody->inputCallback = [&](Item &item, const InputEvent &event) { auto ret = currentFreqSpinner->onInput(event); - auto async = application->async_call( + auto async = application->async_call( service::name::system_manager); application->sync(async); - if (async.getResult().pernament) { + if (async.getResult().permanent) { application->bus.sendUnicastSync( std::make_shared( magic_enum::enum_cast(std::stoi(currentFreqSpinner->getCurrentValue())) diff --git a/module-bsp/board/linux/lpm/LinuxLPM.cpp b/module-bsp/board/linux/lpm/LinuxLPM.cpp index b1bd221d0fc22ca42f7b8aeb05dc7e61d4abac03..046cec64ae62c3a3cef9bc34f445e82a34fde612 100644 --- a/module-bsp/board/linux/lpm/LinuxLPM.cpp +++ b/module-bsp/board/linux/lpm/LinuxLPM.cpp @@ -1,36 +1,31 @@ // Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -// -// Created by mati on 09.09.2019. -// - #include "LinuxLPM.h" namespace bsp { - - int32_t LinuxLPM::PowerOff() + std::int32_t LinuxLPM::PowerOff() { return 0; } - int32_t LinuxLPM::Reboot(RebootType) + std::int32_t LinuxLPM::Reboot([[maybe_unused]] RebootType reason) { return 0; } - void LinuxLPM::SetCpuFrequency(bsp::CpuFrequencyMHz freq) + void LinuxLPM::SetCpuFrequency(CpuFrequencyMHz freq) { currentFrequency = freq; } - uint32_t LinuxLPM::GetCpuFrequency() const noexcept + std::uint32_t LinuxLPM::GetCpuFrequency() const noexcept { return 0; } - void LinuxLPM::SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource source) + void LinuxLPM::SwitchOscillatorSource(LowPowerMode::OscillatorSource source) {} void LinuxLPM::EnableDcdcPowerSaveMode() @@ -38,11 +33,4 @@ namespace bsp void LinuxLPM::DisableDcdcPowerSaveMode() {} - - void LinuxLPM::SwitchToRegularModeLDO() - {} - - void LinuxLPM::SwitchToLowPowerModeLDO() - {} - } // namespace bsp diff --git a/module-bsp/board/linux/lpm/LinuxLPM.h b/module-bsp/board/linux/lpm/LinuxLPM.h index f7864847c22e0d79d4f8ef34739a7ccd3765c209..57238788b5a830fb086d01aee348e5b9e8a5fff4 100644 --- a/module-bsp/board/linux/lpm/LinuxLPM.h +++ b/module-bsp/board/linux/lpm/LinuxLPM.h @@ -1,30 +1,22 @@ // Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#ifndef PUREPHONE_LINUXLPM_H -#define PUREPHONE_LINUXLPM_H +#pragma once #include "bsp/lpm/bsp_lpm.hpp" namespace bsp { - class LinuxLPM : public LowPowerMode { public: - int32_t PowerOff() override final; - int32_t Reboot(RebootType reason) override final; + std::int32_t PowerOff() override final; + std::int32_t Reboot(RebootType reason) override final; void SetCpuFrequency(CpuFrequencyMHz freq) final; - [[nodiscard]] uint32_t GetCpuFrequency() const noexcept final; + [[nodiscard]] std::uint32_t GetCpuFrequency() const noexcept final; void SwitchOscillatorSource(OscillatorSource source) final; void EnableDcdcPowerSaveMode() final; void DisableDcdcPowerSaveMode() final; - - void SwitchToRegularModeLDO() final; - void SwitchToLowPowerModeLDO() final; }; - } // namespace bsp - -#endif // PUREPHONE_LINUXLPM_H diff --git a/module-bsp/board/rt1051/CMakeLists.txt b/module-bsp/board/rt1051/CMakeLists.txt index 2b62c5597f5a1b2c73e1da92b0c08401d7fc0977..88022f23185fba07c169ed27c8bafac0e111c447 100644 --- a/module-bsp/board/rt1051/CMakeLists.txt +++ b/module-bsp/board/rt1051/CMakeLists.txt @@ -1,7 +1,6 @@ # Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. # For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - target_sources(module-bsp PRIVATE bluetooth/BlueKitchen.cpp @@ -28,6 +27,8 @@ target_sources(module-bsp bsp/lpm/Oscillator.cpp bsp/lpm/RT1051LPMCommon.cpp bsp/lpm/Bandgap.cpp + bsp/lpm/LDO.cpp + bsp/lpm/DCDC.cpp bsp/magnetometer/ALS31300.cpp bsp/pit/pit.cpp bsp/trng/trng.cpp @@ -74,6 +75,8 @@ set_source_files_properties( target_compile_definitions(module-bsp PUBLIC USB_STACK_FREERTOS) +target_compile_definitions(module-bsp PRIVATE BOARD_${PRODUCT}=1) + add_subdirectory(common/fsl_drivers) add_subdirectory(os) add_subdirectory(${BOARD}) diff --git a/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp b/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp index 0d474dafa821cbb98ad58c901719a40a0ad39a8c..912b7a531366269fd764f2a8b54e33221abff17b 100644 --- a/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp +++ b/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp @@ -2,8 +2,6 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051LPM.hpp" -#include -#include namespace bsp { @@ -12,17 +10,4 @@ namespace bsp void RT1051LPM::DisableDcdcPowerSaveMode() {} - - void RT1051LPM::SwitchToRegularModeLDO() - { - RT1051LPMCommon::RegularLDOMode(); - NVIC_ClearPendingIRQ(ANATOP_EVENT0_IRQn); - EnableIRQ(ANATOP_EVENT0_IRQn); - } - - void RT1051LPM::SwitchToLowPowerModeLDO() - { - DisableIRQ(ANATOP_EVENT0_IRQn); - RT1051LPMCommon::LowPowerLDOMode(); - } } // namespace bsp diff --git a/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp b/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp index 4aac802b8ccaaf30dbbf860e18e64830235b875d..c565f42be6fc8db9a46772108e68ed6fcfc9e55f 100644 --- a/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp +++ b/module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp @@ -2,6 +2,7 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once + #include namespace bsp @@ -11,9 +12,5 @@ namespace bsp public: void EnableDcdcPowerSaveMode() final; void DisableDcdcPowerSaveMode() final; - - void SwitchToRegularModeLDO() final; - void SwitchToLowPowerModeLDO() final; }; - } // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp b/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp index b6c465a2c8548c386a99f1b92f49b7afb7201278..136f2e194672f50849523fc948fd6e08cdac33d6 100644 --- a/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp @@ -4,6 +4,7 @@ #include "Bandgap.hpp" #include #include +#include namespace { @@ -14,6 +15,8 @@ namespace bsp::bandgap { void SwitchToRegularMode() { + cpp_freertos::CriticalSection::Enter(); + /* Enable regular bandgap and wait for it to stabilize */ CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_REFTOP_VBGUP_MASK) == 0) {} @@ -21,15 +24,21 @@ namespace bsp::bandgap /* Disable low power bandgap */ XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; PMU->MISC0_CLR = REFTOP_LOWPOWER_MASK; + + cpp_freertos::CriticalSection::Exit(); } void SwitchToLowPowerMode() { + cpp_freertos::CriticalSection::Enter(); + /* Enable low power bandgap */ PMU->MISC0_SET = REFTOP_LOWPOWER_MASK; + XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; /* Disable regular bandgap */ - XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; PMU->MISC0_SET = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + + cpp_freertos::CriticalSection::Exit(); } } // namespace bsp::bandgap diff --git a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp index c7b055eeff9f564cae0dd6bad5e422fe3d3b177d..25946d9a3e2ca0107744451049e953d0ca7734a0 100644 --- a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp @@ -2,7 +2,7 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "CpuFreqLPM.hpp" -#include "fsl_dcdc.h" +#include namespace bsp { diff --git a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp index c6e6c0b47b36cd0248c7eb8d74fa0dc23b3bb1de..d1f96d4637d4e2bb8a0ed6c844b9fb0ed406c4ea 100644 --- a/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp +++ b/module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp @@ -9,6 +9,7 @@ namespace bsp { inline constexpr std::uint32_t VDDRun_950_mV = 0x06; inline constexpr std::uint32_t VDDRun_1150_mV = 0x0E; + inline constexpr std::uint32_t VDDRun_1275_mV = 0x13; inline constexpr std::uint32_t VDDStandby_925_mV = 0x01; diff --git a/module-bsp/board/rt1051/bsp/lpm/DCDC.cpp b/module-bsp/board/rt1051/bsp/lpm/DCDC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf220d5bf08d7340a6a38614808ac1bceadd884b --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/DCDC.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "DCDC.hpp" +#include "CpuFreqLPM.hpp" +#include + +namespace bsp::dcdc +{ + void SwitchToOverdriveConfig() + { + /* Switch to CCM mode for improved stability */ + DCDC_BootIntoCCM(DCDC); + + /* Connect internal DCDC load resistor */ + DCDC->REG1 |= DCDC_REG1_REG_RLOAD_SW_MASK; + + /* Adjust target voltage to 1.275V */ + DCDC_AdjustTargetVoltage(DCDC, VDDRun_1275_mV, VDDStandby_925_mV); + + /* Disable FET ODRIVE */ + PMU->REG_CORE_CLR = PMU_REG_CORE_FET_ODRIVE_MASK; + } + + void SwitchToRegularConfig() + { + /* Adjust target voltage to 1.15V */ + DCDC_AdjustTargetVoltage(DCDC, VDDRun_1150_mV, VDDStandby_925_mV); + } + + void SwitchToLowPowerConfig() + { + /* Adjust target voltage to nominal 0.95V */ + DCDC_AdjustTargetVoltage(DCDC, VDDRun_950_mV, VDDStandby_925_mV); + + /* Switch to DCM mode to reduce current consumption */ + DCDC_BootIntoDCM(DCDC); + + /* Disconnect internal DCDC load resistor */ + DCDC->REG1 &= ~DCDC_REG1_REG_RLOAD_SW_MASK; + + /* Power down output range comparator */ + DCDC->REG0 |= DCDC_REG0_PWD_CMP_OFFSET_MASK; + + /* Enable FET ODRIVE */ + PMU->REG_CORE_SET = PMU_REG_CORE_FET_ODRIVE_MASK; + } +} // namespace bsp::dcdc diff --git a/module-bsp/board/rt1051/bsp/lpm/DCDC.hpp b/module-bsp/board/rt1051/bsp/lpm/DCDC.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bab373bdf3f18c62797779efff4f35ebbe5f4a96 --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/DCDC.hpp @@ -0,0 +1,11 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +namespace bsp::dcdc +{ + void SwitchToOverdriveConfig(); + void SwitchToRegularConfig(); + void SwitchToLowPowerConfig(); +} // namespace bsp::dcdc diff --git a/module-bsp/board/rt1051/bsp/lpm/LDO.cpp b/module-bsp/board/rt1051/bsp/lpm/LDO.cpp new file mode 100644 index 0000000000000000000000000000000000000000..527e779608857819a14d9b45f955601eaee13e63 --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/LDO.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "LDO.hpp" +#include +#include + +namespace +{ + constexpr auto ldoStabilizationDelayUs{40}; +} + +namespace bsp::ldo +{ + void SwitchToRegularMode() + { + cpp_freertos::CriticalSection::Enter(); + + /* Enable regular 2P5 and disable weak 2P5 LDO */ + PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_LINREG_MASK; + PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; + + /* Wait for regular 2P5 to become stable (documentation Low Power AN12085) */ + while ((PMU->REG_2P5 & PMU_REG_2P5_OK_VDD2P5_MASK) == 0) {} + + /* Enable regular 1P1 and disable weak 1P1 LDO */ + PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_LINREG_MASK; + PMU->REG_1P1_CLR = PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; + + /* Wait for regular 1P1 to become stable (documentation Low Power AN12085) */ + while ((PMU->REG_1P1 & PMU_REG_1P1_OK_VDD1P1_MASK) == 0) {} + + cpp_freertos::CriticalSection::Exit(); + +#if BOARD_BellHybrid == 1 + NVIC_ClearPendingIRQ(ANATOP_EVENT0_IRQn); + EnableIRQ(ANATOP_EVENT0_IRQn); +#endif + } + + void SwitchToLowPowerMode() + { +#if BOARD_BellHybrid == 1 + DisableIRQ(ANATOP_EVENT0_IRQn); +#endif + + cpp_freertos::CriticalSection::Enter(); + + /* Enable weak 2P5 and disable regular 2P5 LDO */ + PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; + PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_LINREG_MASK; + + /* Enable weak 1P1 and disable regular 1P1 LDO */ + PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; + PMU->REG_1P1_CLR = PMU_REG_1P1_ENABLE_LINREG_MASK; + + /* Wait for weak LDOs to stabilize */ + SDK_DelayAtLeastUs(ldoStabilizationDelayUs, CLOCK_GetCpuClkFreq()); + + cpp_freertos::CriticalSection::Exit(); + } +} // namespace bsp::ldo diff --git a/module-bsp/board/rt1051/bsp/lpm/LDO.hpp b/module-bsp/board/rt1051/bsp/lpm/LDO.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9d3bbf17548fb457f91c726c118078a16af03a0b --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/LDO.hpp @@ -0,0 +1,10 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +namespace bsp::ldo +{ + void SwitchToRegularMode(); + void SwitchToLowPowerMode(); +} // namespace bsp::ldo diff --git a/module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp b/module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp index 9c19447abc8635a97afc73b09ce5ade8ed1c1c91..6815c84d1bd2c18c57a1b2fd94a532a8e23d692c 100644 --- a/module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp @@ -3,73 +3,92 @@ #include "Oscillator.hpp" #include "ClockState.hpp" +#include #include #include #include -namespace bsp +namespace { - inline constexpr std::uint8_t OscillatorReadyCounterValue{127}; - inline constexpr std::uint32_t CurrentTuningValueInUseForConfig0{0x4}; - inline constexpr std::uint32_t NegativeHysteresisValue{0x2}; - inline constexpr std::uint32_t TuningValue{0xA7}; - inline constexpr std::uint32_t CurrentTuningValueInUseForConfig1{0x40}; - inline constexpr std::uint32_t TargetCountUsedToTune{0x2DC}; + constexpr std::uint8_t oscillatorReadyCounterValue{127}; + constexpr std::uint32_t currentTuningValueInUseForConfig0{0x4}; + constexpr std::uint32_t initialNegativeHysteresisValue{0x2}; + constexpr std::uint32_t negativeHysteresisValue{0x3}; + constexpr std::uint32_t positiveHysteresisValue{0x3}; + constexpr std::uint32_t tuningValue{0xA7}; + constexpr std::uint32_t currentTuningValueInUseForConfig1{0x40}; + constexpr std::uint32_t targetCountUsedToTune{0x2DC}; - inline constexpr std::uint32_t XtalStabilizationTimeUs{200}; - inline constexpr std::uint32_t RcOscStabilizationTimeUs{4000}; + constexpr std::uint32_t xtalStabilizationTimeUs{200}; + constexpr std::uint32_t rcOscStabilizationTimeUs{4000}; +} // namespace - void EnableExternalOscillator() +namespace bsp +{ + void SwitchToExternalOscillator() { + cpp_freertos::CriticalSection::Enter(); if (!IsExternalOscillatorEnabled()) { + /// Init internal oscillator CLOCK_InitExternalClk(false); /// Wait for XTAL to become stable - SDK_DelayAtLeastUs(XtalStabilizationTimeUs, CLOCK_GetCpuClkFreq()); + SDK_DelayAtLeastUs(xtalStabilizationTimeUs, CLOCK_GetCpuClkFreq()); /// Switch DCDC to use DCDC external OSC DCDC_SetClockSource(DCDC, kDCDC_ClockExternalOsc); /// Switch clock source to external OSC. CLOCK_SwitchOsc(kCLOCK_XtalOsc); - /// Wait CCM operation finishes - while (CCM->CDHIPR != 0) {} + /// Deinit internal oscillator + CLOCK_DeinitRcOsc24M(); /// Set Oscillator ready counter value. - CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(bsp::OscillatorReadyCounterValue); + CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(oscillatorReadyCounterValue); } + cpp_freertos::CriticalSection::Exit(); } - void DisableExternalOscillator() + bool SwitchToInternalOscillator() { + cpp_freertos::CriticalSection::Enter(); if (IsExternalOscillatorEnabled()) { if (IsClockEnabled(kCLOCK_Lpuart1) || IsClockEnabled(kCLOCK_Lpuart2) || IsClockEnabled(kCLOCK_Lpuart3) || IsClockEnabled(kCLOCK_Lpuart4) || IsClockEnabled(kCLOCK_Lpuart5) || IsClockEnabled(kCLOCK_Lpuart6) || IsClockEnabled(kCLOCK_Lpuart7) || IsClockEnabled(kCLOCK_Lpuart8)) { - return; + cpp_freertos::CriticalSection::Exit(); + return false; } /// Enable RC OSC. It needs at least 4ms to be stable, so self tuning need to be enabled. - XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; + CLOCK_InitRcOsc24M(); /// Configure self-tuning for RC OSC - XTALOSC24M->OSC_CONFIG0 = XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR(bsp::CurrentTuningValueInUseForConfig0) | - XTALOSC24M_OSC_CONFIG0_SET_HYST_MINUS(bsp::NegativeHysteresisValue) | - XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG(bsp::TuningValue) | + XTALOSC24M->OSC_CONFIG0 = XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR(currentTuningValueInUseForConfig0) | + XTALOSC24M_OSC_CONFIG0_SET_HYST_MINUS(initialNegativeHysteresisValue) | + XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG(tuningValue) | XTALOSC24M_OSC_CONFIG0_START_MASK | XTALOSC24M_OSC_CONFIG0_ENABLE_MASK; - XTALOSC24M->OSC_CONFIG1 = XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR(bsp::CurrentTuningValueInUseForConfig1) | - XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG(bsp::TargetCountUsedToTune); + + XTALOSC24M->OSC_CONFIG1 = XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR(currentTuningValueInUseForConfig1) | + XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG(targetCountUsedToTune); /// Wait for RC OSC to become stable - SDK_DelayAtLeastUs(RcOscStabilizationTimeUs, CLOCK_GetCpuClkFreq()); + SDK_DelayAtLeastUs(rcOscStabilizationTimeUs, CLOCK_GetCpuClkFreq()); + /// Add hysteresis + std::uint32_t oscConfig0Value = XTALOSC24M->OSC_CONFIG0; + oscConfig0Value &= ~(XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK | XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK); + oscConfig0Value |= XTALOSC24M_OSC_CONFIG0_HYST_PLUS(positiveHysteresisValue) | + XTALOSC24M_OSC_CONFIG0_HYST_MINUS(negativeHysteresisValue); + XTALOSC24M->OSC_CONFIG0 = oscConfig0Value; /// Switch DCDC to use DCDC internal OSC DCDC_SetClockSource(DCDC, kDCDC_ClockInternalOsc); /// Switch clock source to internal RC CLOCK_SwitchOsc(kCLOCK_RcOsc); /// Deinit external oscillator CLOCK_DeinitExternalClk(); - /// Wait CCM operation finishes - while (CCM->CDHIPR != 0) {} } + cpp_freertos::CriticalSection::Exit(); + + return true; } [[nodiscard]] bool IsExternalOscillatorEnabled() { - return !(XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_OSC_SEL_MASK); + return not static_cast(XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_OSC_SEL_MASK); } }; // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp b/module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp index 69d9e51a852c3181365a8eeb2136a7d46ace0d99..c506cd9a7e8f6023c46243af9a7b3c275f4d8462 100644 --- a/module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp +++ b/module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp @@ -1,11 +1,11 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once namespace bsp { - void EnableExternalOscillator(); - void DisableExternalOscillator(); + void SwitchToExternalOscillator(); + bool SwitchToInternalOscillator(); [[nodiscard]] bool IsExternalOscillatorEnabled(); } // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp b/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp index a6f3c117a25ad4a22b86fa4a89151f6aefa9dd15..c947a4cca3f990556e31bfe81762b2722eca42e7 100644 --- a/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp +++ b/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp @@ -2,15 +2,13 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051LPMCommon.hpp" - #include #include -#include #include #include "Oscillator.hpp" -#include "critical.hpp" #include "drivers/semc/DriverSEMC.hpp" #include +#include "DCDC.hpp" namespace bsp { @@ -22,13 +20,13 @@ namespace bsp CpuFreq = std::make_unique(); } - int32_t RT1051LPMCommon::PowerOff() + std::int32_t RT1051LPMCommon::PowerOff() { board_power_off(); return 0; } - int32_t RT1051LPMCommon::Reboot(RebootType reason) + std::int32_t RT1051LPMCommon::Reboot(RebootType reason) { switch (reason) { case RebootType::GoToRecoveryUpdate: @@ -62,75 +60,83 @@ namespace bsp Down }; - CpuFrequencyMHz RT1051LPMCommon::onChangeUp(CpuFrequencyMHz freq, bsp::CpuFrequencyMHz newFrequency) + void RT1051LPMCommon::onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency) { if ((freq <= CpuFrequencyMHz::Level_1) && (newFrequency > CpuFrequencyMHz::Level_1)) { - // Switch DCDC to CCM mode to improve stability - DCDC_BootIntoCCM(DCDC); - // Switch external RAM clock source to PLL2 + /* Switch to external crystal oscillator */ + SwitchOscillatorSource(LowPowerMode::OscillatorSource::External); + + /* Switch external RAM clock source to PLL2 */ if (driverSEMC) { driverSEMC->SwitchToPLL2ClockSource(); } - // Enable regular 2P5 and 1P1 LDO, turn off weak 2P5 and 1P1 LDO - SwitchToRegularModeLDO(); - // Switch to external crystal oscillator - SwitchOscillatorSource(LowPowerMode::OscillatorSource::External); } - return newFrequency; } void RT1051LPMCommon::onChangeDown(CpuFrequencyMHz newFrequency) { - if (newFrequency <= bsp::CpuFrequencyMHz::Level_1) { - // Switch to internal RC oscillator - SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::Internal); - // Enable weak 2P5 and 1P1 LDO, turn off regular 2P5 and 1P1 LDO - SwitchToLowPowerModeLDO(); - // Switch external RAM clock source to OSC + if (newFrequency <= CpuFrequencyMHz::Level_1) { + /* Switch to internal RC oscillator */ + SwitchOscillatorSource(LowPowerMode::OscillatorSource::Internal); + + /* Switch external RAM clock source to OSC */ if (driverSEMC) { driverSEMC->SwitchToPeripheralClockSource(); } - // Switch DCDC to DCM mode to reduce current consumption - DCDC_BootIntoDCM(DCDC); } } - void RT1051LPMCommon::SetCpuFrequency(bsp::CpuFrequencyMHz freq) + void RT1051LPMCommon::SetCpuFrequency(CpuFrequencyMHz freq) { if (currentFrequency == freq) { return; } - const Change change = (currentFrequency < freq) ? Change::Up : Change::Down; - if (Change::Up == change) { - freq = onChangeUp(currentFrequency, freq); + + /* Switch to overdrive config for any frequency change above 12MHz */ + const auto isChangeAbove12MHz = + (currentFrequency > CpuFrequencyMHz::Level_1) || (freq > CpuFrequencyMHz::Level_1); + if (isChangeAbove12MHz) { + dcdc::SwitchToOverdriveConfig(); } + + const auto changeDirection = (currentFrequency < freq) ? Change::Up : Change::Down; + if (Change::Up == changeDirection) { + onChangeUp(currentFrequency, freq); + } + switch (freq) { - case bsp::CpuFrequencyMHz::Level_0: + case CpuFrequencyMHz::Level_0: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_4_Mhz); break; - case bsp::CpuFrequencyMHz::Level_1: + case CpuFrequencyMHz::Level_1: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_12_Mhz); break; - case bsp::CpuFrequencyMHz::Level_2: + case CpuFrequencyMHz::Level_2: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_24_Mhz); break; - case bsp::CpuFrequencyMHz::Level_3: + case CpuFrequencyMHz::Level_3: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_66_Mhz); break; - case bsp::CpuFrequencyMHz::Level_4: + case CpuFrequencyMHz::Level_4: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_132_Mhz); break; - case bsp::CpuFrequencyMHz::Level_5: + case CpuFrequencyMHz::Level_5: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_264_Mhz); break; - case bsp::CpuFrequencyMHz::Level_6: + case CpuFrequencyMHz::Level_6: CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_528_Mhz); break; } - if (Change::Down == change) { + /* Switch back to regular config after clock change is done */ + if (isChangeAbove12MHz) { + dcdc::SwitchToRegularConfig(); + } + + if (Change::Down == changeDirection) { onChangeDown(freq); } + LOG_INFO("CPU frequency changed to %lu", CLOCK_GetFreq(kCLOCK_CpuClk)); currentFrequency = freq; } @@ -140,46 +146,16 @@ namespace bsp return CLOCK_GetCpuClkFreq(); } - void RT1051LPMCommon::SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource source) - { - if (source == bsp::LowPowerMode::OscillatorSource::Internal) { - cpp_freertos::CriticalSection::Enter(); - bsp::DisableExternalOscillator(); - cpp_freertos::CriticalSection::Exit(); - } - else if (source == bsp::LowPowerMode::OscillatorSource::External) { - cpp_freertos::CriticalSection::Enter(); - bsp::EnableExternalOscillator(); - cpp_freertos::CriticalSection::Exit(); - } - } - - void RT1051LPMCommon::RegularLDOMode() + void RT1051LPMCommon::SwitchOscillatorSource(LowPowerMode::OscillatorSource source) { - // Enable regular 2P5 and 1P1 LDO - PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_LINREG_MASK; - PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_LINREG_MASK; - - // Wait for regular LDOs to become stable (documentation Low Power AN12085) - while ((PMU->REG_2P5 & PMU_REG_2P5_OK_VDD2P5_MASK) == 0) {} - while ((PMU->REG_1P1 & PMU_REG_1P1_OK_VDD1P1_MASK) == 0) {} - - // Turn off weak 2P5 and 1P1 LDO - PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; - PMU->REG_1P1_CLR = PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; - } - - void RT1051LPMCommon::LowPowerLDOMode() - { - // Enable weak 2P5 and 1P1 LDO - PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; - PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; - - // Wait for 40us for weak LDOs to stabilize - SDK_DelayAtLeastUs(40, CLOCK_GetCpuClkFreq()); + switch (source) { + case LowPowerMode::OscillatorSource::Internal: + SwitchToInternalOscillator(); + break; - // Disable regular 2P5 and 1P1 LDO - PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_LINREG_MASK; - PMU->REG_1P1_CLR = PMU_REG_1P1_ENABLE_LINREG_MASK; + case LowPowerMode::OscillatorSource::External: + SwitchToExternalOscillator(); + break; + } } } // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp b/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp index c93c7d6227997583c2b2e3846f0804681e1304e7..9241bf8ee0c3beb2084dfc7dfb5905098aab7954 100644 --- a/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp +++ b/module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp @@ -13,21 +13,17 @@ namespace bsp { public: RT1051LPMCommon(); - int32_t PowerOff() final; - int32_t Reboot(RebootType reason) final; + std::int32_t PowerOff() final; + std::int32_t Reboot(RebootType reason) final; void SetCpuFrequency(CpuFrequencyMHz freq) final; - [[nodiscard]] uint32_t GetCpuFrequency() const noexcept final; + [[nodiscard]] std::uint32_t GetCpuFrequency() const noexcept final; void SwitchOscillatorSource(OscillatorSource source) final; - void RegularLDOMode(); - void LowPowerLDOMode(); - private: - CpuFrequencyMHz onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency); - void onChangeDown(bsp::CpuFrequencyMHz freq); + void onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency); + void onChangeDown(CpuFrequencyMHz freq); std::unique_ptr CpuFreq; std::shared_ptr driverSEMC; }; - } // namespace bsp diff --git a/module-bsp/board/rt1051/common/board.cpp b/module-bsp/board/rt1051/common/board.cpp index 586eedbd46e7259f30c94feebb6b664f3087d758..7ee24229a530b30ffb78c2072d295cd52edecd8a 100644 --- a/module-bsp/board/rt1051/common/board.cpp +++ b/module-bsp/board/rt1051/common/board.cpp @@ -179,12 +179,6 @@ namespace bsp // SNVS->LPGPR[0] = rebootCode::rebootFailedToBoot; // TODO: Here we can implement boot-time fail detection - // Set internal DCDC to CCM mode, DCM is allowed ONLY in low power modes (see AN12085, 5.3.9, p.33) - DCDC_BootIntoCCM(DCDC); - - // Disconnect DCDC internal load resistor - DCDC->REG1 &= ~DCDC_REG1_REG_RLOAD_SW_MASK; - PrintSystemClocks(); clearAndPrintBootReason(); diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp b/module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp index e41a3ca736d36311587819bb17d9f8ce0efba399..2237ccc78173777d4823cbf175689435160c4b3d 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051DriverOscillator.hpp" @@ -9,7 +9,7 @@ namespace drivers RT1051DriverOscillator::RT1051DriverOscillator() noexcept { - bsp::EnableExternalOscillator(); + bsp::SwitchToExternalOscillator(); } } // namespace drivers diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp index df6df93d1a74e4b55cda3f0e2105effe2d5ebc89..a2a3b1e5b475112a40eeef5cac2824f0315cce5f 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp @@ -3,41 +3,63 @@ #include "RT1051DriverPLL2.hpp" #include "board/rt1051/bsp/lpm/ClockState.hpp" -#include "board/rt1051/bsp/lpm/Bandgap.hpp" #include "board/rt1051/bsp/lpm/CpuFreqLPM.hpp" -#include +#include "board/rt1051/bsp/lpm/Bandgap.hpp" +#include "board/rt1051/bsp/lpm/LDO.hpp" +#include "board/rt1051/bsp/lpm/DCDC.hpp" + +namespace +{ + inline std::uint32_t getCurrentVDDRunVoltage() + { + return (DCDC->REG3 & DCDC_REG3_TRG_MASK); + } +} // namespace namespace drivers { RT1051DriverPLL2::RT1051DriverPLL2() noexcept { if (!IsPLL2Enabled()) { - // Set VDD_SOC_IN to 1.15V required to safely start PLL2 - DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_1150_mV, bsp::VDDStandby_925_mV); + /* Check if switching conditions already met */ + const auto isCurrentVoltageOverdrive = (getCurrentVDDRunVoltage() >= bsp::VDDRun_1275_mV); + if (!isCurrentVoltageOverdrive) { + bsp::dcdc::SwitchToOverdriveConfig(); + } - // Switch to regular bandgap + /* Switch to regular bandgap */ bsp::bandgap::SwitchToRegularMode(); - // Enable PLL2 + /* Switch to regular LDO */ + bsp::ldo::SwitchToRegularMode(); + + /* Switch back to regular config */ + if (!isCurrentVoltageOverdrive) { + bsp::dcdc::SwitchToRegularConfig(); + } + + /* Enable PLL2 */ clkPLL2setup(CLK_ENABLE); } } - RT1051DriverPLL2::~RT1051DriverPLL2() + RT1051DriverPLL2::~RT1051DriverPLL2() noexcept { if ((CLOCK_GetMux(kCLOCK_SemcMux) == SemcMuxPeripheralClock) && !bsp::IsClockEnabled(kCLOCK_Lpspi1) && !bsp::IsClockEnabled(kCLOCK_Lpspi2) && !bsp::IsClockEnabled(kCLOCK_Lpspi3) && !bsp::IsClockEnabled(kCLOCK_Lpspi4) && !bsp::IsClockEnabled(kCLOCK_Usdhc1) && !bsp::IsClockEnabled(kCLOCK_Usdhc2)) { - - // Disable PLL2 + /* Disable PLL2 */ clkPLL2setup(CLK_DISABLE); - // Switch to low power bandgap - bsp::bandgap::SwitchToLowPowerMode(); + /* Switch DCDC to low power config */ + bsp::dcdc::SwitchToLowPowerConfig(); - // After turning off PLL2 and with CPU @4MHZ VDD_SOC_IN can be set to 950mV - DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_950_mV, bsp::VDDStandby_925_mV); + /* Switch to low power LDO */ + bsp::ldo::SwitchToLowPowerMode(); + + /* Switch to low power bandgap */ + bsp::bandgap::SwitchToLowPowerMode(); } } @@ -45,5 +67,4 @@ namespace drivers { return not static_cast(CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_POWERDOWN_MASK); } - } // namespace drivers diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.hpp b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.hpp index 243338432a3a1e7b3987299dd2d423adf0fa59c9..e35e4c7836af34cfc11dfc9a7de6c4ff105706f2 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.hpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.hpp @@ -1,23 +1,23 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include "board/clock_config.h" +#include namespace drivers { - inline constexpr uint32_t SemcMuxPLL2Clock{1}; - inline constexpr uint32_t SemcMuxPeripheralClock{0}; + inline constexpr std::uint32_t SemcMuxPLL2Clock{1}; + inline constexpr std::uint32_t SemcMuxPeripheralClock{0}; class RT1051DriverPLL2 { public: RT1051DriverPLL2() noexcept; - ~RT1051DriverPLL2(); + ~RT1051DriverPLL2() noexcept; private: [[nodiscard]] bool IsPLL2Enabled() const noexcept; }; - } // namespace drivers diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp b/module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp index baa869b8f17bfb8129a954bdd74acfee3a13ffe4..3bc51a322423bad961ae126ba95e28c9ce802635 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp @@ -1,10 +1,9 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051DriverPWM.hpp" #include "RT1051DriverPWMhelper.hpp" #include -#include "../board.h" #include namespace drivers @@ -155,7 +154,6 @@ namespace drivers unsigned numOfChannels, std::uint32_t _clockFrequency) { - pwm_mode_t pwmMode = kPWM_SignedCenterAligned; PWM_SetupPwm(base, pwmModule, config, numOfChannels, pwmMode, parameters.frequency, _clockFrequency); } @@ -174,7 +172,7 @@ namespace drivers void RT1051DriverPWM::UpdateClockFrequency(bsp::CpuFrequencyMHz newFrequency) { cpp_freertos::LockGuard lock(frequencyChangeMutex); - std::uint32_t convertedFrequency = static_cast(newFrequency) * bsp::MHz_frequency_multiplier; + const auto convertedFrequency = static_cast(newFrequency) * bsp::HzPerMHz; if (clockFrequency != convertedFrequency) { SetupPWMInstance(pwmSignalsConfig.data(), enabledChannels.size(), convertedFrequency); diff --git a/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp b/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp index 511cb956cfdc07a17b827d245f6940adab44f3a7..635e48f8fba6174d72111b5c5fa3a992f6f0c4fc 100644 --- a/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp +++ b/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp @@ -2,12 +2,10 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051LPM.hpp" -#include #include namespace bsp { - using namespace drivers; RT1051LPM::RT1051LPM() @@ -16,17 +14,19 @@ namespace bsp DriverGPIOParams{}); gpio_2 = DriverGPIO::Create(static_cast(BoardDefinitions::DCDC_INVERTER_MODE_GPIO), DriverGPIOParams{}); - gpio_1->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, - .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, - .defLogic = 1, - .pin = static_cast(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON)}); - - gpio_2->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, - .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, - .defLogic = 0, - .pin = static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN)}); - - gpio_1->WritePin(static_cast(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON), 1); + gpio_1->ConfPin( + DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 1, + .pin = static_cast(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON)}); + + gpio_2->ConfPin( + DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN)}); + + gpio_1->WritePin(static_cast(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON), 1); EnableDcdcPowerSaveMode(); } @@ -34,23 +34,12 @@ namespace bsp // Current threshold for entry to and exit from the PSM mode is set to 100 mA void RT1051LPM::EnableDcdcPowerSaveMode() { - gpio_2->WritePin(static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN), 0); + gpio_2->WritePin(static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN), 0); } // Forces both bucks to operate in PWM mode void RT1051LPM::DisableDcdcPowerSaveMode() { - gpio_2->WritePin(static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN), 1); - } - - void RT1051LPM::SwitchToRegularModeLDO() - { - RT1051LPMCommon::RegularLDOMode(); + gpio_2->WritePin(static_cast(BoardDefinitions::DCDC_INVERTER_MODE_PIN), 1); } - - void RT1051LPM::SwitchToLowPowerModeLDO() - { - RT1051LPMCommon::LowPowerLDOMode(); - } - } // namespace bsp diff --git a/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp b/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp index 62890cdf42eaaec7bf009d8fd393310cb97d65df..7088dc75598b0067c1f6bf992c43695bfca8a945 100644 --- a/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp +++ b/module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp @@ -14,12 +14,8 @@ namespace bsp void EnableDcdcPowerSaveMode() final; void DisableDcdcPowerSaveMode() final; - void SwitchToRegularModeLDO() final; - void SwitchToLowPowerModeLDO() final; - private: std::shared_ptr gpio_1; std::shared_ptr gpio_2; }; - } // namespace bsp diff --git a/module-bsp/bsp/common.cpp b/module-bsp/bsp/common.cpp index f4ff516f29b4560cc0c94f4e0a47e23217db9258..d8bb74ab52b07ede10492a0e038cec6f29f07571 100644 --- a/module-bsp/bsp/common.cpp +++ b/module-bsp/bsp/common.cpp @@ -1,41 +1,37 @@ #include "common.hpp" -namespace bsp{ - const char *c_str(const Board &board) +namespace bsp +{ + std::uint8_t CpuMHZToLevel(enum CpuFrequencyMHz val) { - switch (board) { - case Board::RT1051: - return "RT1051"; - break; - case Board::Linux: - return "Linux"; - break; - case Board::none: - default: - return "none"; - break; - } - } - - uint8_t CpuMHZToLevel(enum CpuFrequencyMHz val) - { - switch (val) { - case CpuFrequencyMHz::Level_0: + switch (val) { + case CpuFrequencyMHz::Level_0: return 0; - case CpuFrequencyMHz::Level_1: + case CpuFrequencyMHz::Level_1: return 1; - case CpuFrequencyMHz::Level_2: + case CpuFrequencyMHz::Level_2: return 2; - case CpuFrequencyMHz::Level_3: + case CpuFrequencyMHz::Level_3: return 3; - case CpuFrequencyMHz::Level_4: + case CpuFrequencyMHz::Level_4: return 4; - case CpuFrequencyMHz::Level_5: + case CpuFrequencyMHz::Level_5: return 5; - case CpuFrequencyMHz::Level_6: + case CpuFrequencyMHz::Level_6: return 6; - } - return -1; + } + return -1; + } + + const char *c_str(Board board) + { + switch (board) { + case Board::RT1051: + return "RT1051"; + case Board::Linux: + return "Linux"; + default: + return "none"; + } } }; - diff --git a/module-bsp/bsp/common.hpp b/module-bsp/bsp/common.hpp index d69116359e0d9f08af62ca5dd4a134ef17bb5424..226fc2ec363a58f448d5c19c2ca135ece4cf9ace 100644 --- a/module-bsp/bsp/common.hpp +++ b/module-bsp/bsp/common.hpp @@ -4,12 +4,13 @@ #pragma once #include + namespace bsp { - enum class RetCode{ + enum class RetCode + { Success, Failure - }; /// CPU frequency is dependent on the clock settings. @@ -25,16 +26,15 @@ namespace bsp Level_6 = 528 }; - uint8_t CpuMHZToLevel(enum CpuFrequencyMHz val); - - constexpr auto MHz_frequency_multiplier = 1000000U; - - enum class Board{ + enum class Board + { RT1051, - Linux, - none + Linux, + none }; - [[nodiscard]] const char *c_str(const Board &board); -} + constexpr auto HzPerMHz = 1000000U; + [[nodiscard]] std::uint8_t CpuMHZToLevel(CpuFrequencyMHz val); + [[nodiscard]] const char *c_str(Board board); +} diff --git a/module-bsp/bsp/lpm/bsp_lpm.hpp b/module-bsp/bsp/lpm/bsp_lpm.hpp index 55702448ab28a058d7341ea6db1664b99f5bb59e..4b97703a78d6ad83f0ca6e67dd9e1a8d59d8f7c1 100644 --- a/module-bsp/bsp/lpm/bsp_lpm.hpp +++ b/module-bsp/bsp/lpm/bsp_lpm.hpp @@ -14,7 +14,6 @@ namespace drivers namespace bsp { - class LowPowerMode { public: @@ -23,6 +22,7 @@ namespace bsp External, Internal }; + enum class RebootType { NormalRestart, @@ -38,21 +38,18 @@ namespace bsp static std::optional> Create(); - virtual int32_t PowerOff() = 0; - virtual int32_t Reboot(RebootType reason) = 0; + virtual std::int32_t PowerOff() = 0; + virtual std::int32_t Reboot(RebootType reason) = 0; virtual void SetCpuFrequency(CpuFrequencyMHz freq) = 0; [[nodiscard]] CpuFrequencyMHz GetCurrentFrequencyLevel() const noexcept; - [[nodiscard]] virtual uint32_t GetCpuFrequency() const noexcept = 0; + [[nodiscard]] virtual std::uint32_t GetCpuFrequency() const noexcept = 0; virtual void SwitchOscillatorSource(OscillatorSource source) = 0; virtual void EnableDcdcPowerSaveMode() = 0; virtual void DisableDcdcPowerSaveMode() = 0; - virtual void SwitchToRegularModeLDO() = 0; - virtual void SwitchToLowPowerModeLDO() = 0; - protected: CpuFrequencyMHz currentFrequency = CpuFrequencyMHz::Level_6; }; diff --git a/module-sys/SystemManager/PowerManager.cpp b/module-sys/SystemManager/PowerManager.cpp index 8fb434ed4cad36dedc4e9031deb7d8a2b01e05c2..335d1f88676519a862c7a8c9abc869894f3e4bfe 100644 --- a/module-sys/SystemManager/PowerManager.cpp +++ b/module-sys/SystemManager/PowerManager.cpp @@ -21,7 +21,7 @@ namespace sys constexpr auto highestLevelName{"highestCpuFrequency"}; } // namespace - CpuFrequencyMonitor::CpuFrequencyMonitor(const std::string name) : levelName(name) + CpuFrequencyMonitor::CpuFrequencyMonitor(const std::string &name) : levelName(name) {} [[nodiscard]] auto CpuFrequencyMonitor::GetName() const noexcept -> std::string @@ -153,18 +153,18 @@ namespace sys cpuStatistics.TrackChange(ret); } - bool PowerManager::IsCpuPernamentFrequency() + bool PowerManager::IsCpuPermanentFrequency() { return cpuAlgorithms->get(sys::cpu::AlgoID::FrequencyHold) != nullptr; } - void PowerManager::SetPernamentFrequency(bsp::CpuFrequencyMHz freq) + void PowerManager::SetPermanentFrequency(bsp::CpuFrequencyMHz freq) { cpuAlgorithms->emplace(sys::cpu::AlgoID::FrequencyHold, std::make_unique(freq, powerProfile)); } - void PowerManager::ResetPernamentFrequency() + void PowerManager::ResetPermanentFrequency() { cpuAlgorithms->remove(sys::cpu::AlgoID::FrequencyHold); } diff --git a/module-sys/SystemManager/SystemManagerCommon.cpp b/module-sys/SystemManager/SystemManagerCommon.cpp index 6a34e5ef47498edc278f57849c33d3c3cd1d284f..e9bb451098a484f2c965d6f082c10343f9c0faa3 100644 --- a/module-sys/SystemManager/SystemManagerCommon.cpp +++ b/module-sys/SystemManager/SystemManagerCommon.cpp @@ -592,21 +592,18 @@ namespace sys connect(typeid(sys::DeviceRegistrationMessage), [this](sys::Message *message) -> sys::MessagePointer { auto msg = static_cast(message); deviceManager->RegisterNewDevice(msg->getDevice()); - return sys::MessageNone{}; }); connect(typeid(sys::SentinelRegistrationMessage), [this](sys::Message *message) -> sys::MessagePointer { auto msg = static_cast(message); powerManager->RegisterNewSentinel(msg->getSentinel()); - return sys::MessageNone{}; }); connect(typeid(sys::SentinelRemovalMessage), [this](sys::Message *message) -> sys::MessagePointer { auto msg = static_cast(message); powerManager->RemoveSentinel(msg->getSentinelName()); - return std::make_shared(); }); @@ -622,22 +619,21 @@ namespace sys connect(typeid(sys::ReleaseCpuFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer { auto msg = static_cast(message); powerManager->ResetCpuFrequencyRequest(msg->getName()); - return sys::MessageNone{}; }); - connect(typeid(sys::IsCpuPernament), [this](sys::Message *message) -> sys::MessagePointer { - return std::make_shared(powerManager->IsCpuPernamentFrequency()); + connect(typeid(sys::IsCpuPermanent), [this](sys::Message *message) -> sys::MessagePointer { + return std::make_shared(powerManager->IsCpuPermanentFrequency()); }); connect(typeid(sys::HoldCpuFrequencyPermanentlyMessage), [this](sys::Message *message) -> sys::MessagePointer { auto msg = static_cast(message); - powerManager->SetPernamentFrequency(msg->request); + powerManager->SetPermanentFrequency(msg->request); return std::make_shared(); }); connect(typeid(sys::ReleaseCpuPermanentFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer { - powerManager->ResetPernamentFrequency(); + powerManager->ResetPermanentFrequency(); return std::make_shared(); }); @@ -754,7 +750,7 @@ namespace sys void SystemManagerCommon::UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) { - if (newFrequency <= bsp::CpuFrequencyMHz::Level_1) { + if (newFrequency <= bsp::CpuFrequencyMHz::Level_2) { purefs::subsystem::disk_mgr()->pm_control(purefs::blkdev::pm_state::suspend); } else { diff --git a/module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp b/module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp index ab68d1b82447cfa06f212a3e9980c72e58e241b2..6f7628cc21789b54c015c71bcd619c30cbe4ce60 100644 --- a/module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp +++ b/module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "FrequencyStepping.hpp" @@ -23,9 +23,7 @@ namespace sys::cpu case bsp::CpuFrequencyMHz::Level_3: return bsp::CpuFrequencyMHz::Level_2; case bsp::CpuFrequencyMHz::Level_2: - [[fallthrough]]; case bsp::CpuFrequencyMHz::Level_1: - [[fallthrough]]; case bsp::CpuFrequencyMHz::Level_0: return profile.minimalFrequency; } diff --git a/module-sys/SystemManager/include/SystemManager/PowerManager.hpp b/module-sys/SystemManager/include/SystemManager/PowerManager.hpp index f4cd09dc62b37b1ce511bdf3643ebe259ea66f22..454d3ed7276df6a232abb9ed67cc0c93c206be9c 100644 --- a/module-sys/SystemManager/include/SystemManager/PowerManager.hpp +++ b/module-sys/SystemManager/include/SystemManager/PowerManager.hpp @@ -25,7 +25,7 @@ namespace sys class CpuFrequencyMonitor { public: - explicit CpuFrequencyMonitor(const std::string name); + explicit CpuFrequencyMonitor(const std::string &name); [[nodiscard]] auto GetName() const noexcept -> std::string; [[nodiscard]] auto GetPeriodRuntimePercentage(const TickType_t periodTicksIncrease) const noexcept @@ -65,9 +65,9 @@ namespace sys void RemoveSentinel(std::string sentinelName) const; void SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request); void ResetCpuFrequencyRequest(const std::string &sentinelName); - bool IsCpuPernamentFrequency(); - void SetPernamentFrequency(bsp::CpuFrequencyMHz freq); - void ResetPernamentFrequency(); + bool IsCpuPermanentFrequency(); + void SetPermanentFrequency(bsp::CpuFrequencyMHz freq); + void ResetPermanentFrequency(); void LogPowerManagerStatistics(); diff --git a/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp b/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp index 4f88b1ef8376ba872fe7d491e471bfa76f754b47..cdae249c928486e42477fd224b4c2f06927e1784 100644 --- a/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp +++ b/module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -8,20 +8,19 @@ namespace sys { - - struct IsCpuPernament : public sys::DataMessage + struct IsCpuPermanent : public sys::DataMessage { public: - explicit IsCpuPernament() + explicit IsCpuPermanent() {} }; - struct IsCpuPernamentResponse : public sys::ResponseMessage + struct IsCpuPermanentResponse : public sys::ResponseMessage { public: - explicit IsCpuPernamentResponse(bool pernament) : pernament(pernament) + explicit IsCpuPermanentResponse(bool permanent) : permanent(permanent) {} - const bool pernament = false; + const bool permanent = false; }; struct HoldCpuFrequencyPermanentlyMessage : public sys::DataMessage @@ -37,5 +36,4 @@ namespace sys class ReleaseCpuPermanentFrequencyMessage : public sys::DataMessage {}; - } // namespace sys diff --git a/pure_changelog.md b/pure_changelog.md index 88d6a955c453c3ab08f1a9dbf600a7f1b269b006..0af5dde4ad98fe4167525b04970de58b9ffc1081 100644 --- a/pure_changelog.md +++ b/pure_changelog.md @@ -16,6 +16,7 @@ * Change roaming indicator to show domestic roaming as home network * Optimized ServiceAudio power management * Blocked call execution with empty phone number field +* Improved device stability related to frequency scaling ### Fixed