/** ****************************************************************************** * @file ald_rtc.c * @brief RTC module driver. * This file provides firmware functions to manage the following * functionalities of the RTC peripheral: * + Initialization functions * + Time and date functions * + Alarm functions * + Time stamp functions * + Tamper functions * + Wake-up functions * + Clock output functions * + Peripheral Control functions * @version V1.0 * @date 25 Apr 2019 * @author AE Team * @note * Change Logs: * Date Author Notes * 25 Apr 2019 AE Team The first version * * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * 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 * * 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. ********************************************************************************** * @verbatim ============================================================================== ##### How to use this driver ##### ============================================================================== [..] (+) Enable the RTC controller interface clock. (+) Select the RTC source clock(default LOSC). (+) Configure the RTC asynchronous prescaler, synchronous prescaler and hour format using the ald_rtc_init() function. *** Time and date operation *** ================================= [..] (+) To configure the time use the ald_rtc_set_time() function. (+) To configure the date use the ald_rtc_set_date() function. (+) To read the time use the ald_rtc_get_time() function. (+) To read the date use the ald_rtc_get_date() function. *** Alarm operation *** =================================== [..] (+) To configure the alarm use ald_rtc_set_alarm() function (+) To read the alarm use ald_rtc_get_alarm() function (+) To cancel the alarm use ald_rtc_alarm_cmd() function *** Time stamp operation *** =================================== [..] (+) To configure the time stamp use ald_rtc_set_time_stamp() function (+) To read the time stamp use ald_rtc_get_time_stamp() function (+) To cancel the time stamp use ald_rtc_cancel_time_stamp() function *** Tamper operation *** =================================== [..] (+) To configure the tamper use ald_rtc_set_tamper() function (+) To cancel the tamper use ald_rtc_alarm_cmd() function *** Wake-up operation *** =================================== [..] (+) To configure the wake-up parameters use ald_rtc_set_wakeup() function (+) To read the re-load register value use ald_rtc_get_wakeup_timer_value() function (+) To cancel the wake-up use ald_rtc_cancel_wakeup() function *** Output clock operation *** =================================== [..] (+) To configure the clock output type use ald_rtc_set_clock_output() function (+) To cancel the clock output use ald_rtc_cancel_clock_output() function *** Control functions *** =================================== [..] (+) Configure interrupt enable/disable. (+) Enable/disable alarm. (+) Configure rtc shift. (+) Calibrate time. (+) Get interrupt source status. (+) Get interrupt flag status. (+) Clear interrupt flag. ================================================================== ##### RTC and low power modes ##### ================================================================== [..] The MCU can be woken up from a low power mode by an RTC alternate function. [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B), RTC wake-up, RTC tamper event detection and RTC time stamp event detection. These RTC alternate functions can wake up the system from the Stop and Standby low power modes. [..] The system can also wake up from low power modes without depending on an external interrupt (Auto-wake-up mode), by using the RTC alarm or the RTC wake-up events. [..] The RTC provides a programmable time base for waking up from the Stop or Standby mode at regular intervals. Wake-up from STOP and STANDBY modes is possible only when the RTC clock source is LSE or LSI. *** RTC driver macros list *** ============================================= [..] Below the list of most used macros in RTC driver. (+) RTC_UNLOCK() Disable the protect. (+) RTC_LOCK() Enable the protect. (+) RTC_BY_PASS_ENABLE() Enable the by-pass shadow register. (+) RTC_BY_PASS_DISABLE() Disable the by-pass shadow register. (+) RTC_SUMMER_TIME_ENABLE() Enable summer time. (+) RTC_SUMMER_TIME_DISABLE() Disable summer time. (+) RTC_WINTER_TIME_ENABLE() Enable winter time. (+) RTC_WINTER_TIME_DISABLE() Disable winter time. [..] (@) You can refer to the RTC driver header file for used the macros @endverbatim ****************************************************************************** */ #include "ald_conf.h" /** @addtogroup ES32FXXX_ALD * @{ */ /** @defgroup RTC RTC * @brief RTC module driver * @{ */ #ifdef ALD_RTC /** @addtogroup RTC_Private_Functions RTC Private Functions * @{ */ /** * @brief Converts form 2 digit BCD to Binary. * @param bcd: BCD value to be converted. * @retval Converted word. */ static uint32_t bcd_to_dec(uint32_t bcd) { return ((bcd & 0xF) + ((bcd >> 4) & 0xF) * 10); } /** * @brief Converts a 2 digit decimal to BCD format. * @param dec: Byte to be converted. * @retval Converted byte. */ static uint32_t dec_to_bcd(uint32_t dec) { return (((dec / 10) << 4) | (dec % 10)); } /** * @brief Time and Date consistency check. * @param t_last: Last time. * @param d_last: Last date. * @param time: Current time. * @param date: Current time. * @retval status: * 0 - Not consistency * 1 - Consistency */ static int32_t rtc_consistency_check(rtc_time_t *t_last, rtc_date_t *d_last, rtc_time_t *time, rtc_date_t *date) { if (t_last->second != time->second) return 0; if (t_last->minute != time->minute) return 0; if (t_last->hour != time->hour) return 0; if (d_last->day != date->day) return 0; if (d_last->month != date->month) return 0; if (d_last->year != date->year) return 0; return 1; } /** * @} */ /** @defgroup RTC_Public_Functions RTC Public Functions * @{ */ /** @defgroup RTC_Public_Functions_Group1 Initialization functions * @brief Initialization functions * * @verbatim =============================================================================== ##### Initialization function ##### =============================================================================== [..] This section provides functions allowing to initialize and configure the RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable RTC registers Write protection. (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. It is split into 2 programmable prescalers to minimize power consumption. (++) A 7-bit asynchronous prescaler and a 13-bit synchronous prescaler. (++) When both prescalers are used, it is recommended to configure the asynchronous prescaler to a high value to minimize power consumption. (#) All RTC registers are Write protected. Writing to the RTC registers is enabled by writing a key into the Write Protection register. @endverbatim * @{ */ /** * @brief Reset RTC register. * @retval None */ void ald_rtc_reset(void) { RTC_UNLOCK(); WRITE_REG(RTC->CON, 0x0); WRITE_REG(RTC->TAMPCON, 0x0); WRITE_REG(RTC->WUMAT, 0x0); WRITE_REG(RTC->IER, 0x0); WRITE_REG(RTC->IFCR, ~0x0); RTC_LOCK(); return; } /** * @brief Initialize the RTC module. * @param init: Pointer to rtc_init_t structure which contains * the configuration parameters. * @retval None */ void ald_rtc_init(rtc_init_t *init) { assert_param(IS_RTC_HOUR_FORMAT(init->hour_format)); assert_param(IS_RTC_OUTPUT_SEL(init->output)); assert_param(IS_RTC_OUTPUT_POLARITY(init->output_polarity)); ald_rtc_reset(); RTC_UNLOCK(); MODIFY_REG(RTC->CON, RTC_CON_HFM_MSK, init->hour_format << RTC_CON_HFM_POS); MODIFY_REG(RTC->CON, RTC_CON_EOS_MSK, init->output << RTC_CON_EOS_POSS); MODIFY_REG(RTC->CON, RTC_CON_POL_MSK, init->output_polarity << RTC_CON_POL_POS); MODIFY_REG(RTC->PSR, RTC_PSR_SPRS_MSK, init->synch_pre_div << RTC_PSR_SPRS_POSS); MODIFY_REG(RTC->PSR, RTC_PSR_APRS_MSK, init->asynch_pre_div << RTC_PSR_APRS_POSS); SET_BIT(RTC->CON, RTC_CON_GO_MSK); RTC_LOCK(); return; } /** * @brief Configure the RTC source. * @param sel: RTC source type. * @retval None */ void ald_rtc_source_select(rtc_source_sel_t sel) { assert_param(IS_RTC_SOURCE_SEL(sel)); BKPC_UNLOCK(); MODIFY_REG(BKPC->PCCR, BKPC_PCCR_RTCCS_MSK, sel << BKPC_PCCR_RTCCS_POSS); if (sel == RTC_SOURCE_LOSC) { SET_BIT(BKPC->CR, BKPC_CR_LOSCEN_MSK); } else if (sel == RTC_SOURCE_LRC) { SET_BIT(BKPC->CR, BKPC_CR_LRCEN_MSK); } else { ; /* do nothing */ } BKPC_LOCK(); return; } /** * @} */ /** @defgroup RTC_Public_Functions_Group2 Time and Date functions * @brief RTC Time and Date functions * * @verbatim =============================================================================== ##### Time and Date functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the time use the ald_rtc_set_time() function. (+) To configure the date use the ald_rtc_set_date() function. (+) To read the time use the ald_rtc_get_time() function. (+) To read the date use the ald_rtc_get_date() function. @endverbatim * @{ */ /** * @brief Set specified time. * @param time: pointer to a rtc_time_t structure. * @param format: Data format. * @retval ALD status. */ ald_status_t ald_rtc_set_time(rtc_time_t *time, rtc_format_t format) { uint32_t tmp; assert_param(IS_RTC_FORMAT(format)); if (format == RTC_FORMAT_DEC) { assert_param(IS_RTC_SECOND(time->second)); assert_param(IS_RTC_MINUTE(time->minute)); assert_param(IS_RTC_HOUR(time->hour)); tmp = (dec_to_bcd(time->second)) | (dec_to_bcd(time->minute) << 8) | (dec_to_bcd(time->hour) << 16); } else { assert_param(IS_RTC_SECOND(bcd_to_dec(time->second))); assert_param(IS_RTC_MINUTE(bcd_to_dec(time->minute))); assert_param(IS_RTC_HOUR(bcd_to_dec(time->hour))); tmp = time->second | (time->minute << 8) | (time->hour << 16); } RTC_UNLOCK(); WRITE_REG(RTC->TIME, tmp); RTC_LOCK(); tmp = ald_get_tick(); while (READ_BIT(RTC->CON, RTC_CON_BUSY_MSK)) { if ((ald_get_tick() - tmp) > RTC_TIMEOUT_VALUE) return TIMEOUT; } return OK; } /** * @brief Set specified date. * @param date: pointer to a rtc_date_t structure. * @param format: Data format. * @retval ALD status. */ ald_status_t ald_rtc_set_date(rtc_date_t *date, rtc_format_t format) { uint32_t tmp; assert_param(IS_RTC_FORMAT(format)); if (format == RTC_FORMAT_DEC) { assert_param(IS_RTC_DAY(date->day)); assert_param(IS_RTC_MONTH(date->month)); assert_param(IS_RTC_YEAR(date->year)); tmp = (dec_to_bcd(date->day)) | (dec_to_bcd(date->month) << 8) | (dec_to_bcd(date->year) << 16) | (dec_to_bcd(date->week) << 24); } else { assert_param(IS_RTC_DAY(bcd_to_dec(date->day))); assert_param(IS_RTC_MONTH(bcd_to_dec(date->month))); assert_param(IS_RTC_YEAR(bcd_to_dec(date->year))); tmp = date->day | (date->month << 8) | (date->year << 16) | (date->week << 24); } RTC_UNLOCK(); WRITE_REG(RTC->DATE, tmp); RTC_LOCK(); tmp = ald_get_tick(); while (READ_BIT(RTC->CON, RTC_CON_BUSY_MSK)) { if ((ald_get_tick() - tmp) > RTC_TIMEOUT_VALUE) return TIMEOUT; } return OK; } /** * @brief Get current time. * @param time: pointer to a rtc_time_t structure. * @param format: Data format. * @retval None */ void ald_rtc_get_time(rtc_time_t *time, rtc_format_t format) { uint32_t tmp; assert_param(time != NULL); assert_param(IS_RTC_FORMAT(format)); time->sub_sec = RTC->SSEC & 0xFFFF; tmp = RTC->TIME; if (format == RTC_FORMAT_DEC) { time->second = bcd_to_dec(tmp & 0x7F); time->minute = bcd_to_dec((tmp >> 8) & 0x7F); time->hour = bcd_to_dec((tmp >> 16) & 0x7F); } else { time->second = tmp & 0x7F; time->minute = (tmp >> 8) & 0x7F; time->hour = (tmp >> 16) & 0x7F; } return; } /** * @brief Get current date. * @param date: pointer to a rtc_date_t structure. * @param format: Data format. * @retval None */ void ald_rtc_get_date(rtc_date_t *date, rtc_format_t format) { uint32_t tmp = RTC->DATE; assert_param(date != NULL); assert_param(IS_RTC_FORMAT(format)); if (format == RTC_FORMAT_DEC) { date->day = bcd_to_dec(tmp & 0x3F); date->month = bcd_to_dec((tmp >> 8) & 0x1F); date->year = bcd_to_dec((tmp >> 16) & 0xFF); date->week = bcd_to_dec((tmp >> 24) & 0x7); } else { date->day = tmp & 0x3F; date->month = (tmp >> 8) & 0x1F; date->year = (tmp >> 16) & 0xFF; date->week = (tmp >> 24) & 0x7; } return; } /** * @brief Get time and date consistency. * @param date: pointer to a rtc_date_t structure. * @param time: pointer to a rtc_time_t structure. * @param format: Data format. * @retval Status: * 0 - Consistency * -1 - Not consistency */ int32_t ald_rtc_get_date_time(rtc_date_t *date, rtc_time_t *time, rtc_format_t format) { int32_t nr = 3; rtc_date_t d_last; rtc_time_t t_last; while (nr--) { ald_rtc_get_time(&t_last, format); ald_rtc_get_date(&d_last, format); ald_rtc_get_time(time, format); ald_rtc_get_date(date, format); if (rtc_consistency_check(&t_last, &d_last, time, date)) return 0; } return -1; } /** * @} */ /** @defgroup RTC_Public_Functions_Group3 Alarm functions * @brief RTC alarm functions * * @verbatim =============================================================================== ##### Alarm functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the alarm use ald_rtc_set_alarm() function (+) To read the alarm use ald_rtc_get_alarm() function @endverbatim * @{ */ /** * @brief Set alarm. * @param alarm: pointer to rtc_alarm_t struct. * @param format: Data format. * @retval None */ void ald_rtc_set_alarm(rtc_alarm_t *alarm, rtc_format_t format) { unsigned int tmp, ss_tmp; assert_param(IS_RTC_ALARM(alarm->idx)); assert_param(IS_RTC_ALARM_SEL(alarm->sel)); assert_param(IS_RTC_ALARM_SS_MASK(alarm->ss_mask)); assert_param(IS_RTC_FORMAT(format)); if (format == RTC_FORMAT_DEC) { assert_param(IS_RTC_SECOND(alarm->time.second)); assert_param(IS_RTC_MINUTE(alarm->time.minute)); assert_param(IS_RTC_HOUR(alarm->time.hour)); tmp = (dec_to_bcd(alarm->time.second)) | (dec_to_bcd(alarm->time.minute) << 8) | (dec_to_bcd(alarm->time.hour) << 16) | alarm->mask; if (alarm->sel == RTC_SELECT_DAY) { assert_param(IS_RTC_DAY(alarm->day)); tmp |= (dec_to_bcd(alarm->day) << 24); tmp &= 0x7FFFFFFF; /* Reset bit31 */ } else { tmp |= (1 << (alarm->week + 24)); tmp |= 0x80000000; /* Set bit31 */ } } else { assert_param(IS_RTC_SECOND(bcd_to_dec(alarm->time.second))); assert_param(IS_RTC_MINUTE(bcd_to_dec(alarm->time.minute))); assert_param(IS_RTC_HOUR(bcd_to_dec(alarm->time.hour))); tmp = alarm->time.second | (alarm->time.minute << 8) | (alarm->time.hour << 16) | alarm->mask; if (alarm->sel == RTC_SELECT_DAY) { assert_param(IS_RTC_DAY(bcd_to_dec(alarm->day))); tmp |= (alarm->day << 24); tmp &= 0x7FFFFFFF; /* Reset bit31 */ } else { tmp |= (1 << (alarm->week + 24)); tmp |= 0x80000000; /* Set bit31 */ } } ss_tmp = (alarm->time.sub_sec & 0x7F) | (alarm->ss_mask << 24); RTC_UNLOCK(); if (alarm->idx == RTC_ALARM_A) { WRITE_REG(RTC->ALMA, tmp); WRITE_REG(RTC->ALMASSEC, ss_tmp); SET_BIT(RTC->CON, RTC_CON_ALMAEN_MSK); } else { WRITE_REG(RTC->ALMB, tmp); WRITE_REG(RTC->ALMBSSEC, ss_tmp); SET_BIT(RTC->CON, RTC_CON_ALMBEN_MSK); } RTC_LOCK(); return; } /** * @brief Get alarm parameters. * @param alarm: pointer to rtc_alarm_t struct. * @param format: Data format. * @retval None */ void ald_rtc_get_alarm(rtc_alarm_t *alarm, rtc_format_t format) { uint8_t week; uint32_t tmp, ss_tmp; assert_param(alarm != NULL); assert_param(IS_RTC_FORMAT(format)); if (alarm->idx == RTC_ALARM_A) { tmp = RTC->ALMA; ss_tmp = RTC->ALMASSEC; } else { tmp = RTC->ALMB; ss_tmp = RTC->ALMBSSEC; } if ((tmp >> 31) & 0x1) { alarm->sel = RTC_SELECT_WEEK; week = ((tmp >> 24) & 0x7F); switch (week) { case 1: alarm->week = 0; break; case 2: alarm->week = 1; break; case 4: alarm->week = 2; break; case 8: alarm->week = 3; break; case 16: alarm->week = 4; break; case 32: alarm->week = 5; break; case 64: alarm->week = 6; break; default: break; } } else { alarm->sel = RTC_SELECT_DAY; if (format == RTC_FORMAT_DEC) alarm->day = bcd_to_dec((tmp >> 24) & 0x3F); else alarm->day = (tmp >> 24) & 0x3F; } if (format == RTC_FORMAT_DEC) { alarm->time.second = bcd_to_dec(tmp & 0x7F); alarm->time.minute = bcd_to_dec((tmp >> 8) & 0x7F); alarm->time.hour = bcd_to_dec((tmp >> 16) & 0x3F); } else { alarm->time.second = tmp & 0x7F; alarm->time.minute = (tmp >> 8) & 0x7F; alarm->time.hour = (tmp >> 16) & 0x3F; } alarm->time.sub_sec = ss_tmp & 0x7FFF; alarm->ss_mask = (rtc_sub_second_mask_t)((ss_tmp >> 24) & 0xF); alarm->mask = tmp & ALARM_MASK_ALL; return; } /** * @} */ /** @defgroup RTC_Public_Functions_Group4 Time stamp functions * @brief RTC time stamp functions * * @verbatim =============================================================================== ##### Time stamp functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the time stamp use ald_rtc_set_time_stamp() function (+) To read the time stamp use ald_rtc_get_time_stamp() function (+) To cancel the time stamp use ald_rtc_cancel_time_stamp() function @endverbatim * @{ */ /** * @brief Set time stamp. * @param sel: time stamp signal select: * @arg RTC_TS_SIGNAL_SEL_TAMPER0 * @arg RTC_TS_SIGNAL_SEL_TAMPER1 * @param style: time stamp trigger style: * @arg RTC_TS_RISING_EDGE * @arg RTC_TS_FALLING_EDGE * @retval None */ void ald_rtc_set_time_stamp(rtc_ts_signal_sel_t sel, rtc_ts_trigger_style_t style) { assert_param(IS_RTC_TS_SIGNAL(sel)); assert_param(IS_RTC_TS_STYLE(style)); RTC_UNLOCK(); CLEAR_BIT(RTC->CON, RTC_CON_TSEN_MSK); MODIFY_REG(RTC->CON, RTC_CON_TSSEL_MSK, style << RTC_CON_TSSEL_POS); MODIFY_REG(RTC->CON, RTC_CON_TSPIN_MSK, sel << RTC_CON_TSPIN_POS); SET_BIT(RTC->CON, RTC_CON_TSEN_MSK); RTC_LOCK(); return; } /** * @brief Cancel time stamp. * @retval None */ void ald_rtc_cancel_time_stamp(void) { RTC_UNLOCK(); CLEAR_BIT(RTC->CON, RTC_CON_TSEN_MSK); RTC_LOCK(); return; } /** * @brief Get time stamp value. * @param ts_time: pointer to rtc_time_t structure. * @param ts_date: pointer to rtc_date_t structure. * @param format: Data format. * @retval None */ void ald_rtc_get_time_stamp(rtc_time_t *ts_time, rtc_date_t *ts_date, rtc_format_t format) { uint32_t tmp0, tmp1; assert_param(ts_time != NULL); assert_param(ts_date != NULL); assert_param(IS_RTC_FORMAT(format)); ts_time->sub_sec = RTC->TSSSEC & 0xFFFF; tmp0 = RTC->TSTIME; tmp1 = RTC->TSDATE; if (format == RTC_FORMAT_DEC) { ts_time->second = bcd_to_dec(tmp0 & 0x7F); ts_time->minute = bcd_to_dec((tmp0 >> 8) & 0x7F); ts_time->hour = bcd_to_dec((tmp0 >> 16) & 0x3F); ts_date->day = bcd_to_dec(tmp1 & 0x3F); ts_date->month = bcd_to_dec((tmp1 >> 8) & 0x1F); ts_date->year = bcd_to_dec((tmp1 >> 16) & 0xFF); ts_date->week = bcd_to_dec((tmp1 >> 24) & 0x7); } else { ts_time->second = tmp0 & 0x7F; ts_time->minute = (tmp0 >> 8) & 0x7F; ts_time->hour = (tmp0 >> 16) & 0x3F; ts_date->day = tmp1 & 0x3F; ts_date->month = (tmp1 >> 8) & 0x1F; ts_date->year = (tmp1 >> 16) & 0xFF; ts_date->week = (tmp1 >> 24) & 0x7; } return; } /** * @} */ /** @defgroup RTC_Public_Functions_Group5 Tamper functions * @brief RTC tamper functions * * @verbatim =============================================================================== ##### Tamper functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the tamper use ald_rtc_set_tamper() function (+) To cancel the tamper use ald_rtc_alarm_cmd() function @endverbatim * @{ */ /** * @brief Set tamper parameters. * @param tamper: pointer to rtc_tamper_t structure. * @retval None */ void ald_rtc_set_tamper(rtc_tamper_t *tamper) { assert_param(IS_RTC_TAMPER(tamper->idx)); assert_param(IS_RTC_TAMPER_TRIGGER(tamper->trig)); assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(tamper->freq)); assert_param(IS_RTC_TAMPER_DURATION(tamper->dur)); assert_param(IS_FUNC_STATE(tamper->ts)); RTC_UNLOCK(); MODIFY_REG(RTC->TAMPCON, RTC_TAMPCON_TAMPTS_MSK, tamper->ts << RTC_TAMPCON_TAMPTS_POS); MODIFY_REG(RTC->TAMPCON, RTC_TAMPCON_TAMPCKS_MSK, tamper->freq << RTC_TAMPCON_TAMPCKS_POSS); MODIFY_REG(RTC->TAMPCON, RTC_TAMPCON_TAMPFLT_MSK, tamper->dur << RTC_TAMPCON_TAMPFLT_POSS); if (tamper->idx == RTC_TAMPER_0) { MODIFY_REG(RTC->TAMPCON, RTC_TAMPCON_TAMP0LV_MSK, tamper->trig << RTC_TAMPCON_TAMP0LV_POS); SET_BIT(RTC->TAMPCON, RTC_TAMPCON_TAMP0EN_MSK); } else { MODIFY_REG(RTC->TAMPCON, RTC_TAMPCON_TAMP1LV_MSK, tamper->trig << RTC_TAMPCON_TAMP1LV_POS); SET_BIT(RTC->TAMPCON, RTC_TAMPCON_TAMP1EN_MSK); } RTC_LOCK(); return; } /** * @brief Cancel tamper. * @param idx: index of tamper: * @arg RTC_TAMPER_0 * @arg RTC_TAMPER_1 * @retval None */ void ald_rtc_cancel_tamper(rtc_tamper_idx_t idx) { assert_param(IS_RTC_TAMPER(idx)); RTC_UNLOCK(); if (idx == RTC_TAMPER_0) CLEAR_BIT(RTC->TAMPCON, RTC_TAMPCON_TAMP0EN_MSK); else CLEAR_BIT(RTC->TAMPCON, RTC_TAMPCON_TAMP1EN_MSK); RTC_LOCK(); return; } /** * @} */ /** @defgroup RTC_Public_Functions_Group6 Wake-up functions * @brief RTC wake-up functions * * @verbatim =============================================================================== ##### Wake-up functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the wake-up parameters use ald_rtc_set_wakeup() function (+) To read the re-load register value use ald_rtc_get_wakeup_timer_value() function (+) To cancel the wake-up use ald_rtc_cancel_wakeup() function @endverbatim * @{ */ /** * @brief Set wake-up parameters. * @param clock: pointer to rtc_wakeup_clock_t structure. * @param value: re-load value. * @retval None */ void ald_rtc_set_wakeup(rtc_wakeup_clock_t clock, uint16_t value) { assert_param(IS_RTC_WAKEUP_CLOCK(clock)); RTC_UNLOCK(); MODIFY_REG(RTC->CON, RTC_CON_WUCKS_MSK, clock << RTC_CON_WUCKS_POSS); WRITE_REG(RTC->WUMAT, value & 0xFFFF); SET_BIT(RTC->CON, RTC_CON_WUTE_MSK); RTC_LOCK(); return; } /** * @brief Cancel wake-up. * @retval None */ void ald_rtc_cancel_wakeup(void) { RTC_UNLOCK(); CLEAR_BIT(RTC->CON, RTC_CON_WUTE_MSK); RTC_LOCK(); return; } /** * @brief Get wake-up re-load register value. * @retval Value of re-load register. */ uint16_t ald_rtc_get_wakeup_timer_value(void) { return RTC->WUMAT & 0xFFFF; } /** * @} */ /** @defgroup RTC_Public_Functions_Group7 Clock output functions * @brief RTC clock output functions * * @verbatim =============================================================================== ##### Clock output functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) To configure the clock output type use ald_rtc_set_clock_output() function (+) To cancel the clock output use ald_rtc_cancel_clock_output() function @endverbatim * @{ */ /** * @brief Set clock output parameters. * @param clock: pointer to rtc_clock_output_t structure. * @retval ALD status. */ ald_status_t ald_rtc_set_clock_output(rtc_clock_output_t clock) { uint32_t cnt = 4000; assert_param(IS_RTC_CLOCK_OUTPUT(clock)); SYSCFG_UNLOCK(); if (clock == RTC_CLOCK_OUTPUT_EXA_1) { SET_BIT(CMU->CLKENR, CMU_CLKENR_PLL2EN_MSK); while ((READ_BIT(CMU->PLLCFG, CMU_PLLCFG_PLL2LCKN_MSK)) && (--cnt)); cnt = 4000; while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_PLL2RDY_MSK))) && (--cnt)); } else { CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_PLL2EN_MSK); } SYSCFG_LOCK(); RTC_UNLOCK(); MODIFY_REG(RTC->CON, RTC_CON_CKOS_MSK, clock << RTC_CON_CKOS_POSS); SET_BIT(RTC->CON, RTC_CON_CKOE_MSK); RTC_LOCK(); return OK; } /** * @brief Cancel clock output. * @retval None */ void ald_rtc_cancel_clock_output(void) { RTC_UNLOCK(); CLEAR_BIT(RTC->CON, RTC_CON_CKOE_MSK); RTC_LOCK(); return; } /** * @} */ /** @defgroup RTC_Public_Functions_Group8 Control functions * @brief RTC control functions * * @verbatim =============================================================================== ##### Control functions ##### =============================================================================== [..] This section provides functions allowing: [#] (+) Configure interrupt enable/disable. (+) Enable/disable alarm. (+) Configure rtc shift. (+) Calibrate time. (+) Get interrupt source status. (+) Get interrupt flag status. (+) Clear interrupt flag. @endverbatim * @{ */ /** * @brief Enable/disable the specified RTC interrupts. * @param it: Specifies the RTC interrupt sources to be enabled or disabled. * This parameter can be one of the @ref rtc_it_t. * @param state: New state of the specified RTC interrupts. * This parameter can be: * @arg ENABLE * @arg DISABLE * @retval None */ void ald_rtc_interrupt_config(rtc_it_t it, type_func_t state) { assert_param(IS_RTC_IT(it)); assert_param(IS_FUNC_STATE(state)); RTC_UNLOCK(); if (state == ENABLE) SET_BIT(RTC->IER, it); else CLEAR_BIT(RTC->IER, it); RTC_LOCK(); return; } /** * @brief Enable/Disable alarm. * @param idx: index of alarm: * @arg RTC_ALARM_A * @arg RTC_ALARM_B * @param state: New status of the specified alarm: * @arg ENABLE * @arg DISABLE * @retval None */ void ald_rtc_alarm_cmd(rtc_alarm_idx_t idx, type_func_t state) { assert_param(IS_RTC_ALARM(idx)); assert_param(IS_FUNC_STATE(state)); RTC_UNLOCK(); if (idx == RTC_ALARM_A) MODIFY_REG(RTC->CON, RTC_CON_ALMAEN_MSK, state << RTC_CON_ALMAEN_POS); else MODIFY_REG(RTC->CON, RTC_CON_ALMBEN_MSK, state << RTC_CON_ALMBEN_POS); RTC_LOCK(); return; } /** * @brief Set shift parameters. * @param add_1s: Enable/Disable added 1 second. * @param sub_ss: value of sub-sconde. * @retval ALD status. */ ald_status_t ald_rtc_set_shift(type_func_t add_1s, uint16_t sub_ss) { uint32_t tick; assert_param(IS_FUNC_STATE(add_1s)); assert_param(IS_SHIFT_SUB_SS(sub_ss)); RTC_UNLOCK(); MODIFY_REG(RTC->SSECTR, RTC_SSECTR_TRIM_MSK, sub_ss << RTC_SSECTR_TRIM_POSS); MODIFY_REG(RTC->SSECTR, RTC_SSECTR_INC_MSK, add_1s << RTC_SSECTR_INC_POS); RTC_LOCK(); tick = ald_get_tick(); while (READ_BIT(RTC->CON, RTC_CON_SSEC_MSK)) { if ((ald_get_tick() - tick) > RTC_TIMEOUT_VALUE) return TIMEOUT; } return OK; } /** * @brief Set calibation * @param config: pointer to rtc_cali_t structure. * @retval None */ void ald_rtc_set_cali(rtc_cali_t *config) { assert_param(IS_RTC_CALI_FREQ(config->cali_freq)); assert_param(IS_RTC_CALI_TC(config->tc)); assert_param(IS_RTC_CALC_FREQ(config->calc_freq)); assert_param(IS_RTC_CALI_CALC(config->calc)); assert_param(IS_FUNC_STATE(config->acc)); RTC_UNLOCK(); RTC_CALI_UNLOCK(); MODIFY_REG(RTC->CALCON, RTC_CALCON_CALP_MSK, config->cali_freq << RTC_CALCON_CALP_POSS); MODIFY_REG(RTC->CALCON, RTC_CALCON_TCM_MSK, config->tc << RTC_CALCON_TCM_POSS); MODIFY_REG(RTC->CALCON, RTC_CALCON_TCP_MSK, config->calc_freq << RTC_CALCON_TCP_POSS); MODIFY_REG(RTC->CALCON, RTC_CALCON_ALG_MSK, config->calc << RTC_CALCON_ALG_POS); MODIFY_REG(RTC->CALCON, RTC_CALCON_DCMACC_MSK, config->acc << RTC_CALCON_DCMACC_POS); SET_BIT(RTC->CALCON, RTC_CALCON_CALEN_MSK); RTC_CALI_LOCK(); RTC_LOCK(); return; } /** * @brief Cancel calibration * @retval None */ void ald_rtc_cancel_cali(void) { RTC_CALI_UNLOCK(); CLEAR_BIT(RTC->CALCON, RTC_CALCON_CALEN_MSK); RTC_CALI_LOCK(); return; } /** * @brief Get calibration status. * @retval ALD status. */ ald_status_t ald_rtc_get_cali_status(void) { if (READ_BIT(RTC->CALCON, RTC_CALCON_ERR_MSK)) return ERROR; else return OK; } /** * @brief Write temperature value. * @param temp: the value of temperature. * @retval None */ void ald_rtc_write_temp(uint16_t temp) { RTC_CALI_UNLOCK(); MODIFY_REG(RTC->TEMPR, RTC_TEMPR_VAL_MSK, temp << RTC_TEMPR_VAL_POSS); RTC_CALI_LOCK(); return; } /** * @brief Get the status of RTC interrupt source. * @param it: Specifies the RTC interrupt source. * This parameter can be one of the @ref rtc_it_t. * @retval Status: * - 0: RESET * - 1: SET */ it_status_t ald_rtc_get_it_status(rtc_it_t it) { assert_param(IS_RTC_IT(it)); if (READ_BIT(RTC->IER, it)) return SET; return RESET; } /** * @brief Get the status of RTC interrupt flag. * @param flag: Specifies the RTC interrupt flag. * This parameter can be one of the @ref rtc_flag_t. * @retval Status: * - 0: RESET * - 1: SET */ flag_status_t ald_rtc_get_flag_status(rtc_flag_t flag) { assert_param(IS_RTC_IF(flag)); if ((READ_BIT(RTC->IER, flag)) && (READ_BIT(RTC->ISR, flag))) return SET; return RESET; } /** @brief Clear the specified RTC pending flag. * @param flag: specifies the flag to check. * @retval None. */ void ald_rtc_clear_flag_status(rtc_flag_t flag) { assert_param(IS_RTC_IF(flag)); RTC_UNLOCK(); WRITE_REG(RTC->IFCR, flag); RTC_LOCK(); return; } /** * @} */ /** * @} */ #endif /* ALD_RTC */ /** * @} */ /** * @} */