diff --git a/os/hal/include/rtc.h b/os/hal/include/rtc.h index 8e94bc08f..a775ec570 100644 --- a/os/hal/include/rtc.h +++ b/os/hal/include/rtc.h @@ -87,18 +87,7 @@ */ typedef struct RTCDriver RTCDriver; -/** - * @brief Type of a structure representing an RTC date/time stamp. - */ -typedef struct { - uint32_t year:8; /**< @brief Years since 1980. */ - uint32_t month: 4; /**< @brief Months 1..12. */ - uint32_t dstflag: 1; /**< @brief DST correction flag. */ - uint32_t dayofweek: 3; /**< @brief Day of week 1..7. */ - uint32_t day: 5; /**< @brief Day of the month 1..31. */ - uint32_t millisecond: 27; /**< @brief Milliseconds since midnight.*/ -} RTCDateTime; - +#include "chrtclib.h" #include "rtc_lld.h" /*===========================================================================*/ @@ -124,7 +113,6 @@ extern "C" { #if RTC_SUPPORTS_CALLBACKS void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback); #endif - uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec); #ifdef __cplusplus } #endif diff --git a/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.c index 3e1cdde24..f17a553b4 100644 --- a/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.c +++ b/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.c @@ -30,6 +30,8 @@ #if HAL_USE_RTC || defined(__DOXYGEN__) +#include "chrtclib.h" + /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ @@ -59,7 +61,10 @@ RTCDriver RTCD1; * * @notapi */ -#define rtc_lld_apb1_sync() {while ((RTC->CRL & RTC_CRL_RSF) == 0);} +static void rtc_apb1_sync(void) { + while ((RTCD1.rtc->CRL & RTC_CRL_RSF) == 0) + ; +} /** * @brief Wait for for previous write operation complete. @@ -67,7 +72,10 @@ RTCDriver RTCD1; * * @notapi */ -#define rtc_lld_wait_write() {while ((RTC->CRL & RTC_CRL_RTOFF) == 0);} +static void rtc_wait_write_completed(void) { + while ((RTCD1.rtc->CRL & RTC_CRL_RTOFF) == 0) + ; +} /** * @brief Acquires write access to RTC registers. @@ -77,14 +85,56 @@ RTCDriver RTCD1; * * @notapi */ -#define rtc_lld_acquire() {rtc_lld_wait_write(); RTC->CRL |= RTC_CRL_CNF;} +static void rtc_acquire_access(void) { + rtc_wait_write_completed(); + RTCD1.rtc->CRL |= RTC_CRL_CNF; +} /** * @brief Releases write access to RTC registers. * * @notapi */ -#define rtc_lld_release() {RTC->CRL &= ~RTC_CRL_CNF;} +static void rtc_release_access(void) { + RTCD1.rtc->CRL &= ~RTC_CRL_CNF; +} + +/** + * @brief Converts time from timespec to seconds counter. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the TR register encoding. + * + * @notapi + */ +static time_t rtc_encode(const RTCDateTime *timespec) { + struct tm tim; + + rtcConvertDateTimeToStructTm(timespec, &tim); + return mktime(&tim); +} + +/** + * @brief Converts time from seconds/milliseconds to timespec. + * + * @param[in] tv_sec seconds value + * @param[in] tv_msec milliseconds value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode(uint32_t tv_sec, uint32_t tv_msec, + RTCDateTime *timespec) { + struct tm tim; + struct tm *canary; + + /* If the conversion is successful the function returns a pointer + to the object the result was written into.*/ + canary = localtime_r((time_t *)&(tv_sec), &tim); + osalDbgCheck(&tim == canary); + + rtcConvertStructTmToDateTime(&tim, tv_msec, timespec); +} /*===========================================================================*/ /* Driver interrupt handlers. */ @@ -95,18 +145,18 @@ RTCDriver RTCD1; * * @isr */ -CH_IRQ_HANDLER(RTC_IRQHandler) { +OSAL_IRQ_HANDLER(STM32_RTC1_HANDLER) { uint16_t flags; - CH_IRQ_PROLOGUE(); + OSAL_IRQ_PROLOGUE(); - /* This wait works only when AHB1 bus was previously powered off by any - reason (standby, reset, etc). In other cases it does nothing.*/ - rtc_lld_apb1_sync(); + /* Code hits this wait only when AHB1 bus was previously powered off by any + reason (standby, reset, etc). In other cases there is no waiting.*/ + rtc_apb1_sync(); /* Mask of all enabled and pending sources.*/ - flags = RTC->CRH & RTC->CRL; - RTC->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); + flags = RTCD1.rtc->CRH & RTCD1.rtc->CRL; + RTCD1.rtc->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); if (flags & RTC_CRL_SECF) RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); @@ -117,7 +167,7 @@ CH_IRQ_HANDLER(RTC_IRQHandler) { if (flags & RTC_CRL_OWF) RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW); - CH_IRQ_EPILOGUE(); + OSAL_IRQ_EPILOGUE(); } /*===========================================================================*/ @@ -134,11 +184,19 @@ CH_IRQ_HANDLER(RTC_IRQHandler) { * * @notapi */ -void rtc_lld_set_prescaler(void){ - rtc_lld_acquire(); - RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; - RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); - rtc_lld_release(); +void rtc_lld_set_prescaler(void) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); + + rtc_acquire_access(); + RTCD1.rtc->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; + RTCD1.rtc->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); } /** @@ -146,24 +204,27 @@ void rtc_lld_set_prescaler(void){ * * @notapi */ -void rtc_lld_init(void){ +void rtc_lld_init(void) { + + /* RTC pointer initialization.*/ + RTCD1.rtc = RTC; /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock stop. Otherwise its value will not be actual. */ - RTC->CRL &= ~RTC_CRL_RSF; + RTCD1.rtc->CRL &= ~RTC_CRL_RSF; /* Required because access to PRL.*/ - rtc_lld_apb1_sync(); + rtc_apb1_sync(); /* All interrupts initially disabled.*/ - rtc_lld_wait_write(); - RTC->CRH = 0; + rtc_wait_write_completed(); + RTCD1.rtc->CRH = 0; /* Callback initially disabled.*/ RTCD1.callback = NULL; /* IRQ vector permanently assigned to this driver.*/ - nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(STM32_RTC_IRQ_PRIORITY)); + nvicEnableVector(STM32_RTC1_NUMBER, STM32_RTC_IRQ_PRIORITY); } /** @@ -176,14 +237,10 @@ void rtc_lld_init(void){ * * @notapi */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { +void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { + time_t tv_sec = rtc_encode(timespec); - (void)rtcp; - - rtc_lld_acquire(); - RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16); - RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF); - rtc_lld_release(); + rtcSTM32SetSec(rtcp, tv_sec); } /** @@ -194,22 +251,11 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { * * @notapi */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { - (void)rtcp; +void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { + uint32_t tv_sec, tv_msec; - uint32_t time_frac; - - /* Required because access to CNT and DIV.*/ - rtc_lld_apb1_sync(); - - /* Loops until two consecutive read returning the same value.*/ - do { - timespec->tv_sec = ((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL; - time_frac = (((uint32_t)RTC->DIVH) << 16) + (uint32_t)RTC->DIVL; - } while ((timespec->tv_sec) != (((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL)); - - timespec->tv_msec = (uint16_t)(((STM32_RTCCLK - 1 - time_frac) * 1000) / - STM32_RTCCLK); + rtcSTM32GetSecMsec(rtcp, &tv_sec, &tv_msec); + rtc_decode(tv_sec, tv_msec, timespec); } /** @@ -224,22 +270,27 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { * @notapi */ void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, + rtcalarm_t alarm_number, const RTCAlarm *alarmspec) { + syssts_t sts; + (void)alarm_number; - (void)rtcp; - (void)alarm; + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); - rtc_lld_acquire(); + rtc_acquire_access(); if (alarmspec != NULL) { - RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); - RTC->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); + rtcp->rtc->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); + rtcp->rtc->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); } else { - RTC->ALRH = 0; - RTC->ALRL = 0; + rtcp->rtc->ALRH = 0; + rtcp->rtc->ALRL = 0; } - rtc_lld_release(); + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); } /** @@ -256,16 +307,21 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, * @notapi */ void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, + rtcalarm_t alarm_number, RTCAlarm *alarmspec) { + syssts_t sts; + (void)alarm_number; - (void)rtcp; - (void)alarm; + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); /* Required because access to ALR.*/ - rtc_lld_apb1_sync(); + rtc_apb1_sync(); - alarmspec->tv_sec = ((RTC->ALRH << 16) + RTC->ALRL); + alarmspec->tv_sec = ((rtcp->rtc->ALRH << 16) + rtcp->rtc->ALRL); + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); } /** @@ -279,50 +335,92 @@ void rtc_lld_get_alarm(RTCDriver *rtcp, * @notapi */ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); if (callback != NULL) { /* IRQ sources enabled only after setting up the callback.*/ rtcp->callback = callback; - rtc_lld_wait_write(); - RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); - RTC->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; + rtc_wait_write_completed(); + rtcp->rtc->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); + rtcp->rtc->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; } else { - rtc_lld_wait_write(); - RTC->CRH = 0; + rtc_wait_write_completed(); + rtcp->rtc->CRH = 0; /* Callback set to NULL only after disabling the IRQ sources.*/ rtcp->callback = NULL; } + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); } -#include "chrtclib.h" - /** - * @brief Get current time in format suitable for usage in FatFS. + * @brief Get seconds and (optionally) milliseconds from RTC. * * @param[in] rtcp pointer to RTC driver structure - * @return FAT time value. + * @param[out] tv_sec pointer to seconds value + * @param[out] tv_msec pointer to milliseconds value, set it + * to @p NULL if not needed * * @api */ -uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) { - uint32_t fattime; - struct tm timp; +void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec) { + uint32_t time_frac; + syssts_t sts; - rtcGetTimeTm(rtcp, &timp); + osalDbgCheck((NULL != tv_sec) && (NULL != rtcp)); - fattime = (timp.tm_sec) >> 1; - fattime |= (timp.tm_min) << 5; - fattime |= (timp.tm_hour) << 11; - fattime |= (timp.tm_mday) << 16; - fattime |= (timp.tm_mon + 1) << 21; - fattime |= (timp.tm_year - 80) << 25; + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); - return fattime; + /* Required because access to CNT and DIV.*/ + rtc_apb1_sync(); + + /* Loops until two consecutive read returning the same value.*/ + do { + *tv_sec = ((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL; + time_frac = (((uint32_t)rtcp->rtc->DIVH) << 16) + (uint32_t)rtcp->rtc->DIVL; + } while ((*tv_sec) != (((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL)); + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); + + if (NULL != tv_msec) + *tv_msec = (((uint32_t)STM32_RTCCLK - 1 - time_frac) * 1000) / STM32_RTCCLK; } + +/** + * @brief Set seconds in RTC. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] tv_sec seconds value + * + * @api + */ +void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec) { + syssts_t sts; + + osalDbgCheck(NULL != rtcp); + + /* Entering a reentrant critical zone.*/ + sts = chSysGetStatusAndLockX(); + + rtc_acquire_access(); + rtcp->rtc->CNTH = (uint16_t)(tv_sec >> 16); + rtcp->rtc->CNTL = (uint16_t)(tv_sec & 0xFFFF); + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + chSysRestoreStatusX(sts); +} + #endif /* HAL_USE_RTC */ /** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.h b/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.h index 16f0bb96e..31d2b576b 100644 --- a/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.h +++ b/os/hal/ports/STM32/LLD/RTCv1/rtc_lld.h @@ -31,6 +31,8 @@ #if HAL_USE_RTC || defined(__DOXYGEN__) +#include "chrtclib.h" + /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ @@ -115,20 +117,6 @@ struct RTCCallbackConfig{ rtccb_t callback; }; -/** - * @brief Structure representing an RTC time stamp. - */ -struct RTCTime { - /** - * @brief Seconds since UNIX epoch. - */ - uint32_t tv_sec; - /** - * @brief Fractional part. - */ - uint32_t tv_msec; -}; - /** * @brief Structure representing an RTC alarm time stamp. */ @@ -143,6 +131,11 @@ struct RTCAlarm { * @brief Structure representing an RTC driver. */ struct RTCDriver{ + /** + * @brief Pointer to the RTC registers block. + */ + RTC_TypeDef *rtc; + /** * @brief Callback pointer. */ @@ -166,16 +159,18 @@ extern "C" { #endif void rtc_lld_set_prescaler(void); void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, + rtcalarm_t alarm_number, const RTCAlarm *alarmspec); void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, + rtcalarm_t alarm_number, RTCAlarm *alarmspec); void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp); + void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec); + void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec); #ifdef __cplusplus } #endif diff --git a/os/hal/ports/STM32/STM32F1xx/stm32_isr.h b/os/hal/ports/STM32/STM32F1xx/stm32_isr.h index c0c3a84f8..092df2a70 100644 --- a/os/hal/ports/STM32/STM32F1xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F1xx/stm32_isr.h @@ -129,6 +129,13 @@ #define STM32_USB1_HP_NUMBER 19 #define STM32_USB1_LP_NUMBER 20 + +/* + * RTC unit + */ +#define STM32_RTC1_HANDLER Vector4C + +#define STM32_RTC1_NUMBER 3 /** @} */ /*===========================================================================*/ diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c index d4b13ba62..e67abb746 100644 --- a/os/hal/src/rtc.c +++ b/os/hal/src/rtc.c @@ -185,37 +185,6 @@ void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) { } #endif /* RTC_SUPPORTS_CALLBACKS */ -/** - * @brief Get current time in format suitable for usage in FAT file system. - * @note The information about day of week and DST is lost in DOS - * format, the second field loses its least significant bit. - * - * @param[out] timespec pointer to a @p RTCDateTime structure - * @return FAT date/time value. - * - * @api - */ -uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec) { - uint32_t fattime; - uint32_t sec, min, hour, tmp; - - osalDbgCheck(timespec != NULL); - - tmp = timespec->millisecond / 1000; - sec = tmp % 60; - min = (tmp - sec) % 3600; - hour = (tmp - sec - min * 60) / 3600; - - fattime = sec >> 1; - fattime |= min << 5; - fattime |= hour << 11; - fattime |= timespec->day << 16; - fattime |= timespec->month << 21; - fattime |= timespec->year << 25; - - return fattime; -} - #endif /* HAL_USE_RTC */ /** @} */ diff --git a/os/various/chrtclib.c b/os/various/chrtclib.c new file mode 100644 index 000000000..5512fd42e --- /dev/null +++ b/os/various/chrtclib.c @@ -0,0 +1,129 @@ +/* + ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file chrtclib.c + * @brief Time conversion routines. + * + * @addtogroup chrtclib + * @{ + */ + +#include + +#include "chrtclib.h" + +/** + * @brief Convert @p RTCDateTime to broken-down time structure. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @param[out] timp pointer to a broken-down time structure + * + * @api + */ +void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, + struct tm *timp) { + uint32_t tmp; + + timp->tm_year = timespec->year + (1980 - 1900); + timp->tm_mon = timespec->month - 1; + timp->tm_mday = timespec->day; + timp->tm_isdst = timespec->dstflag; + + tmp = timespec->millisecond / 1000; + timp->tm_sec = tmp % 60; + tmp -= timp->tm_sec; + timp->tm_min = tmp % 3600; + tmp -= timp->tm_min * 60; + timp->tm_hour = tmp / 3600; +} + +/** + * @brief Convert broken-down time structure to @p RTCDateTime. + * + * @param[in] timp pointer to a broken-down time structure + * @param[in] tv_msec milliseconds value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @api + */ +void rtcConvertStructTmToDateTime(const struct tm *timp, + uint32_t tv_msec, RTCDateTime *timespec) { + + timespec->year = timp->tm_year - (1980 - 1900); + timespec->month = timp->tm_mon + 1; + timespec->day = timp->tm_mday; + timespec->dayofweek = timp->tm_wday + 1; + if (-1 == timp->tm_isdst) + timespec->dstflag = 0; /* set zero if dst is unknown */ + else + timespec->dstflag = timp->tm_isdst; + timespec->millisecond = tv_msec + + (timp->tm_hour * 3600 + timp->tm_min * 60 + timp->tm_sec) * 1000; +} + +/* + * Lookup table for months' length + */ +static const uint8_t month_len[12] = { + 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +/** + * @brief Get current time in format suitable for usage in FAT file system. + * @note The information about day of week and DST is lost in DOS + * format, the second field loses its least significant bit. + * + * @param[out] timespec pointer to a @p RTCDateTime structure + * @return FAT date/time value. + * + * @api + */ +uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec) { + uint32_t fattime; + uint32_t sec, min, hour, day, month, tmp; + + tmp = timespec->millisecond / 1000; + sec = tmp % 60; + min = (tmp - sec) % 3600; + hour = (tmp - sec - min * 60) / 3600; + day = timespec->day; + month = timespec->month; + + /* handle DST flag */ + if (1 == timespec->dstflag) { + hour += 1; + if (hour == 24) { + hour = 0; + day += 1; + if (day > month_len[month - 1]) { + day = 1; + month += 1; + } + } + } + + fattime = sec >> 1; + fattime |= min << 5; + fattime |= hour << 11; + fattime |= day << 16; + fattime |= month << 21; + fattime |= timespec->year << 25; + + return fattime; +} + +/** @} */ diff --git a/os/various/chrtclib.h b/os/various/chrtclib.h new file mode 100644 index 000000000..ad9b4c706 --- /dev/null +++ b/os/various/chrtclib.h @@ -0,0 +1,59 @@ +/* + ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _CHRTCLIB_H_ +#define _CHRTCLIB_H_ + +#include +#include + +/** + * @file chrtclib.h + * @brief Time conversion routines. + * + * @addtogroup chrtclib + * @{ + */ + +/** + * @brief Type of a structure representing an RTC date/time stamp. + */ +typedef struct { + uint32_t year: 8; /**< @brief Years since 1980. */ + uint32_t month: 4; /**< @brief Months 1..12. */ + uint32_t dstflag: 1; /**< @brief DST correction flag. */ + uint32_t dayofweek: 3; /**< @brief Day of week 1..7. */ + uint32_t day: 5; /**< @brief Day of the month 1..31. */ + uint32_t millisecond: 27; /**< @brief Milliseconds since midnight.*/ +} RTCDateTime; + +#ifdef __cplusplus +extern "C" { +#endif + uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec); + void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, + struct tm *timp); + void rtcConvertStructTmToDateTime(const struct tm *timp, + uint32_t tv_msec, + RTCDateTime *timespec); +#ifdef __cplusplus +} +#endif + + +#endif /* _CHRTCLIB_H_ */ + +/** @} */