From 9d343de5f9f3620f8d915a2e6dadf874ef2d02cb Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 11 Dec 2011 23:40:49 +0000 Subject: RTC. Driver broken. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3598 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/RTCv2/rtc_lld.c | 151 +++++++++++++++++++++++---------- os/hal/platforms/STM32/RTCv2/rtc_lld.h | 73 +++++++++++++--- 2 files changed, 170 insertions(+), 54 deletions(-) (limited to 'os/hal/platforms/STM32/RTCv2') diff --git a/os/hal/platforms/STM32/RTCv2/rtc_lld.c b/os/hal/platforms/STM32/RTCv2/rtc_lld.c index cdf3aff81..cc1e846e7 100644 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.c +++ b/os/hal/platforms/STM32/RTCv2/rtc_lld.c @@ -19,8 +19,8 @@ */ /** - * @file STM32/RTCv1/rtc_lld.c - * @brief STM32 RTC subsystem low level driver header. + * @file STM32/RTCv2/rtc_lld.c + * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver header. * * @addtogroup RTC * @{ @@ -83,6 +83,8 @@ RTCDriver RTCD1; * @notapi */ void rtc_lld_init(void){ + RTCD1.id_rtc = RTC; + /* Asynchronous part of preloader. Set it to maximum value. */ #define PREDIV_A ((uint32_t)0x7F) @@ -129,21 +131,19 @@ void rtc_lld_init(void){ /* If calendar not init yet. */ if (!(RTC->ISR & RTC_ISR_INITS)){ /* Disable write protection on RTC registers. */ - RTC->WPR = 0xCA; - RTC->WPR = 0x53; + + RTCD1.id_rtc->WPR = 0xCA; + RTCD1.id_rtc->WPR = 0x53; /* Enter in init mode. */ - RTC->ISR |= RTC_ISR_INIT; + RTCD1.id_rtc->ISR |= RTC_ISR_INIT; while(!(RTC->ISR & RTC_ISR_INITF)) ; /* Prescaler registers must be written in by two separate writes. */ - RTC->PRER = preload; - RTC->PRER = preload; - RTC->ISR &= ~RTC_ISR_INIT; + RTCD1.id_rtc->PRER = preload; + RTCD1.id_rtc->PRER = preload; + RTCD1.id_rtc->ISR &= ~RTC_ISR_INIT; } - - /* Callback initially disabled.*/ - RTCD1.rtc_cb = NULL; } /** @@ -159,12 +159,12 @@ void rtc_lld_init(void){ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { (void)rtcp; - RTC->ISR |= RTC_ISR_INIT; + RTCD1.id_rtc->ISR |= RTC_ISR_INIT; while(!(RTC->ISR & RTC_ISR_INITF)) ; - RTC->TR = timespec->tv_time; - RTC->DR = timespec->tv_date; - RTC->ISR &= ~RTC_ISR_INIT; + RTCD1.id_rtc->TR = timespec->tv_time; + RTCD1.id_rtc->DR = timespec->tv_date; + RTCD1.id_rtc->ISR &= ~RTC_ISR_INIT; } /** @@ -185,74 +185,139 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { while(!(RTC->ISR & RTC_ISR_RSF)) ; - timespec->tv_time = RTC->TR; - timespec->tv_date = RTC->DR; + timespec->tv_time = RTCD1.id_rtc->TR; + timespec->tv_date = RTCD1.id_rtc->DR; #if RTC_HAS_SUBSECONDS - timespec->tv_msec = ((RTC->PRER & 0x7FFF) - RTC->SSR) / ((RTC->PRER & 0x7FFF) + 1); + timespec->tv_msec = ((RTCD1.id_rtc->PRER & 0x7FFF) - RTCD1.id_rtc->SSR) / + ((RTCD1.id_rtc->PRER & 0x7FFF) + 1); #else timespec->tv_msec = 0; #endif /* STM32_RTC_HAS_SUBSECONDS */ } - /** - * @brief Set alarm time. + * @brief Set alarm time. * - * @note Default value after BKP domain reset is 0xFFFFFFFF + * @note Default value after BKP domain reset for both comparators is 0. + * @note Function does not performs any checks of alarm time validity. * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[in] alarmspec pointer to a @p RTCAlarm structure + * @param[in] rtcp Pointer to RTC driver structure. + * @param[in] alarm Alarm identifier. Can be 1 or 2. + * @param[in] alarmspec Pointer to a @p RTCAlarm structure. * * @notapi */ void rtc_lld_set_alarm(RTCDriver *rtcp, rtcalarm_t alarm, const RTCAlarm *alarmspec) { - (void)rtcp; - (void)alarm; - (void)alarmspec; + if (alarm == 1){ + rtcp->id_rtc->CR &= ~RTC_CR_ALRAE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRAWF)) + ; + rtcp->id_rtc->ALRMAR = alarmspec->tv_datetime; + rtcp->id_rtc->CR |= RTC_CR_ALRAE; + } + else{ + rtcp->id_rtc->CR &= ~RTC_CR_ALRBE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRBWF)) + ; + rtcp->id_rtc->ALRMAR = alarmspec->tv_datetime; + rtcp->id_rtc->CR |= RTC_CR_ALRBE; + } } /** - * @brief Get current alarm. - * @note If an alarm has not been set then the returned alarm specification - * is not meaningful. - * - * @note Default value after BKP domain reset is 0xFFFFFFFF. + * @brief Get alarm time. * * @param[in] rtcp pointer to RTC driver structure * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure + * @param[in] alarmspec pointer to a @p RTCAlarm structure * * @notapi */ void rtc_lld_get_alarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec) { + if (alarm == 1) + alarmspec->tv_datetime = rtcp->id_rtc->ALRMAR; + else + alarmspec->tv_datetime = rtcp->id_rtc->ALRMBR; +} - (void)rtcp; - (void)alarm; - (void)alarmspec; +/** + * @brief Sets time of periodic wakeup. + * + * @note Default value after BKP domain reset is 0x0000FFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] wakeupspec pointer to a @p RTCWakeup structure + * + * @notapi + */ +void rtc_lld_set_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec){ + chDbgCheck((wakeupspec->wutr != 0) || ((wakeupspec->wucksel & 0x7) != 3), + "rtc_lld_set_periodic_wakeup, forbidden combination"); + + rtcp->id_rtc->CR &= ~RTC_CR_WUTE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_WUTWF)) + ; + rtcp->id_rtc->WUTR = wakeupspec->wutr & 0xFFFF; + rtcp->id_rtc->CR = wakeupspec->wucksel & 0x7; + rtcp->id_rtc->CR |= RTC_CR_WUTE; } +/** + * @brief Gets time of periodic wakeup. + * + * @note Default value after BKP domain reset is 0x0000FFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] wakeupspec pointer to a @p RTCWakeup structure + * + * @notapi + */ +void rtc_lld_get_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec){ + wakeupspec->wutr = rtcp->id_rtc->WUTR; + wakeupspec->wucksel = rtcp->id_rtc->CR & 0x7; +} + + + + + + + + /** * @brief Enables or disables RTC callbacks. - * @details This function enables or disables callbacks, use a @p NULL pointer - * in order to disable a callback. + * @details TODO: * * @param[in] rtcp pointer to RTC driver structure * @param[in] callback callback function pointer or @p NULL * * @notapi */ -void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { - if (callback != NULL) { - rtcp->rtc_cb = callback; - } - return; +void rtc_lld_set_callback(RTCDriver *rtcp, RTCCallbackConfig *cb_cfg) { + (void)rtcp; + (void)cb_cfg; +// if (callback != NULL) { +// rtcp->rtc_cb = callback; +// NVICEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(STM32_RTC_IRQ_PRIORITY)); +// +// /* Interrupts are enabled only after setting up the callback, this +// way there is no need to check for the NULL callback pointer inside +// the IRQ handler.*/ +// RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); +// RTC->CRH |= RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; +// } +// else { +// NVICDisableVector(RTC_IRQn); +// RTC->CRL = 0; +// RTC->CRH = 0; +// } } + #endif /* HAL_USE_RTC */ /** @} */ diff --git a/os/hal/platforms/STM32/RTCv2/rtc_lld.h b/os/hal/platforms/STM32/RTCv2/rtc_lld.h index dd5a4160e..626f236a0 100644 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.h +++ b/os/hal/platforms/STM32/RTCv2/rtc_lld.h @@ -19,8 +19,8 @@ */ /** - * @file STM32/RTCv1/rtc_lld.h - * @brief STM32 RTC subsystem low level driver header. + * @file STM32/RTCv2/rtc_lld.h + * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver header. * * @addtogroup RTC * @{ @@ -38,7 +38,9 @@ /** * @brief This RTC implementation supports callbacks. */ -#define RTC_SUPPORTS_CALLBACKS TRUE +#if !defined(RTC_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__) +#define RTC_SUPPORTS_CALLBACKS FALSE +#endif /** * @brief Two alarm comparators available on STM32F4x. @@ -63,7 +65,7 @@ #endif #if RTC_SUPPORTS_CALLBACKS && !(HAL_USE_EXT) -#error "interrupts from STM32 RTC works only through EXTI" +#error "interrupts from RTC works only through EXTI on this platform" #endif /*===========================================================================*/ @@ -71,12 +73,23 @@ /*===========================================================================*/ /** - * @brief Type of a structure representing an RTC alarm stamp. + * @brief Type of a structure representing an RTC alarm time stamp. */ typedef struct RTCAlarm RTCAlarm; +/** + * @brief Type of a structure representing an RTC wakeup period. + */ +typedef struct RTCWakeup RTCWakeup; + +/** + * @brief Type of a structure representing an RTC callbacks config. + */ +typedef struct RTCCallbackConfig RTCCallbackConfig; + /** * @brief Type of an RTC alarm. + * @details Meaningful on platforms with more than 1 alarm comparator. */ typedef uint32_t rtcalarm_t; @@ -112,12 +125,11 @@ struct RTCTime { * @brief Fractional part of time. * @note If platform does not support subseconds than always zero. */ - uint16_t tv_msec; + uint32_t tv_msec; }; - /** - * @brief Structure representing an RTC alarm specification. + * @brief Structure representing an RTC alarm time stamp. */ struct RTCAlarm { /** @@ -126,15 +138,52 @@ struct RTCAlarm { uint32_t tv_datetime; }; +/** + * @brief Structure representing an RTC periodic wakeup period. + */ +struct RTCWakeup { + /** + * @brief RTC WUTR register. + */ + uint32_t wutr; + /** + * @brief RTC WUCKSEL bits of CR register. + */ + uint32_t wucksel; +}; + +/** + * @brief Structure representing an RTC callbacks config. + */ +struct RTCCallbackConfig{ +#if RTC_SUPPORTS_CALLBACKS + /** + * @brief Alarm callback pointer. + */ + rtccb_t alarm_cb; + /** + * @brief Tamper or TimeStamp callback pointer. + */ + rtccb_t tamper_timestapm_cb; + /** + * @brief Periodic wakeup callback pointer. + */ + rtccb_t wakeup_cb; +#endif /* RTC_SUPPORTS_CALLBACKS */ +}; /** * @brief Structure representing an RTC driver. */ struct RTCDriver{ /** - * @brief Callback pointer. + * @brief Pointer to the RTC registers block. + */ + RTC_TypeDef *id_rtc; + /** + * @brief Current configuration data. */ - rtccb_t rtc_cb; + const RTCCallbackConfig *cb_config; }; /*===========================================================================*/ @@ -161,7 +210,9 @@ extern "C" { void rtc_lld_get_alarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec); - void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); + void rtc_lld_set_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); + void rtc_lld_get_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); + void rtc_lld_set_callback(RTCDriver *rtcp, RTCCallbackConfig *cb_cfg); #ifdef __cplusplus } #endif -- cgit v1.2.3