Kashish Haresh Shah
/
HXCClientShield
HXC Client Shield Repository.
Diff: Driver/hw_rtc.c
- Revision:
- 0:bacc6e701fb4
diff -r 000000000000 -r bacc6e701fb4 Driver/hw_rtc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Driver/hw_rtc.c Mon Mar 29 15:37:08 2021 +0000 @@ -0,0 +1,716 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: MCU RTC timer + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +/******************************************************************************* + * @file hw_rtc.c + * @author MCD Application Team + * @version V1.1.4 + * @date 08-January-2018 + * @brief driver for RTC + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved.</center></h2> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "hw.h" +#include "low_power_manager.h" + +/* Private typedef -----------------------------------------------------------*/ +typedef struct +{ + uint32_t Rtc_Time; /* Reference time */ + + RTC_TimeTypeDef RTC_Calndr_Time; /* Reference time in calendar format */ + + RTC_DateTypeDef RTC_Calndr_Date; /* Reference date in calendar format */ + +} RtcTimerContext_t; + +/* Private define ------------------------------------------------------------*/ + +/* MCU Wake Up Time */ +#define MIN_ALARM_DELAY 3U /* in ticks */ + +/* subsecond number of bits */ +#define N_PREDIV_S 10U + +/* Synchronous prediv */ +#define PREDIV_S ((1<<N_PREDIV_S)-1) + +/* Asynchronous prediv */ +#define PREDIV_A (1<<(15-N_PREDIV_S))-1 + +/* Sub-second mask definition */ +#if (N_PREDIV_S == 10) +#define HW_RTC_ALARMSUBSECONDMASK RTC_ALARMSUBSECONDMASK_SS14_10 +#else +#error "Please define HW_RTC_ALARMSUBSECONDMASK" +#endif + +/* RTC Time base in us */ +#define USEC_NUMBER 1000000U +#define MSEC_NUMBER (USEC_NUMBER/1000) +#define RTC_ALARM_TIME_BASE (USEC_NUMBER>>N_PREDIV_S) + +#define COMMON_FACTOR 3U +#define CONV_NUMER (MSEC_NUMBER>>COMMON_FACTOR) +#define CONV_DENOM (1<<(N_PREDIV_S-COMMON_FACTOR)) + + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/*! + * \brief Indicates if the RTC is already Initialized or not + */ +static bool HW_RTC_Initalized = false; + +/*! + * \brief compensates MCU wakeup time + */ + +static bool McuWakeUpTimeInitialized = false; + +/*! + * \brief compensates MCU wakeup time + */ + +static int16_t McuWakeUpTimeCal = 0; + +/*! + * Number of seconds in a minute + */ +static const uint8_t SecondsInMinute = 60; + +/*! + * Number of seconds in an hour + */ +static const uint16_t SecondsInHour = 3600; + +/*! + * Number of seconds in a day + */ +static const uint32_t SecondsInDay = 86400; + +/*! + * Number of hours in a day + */ +static const uint8_t HoursInDay = 24; + +/*! + * Number of days in a standard year + */ +static const uint16_t DaysInYear = 365; + +/*! + * Number of days in a leap year + */ +static const uint16_t DaysInLeapYear = 366; + +/*! + * Number of days in each month on a normal year + */ +static const uint8_t DaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +/*! + * Number of days in each month on a leap year + */ +static const uint8_t DaysInMonthLeapYear[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static RTC_HandleTypeDef RtcHandle={0}; + +static RTC_AlarmTypeDef RTC_AlarmStructure; + +/*! + * Keep the value of the RTC timer when the RTC alarm is set + * Set with the HW_RTC_SetTimerContext function + * Value is kept as a Reference to calculate alarm + */ +static RtcTimerContext_t RtcTimerContext; + +/* Private function prototypes -----------------------------------------------*/ + +static void HW_RTC_SetConfig( void ); + +static void HW_RTC_SetAlarmConfig( void ); + +static void HW_RTC_StartWakeUpAlarm( uint32_t timeoutValue ); + +static uint32_t HW_RTC_GetCalendarValue( RTC_DateTypeDef* RTC_DateStruct, RTC_TimeTypeDef* RTC_TimeStruct ); + +/* Exported functions ---------------------------------------------------------*/ + +/*! + * @brief Initializes the RTC timer + * @note The timer is based on the RTC + * @param none + * @retval none + */ +void HW_RTC_Init( void ) +{ + if( HW_RTC_Initalized == false ) + { + HW_RTC_SetConfig( ); + HW_RTC_SetAlarmConfig( ); + HW_RTC_SetTimerContext( ); + HW_RTC_Initalized = true; + } +} + +/*! + * @brief Configures the RTC timer + * @note The timer is based on the RTC + * @param none + * @retval none + */ +static void HW_RTC_SetConfig( void ) +{ + RTC_TimeTypeDef RTC_TimeStruct; + RTC_DateTypeDef RTC_DateStruct; + + RtcHandle.Instance = RTC; + + RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; + RtcHandle.Init.AsynchPrediv = PREDIV_A; /* RTC_ASYNCH_PREDIV; */ + RtcHandle.Init.SynchPrediv = PREDIV_S; /* RTC_SYNCH_PREDIV; */ + RtcHandle.Init.OutPut = RTC_OUTPUT; + RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + + HAL_RTC_Init( &RtcHandle ); + + /*Monday 1st January 2016*/ + RTC_DateStruct.Year = 16; + RTC_DateStruct.Month = RTC_MONTH_JANUARY; + RTC_DateStruct.Date = 1; + RTC_DateStruct.WeekDay = RTC_WEEKDAY_MONDAY; + HAL_RTC_SetDate(&RtcHandle , &RTC_DateStruct, RTC_FORMAT_BIN); + + /*at 0:0:0*/ + RTC_TimeStruct.Hours = 0; + RTC_TimeStruct.Minutes = 0; + + RTC_TimeStruct.Seconds = 0; + RTC_TimeStruct.TimeFormat = 0; + RTC_TimeStruct.SubSeconds = 0; + RTC_TimeStruct.StoreOperation = RTC_DAYLIGHTSAVING_NONE; + RTC_TimeStruct.DayLightSaving = RTC_STOREOPERATION_RESET; + + HAL_RTC_SetTime(&RtcHandle , &RTC_TimeStruct, RTC_FORMAT_BIN); + + /*Enable Direct Read of the calendar registers (not through Shadow) */ + HAL_RTCEx_EnableBypassShadow(&RtcHandle); +} + +/*! + * @brief calculates the wake up time between wake up and mcu start + * @note resolution in RTC_ALARM_TIME_BASE in timer ticks + * @param none + * @retval none + */ +void HW_RTC_setMcuWakeUpTime( void ) +{ + RTC_TimeTypeDef RTC_TimeStruct; + RTC_DateTypeDef RTC_DateStruct; + + uint32_t now, hit; + int16_t McuWakeUpTime; + + if ((McuWakeUpTimeInitialized == false) && + ( HAL_NVIC_GetPendingIRQ( RTC_Alarm_IRQn ) == 1)) + { /* warning: works ok if now is below 30 days + it is ok since it's done once at first alarm wake-up*/ + McuWakeUpTimeInitialized = true; + now = HW_RTC_GetCalendarValue( &RTC_DateStruct, &RTC_TimeStruct ); + + DBG_GPIO_SET(GPIOB, GPIO_PIN_13); + DBG_GPIO_RST(GPIOB, GPIO_PIN_13); + HAL_RTC_GetAlarm(&RtcHandle, &RTC_AlarmStructure, RTC_ALARM_A, RTC_FORMAT_BIN ); + hit = RTC_AlarmStructure.AlarmTime.Seconds+ + 60*(RTC_AlarmStructure.AlarmTime.Minutes+ + 60*(RTC_AlarmStructure.AlarmTime.Hours+ + 24*(RTC_AlarmStructure.AlarmDateWeekDay))); + hit = ( hit << N_PREDIV_S ) + (PREDIV_S - RTC_AlarmStructure.AlarmTime.SubSeconds); + + McuWakeUpTime = (int16_t) ((now-hit)); + McuWakeUpTimeCal += McuWakeUpTime; + DBG_PRINTF("Cal=%d, %d\n",McuWakeUpTimeCal, McuWakeUpTime); + } +} + +int16_t HW_RTC_getMcuWakeUpTime( void ) +{ + return McuWakeUpTimeCal; +} + +/*! + * @brief returns the wake up time in ticks + * @param none + * @retval wake up time in ticks + */ +uint32_t HW_RTC_GetMinimumTimeout( void ) +{ + return( MIN_ALARM_DELAY ); +} + +/*! + * @brief converts time in ms to time in ticks + * @param [IN] time in milliseconds + * @retval returns time in timer ticks + */ +uint32_t HW_RTC_ms2Tick( uint32_t timeMicroSec ) +{ +/*return( ( timeMicroSec / RTC_ALARM_TIME_BASE ) ); */ + return ( uint32_t) ( ( ((uint64_t)timeMicroSec) * CONV_DENOM ) / CONV_NUMER ); +} + +/*! + * @brief converts time in ticks to time in ms + * @param [IN] time in timer ticks + * @retval returns time in milliseconds + */ +uint32_t HW_RTC_Tick2ms( uint32_t tick ) +{ +/*return( ( timeMicroSec * RTC_ALARM_TIME_BASE ) ); */ + return ( ( (uint64_t)( tick )* CONV_NUMER ) / CONV_DENOM ); +} + +/*! + * @brief Set the alarm + * @note The alarm is set at now (read in this funtion) + timeout + * @param timeout Duration of the Timer ticks + */ +void HW_RTC_SetAlarm( uint32_t timeout ) +{ + /* we don't go in Low Power mode for timeout below MIN_ALARM_DELAY */ + if ( (MIN_ALARM_DELAY + McuWakeUpTimeCal ) < ((timeout - HW_RTC_GetTimerElapsedTime( ) )) ) + { + LPM_SetStopMode(LPM_RTC_Id , LPM_Enable ); + } + else + { + LPM_SetStopMode(LPM_RTC_Id , LPM_Disable ); + } + + /*In case stop mode is required */ + if( LPM_GetMode() == LPM_StopMode ) + { + timeout = timeout - McuWakeUpTimeCal; + } + + HW_RTC_StartWakeUpAlarm( timeout ); +} + +/*! + * @brief Get the RTC timer elapsed time since the last Alarm was set + * @param none + * @retval RTC Elapsed time in ticks + */ +uint32_t HW_RTC_GetTimerElapsedTime( void ) +{ + RTC_TimeTypeDef RTC_TimeStruct; + RTC_DateTypeDef RTC_DateStruct; + + uint32_t CalendarValue = HW_RTC_GetCalendarValue(&RTC_DateStruct, &RTC_TimeStruct ); + + return( ( uint32_t )( CalendarValue - RtcTimerContext.Rtc_Time )); +} + +/*! + * @brief Get the RTC timer value + * @param none + * @retval RTC Timer value in ticks + */ +uint32_t HW_RTC_GetTimerValue( void ) +{ + RTC_TimeTypeDef RTC_TimeStruct; + RTC_DateTypeDef RTC_DateStruct; + + uint32_t CalendarValue = (uint32_t) HW_RTC_GetCalendarValue(&RTC_DateStruct, &RTC_TimeStruct ); + + return( CalendarValue ); +} + +/*! + * @brief Stop the Alarm + * @param none + * @retval none + */ +void HW_RTC_StopAlarm( void ) +{ + + /* Clear RTC Alarm Flag */ + __HAL_RTC_ALARM_CLEAR_FLAG( &RtcHandle, RTC_FLAG_ALRAF); + + /* Disable the Alarm A interrupt */ + + HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A ); +} + +/*! + * @brief RTC IRQ Handler on the RTC Alarm + * @param none + * @retval none + */ +void HW_RTC_IrqHandler ( void ) +{ + RTC_HandleTypeDef* hrtc=&RtcHandle; + /* enable low power at irq*/ + LPM_SetStopMode(LPM_RTC_Id , LPM_Enable ); + + /* Get the AlarmA interrupt source enable status */ + if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET) + { + /* Get the pending status of the AlarmA Interrupt */ + if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET) + { + /* Clear the AlarmA interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + /* Clear the EXTI's line Flag for RTC Alarm */ + __HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); + /* AlarmA callback */ + HAL_RTC_AlarmAEventCallback(hrtc); + } + } +} + + +/*! + * @brief a delay of delay ms by polling RTC + * @param delay in ms + * @retval none + */ +void HW_RTC_DelayMs( uint32_t delay ) +{ + uint32_t delayValue = 0; + uint32_t timeout = 0; + + delayValue = HW_RTC_ms2Tick( delay ); + + /* Wait delay ms */ + timeout = HW_RTC_GetTimerValue( ); + while( ( ( HW_RTC_GetTimerValue( ) - timeout ) ) < delayValue ) + { + __NOP( ); + } +} + +/*! + * @brief set Time Reference set also the RTC_DateStruct and RTC_TimeStruct + * @param none + * @retval Timer Value + */ +uint32_t HW_RTC_SetTimerContext( void ) +{ + RtcTimerContext.Rtc_Time = HW_RTC_GetCalendarValue( &RtcTimerContext.RTC_Calndr_Date, &RtcTimerContext.RTC_Calndr_Time ); + return ( uint32_t ) RtcTimerContext.Rtc_Time; +} + +/*! + * @brief Get the RTC timer Reference + * @param none + * @retval Timer Value in Ticks + */ +uint32_t HW_RTC_GetTimerContext( void ) +{ + return (uint32_t) RtcTimerContext.Rtc_Time; +} +/* Private functions ---------------------------------------------------------*/ + +/*! + * @brief configure alarm at init + * @param none + * @retval none + */ +static void HW_RTC_SetAlarmConfig( void ) +{ + HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A); +} + +/*! + * @brief start wake up alarm + * @note alarm in RtcTimerContext.Rtc_Time + timeoutValue + * @param timeoutValue in ticks + * @retval none + */ +static void HW_RTC_StartWakeUpAlarm( uint32_t timeoutValue ) +{ + uint16_t rtcAlarmSubSeconds = 0; + uint16_t rtcAlarmSeconds = 0; + uint16_t rtcAlarmMinutes = 0; + uint16_t rtcAlarmHours = 0; + uint16_t rtcAlarmDays = 0; + RTC_TimeTypeDef RTC_TimeStruct = RtcTimerContext.RTC_Calndr_Time; + RTC_DateTypeDef RTC_DateStruct = RtcTimerContext.RTC_Calndr_Date; + + HW_RTC_StopAlarm( ); + DBG_GPIO_SET(GPIOB, GPIO_PIN_13); + + /*reverse counter */ + rtcAlarmSubSeconds = PREDIV_S - RTC_TimeStruct.SubSeconds; + rtcAlarmSubSeconds += ( timeoutValue & PREDIV_S); + /* convert timeout to seconds */ + timeoutValue >>= N_PREDIV_S; /* convert timeout in seconds */ + + /*convert microsecs to RTC format and add to 'Now' */ + rtcAlarmDays = RTC_DateStruct.Date; + while (timeoutValue >= SecondsInDay) + { + timeoutValue -= SecondsInDay; + rtcAlarmDays++; + } + + /* calc hours */ + rtcAlarmHours = RTC_TimeStruct.Hours; + while (timeoutValue >= SecondsInHour) + { + timeoutValue -= SecondsInHour; + rtcAlarmHours++; + } + + /* calc minutes */ + rtcAlarmMinutes = RTC_TimeStruct.Minutes; + while (timeoutValue >= SecondsInMinute) + { + timeoutValue -= SecondsInMinute; + rtcAlarmMinutes++; + } + + /* calc seconds */ + rtcAlarmSeconds = RTC_TimeStruct.Seconds + timeoutValue; + + /***** correct for modulo********/ + while (rtcAlarmSubSeconds >= (PREDIV_S+1)) + { + rtcAlarmSubSeconds -= (PREDIV_S+1); + rtcAlarmSeconds++; + } + + while (rtcAlarmSeconds >= 60) + { + rtcAlarmSeconds -= 60; + rtcAlarmMinutes++; + } + + while (rtcAlarmMinutes >= 60) + { + rtcAlarmMinutes -= 60; + rtcAlarmHours++; + } + + while (rtcAlarmHours >= HoursInDay) + { + rtcAlarmHours -= HoursInDay; + rtcAlarmDays++; + } + + if( RTC_DateStruct.Year % 4 == 0 ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.Month - 1 ]; + } + } + + /* Set RTC_AlarmStructure with calculated values*/ + RTC_AlarmStructure.AlarmTime.SubSeconds = PREDIV_S-rtcAlarmSubSeconds; + RTC_AlarmStructure.AlarmSubSecondMask = HW_RTC_ALARMSUBSECONDMASK; + RTC_AlarmStructure.AlarmTime.Seconds = rtcAlarmSeconds; + RTC_AlarmStructure.AlarmTime.Minutes = rtcAlarmMinutes; + RTC_AlarmStructure.AlarmTime.Hours = rtcAlarmHours; + RTC_AlarmStructure.AlarmDateWeekDay = ( uint8_t )rtcAlarmDays; + RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_TimeStruct.TimeFormat; + RTC_AlarmStructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; + RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_NONE; + RTC_AlarmStructure.Alarm = RTC_ALARM_A; + RTC_AlarmStructure.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; + RTC_AlarmStructure.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET; + + /* Set RTC_Alarm */ + HAL_RTC_SetAlarm_IT( &RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN ); + + /* Debug Printf*/ + DBG( HW_RTC_GetCalendarValue( &RTC_DateStruct, &RTC_TimeStruct ); ); + //DBG_PRINTF("it's %d:%d:%d:%d ", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds, (uint16_t)((PREDIV_S - RTC_TimeStruct.SubSeconds)*1000)>>N_PREDIV_S); + //DBG_PRINTF("WU@ %d:%d:%d:%d\n", rtcAlarmHours, rtcAlarmMinutes, rtcAlarmSeconds, (rtcAlarmSubSeconds*1000)>>N_PREDIV_S ); + + DBG_GPIO_RST(GPIOB, GPIO_PIN_13); +} + + +/*! + * @brief get current time from calendar in ticks + * @param pointer to RTC_DateStruct + * @param pointer to RTC_TimeStruct + * @retval time in ticks + */ +static uint32_t HW_RTC_GetCalendarValue( RTC_DateTypeDef* RTC_DateStruct, RTC_TimeTypeDef* RTC_TimeStruct ) +{ + uint32_t calendarValue = 0; + uint32_t i = 0; + uint32_t first_read; + + /* Get Time and Date*/ + HAL_RTC_GetTime( &RtcHandle, RTC_TimeStruct, RTC_FORMAT_BIN ); + + /* make sure it is correct due to asynchronus nature of RTC*/ + do { + first_read = RTC_TimeStruct->SubSeconds; + HAL_RTC_GetDate( &RtcHandle, RTC_DateStruct, RTC_FORMAT_BIN ); + HAL_RTC_GetTime( &RtcHandle, RTC_TimeStruct, RTC_FORMAT_BIN ); + } while (first_read != RTC_TimeStruct->SubSeconds); + + /* years (calc valid up to year 2099)*/ + for( i = 0; i < RTC_DateStruct->Year; i++ ) + { + if( (i % 4) == 0 ) + { + calendarValue += DaysInLeapYear * SecondsInDay; + } + else + { + calendarValue += DaysInYear * SecondsInDay; + } + } + + /* months (calc valid up to year 2099)*/ + if(( (RTC_DateStruct->Year % 4) == 0 ) ) + { + for( i = 0; i < ( RTC_DateStruct->Month - 1 ); i++ ) + { + calendarValue += DaysInMonthLeapYear[i] * SecondsInDay; + } + } + else + { + for( i = 0; i < ( RTC_DateStruct->Month - 1 ); i++ ) + { + calendarValue += DaysInMonth[i] * SecondsInDay; + } + } + + /* days */ + calendarValue += ( ( uint32_t )RTC_TimeStruct->Seconds + + ( ( uint32_t )RTC_TimeStruct->Minutes * SecondsInMinute ) + + ( ( uint32_t )RTC_TimeStruct->Hours * SecondsInHour ) + + ( ( uint32_t )( RTC_DateStruct->Date * SecondsInDay ) ) ); + + calendarValue = (calendarValue<<N_PREDIV_S) + ( PREDIV_S - RTC_TimeStruct->SubSeconds); + + return( calendarValue ); +} + + +/** + * @brief RTC MSP Initialization + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * @param hrtc: RTC handle pointer + * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select + * the RTC clock source; in this case the Backup domain will be reset in + * order to modify the RTC Clock source, as consequence RTC registers (including + * the backup registers) and RCC_CSR register are set to their reset values. + * @retval None + */ +void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) +{ + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + + /*##-1- Configue the RTC clock soucre ######################################*/ + /* -a- Enable LSE Oscillator */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + DBG_PRINTF("Error_Handler\n\r"); + while(1); + } + + /* -b- Select LSI as RTC clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + DBG_PRINTF("Error_Handler\n\r"); + while(1); + } + + /*##-2- Enable the RTC peripheral Clock ####################################*/ + /* Enable RTC Clock */ + __HAL_RCC_RTC_ENABLE(); + + /*##-3- Configure the NVIC for RTC Alarm ###################################*/ + HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); +} + +/** + * @brief RTC MSP De-Initialization + * This function freeze the hardware resources used in this example: + * - Disable the Peripheral's clock + * @param hrtc: RTC handle pointer + * @retval None + */ +void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc) +{ + /* Reset peripherals */ + __HAL_RCC_RTC_DISABLE(); +} +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + +