~aleteoryx/muditaos

3e1170daf75b79d6ef461b3b38e5d96683047c7d — Lefucjusz 2 years ago c1a8e47
[BH-1673] Harmony random resets fixes

* Switching VDD_SOC_IN only after PLL2 is turned off.
* Weak LDO stabilization delay.
* Removed switching to 1.275V before frequency change.
* Cleanups in LDO switching.
* Removed switching PeriphClk2Div for fCPU <= 24MHz,
using AhbDiv instead.
* Removed log from _exit that caused logger mutex deadlock
M module-bsp/board/rt1051/bellpx/clock_config.cpp => module-bsp/board/rt1051/bellpx/clock_config.cpp +1 -0
@@ 140,6 140,7 @@ void BOARD_BootClockRUN(void)
    /* OSC_CLK (24M) */
    CLOCK_SetMux(kCLOCK_PeriphClk2Mux,
                 1); // CBCMR (13-12) 0 - pll3_sw_clk, 1 - osc_clk (pll1_ref_clk), 2 - pll2_bypass_clk, 3 - reserved
    CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); // No division
    /* PERIPH_CLK2_SEL */
    CLOCK_SetMux(kCLOCK_PeriphMux, 1); // CBCDR (25) 0 - pre_periph_clk_sel, 1 - periph_clk2_clk_divided


M module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp => module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.cpp +15 -44
@@ 11,72 11,43 @@ namespace bsp

    void CpuFreqLPM::SetCpuFrequency(CpuFreqLPM::CpuClock freq)
    {
        DCDC_AdjustTargetVoltage(DCDC, VDDRun_1275_mV, VDDStandby_925_mV);

        switch (freq) {
        case CpuClock::CpuClock_Osc_4_Mhz:
            /* Set PERIPH_CLK2_PODF. */
            CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 2);
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 1); // CBCDR

            DCDC_AdjustTargetVoltage(DCDC, VDDRun_975_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv6);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourceOsc_24MHz);
            break;
        case CpuClock::CpuClock_Osc_12_Mhz:
            /* Set PERIPH_CLK2_PODF. */
            CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0);
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 1); // CBCDR

            DCDC_AdjustTargetVoltage(DCDC, VDDRun_975_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv2);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourceOsc_24MHz);
            break;
        case CpuClock::CpuClock_Osc_24_Mhz:
            /* Set PERIPH_CLK2_PODF. */
            CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0);
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 0); // CBCDR

            DCDC_AdjustTargetVoltage(DCDC, VDDRun_1050_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv1);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourceOsc_24MHz);
            break;
        case CpuClock::CpuClock_Pll2_66_Mhz:
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 7); // CBCDR
            DCDC_AdjustTargetVoltage(DCDC, VDDRun_1075_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv8);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourcePll2_528MHz);
            break;
        case CpuClock::CpuClock_Pll2_132_Mhz:
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 3); // CBCDR
            DCDC_AdjustTargetVoltage(DCDC, VDDRun_1100_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv4);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourcePll2_528MHz);
            break;
        case CpuClock::CpuClock_Pll2_264_Mhz:
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 1); // CBCDR
            DCDC_AdjustTargetVoltage(DCDC, VDDRun_1125_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv2);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourcePll2_528MHz);
            break;
        case CpuClock::CpuClock_Pll2_528_Mhz:
            /* Set AHB_PODF. */
            CLOCK_SetDiv(kCLOCK_AhbDiv, 0); // CBCDR
            DCDC_AdjustTargetVoltage(DCDC, VDDRun_1150_mV, VDDStandby_925_mV);
            CLOCK_SetDiv(kCLOCK_AhbDiv, AhbDiv1);
            CLOCK_SetMux(kCLOCK_PeriphMux, PeriphMuxSourcePll2_528MHz);
            break;
        }

        if (freq == CpuClock::CpuClock_Osc_4_Mhz || freq == CpuClock::CpuClock_Osc_12_Mhz ||
            freq == CpuClock::CpuClock_Osc_24_Mhz) {
            /* Set periph clock source. */
            CLOCK_SetMux(kCLOCK_PeriphMux, 1);
        }
        else {
            /* Set periph clock source. */
            CLOCK_SetMux(kCLOCK_PeriphMux, 0);
        }

        /* Set SystemCoreClock variable. */
        SystemCoreClockUpdate();
    }

    void CpuFreqLPM::SetHighestCoreVoltage()
    {
        DCDC_AdjustTargetVoltage(DCDC, VDDRun_1275_mV, VDDStandby_925_mV);
        DCDC_AdjustTargetVoltage(DCDC, VDDRun_1150_mV, VDDStandby_925_mV);
    }

} // namespace bsp

M module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp => module-bsp/board/rt1051/bsp/lpm/CpuFreqLPM.hpp +20 -1
@@ 7,6 7,7 @@

namespace bsp
{
    inline constexpr std::uint32_t VDDRun_950_mV  = 0x06;
    inline constexpr std::uint32_t VDDRun_975_mV  = 0x07;
    inline constexpr std::uint32_t VDDRun_1050_mV = 0x0A;
    inline constexpr std::uint32_t VDDRun_1075_mV = 0x0B;


@@ 31,9 32,27 @@ namespace bsp
            CpuClock_Pll2_528_Mhz
        };

        /* Plain enums to avoid casting when passing to FSL functions */
        enum AhbDivValues
        {
            AhbDiv1 = 0,
            AhbDiv2,
            AhbDiv3,
            AhbDiv4,
            AhbDiv5,
            AhbDiv6,
            AhbDiv7,
            AhbDiv8
        };

        enum PeriphMuxSources
        {
            PeriphMuxSourcePll2_528MHz = 0,
            PeriphMuxSourceOsc_24MHz
        };

        CpuFreqLPM();
        void SetCpuFrequency(CpuClock freq);
        void SetHighestCoreVoltage();
    };
} // namespace bsp


M module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPMCommon.cpp +20 -17
@@ 65,7 65,7 @@ namespace bsp
    CpuFrequencyMHz RT1051LPMCommon::onChangeUp(CpuFrequencyMHz freq, bsp::CpuFrequencyMHz newFrequency)
    {
        if ((freq <= CpuFrequencyMHz::Level_1) && (newFrequency > CpuFrequencyMHz::Level_1)) {
            // connect internal the load resistor
            // connect internal load resistor
            ConnectInternalLoadResistor();
            // Switch DCDC to full throttle during oscillator switch
            SetHighestCoreVoltage();


@@ 97,7 97,7 @@ namespace bsp
                driverSEMC->SwitchToPeripheralClockSource();
            }

            // disconnect internal the load resistor
            // disconnect internal load resistor
            DisconnectInternalLoadResistor();
        }
    }


@@ 107,7 107,7 @@ namespace bsp
        if (currentFrequency == freq) {
            return;
        }
        Change change = currentFrequency < freq ? Change::Up : Change::Down;
        const Change change = (currentFrequency < freq) ? Change::Up : Change::Down;
        if (Change::Up == change) {
            freq = onChangeUp(currentFrequency, freq);
        }


@@ 178,27 178,30 @@ namespace bsp

    void RT1051LPMCommon::RegularLDOMode()
    {
        // Enable regular 2P5 and wait it stable
        // Enable regular 2P5 and 1P1 LDO
        PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_LINREG_MASK;
        // It is recommended to wait for stabilization (documentation Low Power AN12085)
        while ((PMU->REG_2P5 & PMU_REG_2P5_OK_VDD2P5_MASK) == 0) {}
        // Turn off weak 2P5
        PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK;
        // Enable regular 1P1 and wait for stable
        PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_LINREG_MASK;
        // It is recommended to wait for stabilization (documentation Low Power AN12085)

        // 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 1P1

        // 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 turn off regular 2P5
        PMU->REG_2P5 |= PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK;
        PMU->REG_2P5 &= ~PMU_REG_2P5_ENABLE_LINREG_MASK;
        // Enable weak 1P1 and turn off regular 1P1
        PMU->REG_1P1 |= PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK;
        PMU->REG_1P1 &= ~PMU_REG_1P1_ENABLE_LINREG_MASK;
        // 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());

        // 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;
    }
} // namespace bsp

M module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp => module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp +8 -1
@@ 1,8 1,10 @@
// 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 "RT1051DriverPLL2.hpp"
#include "board/rt1051/bsp/lpm/ClockState.hpp"
#include "board/rt1051/bsp/lpm/CpuFreqLPM.hpp"
#include "fsl_dcdc.h"

namespace drivers
{


@@ 14,6 16,8 @@ namespace drivers
    RT1051DriverPLL2::RT1051DriverPLL2() noexcept
    {
        if (!IsPLL2Enabled()) {
            // Set VDD_SOC_IN required to safely start PLL2
            DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_1150_mV, bsp::VDDStandby_925_mV);
            // Turn on regular band gap and wait for stable
            CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_REFTOP_PWD_MASK;
            // It is recommended to wait for stabilization (documentation Low Power AN12085)


@@ 39,6 43,9 @@ namespace drivers
            PMU->MISC0_SET              = constants::REFTOP_LOWPOWER_FLAG;
            XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK;
            PMU->MISC0_SET              = CCM_ANALOG_MISC0_REFTOP_PWD_MASK;

            // After turning off PLL2 and with CPU @4MHZ VDD_SOC_IN can be set to 950mV, 975mV to be safe
            DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_975_mV, bsp::VDDStandby_925_mV);
        }
    }


M module-bsp/board/rt1051/drivers/RT1051DriverSEMC.cpp => module-bsp/board/rt1051/drivers/RT1051DriverSEMC.cpp +2 -2
@@ 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 "RT1051DriverSEMC.hpp"


@@ 22,7 22,7 @@ namespace drivers
    void RT1051DriverSEMC::SwitchToPLL2ClockSource()
    {
        cpp_freertos::CriticalSection::Enter();
        if (!pll2Driver) {
        if (pll2Driver == nullptr) {
            pll2Driver = std::make_shared<RT1051DriverPLL2>();
        }
        CLOCK_SetMux(kCLOCK_SemcMux, SemcMuxPLL2Clock);

M module-bsp/board/rt1051/os/_exit.cpp => module-bsp/board/rt1051/os/_exit.cpp +1 -2
@@ 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

/*


@@ 69,7 69,6 @@ static void __attribute__((noreturn)) stop_system(void)

void __attribute__((noreturn, used)) _exit_backtrace(int code, bool bt_dump)
{
    LOG_INFO("_exit %d", code);
    if (bt_dump && !isIRQ()) {
        _StackTrace_Dump_And_Abort();
    }

M module-bsp/board/rt1051/puretx/clock_config.cpp => module-bsp/board/rt1051/puretx/clock_config.cpp +1 -0
@@ 140,6 140,7 @@ void BOARD_BootClockRUN(void)
    /* OSC_CLK (24M) */
    CLOCK_SetMux(kCLOCK_PeriphClk2Mux,
                 1); // CBCMR (13-12) 0 - pll3_sw_clk, 1 - osc_clk (pll1_ref_clk), 2 - pll2_bypass_clk, 3 - reserved
    CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); // No division
    /* PERIPH_CLK2_SEL */
    CLOCK_SetMux(kCLOCK_PeriphMux, 1); // CBCDR (25) 0 - pre_periph_clk_sel, 1 - periph_clk2_clk_divided


M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +1 -1
@@ 39,7 39,7 @@ namespace
}

EventManager::EventManager(LogDumpFunction logDumpFunction, const std::string &name)
    : EventManagerCommon(logDumpFunction,
    : EventManagerCommon(std::move(logDumpFunction),
                         {.battery{.critical = constants::criticalThreshold, .shutdown = constants::shutdownThreshold},
                          .voltage{.shutdown            = constants::shutdownVoltageThreshold,
                                   .measurementMaxCount = constants::measurementThreshold}},