~aleteoryx/muditaos

0c0fdef19b2a06d2be92d6177fca2c0ec4bcd31b — Maciej-Mudita 5 years ago 2b754af
[EGD-4881] Add oscillator clock switching mechanisms

Osc will change automatically at the lowest CPU frequency,
which will save power
M changelog.md => changelog.md +1 -0
@@ 17,6 17,7 @@
* Add custom repeat window for the alarm application.
* Add GUI for custom MMI messages.
* Add CPU frequency shift mechanism to save power.
* Add oscillator clock switching mechanisms.

### Fixed


M module-bsp/board/linux/lpm/LinuxLPM.cpp => module-bsp/board/linux/lpm/LinuxLPM.cpp +5 -0
@@ 24,4 24,9 @@ namespace bsp
    {
        currentFrequency = freq;
    }

    void LinuxLPM::SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource source)
    {
        currentOscSource = source;
    }
} // namespace bsp

M module-bsp/board/linux/lpm/LinuxLPM.h => module-bsp/board/linux/lpm/LinuxLPM.h +1 -0
@@ 16,6 16,7 @@ namespace bsp
        int32_t PowerOff() override final;
        int32_t Reboot() override final;
        void SetCpuFrequency(CpuFrequency freq) final;
        void SwitchOscillatorSource(OscillatorSource source) final;
    };

} // namespace bsp

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +43 -0
@@ 7,6 7,8 @@
#include "log/log.hpp"
#include "bsp/BoardDefinitions.hpp"
#include "bsp/watchdog/watchdog.hpp"
#include <fsl_clock.h>
#include <fsl_dcdc.h>

namespace bsp
{


@@ 66,4 68,45 @@ namespace bsp
        }
        LOG_INFO("CPU frequency changed to %lu", CLOCK_GetFreq(kCLOCK_CpuClk));
    }

    void RT1051LPM::SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource source)
    {
        if (source == bsp::LowPowerMode::OscillatorSource::Internal) {
            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;
            }

            /// Switch DCDC to use DCDC internal OSC
            DCDC_SetClockSource(DCDC, kDCDC_ClockInternalOsc);
            /// Switch clock source to internal RC
            CLOCK_SwitchOsc(kCLOCK_RcOsc);
            CLOCK_DeinitExternalClk();
            /// Wait CCM operation finishes
            while (CCM->CDHIPR != 0) {}
        }
        else if (source == bsp::LowPowerMode::OscillatorSource::External) {
            CLOCK_InitExternalClk(0);
            /// 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) {}
            /// Set Oscillator ready counter value.
            CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(bsp::OscillatorReadyCounterValue);
        }

        currentOscSource = source;
    }

    bool RT1051LPM::IsClockEnabled(clock_ip_name_t name) const noexcept
    {
        const auto index = static_cast<uint32_t>(name) >> CCM_TupleShift;
        const auto shift = static_cast<uint32_t>(name) & CCM_TupleMask;

        return ((*reinterpret_cast<volatile uint32_t *>(&CCM->CCGR0 + index)) & (ClockNeededRunWaitMode << shift));
    }

} // namespace bsp

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp +8 -0
@@ 7,9 7,14 @@
#include "bsp/lpm/bsp_lpm.hpp"
#include "drivers/gpio/DriverGPIO.hpp"
#include "CpuFreqLPM.hpp"
#include <fsl_clock.h>

namespace bsp
{
    inline constexpr uint8_t OscillatorReadyCounterValue{127};
    inline constexpr uint8_t CCM_TupleShift{8};
    inline constexpr uint8_t CCM_TupleMask{0x1F};
    inline constexpr uint32_t ClockNeededRunWaitMode{3};

    class RT1051LPM : public LowPowerMode
    {


@@ 18,8 23,11 @@ namespace bsp
        int32_t PowerOff() override final;
        int32_t Reboot() override final;
        void SetCpuFrequency(CpuFrequency freq) final;
        void SwitchOscillatorSource(OscillatorSource source) final;

      private:
        [[nodiscard]] bool IsClockEnabled(clock_ip_name_t name) const noexcept;

        std::shared_ptr<drivers::DriverGPIO> gpio;
        std::unique_ptr<bsp::CpuFreqLPM> CpuFreq;
    };

M module-bsp/bsp/lpm/bsp_lpm.cpp => module-bsp/bsp/lpm/bsp_lpm.cpp +5 -0
@@ 30,4 30,9 @@ namespace bsp{
    {
    	return currentFrequency;
    }

    LowPowerMode::OscillatorSource LowPowerMode::GetCurrentOscillatorSource() const noexcept
    {
    	return currentOscSource;
    }
}

M module-bsp/bsp/lpm/bsp_lpm.hpp => module-bsp/bsp/lpm/bsp_lpm.hpp +10 -0
@@ 18,6 18,11 @@ namespace bsp {
            Level_5, // 264 MHz
            Level_6  // 528 MHz
        };
        enum class OscillatorSource
        {
            External,
            Internal
        };

        LowPowerMode()          = default;
        virtual ~LowPowerMode() = default;


@@ 26,11 31,16 @@ namespace bsp {

        virtual int32_t PowerOff() = 0;
        virtual int32_t Reboot() = 0;

        virtual void SetCpuFrequency(CpuFrequency freq) = 0;
        [[nodiscard]] CpuFrequency GetCurrentFrequency() const noexcept;

        virtual void SwitchOscillatorSource(OscillatorSource source) = 0;
        [[nodiscard]] OscillatorSource GetCurrentOscillatorSource() const noexcept;

    protected:
        CpuFrequency currentFrequency = CpuFrequency::Level_6;
        OscillatorSource currentOscSource = OscillatorSource::External;
    };
} // namespace bsp


M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +18 -1
@@ 53,7 53,16 @@ namespace sys

    void PowerManager::IncreaseCpuFrequency() const
    {
        bsp::LowPowerMode::CpuFrequency freq = lowPowerControl->GetCurrentFrequency();
        const auto freq      = lowPowerControl->GetCurrentFrequency();
        const auto oscSource = lowPowerControl->GetCurrentOscillatorSource();

        /// switch osc source first
        if (freq == bsp::LowPowerMode::CpuFrequency::Level_1 &&
            oscSource == bsp::LowPowerMode::OscillatorSource::Internal) {
            lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::External);
        }

        /// then increase frequency
        if (freq < bsp::LowPowerMode::CpuFrequency::Level_6) {
            lowPowerControl->SetCpuFrequency(bsp::LowPowerMode::CpuFrequency::Level_6);
        }


@@ 62,6 71,7 @@ namespace sys
    void PowerManager::DecreaseCpuFrequency() const
    {
        const auto freq = lowPowerControl->GetCurrentFrequency();
        const auto oscSource = lowPowerControl->GetCurrentOscillatorSource();
        auto level      = bsp::LowPowerMode::CpuFrequency::Level_1;

        switch (freq) {


@@ 84,9 94,16 @@ namespace sys
            break;
        }

        /// decrease frequency first
        if (level != freq) {
            lowPowerControl->SetCpuFrequency(level);
        }

        /// then switch osc source
        if (level == bsp::LowPowerMode::CpuFrequency::Level_1 &&
            oscSource == bsp::LowPowerMode::OscillatorSource::External) {
            lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::Internal);
        }
    }

    void PowerManager::ResetFrequencyShiftCounter()