From cbbd94719d39b54bea59bfe18f1294c552c22d4d Mon Sep 17 00:00:00 2001 From: Borys Jelenski Date: Thu, 6 May 2021 17:13:15 +0200 Subject: [PATCH] [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. --- .../windows/DateTimeWindow.cpp | 5 +- module-bsp/board/linux/rtc/rtc.cpp | 178 ++++------- module-bsp/board/rt1051/bsp/rtc/rtc.cpp | 300 +++++------------- .../rt1051/common/fsl_drivers/fsl_snvs_hp.c | 88 +++-- .../rt1051/common/fsl_drivers/fsl_snvs_hp.h | 44 +++ .../rt1051/common/fsl_drivers/fsl_snvs_lp.c | 47 ++- .../rt1051/common/fsl_drivers/fsl_snvs_lp.h | 19 ++ module-bsp/bsp/rtc/rtc.hpp | 91 ++---- .../service-evtmgr/EventManager.cpp | 6 +- .../service-evtmgr/WorkerEvent.cpp | 10 +- module-utils/board/cross/time_syscalls.cpp | 4 +- module-utils/time/time_conversion.cpp | 6 +- 12 files changed, 352 insertions(+), 446 deletions(-) diff --git a/module-apps/application-settings/windows/DateTimeWindow.cpp b/module-apps/application-settings/windows/DateTimeWindow.cpp index f629da39082faf18eebae380c742f1b33685262a..fc74c8850e39233bd5c0f4700c583d24e90f6af8 100644 --- a/module-apps/application-settings/windows/DateTimeWindow.cpp +++ b/module-apps/application-settings/windows/DateTimeWindow.cpp @@ -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); } diff --git a/module-bsp/board/linux/rtc/rtc.cpp b/module-bsp/board/linux/rtc/rtc.cpp index 311df8060a7e0d5bd7f707d999c86899fc657045..892d170018f3ee1944bb56de2ffa43dea2cf0d42 100644 --- a/module-bsp/board/linux/rtc/rtc.cpp +++ b/module-bsp/board/linux/rtc/rtc.cpp @@ -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 +#include +#include +#include #include -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(¤t); + + std::uint8_t notification; + if (current == timestampAlarm) { + notification = static_cast(bsp::rtc::IrqNotification::AlarmOccurred); + xQueueSend(qHandleRtcIrq, ¬ification, 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(¤t); 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(¤t) != RtcBspOK) - return RtcBspError; + if (getCurrentTimestamp(¤t) != 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(¤t); - - uint8_t notification; - if (current == timestampAlarm) { - notification = static_cast(bsp::rtcIrqNotifications::alarmOcured); - xQueueSend(qHandleRtcIrq, ¬ification, 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 diff --git a/module-bsp/board/rt1051/bsp/rtc/rtc.cpp b/module-bsp/board/rt1051/bsp/rtc/rtc.cpp index 625a89e5d8c53b88f080c1a73fbada9e2655994c..95e926eae03d78340ca8341f28e24e7e463b0ec9 100644 --- a/module-bsp/board/rt1051/bsp/rtc/rtc.cpp +++ b/module-bsp/board/rt1051/bsp/rtc/rtc.cpp @@ -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 +#include +#include +#include +#include #include -#include "time/time_conversion.hpp" -#include "FreeRTOS.h" -#include +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(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(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(bsp::rtcIrqNotifications::alarmOcured); - bsp::rtc_DisableAlarmIrq(); + std::uint8_t notification = static_cast(bsp::rtc::IrqNotification::AlarmOccurred); + bsp::rtc::disableAlarmIrq(); xQueueSendFromISR(qHandleRtcIrq, ¬ification, &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; -} diff --git a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c index 2a2e0c7e40c70c6e56194fc8f9d53a653635403e..ab33b7937ca7029f6917156e6798cb732f4858d4 100644 --- a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c +++ b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c @@ -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; @@ -403,6 +402,50 @@ void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime) SNVS_HP_ConvertSecondsToDatetime(SNVS_HP_RTC_GetSeconds(base), 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. * @@ -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)) diff --git a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h index 8ca0efc848ff7bb592de932d6f8300660d11831d..8204f9299de678e2fea26ddc7fddcee647a6967d 100644 --- a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h +++ b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h @@ -175,6 +175,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. * @@ -194,6 +216,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. * diff --git a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c index 6d36c80fe21677b8e14eeff9cbd02c960860bf4b..2b48569b090cf33af73c9cdb0780e871787e0f50 100644 --- a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c +++ b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c @@ -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; @@ -352,6 +348,33 @@ static uint32_t SNVS_LP_SRTC_GetSeconds(SNVS_Type *base) return seconds; } +/*! + * 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. * diff --git a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h index 5254466f7d8aa373297e423793d0dc916dd6baa6..ae76ffe8a465bdc6416903e1c055610cd22a2f1e 100644 --- a/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h +++ b/module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h @@ -191,6 +191,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. * diff --git a/module-bsp/bsp/rtc/rtc.hpp b/module-bsp/bsp/rtc/rtc.hpp index 072a3164206d9e8d6574d92e12a0b88152eef294..cfd2f6a51b63b0ee76a92e7f07d22248df1ec7c5 100644 --- a/module-bsp/bsp/rtc/rtc.hpp +++ b/module-bsp/bsp/rtc/rtc.hpp @@ -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 +#include +#include +#include -#include -#include +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_ */ diff --git a/module-services/service-evtmgr/EventManager.cpp b/module-services/service-evtmgr/EventManager.cpp index 97fa1f50980e288780a4af518f57db264b19368c..ecd3431b8a629988f0ddc72748e6753e35ec430f 100644 --- a/module-services/service-evtmgr/EventManager.cpp +++ b/module-services/service-evtmgr/EventManager.cpp @@ -176,7 +176,7 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy if (auto msg = dynamic_cast(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(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(); }); diff --git a/module-services/service-evtmgr/WorkerEvent.cpp b/module-services/service-evtmgr/WorkerEvent.cpp index 0f930e98f6d7042479953ee1eb95b75c33f333fd..f261e9ddf5fd15f4dd96adef3fbf815d14fd1a6c 100644 --- a/module-services/service-evtmgr/WorkerEvent.cpp +++ b/module-services/service-evtmgr/WorkerEvent.cpp @@ -143,8 +143,8 @@ bool WorkerEvent::handleMessage(uint32_t queueID) } time_t timestamp; - bsp::rtc_GetCurrentTimestamp(×tamp); - bsp::rtc_SetMinuteAlarm(timestamp); + bsp::rtc::getCurrentTimestamp(×tamp); + bsp::rtc::setMinuteAlarm(timestamp); auto message = std::make_shared(MessageType::EVMMinuteUpdated); message->timestamp = timestamp; @@ -225,7 +225,7 @@ bool WorkerEvent::init(std::list queuesList) auto queueBatteryHandle = queues[static_cast(WorkerEventQueues::queueBattery)]->GetQueueHandle(); auto queueChargerDetect = queues[static_cast(WorkerEventQueues::queueChargerDetect)]->GetQueueHandle(); bsp::battery_charger::init(queueBatteryHandle, queueChargerDetect); - bsp::rtc_Init(queues[static_cast(WorkerEventQueues::queueRTC)]->GetQueueHandle()); + bsp::rtc::init(queues[static_cast(WorkerEventQueues::queueRTC)]->GetQueueHandle()); bsp::cellular::init(queues[static_cast(WorkerEventQueues::queueCellular)]->GetQueueHandle()); bsp::magnetometer::init(queues[static_cast(WorkerEventQueues::queueMagnetometerIRQ)]->GetQueueHandle()); bsp::torch::init(queues[static_cast(WorkerEventQueues::queueTorch)]->GetQueueHandle()); @@ -234,8 +234,8 @@ bool WorkerEvent::init(std::list queuesList) bsp::light_sensor::init(queues[static_cast(WorkerEventQueues::queueLightSensor)]->GetQueueHandle()); time_t timestamp; - bsp::rtc_GetCurrentTimestamp(×tamp); - bsp::rtc_SetMinuteAlarm(timestamp); + bsp::rtc::getCurrentTimestamp(×tamp); + bsp::rtc::setMinuteAlarm(timestamp); cpuSentinel = std::make_shared( service::name::evt_manager, service, [this](bsp::CpuFrequencyHz newFrequency) { diff --git a/module-utils/board/cross/time_syscalls.cpp b/module-utils/board/cross/time_syscalls.cpp index 346de93189dcff0d11252813c26222f44d0fa71d..732172f910a987baa3dc1af16a1351d579e9e197 100644 --- a/module-utils/board/cross/time_syscalls.cpp +++ b/module-utils/board/cross/time_syscalls.cpp @@ -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; } diff --git a/module-utils/time/time_conversion.cpp b/module-utils/time/time_conversion.cpp index ed6a3eecc108ce758836afd8e9e41d3521f298a5..57fe10b5826c57c6c9970ae7188491a1b96951f3 100644 --- a/module-utils/time/time_conversion.cpp +++ b/module-utils/time/time_conversion.cpp @@ -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); }