M board/rt1051/ldscripts/sections.ld => board/rt1051/ldscripts/sections.ld +17 -9
@@ 17,6 17,8 @@ __ocram_noncached_end = ORIGIN(SRAM_OC) + LENGTH(SRAM_OC);
__dtcm_ram_start = ORIGIN(SRAM_DTC);
__dtcm_ram_end = ORIGIN(SRAM_DTC) + LENGTH(SRAM_DTC);
+__sdram_start = ORIGIN(BOARD_SDRAM_TEXT);
+
__sdram_cached_start = ORIGIN(BOARD_SDRAM_HEAP);
__sdram_cached_end = ORIGIN(BOARD_SDRAM_HEAP) + LENGTH(BOARD_SDRAM_HEAP);
@@ 49,7 51,7 @@ SECTIONS
.text : ALIGN(4)
{
FILL(0x00)
- __vectors_start__ = ABSOLUTE(.) ;
+ __vectors_start__ = ABSOLUTE(.);
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
@@ 64,6 66,11 @@ SECTIONS
LONG( ADDR(.data));
LONG( SIZEOF(.data));
__data_section_table_end = .;
+ __ocramtext_section_table = .;
+ LONG(LOADADDR(.ocramtext));
+ LONG(ADDR(.ocramtext));
+ LONG(SIZEOF(.ocramtext));
+ __ocramtext_section_table_end = .;
__bss_section_table = .;
/* System bss */
LONG( ADDR(.sysbss));
@@ 105,10 112,18 @@ SECTIONS
*libusb_stack.a:*(.data*)
} > SRAM_DTC AT > BOARD_SDRAM_TEXT
+ /* Place WFI and SDRAM driver code in OCRAM to enable switching SDRAM to self-refresh before executing WFI */
+ .ocramtext : ALIGN(4)
+ {
+ *(.wficode*)
+ *fsl_semc.c.obj(.text*)
+ } > SRAM_OC AT > BOARD_SDRAM_TEXT
+
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
- *(.text*)
+ /* Place here all .text* sections except for the ones in fsl_semc.c.obj file */
+ *(EXCLUDE_FILE (*fsl_semc.c.obj) .text*)
*(.rodata .rodata.* .constdata .constdata.*)
. = ALIGN(4);
@@ 191,13 206,6 @@ SECTIONS
*(.sdram.*)
} >BOARD_SDRAM_HEAP
- /* DMA buffers */
- .intramnoncacheable (NOLOAD) : ALIGN(4)
- {
- *(.intramnoncacheable)
- *(.intramnoncacheable.*)
- } > SRAM_OC
-
/* Place system stack at the very end of DTCM */
_StackSize = 0x1000;
.stack ORIGIN(SRAM_DTC) + LENGTH(SRAM_DTC) - _StackSize - 0 : ALIGN(4)
M harmony_changelog.md => harmony_changelog.md +3 -1
@@ 9,6 9,8 @@
* Added setting onboarding year to build date year
* Added low battery notification on the home screen
* Added low battery notification before using the application
+* Added entering WFI when CPU is idle to reduce power consumption
+* Added switching SDRAM to self-refresh before entering WFI for further power consumption reduction
### Changed / Improved
@@ 17,7 19,6 @@
### Added
* Added gradual alarm volume increase
* Added progress bar for all volume control windows
-* Improved factory reset procedure to remove user files
### Changed / Improved
* Increased clock font in Relaxation, Meditation, Power nap mode
@@ 26,6 27,7 @@
* Extended volume scale from 10 to 15 point scale
* Modified volume control characteristic for better user experience
* Reduced power consumption for Meditation and Power Nap applications
+* Improved factory reset procedure to remove user files
## [2.3.0 2023-12-20]
M module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp => module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp +1 -1
@@ 37,7 37,7 @@ namespace gui
});
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuModeTester);
- application->bus.sendUnicastSync(sentinelRegistrationMsg, service::name::system_manager, 30);
+ application->bus.sendUnicastSync(std::move(sentinelRegistrationMsg), service::name::system_manager, 30);
AppWindow::buildInterface();
M module-bsp/board/linux/lpm/LinuxLPM.cpp => module-bsp/board/linux/lpm/LinuxLPM.cpp +23 -0
@@ 33,4 33,27 @@ namespace bsp
void LinuxLPM::DisableDcdcPowerSaveMode()
{}
+
+ void LinuxLPM::AllowEnteringWfiMode()
+ {}
+
+ void LinuxLPM::BlockEnteringWfiMode()
+ {}
+
+ std::uint32_t LinuxLPM::EnterWfiModeIfAllowed()
+ {
+ return 0;
+ }
+
+ std::uint32_t LinuxLPM::GetLastTimeSpentInWfi()
+ {
+ return 0;
+ }
+
+ void LinuxLPM::DisableSysTick()
+ {}
+
+ void LinuxLPM::EnableSysTick()
+ {}
+
} // namespace bsp
M module-bsp/board/linux/lpm/LinuxLPM.h => module-bsp/board/linux/lpm/LinuxLPM.h +8 -0
@@ 18,5 18,13 @@ namespace bsp
void EnableDcdcPowerSaveMode() final;
void DisableDcdcPowerSaveMode() final;
+
+ void AllowEnteringWfiMode() final;
+ void BlockEnteringWfiMode() final;
+ std::uint32_t EnterWfiModeIfAllowed() final;
+ std::uint32_t GetLastTimeSpentInWfi() final;
+
+ void DisableSysTick() final;
+ void EnableSysTick() final;
};
} // namespace bsp
M module-bsp/board/rt1051/bellpx/CMakeLists.txt => module-bsp/board/rt1051/bellpx/CMakeLists.txt +2 -0
@@ 20,6 20,8 @@ target_sources(
bsp/eink/eink_gpio.cpp
bsp/lpm/PowerProfile.cpp
bsp/lpm/RT1051LPM.cpp
+ bsp/lpm/WfiController.cpp
+ bsp/lpm/EnterSleepMode.c
bsp/rotary_encoder/rotary_encoder.cpp
bsp/rtc/rtc_configuration.cpp
bsp/switches/switches.cpp
M module-bsp/board/rt1051/bellpx/board.cpp => module-bsp/board/rt1051/bellpx/board.cpp +16 -4
@@ 51,18 51,30 @@ namespace
namespace bsp
{
- void board_exit(rebootState state)
+ void board_configure()
+ {
+ /* See *
+ * https://patchwork.kernel.org/project/linux-arm-kernel/patch/1471885400-9140-1-git-send-email-Anson.Huang@nxp.com/
+ */
+ CCM->CGPR |= CCM_CGPR_INT_MEM_CLK_LPM_MASK;
+
+ /* ERR050143 */
+ IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_GINT_MASK;
+ }
+
+ void board_exit(RebootState state)
{
switch (state) {
- case rebootState::none:
+ case RebootState::None:
break;
- case rebootState::poweroff:
+ case RebootState::Poweroff:
power_off();
break;
- case rebootState::reboot:
+ case RebootState::Reboot:
reset();
break;
}
+
while (true) {}
}
} // namespace bsp
M module-bsp/board/rt1051/bellpx/brownout.cpp => module-bsp/board/rt1051/bellpx/brownout.cpp +6 -17
@@ 1,7 1,6 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include <cstdint>
#include <fsl_common.h>
#include <fsl_pmu.h>
@@ 9,25 8,15 @@ namespace bsp
{
namespace
{
- constexpr std::uint32_t OutputVoltage1P1 = 0x19; // 1.275V
- constexpr std::uint32_t OutputVoltage2P5 = 0x1F; // 2.875V
-
- constexpr std::uint32_t OffsetVoltage1P1 = 0x05; // 5*25mv
- constexpr std::uint32_t OffsetVoltage2P5 = 0x03; // 3*25mv
- } // namespace
+ constexpr auto outputVoltage2P5 = 0x1BU; // 2.775V
+ constexpr auto offsetVoltage2P5 = 0x03U; // 3*25mV
+ } // namespace
void Brownout_init()
{
- // Config LDO Regulatorsand config Brownout voltage offsets
- PMU_1P1EnableBrownout(PMU, true);
- PMU_1P1SetRegulatorOutputVoltage(PMU, OutputVoltage1P1);
- PMU_1P1SetBrownoutOffsetVoltage(PMU, OffsetVoltage1P1);
- PMU_1P1EnableOutput(PMU, true);
-
PMU_2P5nableBrownout(PMU, true);
- PMU_2P5SetRegulatorOutputVoltage(PMU, OutputVoltage2P5);
- PMU_2P5SetBrownoutOffsetVoltage(PMU, OffsetVoltage2P5);
+ PMU_2P5SetRegulatorOutputVoltage(PMU, outputVoltage2P5);
+ PMU_2P5SetBrownoutOffsetVoltage(PMU, offsetVoltage2P5);
PMU_2P5EnableOutput(PMU, true);
}
-
} // namespace bsp
A module-bsp/board/rt1051/bellpx/bsp/lpm/EnterSleepMode.c => module-bsp/board/rt1051/bellpx/bsp/lpm/EnterSleepMode.c +29 -0
@@ 0,0 1,29 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "EnterSleepMode.h"
+#include <macros.h>
+#include <fsl_semc.h>
+
+extern char __sdram_start; // Defined in linker script
+
+/* This function needs to be compiled either as a C code, or as a C++ code with
+ * exception handling disabled (-fno-exceptions), otherwise it is not possible to relocate
+ * its code into OCRAM. Rationale:
+ * https://stackoverflow.com/questions/52637962/arm-cortex-m7-long-branch-get-error-relocation-truncated-to-fit-r-arm-prel31
+ *
+ * As compiling single C++ file with exception handling disabled seems to be impossible
+ * using CMake and selectively disabling exceptions using #pragmas looks ugly, I've decided
+ * to just put it in a separate .c file. */
+WFI_CODE_SECTION(void enterSleepMode(void))
+{
+ /* Wait until SDRAM operations done and switch to self-refresh mode */
+ __DSB();
+ while ((SEMC->STS0 & SEMC_STS0_IDLE_MASK) == 0) {} // Wait until SEMC idle
+ __ISB();
+ SEMC_SendIPCommand(SEMC, kSEMC_MemType_SDRAM, (uint32_t)&__sdram_start, kSEMC_SDRAMCM_SelfRefresh, 0, NULL);
+
+ /* Go to sleep */
+ __WFI();
+ __ISB();
+}
A module-bsp/board/rt1051/bellpx/bsp/lpm/EnterSleepMode.h => module-bsp/board/rt1051/bellpx/bsp/lpm/EnterSleepMode.h +13 -0
@@ 0,0 1,13 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void enterSleepMode(void);
+#ifdef __cplusplus
+}
+#endif
M module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.cpp +21 -0
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "RT1051LPM.hpp"
+#include "WfiController.hpp"
namespace bsp
{
@@ 10,4 11,24 @@ namespace bsp
void RT1051LPM::DisableDcdcPowerSaveMode()
{}
+
+ void RT1051LPM::AllowEnteringWfiMode()
+ {
+ allowEnteringWfiMode();
+ }
+
+ void RT1051LPM::BlockEnteringWfiMode()
+ {
+ blockEnteringWfiMode();
+ }
+
+ std::uint32_t RT1051LPM::EnterWfiModeIfAllowed()
+ {
+ return enterWfiModeIfAllowed();
+ }
+
+ std::uint32_t RT1051LPM::GetLastTimeSpentInWfi()
+ {
+ return getLastTimeSpentInWfi();
+ }
} // namespace bsp
M module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/bellpx/bsp/lpm/RT1051LPM.hpp +5 -0
@@ 12,5 12,10 @@ namespace bsp
public:
void EnableDcdcPowerSaveMode() final;
void DisableDcdcPowerSaveMode() final;
+
+ void AllowEnteringWfiMode() final;
+ void BlockEnteringWfiMode() final;
+ std::uint32_t EnterWfiModeIfAllowed() final;
+ std::uint32_t GetLastTimeSpentInWfi() final;
};
} // namespace bsp
A module-bsp/board/rt1051/bellpx/bsp/lpm/WfiController.cpp => module-bsp/board/rt1051/bellpx/bsp/lpm/WfiController.cpp +175 -0
@@ 0,0 1,175 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "WfiController.hpp"
+#include "EnterSleepMode.h"
+#include <fsl_gpc.h>
+#include <fsl_rtwdog.h>
+#include <fsl_runtimestat_gpt.h>
+#include <Utils.hpp>
+#include <time/time_constants.hpp>
+#include <ticks.hpp>
+#include <timers.h>
+
+namespace bsp
+{
+ namespace
+ {
+ /* RTC wakes up CPU every minute, so go to sleep only if next timer will
+ * trigger after more than minute - this way no event will ever be missed */
+ constexpr auto timersInactivityTimeMs{60 * utils::time::milisecondsInSecond};
+
+ bool wfiModeAllowed = false;
+ std::uint32_t timeSpentInWFI;
+
+ bool isTimerTaskScheduledSoon()
+ {
+ const auto currentTick = cpp_freertos::Ticks::GetTicks();
+ const auto timersNextWakeUpTick = xTimerGetNextWakeUpTime();
+
+ if (timersNextWakeUpTick > currentTick) {
+ return (cpp_freertos::Ticks::TicksToMs(timersNextWakeUpTick - currentTick) < timersInactivityTimeMs);
+ }
+ return true;
+ }
+
+ bool isWfiModeAllowed()
+ {
+ return wfiModeAllowed;
+ }
+
+ void peripheralEnterDozeMode()
+ {
+ IOMUXC_GPR->GPR8 = IOMUXC_GPR_GPR8_LPI2C1_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPI2C2_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPI2C3_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPI2C4_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPSPI1_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPSPI2_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPSPI3_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPSPI4_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPUART1_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPUART2_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPUART3_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPUART4_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPUART5_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPUART6_IPG_DOZE_MASK |
+ IOMUXC_GPR_GPR8_LPUART7_IPG_DOZE_MASK | IOMUXC_GPR_GPR8_LPUART8_IPG_DOZE_MASK;
+
+ IOMUXC_GPR->GPR12 = IOMUXC_GPR_GPR12_FLEXIO1_IPG_DOZE_MASK | IOMUXC_GPR_GPR12_FLEXIO2_IPG_DOZE_MASK;
+ }
+
+ void peripheralExitDozeMode()
+ {
+ IOMUXC_GPR->GPR8 = 0x00000000;
+ IOMUXC_GPR->GPR12 = 0x00000000;
+ }
+
+ void setRunModeConfig()
+ {
+ CCM->CLPCR &= ~(CCM_CLPCR_LPM_MASK | CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK);
+ }
+
+ void setWaitModeConfig()
+ {
+ std::uint32_t clpcr;
+
+ /*
+ * ERR050143: CCM: When improper low-power sequence is used,
+ * the SoC enters low power mode before the ARM core executes WFI.
+ *
+ * Software workaround:
+ * 1) Software should trigger IRQ #41 (GPR_IRQ) to be always pending
+ * by setting IOMUXC_GPR_GPR1_GINT.
+ * 2) Software should then unmask IRQ #41 in GPC before setting CCM
+ * Low-Power mode.
+ * 3) Software should mask IRQ #41 right after CCM Low-Power mode
+ * is set (set bits 0-1 of CCM_CLPCR).
+ */
+ GPC_EnableIRQ(GPC, GPR_IRQ_IRQn);
+ clpcr = CCM->CLPCR & (~(CCM_CLPCR_LPM_MASK | CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK));
+ CCM->CLPCR = clpcr | CCM_CLPCR_LPM(kCLOCK_ModeWait) | CCM_CLPCR_MASK_SCU_IDLE_MASK |
+ CCM_CLPCR_MASK_L2CC_IDLE_MASK | CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK | CCM_CLPCR_STBY_COUNT_MASK |
+ CCM_CLPCR_BYPASS_LPM_HS0_MASK | CCM_CLPCR_BYPASS_LPM_HS1_MASK;
+ GPC_DisableIRQ(GPC, GPR_IRQ_IRQn);
+ }
+
+ bool isBrownoutOn2P5Output()
+ {
+ return ((PMU->REG_2P5 & PMU_REG_2P5_BO_VDD2P5_MASK) != 0);
+ }
+
+ void disableSystick()
+ {
+ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+ NVIC_ClearPendingIRQ(SysTick_IRQn);
+ }
+
+ void enableSystick()
+ {
+ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+ }
+ } // namespace
+
+ void allowEnteringWfiMode()
+ {
+ wfiModeAllowed = true;
+ }
+
+ /* Block WFI mode so that OS wakes up fully and goes to sleep only after
+ * frequency has dropped back to the lowest level */
+ void blockEnteringWfiMode()
+ {
+ wfiModeAllowed = false;
+ }
+
+ std::uint32_t getLastTimeSpentInWfi()
+ {
+ return timeSpentInWFI;
+ }
+
+ std::uint32_t enterWfiModeIfAllowed()
+ {
+ if (!isWfiModeAllowed()) {
+ return 0;
+ }
+ timeSpentInWFI = 0;
+ if (isTimerTaskScheduledSoon()) {
+ blockEnteringWfiMode();
+ return 0;
+ }
+ if (isBrownoutOn2P5Output()) {
+ LOG_WARN("WFI disabled - brownout detected on 2P5 VDD output");
+ blockEnteringWfiMode();
+ return 0;
+ }
+
+ RTWDOG_Refresh(RTWDOG);
+ setWaitModeConfig();
+ peripheralEnterDozeMode();
+
+ disableSystick();
+ const auto enterWfiTicks = ulHighFrequencyTimerTicks();
+
+ const auto savedPrimask = DisableGlobalIRQ();
+ __DSB();
+ __ISB();
+
+ /* Clear the SLEEPDEEP bit to go into sleep mode (WAIT) */
+ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+
+ /* Switch SDRAM to self-refresh and execute WFI */
+ enterSleepMode();
+
+ __NOP();
+ __NOP();
+ __NOP();
+ __NOP();
+
+ const auto exitWfiTicks = ulHighFrequencyTimerTicks();
+ enableSystick();
+
+ peripheralExitDozeMode();
+ RTWDOG_Refresh(RTWDOG);
+ EnableGlobalIRQ(savedPrimask);
+
+ blockEnteringWfiMode();
+ setRunModeConfig();
+
+ timeSpentInWFI = ulHighFrequencyTimerTicksToMs(utils::computeIncrease(exitWfiTicks, enterWfiTicks));
+ return timeSpentInWFI;
+ }
+} // namespace bsp
A module-bsp/board/rt1051/bellpx/bsp/lpm/WfiController.hpp => module-bsp/board/rt1051/bellpx/bsp/lpm/WfiController.hpp +14 -0
@@ 0,0 1,14 @@
+// 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 <cstdint>
+
+namespace bsp
+{
+ void allowEnteringWfiMode();
+ void blockEnteringWfiMode();
+ std::uint32_t enterWfiModeIfAllowed();
+ std::uint32_t getLastTimeSpentInWfi();
+} // namespace bsp
M module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp +1 -5
@@ 10,14 10,10 @@
#include <timers.h>
#include <bsp/switches/switches.hpp>
#include <board/BoardDefinitions.hpp>
-#include <board.h>
#include <fsl_common.h>
#include <switches/LatchState.hpp>
#include <chrono>
-#include <stdio.h>
-#include <stdint.h>
-#include <assert.h>
#include <map>
#include <vector>
#include <magic_enum.hpp>
@@ 56,7 52,7 @@ namespace bsp::bell_switches
void createTimer(TimerCallback callback, const std::chrono::milliseconds timeout)
{
timer =
- xTimerCreate(magic_enum::enum_name(id).data(), pdMS_TO_TICKS(timeout.count()), false, this, callback);
+ xTimerCreate(magic_enum::enum_name(id).data(), pdMS_TO_TICKS(timeout.count()), pdFALSE, this, callback);
}
};
M module-bsp/board/rt1051/bellpx/clock_config.cpp => module-bsp/board/rt1051/bellpx/clock_config.cpp +3 -0
@@ 453,6 453,9 @@ void BOARD_BootClockRUN(void)
/* PRE_PERIPH_CLK <- PLL1/2 = 432MHz */
CLOCK_SetMux(kCLOCK_PeriphMux, 0); // CBCDR (25) 0 - pre_periph_clk_sel, 1 - periph_clk2_clk_divided
+ /* Enable clock of ARM platform memories when entering LPM */
+ CCM->CGPR |= CCM_CGPR_INT_MEM_CLK_LPM_MASK;
+
/* Set SystemCoreClock variable. */
SystemCoreClockUpdate();
}
M module-bsp/board/rt1051/bellpx/irq_gpio.cpp => module-bsp/board/rt1051/bellpx/irq_gpio.cpp +0 -4
@@ 236,10 236,6 @@ namespace bsp
* immediately reset board's main DCDC converter
* using the WDOG_B pin. This will reset the
* whole board. */
- if (status & kPMU_1P1BrownoutOnOutput) {
- WDOG1->WCR &= ~WDOG_WCR_WDA_MASK;
- }
-
if (status & kPMU_2P5BrownoutOnOutput) {
WDOG1->WCR &= ~WDOG_WCR_WDA_MASK;
}
M module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp +27 -2
@@ 1,8 1,9 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "RT1051LPMCommon.hpp"
#include <log/log.hpp>
+#include <fsl_device_registers.h>
#include <fsl_clock.h>
#include <bsp/bsp.hpp>
#include "Oscillator.hpp"
@@ 66,6 67,9 @@ namespace bsp
void RT1051LPMCommon::onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency)
{
if ((freq <= CpuFrequencyMHz::Level_1) && (newFrequency > CpuFrequencyMHz::Level_1)) {
+ /* Block entering WFI mode */
+ BlockEnteringWfiMode();
+
/* Switch to external crystal oscillator */
SwitchOscillatorSource(LowPowerMode::OscillatorSource::External);
@@ 86,6 90,8 @@ namespace bsp
if (driverSEMC) {
driverSEMC->SwitchToPeripheralClockSource();
}
+ /* Allow entering WFI mode */
+ AllowEnteringWfiMode();
}
}
@@ 140,7 146,7 @@ namespace bsp
onChangeDown(freq);
}
- LOG_INFO("CPU frequency changed to %lu", CLOCK_GetFreq(kCLOCK_CpuClk));
+ LOG_INFO("%s", getFrequencyChangedLog().c_str());
currentFrequency = freq;
}
@@ 161,4 167,23 @@ namespace bsp
break;
}
}
+
+ void RT1051LPMCommon::DisableSysTick()
+ {
+ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+ }
+
+ void RT1051LPMCommon::EnableSysTick()
+ {
+ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+ }
+
+ std::string RT1051LPMCommon::getFrequencyChangedLog()
+ {
+ auto logMsg = "CPU frequency changed to " + std::to_string(CLOCK_GetCpuClkFreq());
+ if (currentFrequency <= CpuFrequencyMHz::Level_1) {
+ logMsg += " (WFI time: " + std::to_string(GetLastTimeSpentInWfi()) + " ms)";
+ }
+ return logMsg;
+ }
} // namespace bsp
M module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.hpp +4 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 18,10 18,13 @@ namespace bsp
void SetCpuFrequency(CpuFrequencyMHz freq) final;
[[nodiscard]] std::uint32_t GetCpuFrequency() const noexcept final;
void SwitchOscillatorSource(OscillatorSource source) final;
+ void DisableSysTick() final;
+ void EnableSysTick() final;
private:
void onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency);
void onChangeDown(CpuFrequencyMHz freq);
+ std::string getFrequencyChangedLog();
std::unique_ptr<bsp::CpuFreqLPM> CpuFreq;
std::shared_ptr<drivers::DriverSEMC> driverSEMC;
M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +126 -128
@@ 1,12 1,8 @@
-
#include "bsp.hpp"
#include "board.h"
-#include "fsl_gpio.h"
-#include <stdint.h>
extern "C"
{
#include "fsl_common.h"
-#include "fsl_clock.h"
#include "fsl_dcdc.h"
#include "fsl_snvs_hp.h"
#include "fsl_snvs_lp.h"
@@ 21,17 17,18 @@ extern "C"
#include <board/debug_console.hpp>
#include <log/log.hpp>
+#include <magic_enum.hpp>
extern std::uint32_t __sdram_cached_start[];
extern "C"
{
- uint32_t boot_reason_get_raw()
+ std::uint32_t boot_reason_get_raw()
{
return SNVS->LPGPR[0];
}
- void boot_reason_set_raw(uint32_t raw)
+ void boot_reason_set_raw(std::uint32_t raw)
{
SNVS->LPGPR[0] = raw;
}
@@ 41,124 38,140 @@ namespace bsp
{
namespace
{
- volatile rebootState rebootProgress{rebootState::none};
- } // namespace
-
- /* MPU configuration. */
- static void BOARD_ConfigMPU(void)
- {
- /* Disable I cache and D cache */
- if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) {
- SCB_DisableICache();
- }
- if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) {
- SCB_DisableDCache();
+ volatile RebootState rebootProgress{RebootState::None};
+
+ struct PlatformExitObject
+ {
+ void (*func)();
+ };
+ unsigned short registeredObjectsCount = 0;
+ constexpr auto maxRegisteredObjectsCount = 16U;
+
+ PlatformExitObject exitObjects[maxRegisteredObjectsCount];
+
+ void call_platform_exit_functions()
+ {
+ while (registeredObjectsCount > 0) {
+ exitObjects[--registeredObjectsCount].func();
+ }
}
- /* Disable MPU */
- ARM_MPU_Disable();
-
- /* MPU configure:
- * Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable,
- * SubRegionDisable, Size) API in core_cm7.h. param DisableExec Instruction access (XN) disable
- * bit,0=instruction fetches enabled, 1=instruction fetches disabled. param AccessPermission Data access
- * permissions, allows you to configure read/write access for User and Privileged mode. Use MACROS defined in
- * core_cm7.h: ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO
- * Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes.
- * TypeExtField IsShareable IsCacheable IsBufferable Memory Attribtue Shareability Cache
- * 0 x 0 0 Strongly Ordered shareable
- * 0 x 0 1 Device shareable
- * 0 0 1 0 Normal not shareable Outer and inner
- * write through no write allocate 0 0 1 1 Normal not
- * shareable Outer and inner write back no write allocate 0 1 1 0 Normal
- * shareable Outer and inner write through no write allocate 0 1 1 1
- * Normal shareable Outer and inner write back no write allocate 1 0 0
- * 0 Normal not shareable outer and inner noncache 1 1 0 0
- * Normal shareable outer and inner noncache 1 0 1 1 Normal
- * not shareable outer and inner write back write/read acllocate 1 1 1 1
- * Normal shareable outer and inner write back write/read acllocate 2 x 0 0 Device
- * not shareable Above are normal use settings, if your want to see more details or want to config different
- * inner/outter cache policy. please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide
- * <dui0646b_cortex_m7_dgug.pdf> param SubRegionDisable Sub-region disable field. 0=sub-region is enabled,
- * 1=sub-region is disabled. param Size Region size of the region to be configured. use
- * ARM_MPU_REGION_SIZE_xxx MACRO in core_cm7.h.
- */
-
- /* Region 0 setting: Memory with Device type, not shareable, non-cacheable. */
- MPU->RBAR = ARM_MPU_RBAR(0, 0xC0000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
-
- /* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */
- MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);
-
- /* Region 2 setting */
+ /* MPU configuration. */
+ void BOARD_ConfigMPU()
+ {
+ /* Disable I cache and D cache */
+ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) {
+ SCB_DisableICache();
+ }
+ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) {
+ SCB_DisableDCache();
+ }
+
+ /* Disable MPU */
+ ARM_MPU_Disable();
+
+ /* MPU configure:
+ * Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable,
+ * SubRegionDisable, Size) API in core_cm7.h. param DisableExec Instruction access (XN) disable
+ * bit,0=instruction fetches enabled, 1=instruction fetches disabled. param AccessPermission Data access
+ * permissions, allows you to configure read/write access for User and Privileged mode. Use MACROS defined in
+ * core_cm7.h: ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO
+ * Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes.
+ * TypeExtField IsShareable IsCacheable IsBufferable Memory Attribtue Shareability Cache
+ * 0 x 0 0 Strongly Ordered shareable
+ * 0 x 0 1 Device shareable
+ * 0 0 1 0 Normal not shareable Outer and inner
+ * write through no write allocate 0 0 1 1 Normal not
+ * shareable Outer and inner write back no write allocate 0 1 1 0 Normal
+ * shareable Outer and inner write through no write allocate 0 1 1 1
+ * Normal shareable Outer and inner write back no write allocate 1 0 0
+ * 0 Normal not shareable outer and inner noncache 1 1 0 0
+ * Normal shareable outer and inner noncache 1 0 1 1 Normal
+ * not shareable outer and inner write back write/read acllocate 1 1 1 1
+ * Normal shareable outer and inner write back write/read acllocate 2 x 0 0 Device
+ * not shareable Above are normal use settings, if your want to see more details or want to config different
+ * inner/outter cache policy. please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide
+ * <dui0646b_cortex_m7_dgug.pdf> param SubRegionDisable Sub-region disable field. 0=sub-region is enabled,
+ * 1=sub-region is disabled. param Size Region size of the region to be configured. use
+ * ARM_MPU_REGION_SIZE_xxx MACRO in core_cm7.h.
+ */
+
+ /* Region 0 setting: Memory with Device type, not shareable, non-cacheable. */
+ MPU->RBAR = ARM_MPU_RBAR(0, 0xC0000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
+
+ /* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */
+ MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);
+
+ /* Region 2 setting */
#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
- /* Setting Memory with Normal type, not shareable, outer/inner write back. */
- MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512MB);
+ /* Setting Memory with Normal type, not shareable, outer/inner write back. */
+ MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512MB);
#else
- /* Setting Memory with Device type, not shareable, non-cacheable. */
- // TODO: MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U);
- // TODO: MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
+ /* Setting Memory with Device type, not shareable, non-cacheable. */
+ // TODO: MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U);
+ // TODO: MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
#endif
- /* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */
- MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);
+ /* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */
+ MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);
- /* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */
- MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
+ /* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */
+ MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
- // CPU doesn't use cache when accessing TCM memories
- /* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
- MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB);
+ // CPU doesn't use cache when accessing TCM memories
+ /* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
+ MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB);
- // OCRAM configured as non-cached segment
- /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
- MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_64KB);
+ // OCRAM configured as non-cached segment
+ /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
+ MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_64KB);
- /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back
- * BOARD_SDRAM_TEXT
- */
- MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U);
+ /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back
+ * BOARD_SDRAM_TEXT
+ */
+ MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U);
#if defined(HW_SDRAM_64_MB) && (HW_SDRAM_64_MB == 1)
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#else
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
#endif
- /* The define sets the cacheable memory to shareable,
- * this suggestion is referred from chapter 2.2.1 Memory regions,
- * types and attributes in Cortex-M7 Devices, Generic User Guide */
+ /* The define sets the cacheable memory to shareable,
+ * this suggestion is referred from chapter 2.2.1 Memory regions,
+ * types and attributes in Cortex-M7 Devices, Generic User Guide */
#if defined(SDRAM_IS_SHAREABLE)
- /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
- MPU->RBAR = ARM_MPU_RBAR(8, 0x80000000U);
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 1, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB);
+ /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
+ MPU->RBAR = ARM_MPU_RBAR(8, 0x80000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 1, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB);
#else
- /* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back
- * BOARD_SDRAM_HEAP
- */
- MPU->RBAR = ARM_MPU_RBAR(9, reinterpret_cast<std::uintptr_t>(__sdram_cached_start));
+ /* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back
+ * BOARD_SDRAM_HEAP
+ */
+ MPU->RBAR = ARM_MPU_RBAR(9, reinterpret_cast<std::uintptr_t>(__sdram_cached_start));
#if defined(HW_SDRAM_64_MB) && (HW_SDRAM_64_MB == 1)
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#else
- MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
#endif // HW_SDRAM_64_MB
#endif // SDRAM_IS_SHAREABLE
- /* Enable MPU */
- ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
+ /* Enable MPU */
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
- SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
+ SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
- /* Enable I cache and D cache */
- SCB_EnableDCache();
- SCB_EnableICache();
- }
+ /* Enable I cache and D cache */
+ SCB_EnableDCache();
+ SCB_EnableICache();
+ }
+ } // namespace
void board_init()
{
@@ 182,6 195,8 @@ namespace bsp
PrintSystemClocks();
clearAndPrintBootReason();
+ board_configure();
+
if (SNVS->LPGPR[1] != 0) {
LOG_INFO("Device seems to have been reset by RTWDOG! Last instruction address: 0x%08lX",
SNVS->LPGPR[1]);
@@ 189,49 204,32 @@ namespace bsp
}
}
- //! Board PowerOff function by cutdown power
+ //! Board PowerOff function by power cutoff
void board_power_off()
{
- rebootProgress = rebootState::poweroff;
+ rebootProgress = RebootState::Poweroff;
}
- //! Board reboot by the SVNC code
+ //! Board reboot by the SNVS code
void board_restart()
{
- rebootProgress = rebootState::reboot;
+ rebootProgress = RebootState::Reboot;
}
- struct PlatformExitObject
+ int register_exit_function(void (*func)())
{
- void (*func)();
- };
- static unsigned short iObject = 0;
- constexpr auto MAX_PLATFORM_EXIT_OBJECTS = 16u;
-
- static PlatformExitObject objects[MAX_PLATFORM_EXIT_OBJECTS];
-
- int register_exit_functions(void (*func)())
- {
- if (iObject >= sizeof(objects)) {
- return -1;
+ if (registeredObjectsCount >= sizeof(exitObjects)) {
+ return -ENOMEM;
}
- objects[iObject].func = func;
- ++iObject;
+ exitObjects[registeredObjectsCount].func = func;
+ ++registeredObjectsCount;
return 0;
}
- void CallPlatformExitFunctions()
- {
- while (iObject > 0) {
- objects[--iObject].func();
- }
- }
-
extern "C" void _platform_exit(void)
{
- CallPlatformExitFunctions();
+ call_platform_exit_functions();
bsp::board_exit(rebootProgress);
}
-
} // namespace bsp
M module-bsp/board/rt1051/common/startup_mimxrt1052.cpp => module-bsp/board/rt1051/common/startup_mimxrt1052.cpp +15 -3
@@ 681,10 681,10 @@ __attribute__((section(".after_vectors.init_bss"))) void bss_init(unsigned int s
// contains the load address, execution address and length of each RW data
// section and the execution and length of each BSS (zero initialized) section.
//*****************************************************************************
-extern unsigned int __textram_section_table;
-extern unsigned int __textram_section_table_end;
extern unsigned int __data_section_table;
extern unsigned int __data_section_table_end;
+extern unsigned int __ocramtext_section_table;
+extern unsigned int __ocramtext_section_table_end;
extern unsigned int __bss_section_table;
extern unsigned int __bss_section_table_end;
@@ 706,7 706,7 @@ __attribute__((section(".after_vectors.reset"))) void ResetISR(void)
// Load base address of Global Section Table
SectionTableAddr = &__data_section_table;
- // Copy the data sections from flash to SRAM.
+ // Copy the data sections from flash to SRAM
while (SectionTableAddr < &__data_section_table_end) {
LoadAddr = *SectionTableAddr++;
ExeAddr = *SectionTableAddr++;
@@ 716,6 716,18 @@ __attribute__((section(".after_vectors.reset"))) void ResetISR(void)
}
}
+ // Load address of OCRAM text section entry in GST
+ SectionTableAddr = &__ocramtext_section_table;
+ // Copy code from SDRAM to OCRAM
+ while (SectionTableAddr < &__ocramtext_section_table_end) {
+ LoadAddr = *SectionTableAddr++;
+ ExeAddr = *SectionTableAddr++;
+ SectionLen = *SectionTableAddr++;
+ if (LoadAddr != ExeAddr) {
+ data_init(LoadAddr, ExeAddr, SectionLen);
+ }
+ }
+
// Initialize BSS section
SectionTableAddr = &__bss_section_table;
// Zero fill the bss segment
M module-bsp/board/rt1051/os/fsl_runtimestat_gpt.c => module-bsp/board/rt1051/os/fsl_runtimestat_gpt.c +16 -2
@@ 1,7 1,11 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "fsl_gpt.h"
+#include <fsl_runtimestat_gpt.h>
+#include <fsl_gpt.h>
+
+static const uint32_t millisecondsInSecond = 1000U;
+static const uint32_t runTimeStatsClockHz = 10000U;
static inline GPT_Type *vPortGetGptBase(void)
{
@@ 31,7 35,17 @@ void vConfigureTimerForRunTimeStats(void)
GPT_StartTimer(pxGptBase);
}
+uint32_t ulHighFrequencyTimerTicksToMs(uint32_t ticks)
+{
+ return (ticks / (runTimeStatsClockHz / millisecondsInSecond));
+}
+
uint32_t ulHighFrequencyTimerTicks(void)
{
return GPT_GetCurrentTimerCount(vPortGetGptBase());
}
+
+uint32_t ulHighFrequencyTimerMs(void)
+{
+ return ulHighFrequencyTimerTicksToMs(ulHighFrequencyTimerTicks());
+}
A module-bsp/board/rt1051/os/include/fsl_runtimestat_gpt.h => module-bsp/board/rt1051/os/include/fsl_runtimestat_gpt.h +19 -0
@@ 0,0 1,19 @@
+// 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 <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void vConfigureTimerForRunTimeStats(void);
+ uint32_t ulHighFrequencyTimerTicks(void);
+ uint32_t ulHighFrequencyTimerMs(void);
+ uint32_t ulHighFrequencyTimerTicksToMs(uint32_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
M module-bsp/board/rt1051/os/include/macros.h => module-bsp/board/rt1051/os/include/macros.h +3 -6
@@ 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
@@ 17,11 17,6 @@
#define CACHEABLE_SECTION_SDRAM_ALIGN(var, alignbytes) \
__attribute__((section(".sdram"))) __attribute__((aligned(alignbytes))) var
-#define NONCACHEABLE_SECTION_DMA(var) __attribute__((section(".intramnoncacheable"))) var
-
-#define NONCACHEABLE_SECTION_DMA_ALIGN(var, alignbytes) \
- __attribute__((section(".intramnoncacheable"))) var __attribute__((aligned(alignbytes)))
-
#define NONCACHEABLE_SECTION_SDRAM(var) var
#define NONCACHEABLE_SECTION_SDRAM_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
@@ 36,6 31,8 @@
#define NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
+#define WFI_CODE_SECTION(var) __attribute__((section(".wficode"), noinline)) var
+
static inline uint32_t IS_MEM_ADDR_CACHED(void *addr)
{
extern uint32_t __ocram_noncached_start[];
M module-bsp/board/rt1051/puretx/board.cpp => module-bsp/board/rt1051/puretx/board.cpp +10 -5
@@ 15,7 15,7 @@ namespace
using namespace drivers;
auto gpio_power = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::POWER_SWITCH_HOLD_GPIO),
DriverGPIOParams{});
- gpio_power->WritePin(static_cast<uint32_t>(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON), 0);
+ gpio_power->WritePin(static_cast<std::uint32_t>(BoardDefinitions::POWER_SWITCH_HOLD_BUTTON), 0);
}
void board_reset()
@@ 26,15 26,20 @@ namespace
namespace bsp
{
- void board_exit(rebootState state)
+ void board_configure()
+ {
+ // no-op for Pure
+ }
+
+ void board_exit(RebootState state)
{
switch (state) {
- case rebootState::none:
+ case RebootState::None:
break;
- case rebootState::poweroff:
+ case RebootState::Poweroff:
board_shutdown();
break;
- case rebootState::reboot:
+ case RebootState::Reboot:
board_reset();
break;
}
M module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.cpp +17 -0
@@ 42,4 42,21 @@ namespace bsp
{
gpio_2->WritePin(static_cast<std::uint32_t>(BoardDefinitions::DCDC_INVERTER_MODE_PIN), 1);
}
+
+ void RT1051LPM::AllowEnteringWfiMode()
+ {}
+
+ void RT1051LPM::BlockEnteringWfiMode()
+ {}
+
+ std::uint32_t RT1051LPM::EnterWfiModeIfAllowed()
+ {
+ return 0;
+ }
+
+ std::uint32_t RT1051LPM::GetLastTimeSpentInWfi()
+ {
+ return 0;
+ }
+
} // namespace bsp
M module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/puretx/bsp/lpm/RT1051LPM.hpp +5 -0
@@ 14,6 14,11 @@ namespace bsp
void EnableDcdcPowerSaveMode() final;
void DisableDcdcPowerSaveMode() final;
+ void AllowEnteringWfiMode() final;
+ void BlockEnteringWfiMode() final;
+ std::uint32_t EnterWfiModeIfAllowed() final;
+ std::uint32_t GetLastTimeSpentInWfi() final;
+
private:
std::shared_ptr<drivers::DriverGPIO> gpio_1;
std::shared_ptr<drivers::DriverGPIO> gpio_2;
M module-bsp/bsp/bsp.hpp => module-bsp/bsp/bsp.hpp +9 -8
@@ 4,22 4,23 @@
namespace bsp
{
- enum class rebootState : uintptr_t
+ enum class RebootState : std::uintptr_t
{
- none,
- poweroff,
- reboot
+ None,
+ Poweroff,
+ Reboot
};
void board_init();
-
void board_power_off();
-
void board_restart();
/// Register platform exit functions
- int register_exit_functions(void (*func)());
+ int register_exit_function(void (*func)());
+
+ /// Board-specific configuration procedure. Currently used to perform WFI-related config for Harmony.
+ void board_configure();
/// Board-specific exit/reset procedure. It is the main exit point from the system.
- [[noreturn]] void board_exit(rebootState);
+ [[noreturn]] void board_exit(RebootState state);
} // namespace bsp
M module-bsp/bsp/lpm/bsp_lpm.hpp => module-bsp/bsp/lpm/bsp_lpm.hpp +7 -0
@@ 51,6 51,13 @@ namespace bsp
virtual void EnableDcdcPowerSaveMode() = 0;
virtual void DisableDcdcPowerSaveMode() = 0;
+ virtual void AllowEnteringWfiMode() = 0;
+ virtual void BlockEnteringWfiMode() = 0;
+ virtual std::uint32_t EnterWfiModeIfAllowed() = 0;
+ virtual std::uint32_t GetLastTimeSpentInWfi() = 0;
+
+ virtual void DisableSysTick() = 0;
+ virtual void EnableSysTick() = 0;
protected:
CpuFrequencyMHz currentFrequency = CpuFrequencyMHz::Level_6;
};
M module-platform/rt1051/src/RT1051Platform.cpp => module-platform/rt1051/src/RT1051Platform.cpp +4 -4
@@ 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 <platform/rt1051/RT1051Platform.hpp>
@@ 16,7 16,7 @@ using platform::rt1051::RT1051Platform;
RT1051Platform::RT1051Platform()
{
bsp::board_init();
- bsp::register_exit_functions(Log::Logger::destroyInstance);
+ bsp::register_exit_function(Log::Logger::destroyInstance);
}
void RT1051Platform::init()
@@ 33,7 33,7 @@ void RT1051Platform::initFilesystem()
auto blockDeviceFactory = std::make_unique<BlockDeviceFactory>();
vfs = purefs::subsystem::initialize(std::move(blockDeviceFactory));
- if (int err = purefs::subsystem::mount_defaults(); err != 0) {
+ if (const auto err = purefs::subsystem::mount_defaults(); err != 0) {
throw std::runtime_error("Failed to initiate filesystem: " + std::to_string(err));
}
@@ 42,7 42,7 @@ void RT1051Platform::initFilesystem()
void platform::rt1051::RT1051Platform::deinit()
{
if (usesFilesystem) {
- if (int err = purefs::subsystem::unmount_all(); err != 0) {
+ if (const auto err = purefs::subsystem::unmount_all(); err != 0) {
throw std::runtime_error("Failed to unmount all: " + std::to_string(err));
}
usesFilesystem = false;
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +1 -1
@@ 75,7 75,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
cpuSentinel = std::make_shared<sys::CpuSentinel>(service::name::bluetooth, this);
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
- bus.sendUnicast(sentinelRegistrationMsg, service::name::system_manager);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
connectionTimeoutTimer =
sys::TimerFactory::createSingleShotTimer(this, "btTimeoutTimer", connectionTimeout, [this](sys::Timer &_) {
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +1 -1
@@ 276,7 276,7 @@ sys::ReturnCodes ServiceCellular::InitHandler()
cpuSentinel);
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
- bus.sendUnicast(sentinelRegistrationMsg, ::service::name::system_manager);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), ::service::name::system_manager);
cmux->registerCellularDevice();
M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +4 -4
@@ 95,11 95,11 @@ namespace service::eink
settings->init(service::ServiceProxy(shared_from_this()));
initStaticData();
- const auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(display->getDevice());
- bus.sendUnicast(deviceRegistrationMsg, service::name::system_manager);
+ auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(display->getDevice());
+ bus.sendUnicast(std::move(deviceRegistrationMsg), service::name::system_manager);
- const auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(eInkSentinel);
- bus.sendUnicast(sentinelRegistrationMsg, service::name::system_manager);
+ auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(eInkSentinel);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
eInkSentinel->HoldMinimumFrequency();
M module-sys/SystemManager/CpuGovernor.cpp => module-sys/SystemManager/CpuGovernor.cpp +39 -0
@@ 68,6 68,16 @@ namespace sys
requestedFrequency = newFrequency;
}
+ void GovernorSentinel::BlockWfiMode(bool request)
+ {
+ wfiBlocked = request;
+ }
+
+ [[nodiscard]] auto GovernorSentinel::IsWfiBlocked() const noexcept -> bool
+ {
+ return wfiBlocked;
+ }
+
bool CpuGovernor::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel)
{
if (newSentinel) {
@@ 149,6 159,25 @@ namespace sys
SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyMHz::Level_0);
}
+ void CpuGovernor::BlockWfiMode(const std::string &sentinelName, bool request)
+ {
+ auto isSentinelRecognized = false;
+ for (auto &sentinel : sentinels) {
+ auto sentinelWeakPointer = sentinel->GetSentinel();
+ if (!sentinelWeakPointer.expired()) {
+ std::shared_ptr<CpuSentinel> sharedResource = sentinelWeakPointer.lock();
+ if (sharedResource->GetName() == sentinelName) {
+ sentinel->BlockWfiMode(request);
+ isSentinelRecognized = true;
+ break;
+ }
+ }
+ }
+ if (!isSentinelRecognized) {
+ LOG_WARN("Sentinel %s is not recognized!", sentinelName.c_str());
+ }
+ }
+
[[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() noexcept -> sentinel::View
{
sentinel::View d;
@@ 174,6 203,16 @@ namespace sys
return d;
}
+ [[nodiscard]] auto CpuGovernor::IsWfiBlocked() noexcept -> bool
+ {
+ for (auto &sentinel : sentinels) {
+ if (sentinel->IsWfiBlocked()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void CpuGovernor::InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) noexcept
{
sentinel_foo foo = [&newFrequency](const std::shared_ptr<CpuSentinel> &s) -> bool {
M module-sys/SystemManager/CpuSentinel.cpp => module-sys/SystemManager/CpuSentinel.cpp +18 -6
@@ 4,6 4,7 @@
#include <SystemManager/CpuSentinel.hpp>
#include "system/messages/RequestCpuFrequencyMessage.hpp"
#include "system/messages/HoldCpuFrequency.hpp"
+#include "system/messages/BlockWfiMode.hpp"
#include "system/Constants.hpp"
#include <Timers/TimerFactory.hpp>
#include <memory>
@@ 19,7 20,7 @@ namespace sys
CpuSentinel::CpuSentinel(std::string name,
sys::Service *service,
std::function<void(bsp::CpuFrequencyMHz)> callback)
- : name(name), owner(service), callback(callback)
+ : name(std::move(name)), owner(service), callback(std::move(callback))
{}
[[nodiscard]] auto CpuSentinel::GetName() const noexcept -> std::string
@@ 36,7 37,7 @@ namespace sys
owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
currentFrequencyToHold = frequencyToHold;
currentReason = std::string("up: ") + owner->getCurrentProcessing() + std::string(" req: ") +
- std::to_string(int(frequencyToHold));
+ std::to_string(static_cast<int>(frequencyToHold));
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
}
}
@@ 51,6 52,16 @@ namespace sys
}
}
+ void CpuSentinel::BlockWfiMode(bool block)
+ {
+ if (blockWfiMode != block) {
+ auto msg = std::make_shared<sys::BlockWfiModeMessage>(GetName(), block, xTaskGetCurrentTaskHandle());
+ owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
+ blockWfiMode = block;
+ ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
+ }
+ }
+
[[nodiscard]] auto CpuSentinel::GetFrequency() const noexcept -> bsp::CpuFrequencyMHz
{
return currentFrequency;
@@ 85,10 96,11 @@ namespace sys
}
TimedCpuSentinel::TimedCpuSentinel(std::string name, sys::Service *service)
- : CpuSentinel(name, service), timerHandle{sys::TimerFactory::createSingleShotTimer(
- owner, "holdFrequencyTimer", defaultHoldFrequencyTime, [this](sys::Timer &) {
- ReleaseMinimumFrequency();
- })}
+ : CpuSentinel(std::move(name), service), timerHandle{sys::TimerFactory::createSingleShotTimer(
+ owner,
+ "holdFrequencyTimer",
+ defaultHoldFrequencyTime,
+ [this](sys::Timer &) { ReleaseMinimumFrequency(); })}
{}
TimedCpuSentinel::~TimedCpuSentinel()
M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +46 -8
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SystemManager/cpu/algorithm/FrequencyHold.hpp"
@@ 12,6 12,8 @@
#include <log/log.hpp>
#include <Logger.hpp>
#include <Utils.hpp>
+#include <FreeRTOS.h>
+#include <ticks.hpp>
namespace sys
{
@@ 20,6 22,7 @@ namespace sys
constexpr auto lowestLevelName{"lowestCpuFrequency"};
constexpr auto middleLevelName{"middleCpuFrequency"};
constexpr auto highestLevelName{"highestCpuFrequency"};
+ constexpr auto WfiName{"WFI"};
constexpr bsp::CpuFrequencyMHz logDumpFrequencyToHold{bsp::CpuFrequencyMHz::Level_4};
} // namespace
@@ 72,9 75,10 @@ namespace sys
cpuAlgorithms->emplace(sys::cpu::AlgoID::FrequencyStepping,
std::make_unique<sys::cpu::FrequencyStepping>(powerProfile));
- cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(lowestLevelName));
- cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(middleLevelName));
- cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(highestLevelName));
+ cpuFrequencyMonitors.push_back(CpuFrequencyMonitor(lowestLevelName));
+ cpuFrequencyMonitors.push_back(CpuFrequencyMonitor(middleLevelName));
+ cpuFrequencyMonitors.push_back(CpuFrequencyMonitor(highestLevelName));
+ cpuFrequencyMonitors.push_back(CpuFrequencyMonitor(WfiName));
}
PowerManager::~PowerManager()
@@ 115,7 119,7 @@ namespace sys
[[nodiscard]] cpu::UpdateResult PowerManager::UpdateCpuFrequency()
{
- std::uint32_t cpuLoad = cpuStatistics.GetPercentageCpuLoad();
+ const std::uint32_t cpuLoad = cpuStatistics.GetPercentageCpuLoad();
cpu::UpdateResult retval;
const cpu::AlgorithmData data{
cpuLoad, lowPowerControl->GetCurrentFrequencyLevel(), GetMinimumCpuFrequencyRequested()};
@@ 147,7 151,7 @@ namespace sys
void PowerManager::RemoveSentinel(std::string sentinelName) const
{
- cpuGovernor->RemoveSentinel(sentinelName);
+ cpuGovernor->RemoveSentinel(std::move(sentinelName));
}
void PowerManager::SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request)
@@ 164,6 168,11 @@ namespace sys
cpuStatistics.TrackChange(ret);
}
+ void PowerManager::BlockWfiMode(const std::string &sentinelName, bool block)
+ {
+ cpuGovernor->BlockWfiMode(sentinelName, block);
+ }
+
bool PowerManager::IsCpuPermanentFrequency()
{
return cpuAlgorithms->get(sys::cpu::AlgoID::FrequencyHold) != nullptr;
@@ 210,7 219,7 @@ namespace sys
? lowestLevelName
: (currentFreq == bsp::CpuFrequencyMHz::Level_6 ? highestLevelName : middleLevelName);
- for (auto &level : cpuFrequencyMonitor) {
+ for (auto &level : cpuFrequencyMonitors) {
if (level.GetName() == levelName) {
level.IncreaseTicks(ticks - lastCpuFrequencyChangeTimestamp);
}
@@ 219,6 228,35 @@ namespace sys
lastCpuFrequencyChangeTimestamp = ticks;
}
+ void PowerManager::UpdateCpuFrequencyMonitor(const std::string &name, std::uint32_t tickIncrease)
+ {
+ for (auto &level : cpuFrequencyMonitors) {
+ if (level.GetName() == name) {
+ level.IncreaseTicks(tickIncrease);
+ }
+ }
+ }
+
+ void PowerManager::EnterWfiIfReady()
+ {
+ if (cpuGovernor->IsWfiBlocked()) {
+ return;
+ }
+
+ const auto timeSpentInWFI = lowPowerControl->EnterWfiModeIfAllowed();
+ if (timeSpentInWFI > 0) {
+ /* We increase the frequency immediately after exiting WFI so that the xTaskCatchUpTicks procedure has
+ * time to execute and does not block the button press detection mechanism. */
+ SetCpuFrequency(bsp::CpuFrequencyMHz::Level_4);
+ portENTER_CRITICAL();
+ lowPowerControl->DisableSysTick();
+ xTaskCatchUpTicks(cpp_freertos::Ticks::MsToTicks(timeSpentInWFI));
+ lowPowerControl->EnableSysTick();
+ portEXIT_CRITICAL();
+ UpdateCpuFrequencyMonitor(WfiName, timeSpentInWFI);
+ }
+ }
+
void PowerManager::LogPowerManagerStatistics()
{
const TickType_t tickCount = xTaskGetTickCount();
@@ 226,7 264,7 @@ namespace sys
UpdateCpuFrequencyMonitor(lowPowerControl->GetCurrentFrequencyLevel());
std::string log{"Last period (total): "};
- for (auto &level : cpuFrequencyMonitor) {
+ for (auto &level : cpuFrequencyMonitors) {
log.append(level.GetName() + ": " + std::to_string(level.GetPeriodRuntimePercentage(periodTickIncrease)) +
"% (" + std::to_string(level.GetTotalRuntimePercentage(tickCount)) + "%) ");
level.SavePeriodTicks();
M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +13 -1
@@ 24,6 24,7 @@
#include <system/messages/SentinelRegistrationMessage.hpp>
#include <system/messages/RequestCpuFrequencyMessage.hpp>
#include <system/messages/HoldCpuFrequency.hpp>
+#include <system/messages/BlockWfiMode.hpp>
#include <time/ScopedTime.hpp>
#include "Timers/TimerFactory.hpp"
#include <service-appmgr/StartupType.hpp>
@@ 240,7 241,7 @@ namespace sys
// Start System manager
StartService();
- freqTimer = sys::TimerFactory::createPeriodicTimer(
+ freqTimer = sys::TimerFactory::createSingleShotTimer(
this, "cpuTick", constants::timerInitInterval, [this](sys::Timer &) { FreqUpdateTick(); });
freqTimer.start();
@@ 654,6 655,15 @@ namespace sys
return sys::MessageNone{};
});
+ connect(typeid(sys::BlockWfiModeMessage), [this](sys::Message *message) -> sys::MessagePointer {
+ auto msg = static_cast<sys::BlockWfiModeMessage *>(message);
+ powerManager->BlockWfiMode(msg->getName(), msg->getRequest());
+ if (msg->getHandle() != nullptr) {
+ xTaskNotifyGive(msg->getHandle());
+ }
+ return sys::MessageNone{};
+ });
+
connect(typeid(sys::IsCpuPermanent), [this](sys::Message *message) -> sys::MessagePointer {
return std::make_shared<sys::IsCpuPermanentResponse>(powerManager->IsCpuPermanentFrequency());
});
@@ 787,6 797,8 @@ namespace sys
auto ret = powerManager->UpdateCpuFrequency();
cpuStatistics->TrackChange(ret);
+ powerManager->EnterWfiIfReady();
+ freqTimer.restart(constants::timerPeriodInterval);
}
void SystemManagerCommon::UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency)
M module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp => module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp +5 -0
@@ 20,10 20,13 @@ namespace sys
[[nodiscard]] auto GetSentinel() const noexcept -> SentinelPointer;
[[nodiscard]] auto GetRequestedFrequency() const noexcept -> bsp::CpuFrequencyMHz;
void SetRequestedFrequency(bsp::CpuFrequencyMHz newFrequency);
+ void BlockWfiMode(bool request);
+ [[nodiscard]] auto IsWfiBlocked() const noexcept -> bool;
private:
SentinelPointer sentinelPtr;
bsp::CpuFrequencyMHz requestedFrequency;
+ bool wfiBlocked{false};
};
using GovernorSentinelPointer = std::unique_ptr<GovernorSentinel>;
@@ 43,8 46,10 @@ namespace sys
void SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request);
void ResetCpuFrequencyRequest(const std::string &sentinelName);
+ void BlockWfiMode(const std::string &sentinelName, bool request);
[[nodiscard]] auto GetMinimumFrequencyRequested() noexcept -> sentinel::View;
+ [[nodiscard]] auto IsWfiBlocked() noexcept -> bool;
void InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) noexcept;
private:
M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp => module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp +5 -0
@@ 29,6 29,10 @@ namespace sys
virtual void HoldMinimumFrequency(bsp::CpuFrequencyMHz frequencyToHold);
virtual void ReleaseMinimumFrequency();
+ /// @brief function used to block entering WFI mode (CPU stop)
+ /// @param block - boolean flag with blocking command
+ void BlockWfiMode(bool block);
+
[[nodiscard]] auto GetFrequency() const noexcept -> bsp::CpuFrequencyMHz;
void CpuFrequencyHasChanged(bsp::CpuFrequencyMHz newFrequency);
@@ 47,6 51,7 @@ namespace sys
std::atomic<bsp::CpuFrequencyMHz> currentFrequency{bsp::CpuFrequencyMHz::Level_0};
sys::Service *owner{nullptr};
TickType_t holdTicks;
+ bool blockWfiMode{false};
/// function called from the PowerManager context
/// to update resources immediately
M module-sys/SystemManager/include/SystemManager/PowerManager.hpp => module-sys/SystemManager/include/SystemManager/PowerManager.hpp +8 -10
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 29,10 29,8 @@ namespace sys
explicit CpuFrequencyMonitor(const std::string &name);
[[nodiscard]] auto GetName() const noexcept -> std::string;
- [[nodiscard]] auto GetPeriodRuntimePercentage(const TickType_t periodTicksIncrease) const noexcept
- -> std::uint32_t;
- [[nodiscard]] auto GetTotalRuntimePercentage(const TickType_t totalTicksIncrease) const noexcept
- -> std::uint32_t;
+ [[nodiscard]] auto GetPeriodRuntimePercentage(TickType_t periodTicksIncrease) const noexcept -> std::uint32_t;
+ [[nodiscard]] auto GetTotalRuntimePercentage(TickType_t totalTicksIncrease) const noexcept -> std::uint32_t;
void IncreaseTicks(TickType_t ticks);
void SavePeriodTicks();
@@ 45,7 43,7 @@ namespace sys
class PowerManager
{
public:
- explicit PowerManager(CpuStatistics &cpuStats, TaskStatistics &taskStats);
+ PowerManager(CpuStatistics &cpuStats, TaskStatistics &taskStats);
~PowerManager();
std::int32_t PowerOff();
@@ 70,19 68,20 @@ namespace sys
bool IsCpuPermanentFrequency();
void SetPermanentFrequency(bsp::CpuFrequencyMHz freq);
void ResetPermanentFrequency();
-
+ void BlockWfiMode(const std::string &sentinelName, bool block);
+ void EnterWfiIfReady();
void LogPowerManagerStatistics();
private:
void SetCpuFrequency(bsp::CpuFrequencyMHz freq);
-
void UpdateCpuFrequencyMonitor(bsp::CpuFrequencyMHz currentFreq);
+ void UpdateCpuFrequencyMonitor(const std::string &name, std::uint32_t tickIncrease);
[[nodiscard]] auto GetMinimumCpuFrequencyRequested() const noexcept -> sentinel::View;
TickType_t lastCpuFrequencyChangeTimestamp{0};
TickType_t lastLogStatisticsTimestamp{0};
- std::vector<CpuFrequencyMonitor> cpuFrequencyMonitor;
+ std::vector<CpuFrequencyMonitor> cpuFrequencyMonitors;
std::shared_ptr<drivers::DriverSEMC> driverSEMC;
std::unique_ptr<bsp::LowPowerMode> lowPowerControl;
@@ 94,5 93,4 @@ namespace sys
CpuStatistics &cpuStatistics;
TaskStatistics &taskStatistics;
};
-
} // namespace sys
A module-sys/common/include/system/messages/BlockWfiMode.hpp => module-sys/common/include/system/messages/BlockWfiMode.hpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include <Service/Message.hpp>
+#include <bsp/common.hpp>
+
+namespace sys
+{
+ class BlockWfiModeMessage : public sys::DataMessage
+ {
+ public:
+ BlockWfiModeMessage(std::string sentinelName, bool block, TaskHandle_t handle)
+ : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName)),
+ block(block), handle(handle)
+ {}
+
+ [[nodiscard]] auto getRequest() const noexcept
+ {
+ return block;
+ };
+
+ [[nodiscard]] auto getName() const
+ {
+ return sentinelName;
+ };
+
+ [[nodiscard]] TaskHandle_t getHandle() const
+ {
+ return handle;
+ }
+
+ private:
+ std::string sentinelName;
+ bool block;
+ TaskHandle_t handle;
+ };
+} // namespace sys
M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +0 -9
@@ 23,7 23,6 @@
#include <audio/ServiceAudio.hpp>
#include <db/ServiceDB.hpp>
#include <evtmgr/EventManager.hpp>
-#include <Service/ServiceCreator.hpp>
#include <service-appmgr/ServiceApplicationManagerName.hpp>
#include <service-desktop/ServiceDesktop.hpp>
#include <service-eink/ServiceEink.hpp>
@@ 31,21 30,13 @@
#include <service-time/ServiceTime.hpp>
#include <service-fileindexer/ServiceFileIndexer.hpp>
-#include <Application.hpp>
-#include <ApplicationLauncher.hpp>
-#include <log/log.hpp>
#include <logdump/logdump.h>
#include <Logger.hpp>
#include <product/version.hpp>
#include <sys/SystemManager.hpp>
-#include <SystemWatchdog/SystemWatchdog.hpp>
-#include <thread.hpp>
#include <time/AlarmOperations.hpp>
#include <Paths.hpp>
-#include <memory>
-#include <vector>
-
#if SYSTEM_VIEW_ENABLED
#include <SEGGER/SEGGER_SYSVIEW.h>
#endif
M products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp => products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp +11 -1
@@ 25,6 25,8 @@
#include <common/windows/SessionPausedWindow.hpp>
#include <common/windows/AppsBatteryStatusWindow.hpp>
+#include <system/messages/SentinelRegistrationMessage.hpp>
+
namespace app
{
MeditationTimer::MeditationTimer(std::string name,
@@ 55,6 57,11 @@ namespace app
return ret;
}
+ cpuSentinel = std::make_shared<sys::CpuSentinel>(defaultName, this);
+ auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
+ cpuSentinel->BlockWfiMode(true);
+
audioModel = std::make_unique<AudioModel>(this);
chimeIntervalModel = std::make_unique<meditation::models::ChimeInterval>(this);
chimeVolumeModel = std::make_unique<meditation::models::ChimeVolume>(*audioModel);
@@ 139,5 146,8 @@ namespace app
return handleAsyncResponse(resp);
}
- MeditationTimer::~MeditationTimer() = default;
+ MeditationTimer::~MeditationTimer()
+ {
+ cpuSentinel->BlockWfiMode(false);
+ }
} // namespace app
M products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp => products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp +1 -0
@@ 49,6 49,7 @@ namespace app
std::unique_ptr<app::meditation::models::StartDelay> startDelayModel;
std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<app::meditation::models::Statistics> statisticsModel;
+ std::shared_ptr<sys::CpuSentinel> cpuSentinel;
std::unique_ptr<AbstractBatteryModel> batteryModel;
std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
};
M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp => products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ApplicationBellOnBoarding.hpp"
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +12 -1
@@ 9,6 9,7 @@
#include <common/models/TimeModel.hpp>
#include <Paths.hpp>
#include <common/windows/SessionPausedWindow.hpp>
+#include <system/messages/SentinelRegistrationMessage.hpp>
namespace app
{
@@ 23,13 24,23 @@ namespace app
bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
}
- ApplicationBellPowerNap::~ApplicationBellPowerNap() = default;
+ ApplicationBellPowerNap::~ApplicationBellPowerNap()
+ {
+ cpuSentinel->BlockWfiMode(false);
+ }
+
sys::ReturnCodes ApplicationBellPowerNap::InitHandler()
{
auto ret = Application::InitHandler();
if (ret != sys::ReturnCodes::Success) {
return ret;
}
+
+ cpuSentinel = std::make_shared<sys::CpuSentinel>(applicationBellPowerNapName, this);
+ auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
+ cpuSentinel->BlockWfiMode(true);
+
createUserInterface();
return sys::ReturnCodes::Success;
M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp => products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp +1 -0
@@ 22,6 22,7 @@ namespace app
{
private:
std::unique_ptr<AbstractAudioModel> audioModel;
+ std::shared_ptr<sys::CpuSentinel> cpuSentinel;
void onStop() override;
public:
M products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp => products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp +16 -7
@@ 28,6 28,7 @@
#include <common/windows/AppsBatteryStatusWindow.hpp>
#include <audio/AudioMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>
+#include <system/messages/SentinelRegistrationMessage.hpp>
#include <log/log.hpp>
@@ 50,7 51,11 @@ namespace app
bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
}
- ApplicationBellRelaxation::~ApplicationBellRelaxation() = default;
+
+ ApplicationBellRelaxation::~ApplicationBellRelaxation()
+ {
+ cpuSentinel->BlockWfiMode(false);
+ }
sys::ReturnCodes ApplicationBellRelaxation::InitHandler()
{
@@ 59,6 64,11 @@ namespace app
return ret;
}
+ cpuSentinel = std::make_shared<sys::CpuSentinel>(applicationBellRelaxationName, this);
+ auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
+ cpuSentinel->BlockWfiMode(true);
+
batteryModel = std::make_unique<app::BatteryModel>(this);
lowBatteryInfoModel = std::make_unique<app::LowBatteryInfoModel>();
player = std::make_unique<relaxation::RelaxationPlayer>(*audioModel);
@@ 111,12 121,11 @@ namespace app
return std::make_unique<gui::RelaxationRunningLoopWindow>(app, std::move(presenter));
});
- windowsFactory.attach(
- gui::window::name::relaxationPaused, [this](ApplicationCommon *app, const std::string &name) {
- auto timeModel = std::make_unique<app::TimeModel>();
- auto presenter = std::make_unique<relaxation::RelaxationPausedPresenter>(std::move(timeModel));
- return std::make_unique<gui::RelaxationPausedWindow>(app, std::move(presenter));
- });
+ windowsFactory.attach(gui::window::name::relaxationPaused, [](ApplicationCommon *app, const std::string &name) {
+ auto timeModel = std::make_unique<app::TimeModel>();
+ auto presenter = std::make_unique<relaxation::RelaxationPausedPresenter>(std::move(timeModel));
+ return std::make_unique<gui::RelaxationPausedWindow>(app, std::move(presenter));
+ });
windowsFactory.attach(gui::popup::window::volume_window,
[this](ApplicationCommon *app, const std::string &name) {
M products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp => products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp +1 -0
@@ 36,6 36,7 @@ namespace app
std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
std::unique_ptr<relaxation::RelaxationPlayer> player;
sys::TimerHandle relaxationRebuildTimerHandle{};
+ std::shared_ptr<sys::CpuSentinel> cpuSentinel;
void onStop() override;
sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassicWithDate.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassicWithDate.cpp +1 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "layouts/HomeScreenLayoutClassicWithDate.hpp"
@@ 86,5 86,4 @@ namespace gui
{
return true;
}
-
}; // namespace gui
M products/BellHybrid/apps/common/src/layouts/HomeScreenLayouts.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayouts.cpp +1 -2
@@ 1,5 1,5 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <common/layouts/HomeScreenLayoutNames.hpp>
@@ 80,5 80,4 @@ namespace gui::factory
{
return gui::layout::ClassicWithBattery;
}
-
} // namespace gui::factory
M products/BellHybrid/services/db/databases/migration/settings_bell/0/up.sql => products/BellHybrid/services/db/databases/migration/settings_bell/0/up.sql +1 -1
@@ 1,4 1,4 @@
--- Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+-- Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
--
M third-party/freeRTOS-kernel/freeRTOS-kernel => third-party/freeRTOS-kernel/freeRTOS-kernel +1 -1
@@ 1,1 1,1 @@
-Subproject commit f621edbabfb5690dbe4171b4243a5c6d40c7876b
+Subproject commit c5d50b33033b8496fcf631b6a183198511454dc0