~aleteoryx/muditaos

67a02a90f57d1e44e8a7774529bb551aafebe66e — Maciej Gibowicz 4 years ago 9ab4fb1
[EGD-4852] Add sleep mode for GSM modem

When the GSM modem is idle and there is no communication,
it enters the sleep mode, where the power consumption
is significantly reduced.
M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp +7 -3
@@ 9,6 9,7 @@
#include "dma_config.h"
#include "fsl_cache.h"
#include <common_data/EventStore.hpp>
#include <ticks.hpp>

#include <algorithm>



@@ 246,9 247,7 @@ namespace bsp
        sendXfer.data     = static_cast<uint8_t *>(buf);
        sendXfer.dataSize = nbytes;

        if (isInSleepMode) {
            ExitSleep();
        }
        ExitSleep();

        uartDmaHandle.userData = xTaskGetCurrentTaskHandle();
        SCB_CleanInvalidateDCache();


@@ 342,6 341,7 @@ namespace bsp

    ssize_t RT1051Cellular::Read(void *buf, size_t nbytes)
    {
        ExitSleep();
        ssize_t ret = xStreamBufferReceive(uartRxStreamBuffer, buf, nbytes, 0);
#if _RT1051_UART_DEBUG
        if (ret > 0) {


@@ 420,6 420,7 @@ namespace bsp

            // Host sleep information must be before UART disable
            InformModemHostAsleep();

            if (driverLPUART) {
                driverLPUART->Disable();
            }


@@ 428,6 429,9 @@ namespace bsp

    void RT1051Cellular::ExitSleep()
    {
        // reset sleep timer countdown
        lastCommunicationTimestamp = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());

        if (isInSleepMode) {
            isInSleepMode = false;


M module-bsp/bsp/cellular/bsp_cellular.cpp => module-bsp/bsp/cellular/bsp_cellular.cpp +5 -0
@@ 36,4 36,9 @@ namespace bsp{
        return driverLPUART;
    }

    [[nodiscard]] auto Cellular::GetLastCommunicationTimestamp() const noexcept -> TickType_t
    {
    	return lastCommunicationTimestamp;
    }

}

M module-bsp/bsp/cellular/bsp_cellular.hpp => module-bsp/bsp/cellular/bsp_cellular.hpp +2 -0
@@ 56,9 56,11 @@ namespace cellular
        virtual bsp::cellular::antenna GetAntenna() = 0;

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

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

M module-cellular/Modem/TS0710/TS0710.cpp => module-cellular/Modem/TS0710/TS0710.cpp +6 -0
@@ 597,6 597,12 @@ 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);
}

[[nodiscard]] auto TS0710::GetLastCommunicationTimestamp() const noexcept -> TickType_t
{
    return pv_cellular->GetLastCommunicationTimestamp();
}

TS0710::ConfState TS0710::SetupEchoCanceller(EchoCancellerStrength strength)
{


M module-cellular/Modem/TS0710/TS0710.h => module-cellular/Modem/TS0710/TS0710.h +1 -0
@@ 441,6 441,7 @@ class TS0710
    void EnterSleepMode(void);
    void ExitSleepMode(void);
    void RegisterCellularDevice(void);
    [[nodiscard]] auto GetLastCommunicationTimestamp() const noexcept -> TickType_t;
};

#endif //_TS0710_H

M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +7 -0
@@ 39,6 39,9 @@ namespace CellularCall
        if (!call.isValid()) {
            LOG_ERROR("startCallAction failed");
            clear();
            if (cpuSentinel) {
                cpuSentinel->ReleaseMinimumFrequency();
            }
            return false;
        }



@@ 62,6 65,10 @@ namespace CellularCall
            return false;
        }

        if (cpuSentinel) {
            cpuSentinel->ReleaseMinimumFrequency();
        }

        if (isActiveCall) {
            auto endTime  = utils::time::Timestamp();
            call.duration = (endTime - startActiveTime).get();

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +20 -4
@@ 93,6 93,7 @@
#include "checkSmsCenter.hpp"
#include <service-desktop/Constants.hpp>
#include <module-utils/gsl/gsl_util>
#include <ticks.hpp>

const char *ServiceCellular::serviceName = "ServiceCellular";



@@ 185,6 186,8 @@ ServiceCellular::ServiceCellular()
        this, "state", std::chrono::milliseconds{1000}, [&](sys::Timer &) { handleStateTimer(); });
    ussdTimer = sys::TimerFactory::createPeriodicTimer(
        this, "ussd", std::chrono::milliseconds{1000}, [this](sys::Timer &) { handleUSSDTimer(); });
    sleepTimer = sys::TimerFactory::createPeriodicTimer(
        this, "sleep", constants::sleepTimerInterval, [this](sys::Timer &) { SleepTimerHandler(); });

    ongoingCall.setStartCallAction([=](const CalllogRecord &rec) {
        auto call = DBServiceAPI::CalllogAdd(this, rec);


@@ 240,6 243,20 @@ static bool isSettingsAutomaticTimeSyncEnabled()
    return true;
}

void ServiceCellular::SleepTimerHandler()
{
    auto currentTime                = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
    auto lastCommunicationTimestamp = cmux->GetLastCommunicationTimestamp();
    auto timeOfInactivity           = currentTime >= lastCommunicationTimestamp
                                ? currentTime - lastCommunicationTimestamp
                                : std::numeric_limits<TickType_t>::max() - lastCommunicationTimestamp + currentTime;

    if (!ongoingCall.isValid() && timeOfInactivity >= constants::enterSleepModeTime.count()) {
        cmux->EnterSleepMode();
        cpuSentinel->ReleaseMinimumFrequency();
    }
}

void ServiceCellular::CallStateTimerHandler()
{
    LOG_DEBUG("CallStateTimerHandler");


@@ 269,10 286,6 @@ sys::ReturnCodes ServiceCellular::InitHandler()

    cmux->RegisterCellularDevice();

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

    return sys::ReturnCodes::Success;
}



@@ 1806,6 1819,7 @@ bool ServiceCellular::handle_fatal_failure()
bool ServiceCellular::handle_ready()
{
    LOG_DEBUG("%s", state.c_str());
    sleepTimer.start();
    return true;
}



@@ 2532,6 2546,8 @@ auto ServiceCellular::handleSimNotReadyNotification(sys::Message *msg) -> std::s

auto ServiceCellular::handleUrcIncomingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    // when handling URC, the CPU frequency does not go below a certain level
    cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_4);
    cmux->ExitSleepMode();
    return std::make_shared<CellularResponseMessage>(true);
}

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +13 -0
@@ 55,6 55,14 @@ namespace packet_data
    class PacketData;
    class PDPContext;
} // namespace packet_data

namespace constants
{
    using namespace std::chrono_literals;
    inline constexpr std::chrono::milliseconds sleepTimerInterval{500ms};
    inline constexpr std::chrono::milliseconds enterSleepModeTime{5s};
} // namespace constants

class ServiceCellular : public sys::Service
{



@@ 171,6 179,11 @@ class ServiceCellular : public sys::Service
    sys::TimerHandle callStateTimer;
    sys::TimerHandle stateTimer;
    sys::TimerHandle ussdTimer;

    // used to enter modem sleep mode
    sys::TimerHandle sleepTimer;

    void SleepTimerHandler();
    void CallStateTimerHandler();
    DLC_channel::Callback_t notificationCallback = nullptr;