~aleteoryx/muditaos

cbbd94719d39b54bea59bfe18f1294c552c22d4d — Borys Jelenski 4 years ago ece6a51
[EGD-6605] Fix RTC time not retained between resets if set manually

When setting datetime from timestamp (manually, not from network),
SRTC is set in order to retain the RTC datetime between resets.

RTC handling was refactored in order to get rid of unnecesary
conversions and third-party code mixed with proprietary code
within a single file.
M module-apps/application-settings/windows/DateTimeWindow.cpp => module-apps/application-settings/windows/DateTimeWindow.cpp +2 -3
@@ 177,8 177,7 @@ namespace gui
    }

    void DateTimeWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
    }
    {}

    gui::Label *DateTimeWindow::addSpacer(const UTF8 &text)
    {


@@ 372,7 371,7 @@ namespace gui
            LOG_ERROR("DateTimeWindow::setRTC: %s", e.what());
        }

        bsp::rtc_SetDateTime(&timeinfo);
        bsp::rtc::setDateTime(&timeinfo);
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
    }


M module-bsp/board/linux/rtc/rtc.cpp => module-bsp/board/linux/rtc/rtc.cpp +61 -117
@@ 1,197 1,141 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * rtc.cpp
 *
 *  Created on: Jun 26, 2019
 *      Author: kuba
 */

#include "bsp/rtc/rtc.hpp"
#include <bsp/rtc/rtc.hpp>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <time.h>

extern "C"
namespace
{
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
}

static time_t timestampOffset;
static time_t timestampAlarm;
time_t localOffset;
static xQueueHandle qHandleRtcIrq   = NULL;
static TaskHandle_t rtcWorkerHandle = NULL;
    time_t timestampOffset;
    time_t timestampAlarm;
    time_t localOffset;
    xQueueHandle qHandleRtcIrq   = NULL;
    TaskHandle_t rtcWorkerHandle = NULL;

static void rtc_worker(void *pvp);
    void rtcWorker(void *pvp)
    {
        while (true) {
            time_t current;
            bsp::rtc::getCurrentTimestamp(&current);

            std::uint8_t notification;
            if (current == timestampAlarm) {
                notification = static_cast<std::uint8_t>(bsp::rtc::IrqNotification::AlarmOccurred);
                xQueueSend(qHandleRtcIrq, &notification, 100);
            }
            vTaskDelay(1000);
        }
    }
} // namespace

namespace bsp
namespace bsp::rtc
{

    RtcBspError_e rtc_Init(xQueueHandle qHandle)
    ErrorCode init(xQueueHandle qHandle)
    {
        qHandleRtcIrq   = qHandle;
        timestampOffset = 0;
        timestampAlarm  = 0;

        xTaskCreate(rtc_worker, "rtc_worker", 512, qHandle, 0, &rtcWorkerHandle);
        return RtcBspOK;
        xTaskCreate(rtcWorker, "rtc_worker", 512, qHandle, 0, &rtcWorkerHandle);
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetDateTimeFromTimestamp(time_t timestamp)
    ErrorCode setDateTimeFromTimestamp(time_t timestamp)
    {

        time_t current   = time(NULL);
        struct tm *local = localtime(&current);

        localOffset = local->tm_gmtoff;

        timestampOffset = timestamp - current;
        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetDateTime(struct tm *tim)
    ErrorCode setDateTime(struct tm *tim)
    {

        time_t current   = time(NULL);
        time_t timestamp = mktime(tim);

        timestampOffset = timestamp - current;
        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetCurrentDateTime(struct tm *datetime)
    ErrorCode getCurrentDateTime(struct tm *datetime)
    {
        time_t t = time(NULL);
        t += timestampOffset;
        *datetime = *gmtime(&t);

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetCurrentTimestamp(time_t *timestamp)
    ErrorCode getCurrentTimestamp(time_t *timestamp)
    {
        *timestamp = time(NULL) + timestampOffset;

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmOnDate(struct tm *datetime)
    ErrorCode setAlarmOnDate(struct tm *datetime)
    {
        if (datetime == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmOnTimestamp(uint32_t secs)
    ErrorCode setAlarmOnTimestamp(std::uint32_t secs)
    {
        timestampAlarm = secs;
        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmInSecondsFromNow(uint32_t secs)
    ErrorCode setAlarmInSecondsFromNow(std::uint32_t secs)
    {
        time_t current;
        if (rtc_GetCurrentTimestamp(&current) != RtcBspOK)
            return RtcBspError;
        if (getCurrentTimestamp(&current) != ErrorCode::OK)
            return ErrorCode::Error;

        current += secs;

        if (rtc_SetAlarmOnTimestamp(current) != RtcBspOK)
            return RtcBspError;
        if (setAlarmOnTimestamp(current) != ErrorCode::OK)
            return ErrorCode::Error;

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetAlarmTimestamp(uint32_t *secs)
    ErrorCode getAlarmTimestamp(std::uint32_t *secs)
    {
        if (secs == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_EnableAlarmIrq()
    ErrorCode enableAlarmIrq()
    {
        uint32_t cnt = 100000;
        std::uint32_t cnt = 100000;

        if (cnt == 0) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        return RtcBspOK;
    }
    // TODO delete function if it will not be used in service
    RtcBspError_e rtc_DisableAlarmIrq()
    {
        return RtcBspOK;
    }
    // TODO delete function if it will not be used in service
    RtcBspError_e zrtc_MaskAlarmIrq()
    {
        return RtcBspOK;
    }
    // TODO delete function if it will not be used in service
    RtcBspError_e rtc_UnmaskAlarmIrq()
    {
        return RtcBspOK;
    }

    time_t rtc_GetSecondCounter()
    {
        time_t seconds = 0;
        time_t tmp     = 0;
        do {

        } while (tmp != seconds);

        return seconds;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetMinuteAlarm(time_t timestamp)
    ErrorCode setMinuteAlarm(time_t timestamp)
    {
        uint32_t secondsToMinute = 60 - (timestamp % 60);
        std::uint32_t secondsToMinute = 60 - (timestamp % 60);

        struct tm date;
        rtc_GetCurrentDateTime(&date);
        getCurrentDateTime(&date);

        return rtc_SetAlarmInSecondsFromNow(secondsToMinute);
        return setAlarmInSecondsFromNow(secondsToMinute);
    }
} // namespace bsp

static void rtc_worker(void *pvp)
{
    while (1) {
        time_t current;
        bsp::rtc_GetCurrentTimestamp(&current);

        uint8_t notification;
        if (current == timestampAlarm) {
            notification = static_cast<uint8_t>(bsp::rtcIrqNotifications::alarmOcured);
            xQueueSend(qHandleRtcIrq, &notification, 100);
        }
        vTaskDelay(1000);
    }
}

// TODO delete function if it will not be used in service
void SNVS_HP_WRAPPER_IRQHandler()
{
    /// HERE on TICK set_time timer monotonic
    /// gmtime    <- based on timer monotonic
    /// localtime <- based on timer monotonic
    /// timezone  <- can be based on offset between two if one super wishes... (+1, +2 etc... )
}
/*
 *  **********************************************************************************************************************
 *  * *
 *  * *
 *  *                             SNVS RTC DRIVER STATIC FUNCTIONS COPIED FOR OUR USE *
 *  * *
 *  * *
 *  **********************************************************************************************************************
 */
} // namespace bsp::rtc

M module-bsp/board/rt1051/bsp/rtc/rtc.cpp => module-bsp/board/rt1051/bsp/rtc/rtc.cpp +77 -223
@@ 1,31 1,24 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * rtc.cpp
 *
 *  Created on: Jun 26, 2019
 *      Author: kuba
 */

#include "bsp/rtc/rtc.hpp"
#include "fsl_snvs_hp.h"
#include "fsl_snvs_lp.h"
#include <bsp/rtc/rtc.hpp>
#include <fsl_snvs_hp.h>
#include <fsl_snvs_lp.h>
#include <module-os/RTOSWrapper/include/ticks.hpp>
#include <module-utils/time/time_conversion.hpp>
#include <time.h>
#include "time/time_conversion.hpp"

#include "FreeRTOS.h"
#include <module-os/RTOSWrapper/include/ticks.hpp>
namespace
{
    constexpr std::uint32_t irqTimeout = 100000;

static xQueueHandle qHandleRtcIrq = NULL;
    xQueueHandle qHandleRtcIrq = NULL;
    snvs_hp_rtc_config_t s_rtcConfig;
} // namespace

static snvs_hp_rtc_config_t s_rtcConfig;
static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime);
static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime);
namespace bsp
namespace bsp::rtc
{

    RtcBspError_e rtc_Init(xQueueHandle qHandle)
    ErrorCode init(xQueueHandle qHandle)
    {
        qHandleRtcIrq = qHandle;



@@ 46,8 39,8 @@ namespace bsp
            }
            timedOut = cpp_freertos::Ticks::GetTicks() > timeoutTicks;
            if (timedOut) {
                LOG_ERROR("rtc_Init timeout!!!");
                return RtcBspError;
                LOG_ERROR("RTC init timeout");
                return ErrorCode::Error;
            }
            vTaskDelay(delay);
        }


@@ 55,36 48,34 @@ namespace bsp
        SNVS_HP_RTC_TimeSynchronize(SNVS);

        NVIC_SetPriority(SNVS_HP_WRAPPER_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);
        /* Enable at the NVIC */
        // Enable at the NVIC
        NVIC_EnableIRQ(SNVS_HP_WRAPPER_IRQn);

        // Start the timer
        SNVS_HP_RTC_StartTimer(SNVS);

        LOG_INFO("RTC configured successfully");
        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetDateTimeFromTimestamp(time_t timestamp)
    ErrorCode setDateTimeFromTimestamp(time_t timestamp)
    {
        snvs_hp_rtc_datetime_t rtcDateTime;

        SNVS_HP_ConvertSecondsToDatetime((uint32_t)timestamp, &rtcDateTime);
        portENTER_CRITICAL();

        SNVS_HP_RTC_StopTimer(SNVS);
        SNVS_HP_RTC_SetDatetime(SNVS, &rtcDateTime);
        SNVS_HP_RTC_StartTimer(SNVS);
        SNVS_LP_SRTC_StopTimer(SNVS);
        SNVS_LP_SRTC_SetSeconds(SNVS, static_cast<std::uint32_t>(timestamp));
        SNVS_LP_SRTC_StartTimer(SNVS);
        SNVS_HP_RTC_TimeSynchronize(SNVS);

        portEXIT_CRITICAL();

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetDateTime(struct tm *time)
    ErrorCode setDateTime(struct tm *time)
    {
        if (time == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        snvs_lp_srtc_datetime_t rtcDate;


@@ 103,13 94,13 @@ namespace bsp
        SNVS_HP_RTC_TimeSynchronize(SNVS);
        portEXIT_CRITICAL();

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetCurrentDateTime(struct tm *datetime)
    ErrorCode getCurrentDateTime(struct tm *datetime)
    {
        if (datetime == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        snvs_hp_rtc_datetime_t rtcDate;


@@ 123,26 114,24 @@ namespace bsp
        datetime->tm_min  = rtcDate.minute;
        datetime->tm_sec  = rtcDate.second;

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetCurrentTimestamp(time_t *timestamp)
    ErrorCode getCurrentTimestamp(time_t *timestamp)
    {
        if (timestamp == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }
        snvs_hp_rtc_datetime_t rtcDate;

        SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);
        *timestamp = (time_t)SNVS_HP_ConvertDatetimeToSeconds(&rtcDate);
        *timestamp = static_cast<time_t>(SNVS_HP_RTC_GetSeconds(SNVS));

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmOnDate(struct tm *datetime)
    ErrorCode setAlarmOnDate(struct tm *datetime)
    {
        if (datetime == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        snvs_hp_rtc_datetime_t rtcDate;


@@ 154,77 143,66 @@ namespace bsp
        rtcDate.minute = datetime->tm_min;
        rtcDate.second = datetime->tm_sec;

        rtc_EnableAlarmIrq();
        enableAlarmIrq();
        SNVS_HP_RTC_SetAlarm(SNVS, &rtcDate);

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmOnTimestamp(uint32_t secs)
    ErrorCode setAlarmOnTimestamp(std::uint32_t secs)
    {
        snvs_hp_rtc_datetime_t rtcDate;

        SNVS_HP_ConvertSecondsToDatetime(secs, &rtcDate);

        if (SNVS_HP_RTC_SetAlarm(SNVS, &rtcDate) != kStatus_Success) {
            return RtcBspError;
        if (SNVS_HP_RTC_SetAlarmSeconds(SNVS, secs) != kStatus_Success) {
            return ErrorCode::Error;
        }

        rtc_EnableAlarmIrq();
        enableAlarmIrq();

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetAlarmInSecondsFromNow(uint32_t secs)
    ErrorCode setAlarmInSecondsFromNow(std::uint32_t secs)
    {
        snvs_hp_rtc_datetime_t rtcDate;

        SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);

        uint32_t seconds = SNVS_HP_ConvertDatetimeToSeconds(&rtcDate);

        std::uint32_t seconds = SNVS_HP_RTC_GetSeconds(SNVS);
        seconds += secs;

        SNVS_HP_ConvertSecondsToDatetime(seconds, &rtcDate);
        enableAlarmIrq();

        rtc_EnableAlarmIrq();
        SNVS_HP_RTC_SetAlarm(SNVS, &rtcDate);
        if (SNVS_HP_RTC_SetAlarmSeconds(SNVS, seconds) != kStatus_Success) {
            return ErrorCode::Error;
        }

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_GetAlarmTimestamp(uint32_t *secs)
    ErrorCode getAlarmTimestamp(std::uint32_t *secs)
    {
        if (secs == NULL) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        snvs_hp_rtc_datetime_t rtcDate;

        SNVS_HP_RTC_GetAlarm(SNVS, &rtcDate);
        *secs = SNVS_HP_RTC_GetAlarmSeconds(SNVS);

        *secs = SNVS_HP_ConvertDatetimeToSeconds(&rtcDate);
        return RtcBspOK;
        return ErrorCode::OK;
    }
    static const uint32_t irqTimeout = 100000;
    RtcBspError_e rtc_EnableAlarmIrq()

    ErrorCode enableAlarmIrq()
    {
        uint32_t cnt = irqTimeout;
        std::uint32_t cnt = irqTimeout;
        SNVS->HPCR |= SNVS_HPCR_HPTA_EN_MASK;
        while ((!(SNVS->HPCR & SNVS_HPCR_HPTA_EN_MASK)) && cnt) {
            cnt--;
        }

        if (cnt == 0) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_DisableAlarmIrq()
    ErrorCode disableAlarmIrq()
    {
        uint32_t cnt = irqTimeout;
        std::uint32_t cnt = irqTimeout;

        SNVS->HPCR &= ~SNVS_HPCR_HPTA_EN_MASK;
        while ((SNVS->HPCR & SNVS_HPCR_HPTA_EN_MASK) && cnt) {


@@ 232,50 210,34 @@ namespace bsp
        }

        if (cnt == 0) {
            return RtcBspError;
            return ErrorCode::Error;
        }

        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_MaskAlarmIrq()
    ErrorCode maskAlarmIrq()
    {
        NVIC_DisableIRQ(SNVS_HP_WRAPPER_IRQn);
        return RtcBspOK;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_UnmaskAlarmIrq()
    ErrorCode unmaskAlarmIrq()
    {
        NVIC_EnableIRQ(SNVS_HP_WRAPPER_IRQn);
        return RtcBspOK;
    }

    time_t rtc_GetSecondCounter()
    {
        time_t seconds = 0;
        time_t tmp     = 0;

        do {
            seconds = tmp;
            tmp     = (SNVS->HPRTCMR << 17U) | (SNVS->HPRTCLR >> 15U);
        } while (tmp != seconds);

        return seconds;
        return ErrorCode::OK;
    }

    RtcBspError_e rtc_SetMinuteAlarm(time_t timestamp)
    ErrorCode setMinuteAlarm(time_t timestamp)
    {
        uint32_t secondsToMinute = 60 - (timestamp % 60);
        std::uint32_t secondsToMinute = 60 - (timestamp % 60);

        struct tm date;
        rtc_GetCurrentDateTime(&date);
        getCurrentDateTime(&date);

        /*		LOG_INFO("seconds %d",  ( timestamp % 60 ));
                LOG_INFO("seconds to minute %d", secondsToMinute);*/

        return rtc_SetAlarmInSecondsFromNow(secondsToMinute);
        return setAlarmInSecondsFromNow(secondsToMinute);
    }
} // namespace bsp
} // namespace bsp::rtc

extern "C"
{


@@ 283,127 245,19 @@ extern "C"
    {
        BaseType_t xHigherPriorityTaskWoken = 0;
        if (SNVS_HP_RTC_GetStatusFlags(SNVS) & kSNVS_RTC_AlarmInterruptFlag) {
            uint8_t notification = static_cast<uint8_t>(bsp::rtcIrqNotifications::alarmOcured);
            bsp::rtc_DisableAlarmIrq();
            std::uint8_t notification = static_cast<std::uint8_t>(bsp::rtc::IrqNotification::AlarmOccurred);
            bsp::rtc::disableAlarmIrq();
            xQueueSendFromISR(qHandleRtcIrq, &notification, &xHigherPriorityTaskWoken);
            // TODO service function call
            //  RtcAlarmIrqHandler();
            /* Clear alarm flag */
            SNVS_HP_RTC_ClearStatusFlags(SNVS, kSNVS_RTC_AlarmInterruptFlag);
        }

        // Switch context if necessary
        portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  exception return operation might vector to incorrect interrupt */

        // Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
        // exception return operation might vector to incorrect interrupt
#if defined __CORTEX_M && (__CORTEX_M == 4U)
        __DSB();
#endif
    }
}
/*
 *  **********************************************************************************************************************
 *  * *
 *  * *
 *  *                             SNVS RTC DRIVER STATIC FUNCTIONS COPIED FOR OUR USE *
 *  * *
 *  * *
 *  **********************************************************************************************************************
 */
static const uint32_t SECONDS_IN_A_DAY    = 86400;
static const uint32_t SECONDS_IN_A_HOUR   = 3600;
static const uint32_t SECONDS_IN_A_MINUTE = 60;
static const uint32_t DAYS_IN_A_YEAR      = 365;
static const uint32_t YEAR_RANGE_START    = 1970;

static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);

    /* Number of days from begin of the non Leap-year*/
    /* Number of days from begin of the non Leap-year*/
    uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
    uint32_t seconds;

    /* Compute number of days from 1970 till given year*/
    seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
    /* Add leap year days */
    seconds += ((datetime->year / 4) - (1970U / 4));
    /* Add number of days till given month*/
    seconds += monthDays[datetime->month];
    /* Add days in given month. We subtract the current day as it is
     * represented in the hours, minutes and seconds field*/
    seconds += (datetime->day - 1);
    /* For leap year if month less than or equal to Febraury, decrement day counter*/
    if ((!(datetime->year & 3U)) && (datetime->month <= 2U)) {
        seconds--;
    }

    seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
              (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;

    return seconds;
}

static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);

    uint32_t x;
    uint32_t secondsRemaining, days;
    uint16_t daysInYear;
    /* Table of days in a month for a non leap year. First entry in the table is not used,
     * valid months start from 1
     */
    uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};

    /* Start with the seconds value that is passed in to be converted to date time format */
    secondsRemaining = seconds;

    /* Calcuate the number of days, we add 1 for the current day which is represented in the
     * hours and seconds field
     */
    days = secondsRemaining / SECONDS_IN_A_DAY + 1;

    /* Update seconds left*/
    secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;

    /* Calculate the datetime hour, minute and second fields */
    datetime->hour   = secondsRemaining / SECONDS_IN_A_HOUR;
    secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
    datetime->minute = secondsRemaining / 60U;
    datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;

    /* Calculate year */
    daysInYear     = DAYS_IN_A_YEAR;
    datetime->year = YEAR_RANGE_START;
    while (days > daysInYear) {
        /* Decrease day count by a year and increment year by 1 */
        days -= daysInYear;
        datetime->year++;

        /* Adjust the number of days for a leap year */
        if (datetime->year & 3U) {
            daysInYear = DAYS_IN_A_YEAR;
        }
        else {
            daysInYear = DAYS_IN_A_YEAR + 1;
        }
    }

    /* Adjust the days in February for a leap year */
    if (!(datetime->year & 3U)) {
        daysPerMonth[2] = 29U;
    }

    for (x = 1U; x <= 12U; x++) {
        if (days <= daysPerMonth[x]) {
            datetime->month = x;
            break;
        }
        else {
            days -= daysPerMonth[x];
        }
    }

    datetime->day = days;
}

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c +70 -18
@@ 60,16 60,6 @@ static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *d
 */
static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime);

/*!
 * @brief Returns RTC time in seconds.
 *
 * This function is used internally to get actual RTC time in seconds.
 *
 * @param base SNVS peripheral base address
 *
 * @return RTC time in seconds
 */
static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base);

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))


@@ 334,7 324,16 @@ void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config)
    config->periodicInterruptFreq = 0U;
}

static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base)
/*!
 * brief Returns RTC time in seconds.
 *
 * This function is used internally to get actual RTC time in seconds.
 *
 * param base SNVS peripheral base address
 *
 * return RTC time in seconds
 */
uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base)
{
    uint32_t seconds = 0;
    uint32_t tmp     = 0;


@@ 404,6 403,50 @@ void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
}

/*!
 * brief Sets the SNVS RTC alarm time in seconds.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time
 * is greater than the present time. If not, the function does not set the alarm
 * and returns an error.
 *
 * param base      SNVS peripheral base address
 * param alarmTime Alarm time in seconds
 *
 * return kStatus_Success: success in setting the SNVS RTC alarm
 *         kStatus_Fail: Error because the alarm time has already passed
 */
status_t SNVS_HP_RTC_SetAlarmSeconds(SNVS_Type *base, uint32_t alarmSeconds)
{
    assert(alarmTime != NULL);

    uint32_t currSeconds  = 0U;
    uint32_t tmp          = base->HPCR;

    currSeconds  = SNVS_HP_RTC_GetSeconds(base);

    /* Return error if the alarm time has passed */
    if (alarmSeconds < currSeconds)
    {
        return kStatus_Fail;
    }

    /* disable RTC alarm interrupt */
    base->HPCR &= ~SNVS_HPCR_HPTA_EN_MASK;
    while ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U)
    {
    }

    /* Set alarm in seconds*/
    base->HPTAMR = (uint32_t)(alarmSeconds >> 17U);
    base->HPTALR = (uint32_t)(alarmSeconds << 15U);

    /* reenable RTC alarm interrupt in case that it was enabled before */
    base->HPCR = tmp;

    return kStatus_Success;
}

/*!
 * brief Sets the SNVS RTC alarm time.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time


@@ 457,22 500,31 @@ status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *ala
}

/*!
 * brief Returns the SNVS RTC alarm time.
 * brief Returns the SNVS RTC alarm time in seconds.
 *
 * param base     SNVS peripheral base address
 * param datetime Pointer to the structure where the alarm date and time details are stored.
 */
void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
uint32_t SNVS_HP_RTC_GetAlarmSeconds(SNVS_Type *base)
{
    assert(datetime != NULL);

    uint32_t alarmSeconds = 0U;

    /* Get alarm in seconds  */
    alarmSeconds = (base->HPTAMR << 17U);
    alarmSeconds |= (base->HPTALR >> 15U);

    SNVS_HP_ConvertSecondsToDatetime(alarmSeconds, datetime);
    return alarmSeconds;
}

/*!
 * brief Returns the SNVS RTC alarm time.
 *
 * param base     SNVS peripheral base address
 * param datetime Pointer to the structure where the alarm date and time details are stored.
 */
void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime != NULL);

    SNVS_HP_ConvertSecondsToDatetime(SNVS_HP_RTC_GetAlarmSeconds(SNVS), datetime);
}

#if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0))

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h +44 -0
@@ 176,6 176,28 @@ void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config);
 */

/*!
 * @brief Returns RTC time in seconds.
 *
 * This function is used internally to get actual RTC time in seconds.
 *
 * @param base SNVS peripheral base address
 *
 * @return RTC time in seconds
 */
uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base);

/*!
 * @brief Sets the SNVS SRTC date and time provided in seconds.
 *
 * @param base     SNVS peripheral base address
 * @param seconds  Date and time in seconds.
 *
 * @return kStatus_Success: Success in setting the time and starting the SNVS SRTC
 *         kStatus_InvalidArgument: Error because the datetime format is incorrect
 */
status_t SNVS_LP_SRTC_SetSeconds(SNVS_Type *base, uint32_t seconds);

/*!
 * @brief Sets the SNVS RTC date and time according to the given time structure.
 *
 * @param base     SNVS peripheral base address


@@ 195,6 217,28 @@ status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *
void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime);

/*!
 * @brief Returns the SNVS RTC alarm time in seconds.
 *
 * @param base     SNVS peripheral base address
 */
uint32_t SNVS_HP_RTC_GetAlarmSeconds(SNVS_Type *base);

/*!
 * @brief Sets the SNVS RTC alarm time in seconds.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time
 * is greater than the present time. If not, the function does not set the alarm
 * and returns an error.
 *
 * @param base      SNVS peripheral base address
 * @param alarmTime Alarm time in seconds
 *
 * @return kStatus_Success: success in setting the SNVS RTC alarm
 *         kStatus_Fail: Error because the alarm time has already passed
 */
status_t SNVS_HP_RTC_SetAlarmSeconds(SNVS_Type *base, uint32_t alarmSeconds);

/*!
 * @brief Sets the SNVS RTC alarm time.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c +35 -12
@@ 55,17 55,6 @@ static uint32_t SNVS_LP_ConvertDatetimeToSeconds(const snvs_lp_srtc_datetime_t *
 */
static void SNVS_LP_ConvertSecondsToDatetime(uint32_t seconds, snvs_lp_srtc_datetime_t *datetime);

/*!
 * @brief Returns SRTC time in seconds.
 *
 * This function is used internally to get actual SRTC time in seconds.
 *
 * @param base SNVS peripheral base address
 *
 * @return SRTC time in seconds
 */
static uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base);

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_LP_CLOCKS))
/*!


@@ 336,7 325,14 @@ void SNVS_LP_SRTC_GetDefaultConfig(snvs_lp_srtc_config_t *config)
    config->srtcCalValue  = 0U;
}

static uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base)
/*!
 * brief Gets the SNVS SRTC actual date and time in seconds.
 *
 * param base     SNVS peripheral base address
 *
 * return SRTC actual date and time in seconds.
 */
uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base)
{
    uint32_t seconds = 0;
    uint32_t tmp     = 0;


@@ 353,6 349,33 @@ static uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base)
}

/*!
 * brief Sets the SNVS SRTC date and time provided in seconds.
 *
 * param base     SNVS peripheral base address
 * param seconds  Date and time in seconds.
 *
 * return kStatus_Success: Success in setting the time and starting the SNVS SRTC
 */
status_t SNVS_LP_SRTC_SetSeconds(SNVS_Type *base, uint32_t seconds)
{
    uint32_t tmp = base->LPCR;

    /* disable RTC */
    SNVS_LP_SRTC_StopTimer(base);

    base->LPSRTCMR = (uint32_t)(seconds >> 17U);
    base->LPSRTCLR = (uint32_t)(seconds << 15U);

    /* reenable SRTC in case that it was enabled before */
    if ((tmp & SNVS_LPCR_SRTC_ENV_MASK) != 0U)
    {
        SNVS_LP_SRTC_StartTimer(base);
    }

    return kStatus_Success;
}

/*!
 * brief Sets the SNVS SRTC date and time according to the given time structure.
 *
 * param base     SNVS peripheral base address

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h +19 -0
@@ 192,6 192,25 @@ void SNVS_LP_SRTC_GetDefaultConfig(snvs_lp_srtc_config_t *config);
 */

/*!
 * @brief Gets the SNVS SRTC actual date and time in seconds.
 *
 * @param base     SNVS peripheral base address
 *
 * @return SRTC actual date and time in seconds.
 */
uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base);

/*!
 * @brief Sets the SNVS SRTC date and time provided in seconds.
 *
 * @param base     SNVS peripheral base address
 * @param seconds  Date and time in seconds.
 *
 * @return kStatus_Success: Success in setting the time and starting the SNVS SRTC
 */
status_t SNVS_LP_SRTC_SetSeconds(SNVS_Type *base, uint32_t seconds);

/*!
 * @brief Sets the SNVS SRTC date and time according to the given time structure.
 *
 * @param base     SNVS peripheral base address

M module-bsp/bsp/rtc/rtc.hpp => module-bsp/bsp/rtc/rtc.hpp +31 -60
@@ 1,68 1,39 @@
/*
 * rtc.hpp
 *
 *  Created on: Jun 26, 2019
 *      Author: kuba
 */
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef MODULE_BSP_BSP_RTC_RTC_HPP_
#define MODULE_BSP_BSP_RTC_RTC_HPP_
#pragma once

#include <FreeRTOS.h>
#include <queue.h>
#include <ctime>
#include <cstdint>

#include <time.h>
#include <stdint.h>
namespace bsp::rtc {
	enum class IrqNotification
    {
        AlarmOccurred = 0x01
    };

extern "C" {
	#include "FreeRTOS.h"
	#include "task.h"
	#include "queue.h"
}

typedef enum
{
    RtcBspOK,
    RtcBspError
} RtcBspError_e;


namespace bsp {

	enum class rtcIrqNotifications
	enum class ErrorCode
	{
		alarmOcured = 0x01
		OK,
		Error
	};

	/*
	 * RTC functions are using FreeRTOS functions, RTC should be initialized after scheduler starts.
	 * */
	RtcBspError_e rtc_Init(xQueueHandle qHandle);

	RtcBspError_e rtc_EnableAlarmIrq();

	RtcBspError_e rtc_DisableAlarmIrq();

	RtcBspError_e rtc_MaskAlarmIrq();

	RtcBspError_e rtc_UnmaskAlarmIrq();

	RtcBspError_e rtc_SetDateTimeFromTimestamp(time_t timestamp);

	RtcBspError_e rtc_SetDateTime(struct tm* time);

	RtcBspError_e rtc_GetCurrentDateTime(struct tm* datetime);

	RtcBspError_e rtc_GetCurrentTimestamp(time_t* timestamp);

	RtcBspError_e rtc_SetAlarmOnDate(struct tm* datetime);

	RtcBspError_e rtc_SetAlarmOnTimestamp(uint32_t secs);

	RtcBspError_e rtc_SetAlarmInSecondsFromNow(uint32_t secs);

	RtcBspError_e rtc_GetAlarmTimestamp(uint32_t* secs);

	time_t rtc_GetSecondCounter();

;	RtcBspError_e rtc_SetMinuteAlarm(time_t timestamp);
	// RTC functions are using FreeRTOS functions, RTC should be initialized after scheduler starts.

	ErrorCode init(xQueueHandle qHandle);
	ErrorCode enableAlarmIrq();
	ErrorCode disableAlarmIrq();
	ErrorCode maskAlarmIrq();
	ErrorCode unmaskAlarmIrq();
	ErrorCode setDateTimeFromTimestamp(time_t timestamp);
	ErrorCode setDateTime(struct tm* time);
	ErrorCode getCurrentDateTime(struct tm* datetime);
	ErrorCode getCurrentTimestamp(time_t* timestamp);
	ErrorCode setAlarmOnDate(struct tm* datetime);
	ErrorCode setAlarmOnTimestamp(std::uint32_t secs);
	ErrorCode setAlarmInSecondsFromNow(std::uint32_t secs);
	ErrorCode getAlarmTimestamp(std::uint32_t* secs);
	ErrorCode setMinuteAlarm(time_t timestamp);
}
#endif /* MODULE_BSP_BSP_RTC_RTC_HPP_ */

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +3 -3
@@ 176,7 176,7 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
            if (auto msg = dynamic_cast<CellularTimeNotificationMessage *>(msgl)) {
                if (auto time = msg->getTime(); time) {
                    LOG_INFO("RTC set by network time.");
                    bsp::rtc_SetDateTime(&time.value());
                    bsp::rtc::setDateTime(&time.value());
                }
                if (auto timeZoneOffset = msg->getTimeZoneOffset(); timeZoneOffset) {
                    setSettingsTimeZone(msg->getTimeZoneString().value());


@@ 263,8 263,8 @@ sys::ReturnCodes EventManager::InitHandler()
    });
    connect(sevm::RtcUpdateTimeMessage(0), [&](sys::Message *msgl) {
        auto msg = static_cast<sevm::RtcUpdateTimeMessage *>(msgl);
        bsp::rtc_SetDateTimeFromTimestamp(msg->getTime());
        bsp::rtc_SetMinuteAlarm(msg->getTime());
        bsp::rtc::setDateTimeFromTimestamp(msg->getTime());
        bsp::rtc::setMinuteAlarm(msg->getTime());
        handleMinuteUpdate(msg->getTime());
        return sys::msgHandled();
    });

M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +5 -5
@@ 143,8 143,8 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
        }

        time_t timestamp;
        bsp::rtc_GetCurrentTimestamp(&timestamp);
        bsp::rtc_SetMinuteAlarm(timestamp);
        bsp::rtc::getCurrentTimestamp(&timestamp);
        bsp::rtc::setMinuteAlarm(timestamp);

        auto message       = std::make_shared<sevm::RtcMinuteAlarmMessage>(MessageType::EVMMinuteUpdated);
        message->timestamp = timestamp;


@@ 225,7 225,7 @@ bool WorkerEvent::init(std::list<sys::WorkerQueueInfo> queuesList)
    auto queueBatteryHandle = queues[static_cast<int32_t>(WorkerEventQueues::queueBattery)]->GetQueueHandle();
    auto queueChargerDetect = queues[static_cast<int32_t>(WorkerEventQueues::queueChargerDetect)]->GetQueueHandle();
    bsp::battery_charger::init(queueBatteryHandle, queueChargerDetect);
    bsp::rtc_Init(queues[static_cast<int32_t>(WorkerEventQueues::queueRTC)]->GetQueueHandle());
    bsp::rtc::init(queues[static_cast<int32_t>(WorkerEventQueues::queueRTC)]->GetQueueHandle());
    bsp::cellular::init(queues[static_cast<int32_t>(WorkerEventQueues::queueCellular)]->GetQueueHandle());
    bsp::magnetometer::init(queues[static_cast<int32_t>(WorkerEventQueues::queueMagnetometerIRQ)]->GetQueueHandle());
    bsp::torch::init(queues[static_cast<int32_t>(WorkerEventQueues::queueTorch)]->GetQueueHandle());


@@ 234,8 234,8 @@ bool WorkerEvent::init(std::list<sys::WorkerQueueInfo> queuesList)
    bsp::light_sensor::init(queues[static_cast<int32_t>(WorkerEventQueues::queueLightSensor)]->GetQueueHandle());

    time_t timestamp;
    bsp::rtc_GetCurrentTimestamp(&timestamp);
    bsp::rtc_SetMinuteAlarm(timestamp);
    bsp::rtc::getCurrentTimestamp(&timestamp);
    bsp::rtc::setMinuteAlarm(timestamp);

    cpuSentinel = std::make_shared<sys::CpuSentinel>(
        service::name::evt_manager, service, [this](bsp::CpuFrequencyHz newFrequency) {

M module-utils/board/cross/time_syscalls.cpp => module-utils/board/cross/time_syscalls.cpp +2 -2
@@ 21,8 21,8 @@ namespace utils::internal::syscalls
            return -1;
        }
        time_t curtime;
        auto err = bsp::rtc_GetCurrentTimestamp(&curtime);
        if (err != RtcBspOK) {
        auto err = bsp::rtc::getCurrentTimestamp(&curtime);
        if (err != bsp::rtc::ErrorCode::OK) {
            _errno_ = EIO;
            return -1;
        }

M module-utils/time/time_conversion.cpp => module-utils/time/time_conversion.cpp +3 -3
@@ 82,10 82,10 @@ namespace utils::time

    Timestamp::Timestamp()
    {
        auto err     = bsp::rtc_GetCurrentTimestamp(&time);
        auto err = bsp::rtc::getCurrentTimestamp(&time);
        time += utils::time::Time::getTimeZoneOffset();
        if (err) {
            LOG_ERROR("rtc_GetCurrentTimestamp failure!");
        if (err != bsp::rtc::ErrorCode::OK) {
            LOG_ERROR("rtc::getCurrentTimestamp failure!");
        }
        timeinfo = *localtime(&time);
    }