diff --git a/include/libopencm3/stm32/f1/rtc.h b/include/libopencm3/stm32/f1/rtc.h index 3a60fca6..60d60cc2 100644 --- a/include/libopencm3/stm32/f1/rtc.h +++ b/include/libopencm3/stm32/f1/rtc.h @@ -138,12 +138,18 @@ /* TODO */ -/* --- Function prototypes --------------------------------------------------*/ - +/** RTC Interrupt Flags */ typedef enum { - RTC_SEC, RTC_ALR, RTC_OW, +/** Counter Second Flag */ + RTC_SEC, +/** Alarm Event Flag */ + RTC_ALR, +/** Counter Overflow Flag */ + RTC_OW, } rtcflag_t; +/* --- Function prototypes --------------------------------------------------*/ + BEGIN_DECLS void rtc_awake_from_off(enum rcc_osc clock_source); diff --git a/lib/stm32/f1/rtc.c b/lib/stm32/f1/rtc.c index b2d7b83f..408ffef8 100644 --- a/lib/stm32/f1/rtc.c +++ b/lib/stm32/f1/rtc.c @@ -11,6 +11,38 @@ * * @date 4 March 2013 * + * The Real Time Clock peripheral consists of a set of 16 bit control, status, + * prescaler, counter and alarm registers. Before the latter three can be + * written the RTC must be placed in configuration mode by a call to + * @ref rtc_enter_config_mode(). The functions below handle this implictly. + * + * The RTC is completely reset by performing a Backup Domain reset. Note + * that this can affect unrelated user data contained in the Backup Domain + * registers. Other forms of reset will not affect the RTC registers as they + * are contained within the backup domain. + * + * The RTC clock source to be used is selected by calling + * @ref rcc_set_rtc_clock_source(). + * + * The LSE clock source normally comes from a 32.768kHz external crystal + * This clock is in the backup domain and so continues to run when only the + * V_BAT supply is present. A prescaler value of 7FFF will give a 1 second + * count quantum. + * + * The LSI clock source is a low accuracy internal clock of about 40kHz + * frequency, and the HSE clock source is the external high speed clock + * divided by 128. + * + * Initial configuration of the RTC consists of: + * + * @li perform a Backup Domain reset if appropriate; + * @li select the clock to be used; + * @li set the prescaler, counter and configuration values; + * @li enable the RTC. + * + * @note reading the RTC registers may result in a corrupted value being + * returned in certain cases. Refer to the STM32F1xx Reference Manual. + * * LGPL License Terms @ref lgpl_license */ @@ -40,6 +72,21 @@ #include #include +/*---------------------------------------------------------------------------*/ +/** @brief RTC Set Operational from the Off state. + +Power up the backup domain clocks, enable write access to the backup domain, +select the clock source and enable the RTC. + +After calling this function all counter and control settings must be +established. + +@note The Backup Domain is reset by this function and will therefore result in +the loss of any unrelated user data stored there. + +@param[in] clock_source ::rcc_osc. RTC clock source. Only HSE/128, LSE and LSI. +*/ + void rtc_awake_from_off(enum rcc_osc clock_source) { uint32_t reg32; @@ -106,6 +153,13 @@ void rtc_awake_from_off(enum rcc_osc clock_source) while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Enter Configuration Mode. + +Prime the RTC for configuration changes by giving access to the prescaler, +and counter and alarm registers. +*/ + void rtc_enter_config_mode(void) { uint32_t reg32; @@ -117,6 +171,12 @@ void rtc_enter_config_mode(void) RTC_CRL |= RTC_CRL_CNF; } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Leave Configuration Mode. + +Revert the RTC to operational state. +*/ + void rtc_exit_config_mode(void) { uint32_t reg32; @@ -128,6 +188,12 @@ void rtc_exit_config_mode(void) while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Set the Alarm Time. + +@param[in] alarm_time uint32_t. time at which the alarm event is triggered. +*/ + void rtc_set_alarm_time(uint32_t alarm_time) { rtc_enter_config_mode(); @@ -136,6 +202,11 @@ void rtc_set_alarm_time(uint32_t alarm_time) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Enable the Alarm. + +*/ + void rtc_enable_alarm(void) { rtc_enter_config_mode(); @@ -143,6 +214,11 @@ void rtc_enable_alarm(void) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Disable the Alarm. + +*/ + void rtc_disable_alarm(void) { rtc_enter_config_mode(); @@ -150,6 +226,12 @@ void rtc_disable_alarm(void) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Set the prescaler Value + +@param[in] prescale_val uint32_t. 20 bit prescale divider. +*/ + void rtc_set_prescale_val(uint32_t prescale_val) { rtc_enter_config_mode(); @@ -158,21 +240,45 @@ void rtc_set_prescale_val(uint32_t prescale_val) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC return the Counter Value + +@returns uint32_t: the 32 bit counter value. +*/ + uint32_t rtc_get_counter_val(void) { return (RTC_CNTH << 16) | RTC_CNTL; } +/*---------------------------------------------------------------------------*/ +/** @brief RTC return the prescaler Value + +@returns uint32_t: the 20 bit prescale divider. +*/ + uint32_t rtc_get_prescale_div_val(void) { return (RTC_DIVH << 16) | RTC_DIVL; } +/*---------------------------------------------------------------------------*/ +/** @brief RTC return the Alarm Value + +@returns uint32_t: the 32 bit alarm value. +*/ + uint32_t rtc_get_alarm_val(void) { return (RTC_ALRH << 16) | RTC_ALRL; } +/*---------------------------------------------------------------------------*/ +/** @brief RTC set the Counter + +@param[in] uint32_t counter_val: 32 bit time setting for the counter. +*/ + void rtc_set_counter_val(uint32_t counter_val) { rtc_enter_config_mode(); @@ -181,6 +287,12 @@ void rtc_set_counter_val(uint32_t counter_val) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Enable Interrupt + +@param[in] flag_val ::rtcflag_t: The flag to enable. +*/ + void rtc_interrupt_enable(rtcflag_t flag_val) { rtc_enter_config_mode(); @@ -201,6 +313,12 @@ void rtc_interrupt_enable(rtcflag_t flag_val) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Disable Interrupt + +@param[in] flag_val ::rtcflag_t: The flag to disable. +*/ + void rtc_interrupt_disable(rtcflag_t flag_val) { rtc_enter_config_mode(); @@ -221,6 +339,12 @@ void rtc_interrupt_disable(rtcflag_t flag_val) rtc_exit_config_mode(); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Clear an Interrupt Flag + +@param[in] flag_val ::rtcflag_t: The flag to clear. +*/ + void rtc_clear_flag(rtcflag_t flag_val) { /* Configuration mode not needed. */ @@ -239,6 +363,13 @@ void rtc_clear_flag(rtcflag_t flag_val) } } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Return a Flag Setting + +@param[in] flag_val ::rtcflag_t: The flag to check. +@returns uint32_t: a nonzero value if the flag is set, zero otherwise. +*/ + uint32_t rtc_check_flag(rtcflag_t flag_val) { uint32_t reg32; @@ -262,6 +393,13 @@ uint32_t rtc_check_flag(rtcflag_t flag_val) return reg32; } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Start RTC after Standby Mode. + +Enable the backup domain clocks, enable write access to the backup +domain and the RTC, and synchronise the RTC register access. +*/ + void rtc_awake_from_standby(void) { uint32_t reg32; @@ -281,6 +419,17 @@ void rtc_awake_from_standby(void) while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0); } +/*---------------------------------------------------------------------------*/ +/** @brief RTC Configuration on Wakeup + +Enable the backup domain clocks and write access to the backup domain. +If the RTC has not been enabled, set the clock source and prescaler value. +The parameters are not used if the RTC has already been enabled. + +@param[in] clock_source ::rcc_osc. RTC clock source. Only HSE/128, LSE and LSI. +@param[in] prescale_val uint32_t. 20 bit prescale divider. +*/ + void rtc_auto_awake(enum rcc_osc clock_source, uint32_t prescale_val) { uint32_t reg32;