~aleteoryx/muditaos

9f87dead1c4420f9679ab36856faf581e0129596 — Maciej Gibowicz 5 years ago f9703ad
[EGD-4853] Add Wake up GSM modem on demand

System wakes up Cellular when there is a need to communicate
with the modem, e.g. to handle an outgoing call
M module-bsp/CMakeLists.txt => module-bsp/CMakeLists.txt +1 -0
@@ 15,6 15,7 @@ set(SOURCES
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/i2c/DriverI2C.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/pwm/DriverPWM.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/lpspi/DriverLPSPI.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/lpuart/DriverLPUART.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/usdhc/DriverUSDHC.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/semc/DriverSEMC.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/drivers/gpio/DriverGPIO.cpp"

M module-bsp/board/linux/lpm/LinuxLPM.cpp => module-bsp/board/linux/lpm/LinuxLPM.cpp +0 -1
@@ 32,7 32,6 @@ namespace bsp

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

} // namespace bsp

M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp +15 -0
@@ 84,6 84,9 @@ namespace bsp
            return;
        }

        driverLPUART = drivers::DriverLPUART::Create(
            "cellular", static_cast<drivers::LPUARTInstances>(BoardDefinitions::CELLULAR_LPUART_INSTANCE));

        lpuart_config_t s_cellularConfig;

        LPUART_GetDefaultConfig(&s_cellularConfig);


@@ 210,6 213,10 @@ namespace bsp
        sendXfer.data     = static_cast<uint8_t *>(buf);
        sendXfer.dataSize = nbytes;

        if (isInSleepMode) {
            ExitSleep();
        }

        EnableTx();

        uartDmaHandle.userData = xTaskGetCurrentTaskHandle();


@@ 280,12 287,20 @@ namespace bsp
    {
        gpio_3->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_3_DTR_PIN), 1);
        gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_WAKEUP_PIN), 1);
        if (driverLPUART) {
            driverLPUART->Disable();
        }
        isInSleepMode = true;
    }

    void RT1051Cellular::ExitSleep()
    {
        if (driverLPUART) {
            driverLPUART->Enable();
        }
        gpio_3->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_3_DTR_PIN), 0);
        gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_WAKEUP_PIN), 0);
        isInSleepMode = false;
        vTaskDelay(pdMS_TO_TICKS(15));
    }


M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp +1 -0
@@ 114,6 114,7 @@ namespace bsp
        static TaskHandle_t blockedTaskHandle;

      private:
        bool isInSleepMode{false};
        // Constants
        const static uint32_t baudrate                               = 115200;
        const static uint32_t rxStreamBufferLength                   = 1024;

A module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp => module-bsp/board/rt1051/bsp/lpm/Oscillator.cpp +50 -0
@@ 0,0 1,50 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Oscillator.hpp"
#include "ClockState.hpp"
#include <fsl_dcdc.h>

namespace bsp
{
    inline constexpr uint8_t OscillatorReadyCounterValue{127};

    void EnableExternalOscillator()
    {
        if (!IsExternalOscillatorEnabled()) {
            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);
        }
    }

    void DisableExternalOscillator()
    {
        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;
            }

            /// 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) {}
        }
    }

    [[nodiscard]] bool IsExternalOscillatorEnabled()
    {
        return !(XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_OSC_SEL_MASK);
    }
}; // namespace bsp

A module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp => module-bsp/board/rt1051/bsp/lpm/Oscillator.hpp +11 -0
@@ 0,0 1,11 @@
// Copyright (c) 2017-2021, 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();
    [[nodiscard]] bool IsExternalOscillatorEnabled();
} // namespace bsp

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +8 -25
@@ 9,8 9,9 @@
#include "bsp/watchdog/watchdog.hpp"
#include <clock_config.h>
#include <fsl_clock.h>
#include <fsl_dcdc.h>
#include "ClockState.hpp"
#include "Oscillator.hpp"
#include "critical.hpp"

namespace bsp
{


@@ 78,33 79,15 @@ namespace bsp
    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) {}
            cpp_freertos::CriticalSection::Enter();
            bsp::DisableExternalOscillator();
            cpp_freertos::CriticalSection::Exit();
        }
        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);
            cpp_freertos::CriticalSection::Enter();
            bsp::EnableExternalOscillator();
            cpp_freertos::CriticalSection::Exit();
        }

        currentOscSource = source;
    }

} // namespace bsp

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp +0 -2
@@ 10,8 10,6 @@

namespace bsp
{
    inline constexpr uint8_t OscillatorReadyCounterValue{127};

    class RT1051LPM : public LowPowerMode
    {
      public:

A module-bsp/board/rt1051/drivers/RT1051DriverLPUART.cpp => module-bsp/board/rt1051/drivers/RT1051DriverLPUART.cpp +63 -0
@@ 0,0 1,63 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RT1051DriverLPUART.hpp"
#include "critical.hpp"
#include "board/rt1051/bsp/lpm/ClockState.hpp"

namespace drivers
{

    RT1051DriverLPUART::RT1051DriverLPUART(std::string name, LPUARTInstances inst) : DriverLPUART(std::move(name), inst)
    {
        switch (instance) {
        case LPUARTInstances::LPUART_1:
            lpuartClock = kCLOCK_Lpuart1;
            break;
        case LPUARTInstances::LPUART_2:
            lpuartClock = kCLOCK_Lpuart2;
            break;
        case LPUARTInstances::LPUART_3:
            lpuartClock = kCLOCK_Lpuart3;
            break;
        case LPUARTInstances::LPUART_4:
            lpuartClock = kCLOCK_Lpuart4;
            break;
        case LPUARTInstances::LPUART_5:
            lpuartClock = kCLOCK_Lpuart5;
            break;
        case LPUARTInstances::LPUART_6:
            lpuartClock = kCLOCK_Lpuart6;
            break;
        case LPUARTInstances::LPUART_7:
            lpuartClock = kCLOCK_Lpuart7;
            break;
        case LPUARTInstances::LPUART_8:
            lpuartClock = kCLOCK_Lpuart8;
            break;
        }
    }

    void RT1051DriverLPUART::Enable()
    {
        cpp_freertos::CriticalSection::Enter();
        if (!oscillatorDriver) {
            oscillatorDriver = std::make_shared<RT1051DriverOscillator>();
        }
        if (!bsp::IsClockEnabled(lpuartClock)) {
            CLOCK_EnableClock(lpuartClock);
        }
        cpp_freertos::CriticalSection::Exit();
    }

    void RT1051DriverLPUART::Disable()
    {
        cpp_freertos::CriticalSection::Enter();
        if (bsp::IsClockEnabled(lpuartClock)) {
            CLOCK_DisableClock(lpuartClock);
        }
        oscillatorDriver.reset();
        cpp_freertos::CriticalSection::Exit();
    }

} // namespace drivers

A module-bsp/board/rt1051/drivers/RT1051DriverLPUART.hpp => module-bsp/board/rt1051/drivers/RT1051DriverLPUART.hpp +25 -0
@@ 0,0 1,25 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "drivers/lpuart/DriverLPUART.hpp"
#include "RT1051DriverOscillator.hpp"
#include "board/rt1051/common/clock_config.h"

namespace drivers
{
    class RT1051DriverLPUART : public DriverLPUART
    {
      public:
        explicit RT1051DriverLPUART(std::string name, LPUARTInstances inst);

        void Enable() final;
        void Disable() final;

      private:
        std::shared_ptr<RT1051DriverOscillator> oscillatorDriver;
        clock_ip_name_t lpuartClock;
    };

} // namespace drivers

A module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp => module-bsp/board/rt1051/drivers/RT1051DriverOscillator.cpp +15 -0
@@ 0,0 1,15 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RT1051DriverOscillator.hpp"
#include "board/rt1051/bsp/lpm/Oscillator.hpp"

namespace drivers
{

    RT1051DriverOscillator::RT1051DriverOscillator() noexcept
    {
        bsp::EnableExternalOscillator();
    }

} // namespace drivers

A module-bsp/board/rt1051/drivers/RT1051DriverOscillator.hpp => module-bsp/board/rt1051/drivers/RT1051DriverOscillator.hpp +16 -0
@@ 0,0 1,16 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "board/rt1051/common/clock_config.h"

namespace drivers
{
    class RT1051DriverOscillator
    {
      public:
        RT1051DriverOscillator() noexcept;
    };

} // namespace drivers

M module-bsp/bsp/BoardDefinitions.hpp => module-bsp/bsp/BoardDefinitions.hpp +2 -0
@@ 8,6 8,7 @@
#include "drivers/gpio/DriverGPIO.hpp"
#include "drivers/lpspi/DriverLPSPI.hpp"
#include "drivers/usdhc/DriverUSDHC.hpp"
#include "drivers/lpuart/DriverLPUART.hpp"

enum class BoardDefinitions
{


@@ 76,6 77,7 @@ enum class BoardDefinitions
    CELLULAR_GPIO_2_ANTSEL_PIN = 2,
    CELLULAR_GPIO_1_STATUS_PIN = 2, // GPIO_AD_B0_02
    CELLULAR_GPIO_2_USB_BOOT_PIN = 24, // GPIO_B1_08, output
    CELLULAR_LPUART_INSTANCE = static_cast<int >(drivers::LPUARTInstances::LPUART_1),

    EINK_DMA = static_cast<int >(drivers::DMAInstances ::DMA_0),
    EINK_DMAMUX = static_cast<int >(drivers::DMAMuxInstances ::DMAMUX0),

M module-bsp/bsp/cellular/bsp_cellular.cpp => module-bsp/bsp/cellular/bsp_cellular.cpp +6 -1
@@ 31,4 31,9 @@ namespace bsp{
        return {};
    }

}
\ No newline at end of file
    [[nodiscard]] auto Cellular::GetCellularDevice() const noexcept -> std::shared_ptr<devices::Device>
    {
        return driverLPUART;
    }

}

M module-bsp/bsp/cellular/bsp_cellular.hpp => module-bsp/bsp/cellular/bsp_cellular.hpp +4 -1
@@ 7,7 7,7 @@
#include <memory>
#include <FreeRTOS.h>
#include <FreeRTOS/include/queue.h>

#include "drivers/lpuart/DriverLPUART.hpp"
#include <common_data/EventStore.hpp>

namespace bsp {


@@ 55,8 55,11 @@ namespace cellular
        virtual void SelectAntenna(bsp::cellular::antenna antenna) = 0;
        virtual bsp::cellular::antenna GetAntenna() = 0;

        [[nodiscard]] auto GetCellularDevice() const noexcept -> std::shared_ptr<devices::Device>;

    protected:
        bool isInitialized = false;
        std::shared_ptr<drivers::DriverLPUART> driverLPUART;
    };
    namespace cellular
        {

M module-bsp/bsp/lpm/bsp_lpm.cpp => module-bsp/bsp/lpm/bsp_lpm.cpp +0 -5
@@ 33,9 33,4 @@ 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 +0 -2
@@ 31,11 31,9 @@ namespace bsp {
        [[nodiscard]] virtual uint32_t GetCpuFrequency() const noexcept = 0;

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

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


A module-bsp/drivers/lpuart/DriverLPUART.cpp => module-bsp/drivers/lpuart/DriverLPUART.cpp +41 -0
@@ 0,0 1,41 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DriverLPUART.hpp"
#include "critical.hpp"

#if defined(TARGET_RT1051)
#include "board/rt1051/drivers/RT1051DriverLPUART.hpp"
#elif defined(TARGET_Linux)

#else
#error "Unsupported target"
#endif

namespace drivers
{

    std::weak_ptr<DriverLPUART> DriverLPUART::singleton[magic_enum::enum_count<LPUARTInstances>()];

    std::shared_ptr<DriverLPUART> DriverLPUART::Create(std::string name, const drivers::LPUARTInstances instance)
    {
        cpp_freertos::CriticalSection::Enter();
        std::shared_ptr<DriverLPUART> inst = singleton[static_cast<uint32_t>(instance)].lock();

        if (!inst) {
#if defined(TARGET_RT1051)
            inst = std::make_shared<RT1051DriverLPUART>(std::move(name), instance);
#elif defined(TARGET_Linux)
#else
#error "Unsupported target"
#endif

            singleton[static_cast<uint32_t>(instance)] = std::move(inst);
        }

        cpp_freertos::CriticalSection::Exit();

        return inst;
    }

} // namespace drivers

A module-bsp/drivers/lpuart/DriverLPUART.hpp => module-bsp/drivers/lpuart/DriverLPUART.hpp +40 -0
@@ 0,0 1,40 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <memory>
#include <devices/Device.hpp>
#include <magic_enum.hpp>

namespace drivers
{

    enum class LPUARTInstances
    {
        LPUART_1,
        LPUART_2,
        LPUART_3,
        LPUART_4,
        LPUART_5,
        LPUART_6,
        LPUART_7,
        LPUART_8
    };

    class DriverLPUART : public devices::Device
    {
      public:
        static std::shared_ptr<DriverLPUART> Create(std::string name, const LPUARTInstances inst);

        explicit DriverLPUART(std::string name, LPUARTInstances inst) : devices::Device(std::move(name)), instance(inst)
        {}

      protected:
        LPUARTInstances instance;

      private:
        static std::weak_ptr<DriverLPUART> singleton[magic_enum::enum_count<LPUARTInstances>()];
    };

} // namespace drivers

M module-bsp/targets/Target_RT1051.cmake => module-bsp/targets/Target_RT1051.cmake +3 -0
@@ 58,6 58,7 @@ set(BOARD_SOURCES ${BOARD_SOURCES}
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/lpm/RT1051LPM.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/lpm/CpuFreqLPM.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/lpm/ClockState.cpp"	
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/lpm/Oscillator.cpp"		
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bluetooth/BluetoothCommon.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bluetooth/BlueKitchen.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/rtc/rtc.cpp"


@@ 68,6 69,8 @@ set(BOARD_SOURCES ${BOARD_SOURCES}
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverPLL.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverPLL2.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverLPSPI.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverLPUART.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverOscillator.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverUSDHC.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverSEMC.cpp"
	"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/drivers/RT1051DriverI2C.cpp"

M module-cellular/Modem/TS0710/TS0710.cpp => module-cellular/Modem/TS0710/TS0710.cpp +8 -1
@@ 11,6 11,7 @@
#include <memory>
#include <module-os/RTOSWrapper/include/ticks.hpp>
#include <sstream>
#include <SystemManager/messages/DeviceRegistrationMessage.hpp>

std::map<TypeOfFrame_e, std::string> TypeOfFrame_text = {{TypeOfFrame_e::SABM, "SABM"},
                                                         {TypeOfFrame_e::UA, "UA"},


@@ 560,6 561,12 @@ void TS0710::ExitSleepMode(void)
    return pv_cellular->ExitSleep();
}

void TS0710::RegisterCellularDevice(void)
{
    auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(pv_cellular->GetCellularDevice());
    pv_parent->bus.sendUnicast(std::move(deviceRegistrationMsg), service::name::system_manager);
}

void TS0710::SetupEchoCalceller(EchoCancellerStrength strength)
{
    switch (strength) {


@@ 620,4 627,4 @@ void TS0710::SetupEchoCalceller(EchoCancellerStrength strength)
        parser->cmd(at::factory(at::AT::QEEC) + "24,768");
        parser->cmd(at::factory(at::AT::QEEC) + "33,896");
    };
}
\ No newline at end of file
}

M module-cellular/Modem/TS0710/TS0710.h => module-cellular/Modem/TS0710/TS0710.h +1 -0
@@ 439,6 439,7 @@ class TS0710
    void TurnOffModem(void);
    void EnterSleepMode(void);
    void ExitSleepMode(void);
    void RegisterCellularDevice(void);
};

#endif //_TS0710_H

M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +10 -0
@@ 25,6 25,10 @@ namespace CellularCall
            return false;
        }

        if (cpuSentinel) {
            cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6);
        }

        clear();
        CalllogRecord callRec;
        callRec.type        = type;


@@ 101,4 105,10 @@ namespace CellularCall
        call.presentation = number.getFormatted().empty() ? PresentationType::PR_UNKNOWN : PresentationType::PR_ALLOWED;
        call.phoneNumber  = number;
    }

    void CellularCall::setCpuSentinel(std::shared_ptr<sys::CpuSentinel> sentinel)
    {
        cpuSentinel = std::move(sentinel);
    }

} // namespace CellularCall

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +3 -0
@@ 257,10 257,13 @@ sys::ReturnCodes ServiceCellular::InitHandler()
        ::settings::SettingsScope::Global);

    cpuSentinel = std::make_shared<sys::CpuSentinel>(serviceName, this);
    ongoingCall.setCpuSentinel(cpuSentinel);

    auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
    bus.sendUnicast(sentinelRegistrationMsg, service::name::system_manager);

    cmux->RegisterCellularDevice();

    // temporarily limit the minimum CPU frequency
    // due to problems with the UART of the GSM modem
    cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_4);

M module-services/service-cellular/service-cellular/CellularCall.hpp => module-services/service-cellular/service-cellular/CellularCall.hpp +5 -0
@@ 15,6 15,7 @@
#include <iosfwd>
#include <string>
#include <sys/types.h>
#include <Service/CpuSentinel.hpp>

namespace CellularCall
{


@@ 32,6 33,8 @@ namespace CellularCall
        std::function<bool(const CalllogRecord &rec)> endCallAction;
        utils::time::Timestamp startActiveTime = 0;

        std::shared_ptr<sys::CpuSentinel> cpuSentinel;

        void setType(const CallType type)
        {
            call.type = type;


@@ 84,5 87,7 @@ namespace CellularCall
        {
            return call.ID != 0;
        }

        void setCpuSentinel(std::shared_ptr<sys::CpuSentinel> sentinel);
    };
} // namespace CellularCall

M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +2 -9
@@ 59,13 59,10 @@ namespace sys
    void PowerManager::IncreaseCpuFrequency() const
    {
        const auto freq      = lowPowerControl->GetCurrentFrequencyLevel();
        const auto oscSource = lowPowerControl->GetCurrentOscillatorSource();

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

            // then switch external RAM clock source
            if (driverSEMC) {


@@ 110,12 107,8 @@ namespace sys
        }

        if (level == bsp::CpuFrequencyHz::Level_1) {
            const auto oscSource = lowPowerControl->GetCurrentOscillatorSource();

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

            // and switch external RAM clock source
            if (driverSEMC) {