From da68de0d34eaeeb4f0638c64b661c38c7f06b871 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 8 Dec 2011 21:17:19 +0000 Subject: [PATCH 1/7] RTC. Initial commit. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3586 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F4xx/platform.mk | 7 +- os/hal/platforms/STM32F4xx/rtc_lld.c | 319 +++++++++++++++++++++++++ os/hal/platforms/STM32F4xx/rtc_lld.h | 160 +++++++++++++ 3 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 os/hal/platforms/STM32F4xx/rtc_lld.c create mode 100644 os/hal/platforms/STM32F4xx/rtc_lld.h diff --git a/os/hal/platforms/STM32F4xx/platform.mk b/os/hal/platforms/STM32F4xx/platform.mk index 449b40731..ce6f7bf57 100644 --- a/os/hal/platforms/STM32F4xx/platform.mk +++ b/os/hal/platforms/STM32F4xx/platform.mk @@ -2,6 +2,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ ${CHIBIOS}/os/hal/platforms/STM32F4xx/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32F4xx/adc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx/rtc_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/gpt_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/icu_lld.c \ @@ -10,9 +11,11 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ # Required include directories PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32F4xx \ ${CHIBIOS}/os/hal/platforms/STM32 \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + + diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.c b/os/hal/platforms/STM32F4xx/rtc_lld.c new file mode 100644 index 000000000..cae23525f --- /dev/null +++ b/os/hal/platforms/STM32F4xx/rtc_lld.c @@ -0,0 +1,319 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file STM32/RTCv1/rtc_lld.c + * @brief STM32 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] rtcp pointer to a @p RTCDriver object + * + * @notapi + */ +static void rtc_lld_serve_interrupt(RTCDriver *rtcp) { + + chSysLockFromIsr(); + + if ((RTC->CRH & RTC_CRH_SECIE) && (RTC->CRL & RTC_CRL_SECF)) { + rtcp->rtc_cb(rtcp, RTC_EVENT_SECOND); + RTC->CRL &= ~RTC_CRL_SECF; + } + if ((RTC->CRH & RTC_CRH_ALRIE) && (RTC->CRL & RTC_CRL_ALRF)) { + rtcp->rtc_cb(rtcp, RTC_EVENT_ALARM); + RTC->CRL &= ~RTC_CRL_ALRF; + } + if ((RTC->CRH & RTC_CRH_OWIE) && (RTC->CRL & RTC_CRL_OWF)) { + rtcp->rtc_cb(rtcp, RTC_EVENT_OVERFLOW); + RTC->CRL &= ~RTC_CRL_OWF; + } + + chSysUnlockFromIsr(); +} + +/** + * @brief Waits for the previous registers write to finish. + * + * @notapi + */ +static void rtc_lld_wait_write(void) { + + /* Waits registers write completion.*/ + while (!(RTC->CRL & RTC_CRL_RTOFF)) + ; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief RTC interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(RTC_IRQHandler) { + + CH_IRQ_PROLOGUE(); + + rtc_lld_serve_interrupt(&RTCD1); + + CH_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enable access to registers and initialize RTC if BKP domain + * was previously reseted. + * @note: Cold start time of LSE oscillator on STM32 platform + * takes about 3 seconds. + * + * @notapi + */ +void rtc_lld_init(void){ + uint32_t preload; + + rccEnableBKPInterface(FALSE); + + /* Enables access to BKP registers.*/ + PWR->CR |= PWR_CR_DBP; + + /* If the RTC is not enabled then performs a reset of the backup domain.*/ + if (!(RCC->BDCR & RCC_BDCR_RTCEN)) { + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_RTC == STM32_RTC_LSE + if (!(RCC->BDCR & RCC_BDCR_LSEON)) { + RCC->BDCR |= RCC_BDCR_LSEON; + while (!(RCC->BDCR & RCC_BDCR_LSERDY)) + ; + } + preload = STM32_LSECLK - 1; +#elif STM32_RTC == STM32_RTC_LSI + /* TODO: Move the LSI clock initialization in the HAL low level driver.*/ + RCC->CSR |= RCC_CSR_LSION; + while (!(RCC->CSR & RCC_CSR_LSIRDY)) + ; + /* According to errata sheet we must wait additional 100 uS for + stabilization. + TODO: Change this code, software loops are not reliable.*/ + uint32_t tmo = (STM32_SYSCLK / 1000000) * 100; + while (tmo--) + ; + preload = STM32_LSICLK - 1; +#elif STM32_RTC == STM32_RTC_HSE + preload = (STM32_HSICLK / 128) - 1; +#endif + + /* Selects clock source (previously enabled and stabilized).*/ + RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | STM32_RTC; + + /* RTC enabled regardless its previous status.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + + /* Ensure that RTC_CNT and RTC_DIV contain actual values after enabling + clocking on APB1, because these values only update when APB1 + functioning.*/ + RTC->CRL = 0; + while (!(RTC->CRL & RTC_CRL_RSF)) + ; + + /* Write preload register only if its value differs.*/ + if (preload != ((((uint32_t)(RTC->PRLH)) << 16) + (uint32_t)RTC->PRLL)) { + + rtc_lld_wait_write(); + + /* Enters configuration mode and writes PRLx registers then leaves the + configuration mode.*/ + RTC->CRL |= RTC_CRL_CNF; + RTC->PRLH = (uint16_t)(preload >> 16); + RTC->PRLL = (uint16_t)(preload & 0xFFFF); + RTC->CRL &= ~RTC_CRL_CNF; + } + + /* All interrupts initially disabled.*/ + RTC->CRH = 0; + + /* Callback initially disabled.*/ + RTCD1.rtc_cb = NULL; +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to change it on STM32F1xx platform. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { + + (void)rtcp; + + rtc_lld_wait_write(); + + RTC->CRL |= RTC_CRL_CNF; + RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16); + RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF); + RTC->CRL &= ~RTC_CRL_CNF; +} + +/** + * @brief Get current time. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { + uint32_t time_frac; + + (void)rtcp; + + time_frac = (((uint32_t)RTC->DIVH) << 16) + (uint32_t)RTC->DIVL; + timespec->tv_msec = (uint16_t)(((STM32_LSECLK - time_frac) * 1000) / + STM32_LSECLK); + timespec->tv_sec = (RTC->CNTH << 16) + RTC->CNTL; +} + +/** + * @brief Set alarm time. + * + * @note Default value after BKP domain reset is 0xFFFFFFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @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; + + rtc_lld_wait_write(); + + /* Enters configuration mode and writes ALRHx registers then leaves the + configuration mode.*/ + RTC->CRL |= RTC_CRL_CNF; + if (alarmspec != NULL) { + RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); + RTC->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); + } + else { + RTC->ALRH = 0; + RTC->ALRL = 0; + } + RTC->CRL &= ~RTC_CRL_CNF; +} + +/** + * @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. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + (void)rtcp; + (void)alarm; + + alarmspec->tv_sec = ((RTC->ALRH << 16) + RTC->ALRL); +} + +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * + * @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; + 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/STM32F4xx/rtc_lld.h b/os/hal/platforms/STM32F4xx/rtc_lld.h new file mode 100644 index 000000000..e3ce0e365 --- /dev/null +++ b/os/hal/platforms/STM32F4xx/rtc_lld.h @@ -0,0 +1,160 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file STM32/RTCv1/rtc_lld.h + * @brief STM32 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef _RTC_LLD_H_ +#define _RTC_LLD_H_ + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief This RTC implementation supports callbacks. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief One alarm comparator available. + */ +#define RTC_ALARMS 1 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if !(STM32_RTC == STM32_RTC_LSE) && !(STM32_RTC == STM32_RTC_LSI) && \ + !(STM32_RTC == STM32_RTC_HSE) +#error "invalid source selected for RTC clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an RTC alarm stamp. + */ +typedef struct RTCAlarm RTCAlarm; + +/** + * @brief Type of an RTC alarm. + */ +typedef uint32_t rtcalarm_t; + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_SECOND = 0, /** Triggered every second. */ + RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ + RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ +} rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @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 specification. + */ +struct RTCAlarm { + /** + * @brief Seconds since UNIX epoch. + */ + uint32_t tv_sec; +}; + +/** + * @brief Structure representing an RTC driver. + */ +struct RTCDriver{ + /** + * @brief Callback pointer. + */ + rtccb_t rtc_cb; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern RTCDriver RTCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + 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_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* _RTC_LLD_H_ */ + +/** @} */ From 7a783452728d82c395a6273022ea239375db0c64 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 9 Dec 2011 22:14:09 +0000 Subject: [PATCH 2/7] RTC. Setting and getting time now works. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3589 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F4xx/hal_lld.h | 9 +++--- os/hal/platforms/STM32F4xx/rtc_lld.c | 42 ++++------------------------ os/hal/platforms/STM32F4xx/rtc_lld.h | 16 ++++++----- 3 files changed, 20 insertions(+), 47 deletions(-) diff --git a/os/hal/platforms/STM32F4xx/hal_lld.h b/os/hal/platforms/STM32F4xx/hal_lld.h index f292285da..40064787c 100644 --- a/os/hal/platforms/STM32F4xx/hal_lld.h +++ b/os/hal/platforms/STM32F4xx/hal_lld.h @@ -424,8 +424,9 @@ #define WWDG_IRQHandler Vector40 /**< Window Watchdog. */ #define PVD_IRQHandler Vector44 /**< PVD through EXTI Line detect. */ -#define TAMPER_IRQHandler Vector48 /**< Tamper. */ -#define RTC_IRQHandler Vector4C /**< RTC. */ +#define TAMP_STAMP_IRQHandler Vector48 /**< Tamper and TimeStamp + through EXTI Line. */ +#define RTC_WKUP_IRQHandler Vector4C /**< RTC wakeup EXTI Line. */ #define FLASH_IRQHandler Vector50 /**< Flash. */ #define RCC_IRQHandler Vector54 /**< RCC. */ #define EXTI0_IRQHandler Vector58 /**< EXTI Line 0. */ @@ -464,8 +465,8 @@ #define USART2_IRQHandler VectorD8 /**< USART2. */ #define USART3_IRQHandler VectorDC /**< USART3. */ #define EXTI15_10_IRQHandler VectorE0 /**< EXTI Line 15..10. */ -#define RTC_Alarm_IRQHandler VectorE4 /**< RTC alarm through EXTI - line. */ +#define RTC_Alarm_IRQHandler VectorE4 /**< RTC alarms (A and B) + through EXTI line. */ #define OTG_FS_WKUP_IRQHandler VectorE8 /**< USB OTG FS Wakeup through EXTI line. */ #define TIM8_BRK_IRQHandler VectorEC /**< TIM8 Break. */ diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.c b/os/hal/platforms/STM32F4xx/rtc_lld.c index 93d1b8e52..da7f73890 100644 --- a/os/hal/platforms/STM32F4xx/rtc_lld.c +++ b/os/hal/platforms/STM32F4xx/rtc_lld.c @@ -48,42 +48,10 @@ RTCDriver RTCD1; /* Driver local functions. */ /*===========================================================================*/ -/** - * @brief Shared IRQ handler. - * - * @param[in] rtcp pointer to a @p RTCDriver object - * - * @notapi - */ -static void rtc_lld_serve_interrupt(RTCDriver *rtcp) { - - chSysLockFromIsr(); - rtcp->rtc_cb(rtcp, RTC_EVENT_SECOND); - rtcp->rtc_cb(rtcp, RTC_EVENT_ALARM); - rtcp->rtc_cb(rtcp, RTC_EVENT_OVERFLOW); - chSysUnlockFromIsr(); -} - - - /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ -/** - * @brief RTC interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(RTC_IRQHandler) { - - CH_IRQ_PROLOGUE(); - - rtc_lld_serve_interrupt(&RTCD1); - - CH_IRQ_EPILOGUE(); -} - /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -137,18 +105,20 @@ void rtc_lld_init(void){ /* RTC enabled regardless its previous status.*/ RCC->BDCR |= RCC_BDCR_RTCEN; - /* Calendar not init yet. */ - if (!(RTC->ISR & RTC_ISR_INITS)){ + if (!(RTC->ISR & RTC_ISR_INITS)){/* Calendar not init yet. */ /* Disable write protection on RTC registers. */ RTC->WPR = 0xCA; RTC->WPR = 0x53; + /* Enter in init mode. */ RTC->ISR |= RTC_ISR_INIT; while(!(RTC->ISR & RTC_ISR_INITF)) ; /* Prescaler registers must be written in by two separate writes. */ - RTC->PRER = 0; RTC->PRER = 0x007F00FF; + RTC->PRER = 0x007F00FF; + RTC->ISR &= ~RTC_ISR_INIT; + /* Wait until calendar data will updated. */ while(!(RTC->ISR & RTC_ISR_RSF)) ; @@ -174,9 +144,9 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { 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; /* Wait until calendar data will updated. */ while(!(RTC->ISR & RTC_ISR_RSF)) diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.h b/os/hal/platforms/STM32F4xx/rtc_lld.h index 65eed6781..529215483 100644 --- a/os/hal/platforms/STM32F4xx/rtc_lld.h +++ b/os/hal/platforms/STM32F4xx/rtc_lld.h @@ -43,7 +43,7 @@ /** * @brief One alarm comparator available. */ -#define RTC_ALARMS 1 +#define RTC_ALARMS 2 /*===========================================================================*/ /* Driver pre-compile time settings. */ @@ -80,9 +80,11 @@ typedef uint32_t rtcalarm_t; * @brief Type of an RTC event. */ typedef enum { - RTC_EVENT_SECOND = 0, /** Triggered every second. */ - RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ - RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ + RTC_EVENT_WAKEUP = 0, /** Triggered every wakeup event. */ + RTC_EVENT_ALARM_A = 1, /** Triggered on alarm A. */ + RTC_EVENT_ALARM_B = 2, /** Triggered on alarm B. */ + RTC_EVENT_TAMPER = 3, /** Triggered on Tamper event. */ + RTC_EVENT_TIMESTAMP = 4, /** Triggered on TimeStamp event. */ } rtcevent_t; /** @@ -105,17 +107,17 @@ struct RTCTime { }; - /** * @brief Structure representing an RTC alarm specification. */ struct RTCAlarm { /** - * @brief Seconds since UNIX epoch. + * @brief Date and time of alarm in BCD. */ - uint32_t tv_sec; + uint32_t tv_datetime; }; + /** * @brief Structure representing an RTC driver. */ From 9a52743e90152091c6cf1eabeee839c93948864c Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 11 Dec 2011 20:05:55 +0000 Subject: [PATCH 3/7] RTC. Setting and getting time works on STM32F4x git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3596 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F4xx/hal_lld.h | 1 + os/hal/platforms/STM32F4xx/rtc_lld.c | 67 ++++++++++++++++++---------- os/hal/platforms/STM32F4xx/rtc_lld.h | 17 +++++-- testhal/STM32F1xx/RTC/main.c | 6 +-- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/os/hal/platforms/STM32F4xx/hal_lld.h b/os/hal/platforms/STM32F4xx/hal_lld.h index 40064787c..496c4304f 100644 --- a/os/hal/platforms/STM32F4xx/hal_lld.h +++ b/os/hal/platforms/STM32F4xx/hal_lld.h @@ -320,6 +320,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO TRUE diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.c b/os/hal/platforms/STM32F4xx/rtc_lld.c index da7f73890..cdf3aff81 100644 --- a/os/hal/platforms/STM32F4xx/rtc_lld.c +++ b/os/hal/platforms/STM32F4xx/rtc_lld.c @@ -31,6 +31,24 @@ #if HAL_USE_RTC || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Notes. */ +/*===========================================================================*/ +/* +This structure is used to hold the values representing a calendar time. +It contains the following members, with the meanings as shown. + +int tm_sec // seconds after minute [0-61] (61 allows for 2 leap-seconds) +int tm_min // minutes after hour [0-59] +int tm_hour // hours after midnight [0-23] +int tm_mday // day of the month [1-31] +int tm_mon // month of year [0-11] +int tm_year // current year-1900 +int tm_wday // days since Sunday [0-6] +int tm_yday // days since January 1st [0-365] +int tm_isdst // daylight savings indicator (1 = yes, 0 = no, -1 = unknown) +*/ + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -65,7 +83,11 @@ RTCDriver RTCD1; * @notapi */ void rtc_lld_init(void){ - uint32_t preload; + /* Asynchronous part of preloader. Set it to maximum value. */ + #define PREDIV_A ((uint32_t)0x7F) + + /* Add async part to preload value. */ + uint32_t preload = PREDIV_A << 16; /* Enables access to BKP registers.*/ PWR->CR |= PWR_CR_DBP; @@ -77,35 +99,35 @@ void rtc_lld_init(void){ } #if STM32_RTC == STM32_RTC_LSE + #define RTC_CLK STM32_LSECLK if (!(RCC->BDCR & RCC_BDCR_LSEON)) { RCC->BDCR |= RCC_BDCR_LSEON; while (!(RCC->BDCR & RCC_BDCR_LSERDY)) ; } - preload = STM32_LSECLK - 1; + #elif STM32_RTC == STM32_RTC_LSI + #define RTC_CLK STM32_LSICLK /* TODO: Move the LSI clock initialization in the HAL low level driver.*/ RCC->CSR |= RCC_CSR_LSION; while (!(RCC->CSR & RCC_CSR_LSIRDY)) ; - /* According to errata sheet we must wait additional 100 uS for - stabilization. - TODO: Change this code, software loops are not reliable.*/ - uint32_t tmo = (STM32_SYSCLK / 1000000) * 100; - while (tmo--) - ; - preload = STM32_LSICLK - 1; + #elif STM32_RTC == STM32_RTC_HSE - preload = (STM32_HSICLK / 128) - 1; + #define RTC_CLK (STM32_HSICLK / 31) #endif + /* Add sync part to preload value. */ + preload |= ((RTC_CLK / (PREDIV_A + 1)) - 1) & 0x7FFF; + /* Selects clock source (previously enabled and stabilized).*/ RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | STM32_RTC; /* RTC enabled regardless its previous status.*/ RCC->BDCR |= RCC_BDCR_RTCEN; - if (!(RTC->ISR & RTC_ISR_INITS)){/* Calendar not init yet. */ + /* If calendar not init yet. */ + if (!(RTC->ISR & RTC_ISR_INITS)){ /* Disable write protection on RTC registers. */ RTC->WPR = 0xCA; RTC->WPR = 0x53; @@ -115,13 +137,9 @@ void rtc_lld_init(void){ while(!(RTC->ISR & RTC_ISR_INITF)) ; /* Prescaler registers must be written in by two separate writes. */ - RTC->PRER = 0x007F00FF; - RTC->PRER = 0x007F00FF; + RTC->PRER = preload; + RTC->PRER = preload; RTC->ISR &= ~RTC_ISR_INIT; - - /* Wait until calendar data will updated. */ - while(!(RTC->ISR & RTC_ISR_RSF)) - ; } /* Callback initially disabled.*/ @@ -147,10 +165,6 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { RTC->TR = timespec->tv_time; RTC->DR = timespec->tv_date; RTC->ISR &= ~RTC_ISR_INIT; - - /* Wait until calendar data will updated. */ - while(!(RTC->ISR & RTC_ISR_RSF)) - ; } /** @@ -168,13 +182,19 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { * the frequency of RTCCLK, BYPSHAD must be set to ‘1’ .*/ /* Wait until calendar data will updated. */ - while(!(RTC->ISR & RTC_ISR_RSF)) - ; + while(!(RTC->ISR & RTC_ISR_RSF)) + ; timespec->tv_time = RTC->TR; timespec->tv_date = RTC->DR; +#if RTC_HAS_SUBSECONDS + timespec->tv_msec = ((RTC->PRER & 0x7FFF) - RTC->SSR) / ((RTC->PRER & 0x7FFF) + 1); +#else + timespec->tv_msec = 0; +#endif /* STM32_RTC_HAS_SUBSECONDS */ } + /** * @brief Set alarm time. * @@ -189,7 +209,6 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { void rtc_lld_set_alarm(RTCDriver *rtcp, rtcalarm_t alarm, const RTCAlarm *alarmspec) { - (void)rtcp; (void)alarm; (void)alarmspec; diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.h b/os/hal/platforms/STM32F4xx/rtc_lld.h index 529215483..dd5a4160e 100644 --- a/os/hal/platforms/STM32F4xx/rtc_lld.h +++ b/os/hal/platforms/STM32F4xx/rtc_lld.h @@ -41,7 +41,7 @@ #define RTC_SUPPORTS_CALLBACKS TRUE /** - * @brief One alarm comparator available. + * @brief Two alarm comparators available on STM32F4x. */ #define RTC_ALARMS 2 @@ -62,6 +62,10 @@ #error "invalid source selected for RTC clock" #endif +#if RTC_SUPPORTS_CALLBACKS && !(HAL_USE_EXT) +#error "interrupts from STM32 RTC works only through EXTI" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -97,13 +101,18 @@ typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); */ struct RTCTime { /** - * @brief RTC date register in BCD format. + * @brief RTC date register in STM32 BCD format. */ uint32_t tv_date; /** - * @brief RTC time register in BCD format. + * @brief RTC time register in STM32 BCD format. */ uint32_t tv_time; + /** + * @brief Fractional part of time. + * @note If platform does not support subseconds than always zero. + */ + uint16_t tv_msec; }; @@ -112,7 +121,7 @@ struct RTCTime { */ struct RTCAlarm { /** - * @brief Date and time of alarm in BCD. + * @brief Date and time of alarm in STM32 BCD. */ uint32_t tv_datetime; }; diff --git a/testhal/STM32F1xx/RTC/main.c b/testhal/STM32F1xx/RTC/main.c index ea7155f47..19043a02a 100644 --- a/testhal/STM32F1xx/RTC/main.c +++ b/testhal/STM32F1xx/RTC/main.c @@ -24,7 +24,7 @@ RTCTime timespec; RTCAlarm alarmspec; -#define TEST_ALARM_WAKEUP FALSE +#define TEST_ALARM_WAKEUP TRUE #if TEST_ALARM_WAKEUP @@ -45,9 +45,9 @@ int main(void) { chThdCreateStatic(blinkWA, sizeof(blinkWA), NORMALPRIO, blink_thd, NULL); /* set alarm in near future */ - rtcGetTime(×pec); + rtcGetTime(&RTCD1, ×pec); alarmspec.tv_sec = timespec.tv_sec + 60; - rtcSetAlarm(&alarmspec); + rtcSetAlarm(&RTCD1, 0, &alarmspec); while (TRUE){ chThdSleepSeconds(10); From 91fd67be1f1c806a0e4414dd8e03d72d34d37007 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 11 Dec 2011 20:14:45 +0000 Subject: [PATCH 4/7] RTC. Code reorganization. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3597 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/{STM32F4xx => STM32/RTCv2}/rtc_lld.c | 0 os/hal/platforms/{STM32F4xx => STM32/RTCv2}/rtc_lld.h | 0 os/hal/platforms/STM32F1xx/hal_lld_f100.h | 1 + os/hal/platforms/STM32F1xx/hal_lld_f103.h | 1 + os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h | 1 + os/hal/platforms/STM32F2xx/hal_lld.h | 1 + os/hal/platforms/STM32F4xx/platform.mk | 3 ++- os/hal/platforms/STM32L1xx/hal_lld.h | 1 + 8 files changed, 7 insertions(+), 1 deletion(-) rename os/hal/platforms/{STM32F4xx => STM32/RTCv2}/rtc_lld.c (100%) rename os/hal/platforms/{STM32F4xx => STM32/RTCv2}/rtc_lld.h (100%) diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.c b/os/hal/platforms/STM32/RTCv2/rtc_lld.c similarity index 100% rename from os/hal/platforms/STM32F4xx/rtc_lld.c rename to os/hal/platforms/STM32/RTCv2/rtc_lld.c diff --git a/os/hal/platforms/STM32F4xx/rtc_lld.h b/os/hal/platforms/STM32/RTCv2/rtc_lld.h similarity index 100% rename from os/hal/platforms/STM32F4xx/rtc_lld.h rename to os/hal/platforms/STM32/RTCv2/rtc_lld.h diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f100.h b/os/hal/platforms/STM32F1xx/hal_lld_f100.h index 16bb84cbf..bab4957e1 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f100.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f100.h @@ -182,6 +182,7 @@ #define STM32_SPI3_TX_DMA_CHN 0x00000000 #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f103.h b/os/hal/platforms/STM32F1xx/hal_lld_f103.h index 108854ff7..cbcce1b53 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f103.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f103.h @@ -193,6 +193,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h b/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h index 9a612b0ee..75a9361df 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h @@ -185,6 +185,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F2xx/hal_lld.h b/os/hal/platforms/STM32F2xx/hal_lld.h index cad926330..193d5cf65 100644 --- a/os/hal/platforms/STM32F2xx/hal_lld.h +++ b/os/hal/platforms/STM32F2xx/hal_lld.h @@ -180,6 +180,7 @@ #define STM32_I2C3_TX_DMA_CHN 0x00030000 #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS FALSE #define STM32_HAS_SDIO TRUE diff --git a/os/hal/platforms/STM32F4xx/platform.mk b/os/hal/platforms/STM32F4xx/platform.mk index ce6f7bf57..5f6f4f32f 100644 --- a/os/hal/platforms/STM32F4xx/platform.mk +++ b/os/hal/platforms/STM32F4xx/platform.mk @@ -2,7 +2,6 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ ${CHIBIOS}/os/hal/platforms/STM32F4xx/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32F4xx/adc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx/rtc_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/gpt_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/icu_lld.c \ @@ -12,10 +11,12 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ # Required include directories PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32F4xx \ ${CHIBIOS}/os/hal/platforms/STM32 \ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ diff --git a/os/hal/platforms/STM32L1xx/hal_lld.h b/os/hal/platforms/STM32L1xx/hal_lld.h index 8d6cfd6f0..040c3af15 100644 --- a/os/hal/platforms/STM32L1xx/hal_lld.h +++ b/os/hal/platforms/STM32L1xx/hal_lld.h @@ -217,6 +217,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE +#define RTC_HAS_SUBSECONDS FALSE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE From 9d343de5f9f3620f8d915a2e6dadf874ef2d02cb Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 11 Dec 2011 23:40:49 +0000 Subject: [PATCH 5/7] 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/include/rtc.h | 9 +- os/hal/platforms/STM32/RTCv1/rtc_lld.c | 2 +- os/hal/platforms/STM32/RTCv1/rtc_lld.h | 24 +++- os/hal/platforms/STM32/RTCv2/rtc_lld.c | 171 +++++++++++++++++-------- os/hal/platforms/STM32/RTCv2/rtc_lld.h | 73 +++++++++-- os/hal/src/rtc.c | 42 +++++- 6 files changed, 244 insertions(+), 77 deletions(-) diff --git a/os/hal/include/rtc.h b/os/hal/include/rtc.h index 1264c5bd8..ddb495205 100644 --- a/os/hal/include/rtc.h +++ b/os/hal/include/rtc.h @@ -85,15 +85,18 @@ extern "C" { void rtcInit(void); void rtcSetTime(RTCDriver *rtcp, const RTCTime *timespec); void rtcGetTime(RTCDriver *rtcp, RTCTime *timespec); + #if RTC_ALARMS > 0 void rtcSetAlarm(RTCDriver *rtcp, rtcalarm_t alarm, const RTCAlarm *alarmspec); void rtcGetAlarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec); -#endif +#endif /* RTC_ALARMS > 0 */ + #if RTC_SUPPORTS_CALLBACKS - void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback); -#endif + void rtcSetCallback(RTCDriver *rtcp, RTCCallbackConfig *cb_cfg); +#endif /* RTC_SUPPORTS_CALLBACKS */ + #ifdef __cplusplus } #endif diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.c b/os/hal/platforms/STM32/RTCv1/rtc_lld.c index 1a6c85d8b..88c0814fc 100644 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.c +++ b/os/hal/platforms/STM32/RTCv1/rtc_lld.c @@ -282,7 +282,7 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, * * @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 */ diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.h b/os/hal/platforms/STM32/RTCv1/rtc_lld.h index e3ce0e365..6e682db61 100644 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.h +++ b/os/hal/platforms/STM32/RTCv1/rtc_lld.h @@ -20,7 +20,7 @@ /** * @file STM32/RTCv1/rtc_lld.h - * @brief STM32 RTC subsystem low level driver header. + * @brief STM32F1xx RTC subsystem low level driver header. * * @addtogroup RTC * @{ @@ -67,12 +67,18 @@ /*===========================================================================*/ /** - * @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 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; @@ -90,6 +96,18 @@ typedef enum { */ typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); +/** + * @brief Structure representing an RTC callbacks config. + */ +struct RTCCallbackConfig{ +#if RTC_SUPPORTS_CALLBACKS + /** + * @brief Generic RTC callback pointer. + */ + rtccb_t rtc_cb; +#endif /* RTC_SUPPORTS_CALLBACKS */ +}; + /** * @brief Structure representing an RTC time stamp. */ @@ -105,7 +123,7 @@ struct RTCTime { }; /** - * @brief Structure representing an RTC alarm specification. + * @brief Structure representing an RTC alarm time stamp. */ struct RTCAlarm { /** 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,20 +185,49 @@ 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. + * + * @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. 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) { + 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 Set alarm time. - * - * @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 @@ -206,53 +235,89 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { * * @notapi */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - (void)rtcp; - (void)alarm; - (void)alarmspec; -} - -/** - * @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. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ void rtc_lld_get_alarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec) { - - (void)rtcp; - (void)alarm; - (void)alarmspec; + if (alarm == 1) + alarmspec->tv_datetime = rtcp->id_rtc->ALRMAR; + else + alarmspec->tv_datetime = rtcp->id_rtc->ALRMBR; } +/** + * @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. */ - rtccb_t rtc_cb; + RTC_TypeDef *id_rtc; + /** + * @brief Current configuration data. + */ + 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 diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c index dda5a9c95..f7ce21529 100644 --- a/os/hal/src/rtc.c +++ b/os/hal/src/rtc.c @@ -134,25 +134,55 @@ void rtcGetAlarm(RTCDriver *rtcp, } #endif /* RTC_ALARMS > 0 */ + + + + + + +/** + * @brief Sets periodic wakeup period. + */ +void rtcSetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { + chDbgCheck((rtcp != NULL) && (wakeupspec != NULL), "rtcSetPeriodicWakeup"); + rtc_lld_set_periodic_wakeup(rtcp, wakeupspec); +} +/** + * @brief Gets periodic wakeup period. + */ +void rtcGetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { + chDbgCheck((rtcp != NULL) && (wakeupspec != NULL), "rtcGetPeriodicWakeup"); + rtc_lld_get_periodic_wakeup(rtcp, wakeupspec); +} + + + + + + + #if RTC_SUPPORTS_CALLBACKS || defined(__DOXYGEN__) /** * @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 + * @param[in] cb_cfg callback configuration struct * * @api */ -void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) { +void rtcSetCallback(RTCDriver *rtcp, RTCCallbackConfig *cb_cfg) { - chDbgCheck((rtcp != NULL), "rtcSetCallback"); + chDbgCheck(((rtcp != NULL) && (cb_cfg != NULL)), "rtcSetCallback"); - rtc_lld_set_callback(rtcp, callback); + rtc_lld_set_callback(rtcp, cb_cfg); } #endif /* RTC_SUPPORTS_CALLBACKS */ + + + + #endif /* HAL_USE_RTC */ /** @} */ From ddff11cafeab64744aa00fff748ee90bab183f9e Mon Sep 17 00:00:00 2001 From: barthess Date: Mon, 12 Dec 2011 08:33:53 +0000 Subject: [PATCH 6/7] RTC. Naming convention fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3599 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F1xx/hal_lld_f100.h | 2 +- os/hal/platforms/STM32F1xx/hal_lld_f103.h | 2 +- os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h | 2 +- os/hal/platforms/STM32F2xx/hal_lld.h | 2 +- os/hal/platforms/STM32F4xx/hal_lld.h | 2 +- os/hal/platforms/STM32L1xx/hal_lld.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f100.h b/os/hal/platforms/STM32F1xx/hal_lld_f100.h index bab4957e1..1e34f9728 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f100.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f100.h @@ -182,7 +182,7 @@ #define STM32_SPI3_TX_DMA_CHN 0x00000000 #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f103.h b/os/hal/platforms/STM32F1xx/hal_lld_f103.h index cbcce1b53..77672ad01 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f103.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f103.h @@ -193,7 +193,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h b/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h index 75a9361df..60c3b421a 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h +++ b/os/hal/platforms/STM32F1xx/hal_lld_f105_f107.h @@ -185,7 +185,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE diff --git a/os/hal/platforms/STM32F2xx/hal_lld.h b/os/hal/platforms/STM32F2xx/hal_lld.h index 193d5cf65..43a4a5c27 100644 --- a/os/hal/platforms/STM32F2xx/hal_lld.h +++ b/os/hal/platforms/STM32F2xx/hal_lld.h @@ -180,7 +180,7 @@ #define STM32_I2C3_TX_DMA_CHN 0x00030000 #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS FALSE +#define STM32_RTC_HAS_SUBSECONDS FALSE #define STM32_HAS_SDIO TRUE diff --git a/os/hal/platforms/STM32F4xx/hal_lld.h b/os/hal/platforms/STM32F4xx/hal_lld.h index 496c4304f..1aeed4755 100644 --- a/os/hal/platforms/STM32F4xx/hal_lld.h +++ b/os/hal/platforms/STM32F4xx/hal_lld.h @@ -320,7 +320,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE /* SDIO attributes.*/ #define STM32_HAS_SDIO TRUE diff --git a/os/hal/platforms/STM32L1xx/hal_lld.h b/os/hal/platforms/STM32L1xx/hal_lld.h index 040c3af15..fce1a80f6 100644 --- a/os/hal/platforms/STM32L1xx/hal_lld.h +++ b/os/hal/platforms/STM32L1xx/hal_lld.h @@ -217,7 +217,7 @@ /* RTC attributes.*/ #define STM32_HAS_RTC TRUE -#define RTC_HAS_SUBSECONDS FALSE +#define STM32_RTC_HAS_SUBSECONDS FALSE /* SDIO attributes.*/ #define STM32_HAS_SDIO FALSE From facfe77b186a05dde255b4c66d22cdddaf0fd0f6 Mon Sep 17 00:00:00 2001 From: barthess Date: Mon, 12 Dec 2011 10:56:51 +0000 Subject: [PATCH 7/7] RTC. Development suspended until EXTI driver API will changed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/rtc_dev@3600 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/RTCv1/rtc_lld.c | 8 +- os/hal/platforms/STM32/RTCv2/rtc_lld.c | 118 +++++++++++++++++-------- os/hal/platforms/STM32/RTCv2/rtc_lld.h | 19 ++-- os/hal/src/rtc.c | 10 +-- 4 files changed, 100 insertions(+), 55 deletions(-) diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.c b/os/hal/platforms/STM32/RTCv1/rtc_lld.c index 88c0814fc..931d028f4 100644 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.c +++ b/os/hal/platforms/STM32/RTCv1/rtc_lld.c @@ -215,7 +215,7 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { * @brief Get current time. * * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCTime structure + * @param[out] timespec pointer to a @p RTCTime structure * * @notapi */ @@ -280,9 +280,9 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, * * @note Default value after BKP domain reset is 0xFFFFFFFF. * - * @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 + * @param[out] alarmspec pointer to a @p RTCAlarm structure * * @notapi */ diff --git a/os/hal/platforms/STM32/RTCv2/rtc_lld.c b/os/hal/platforms/STM32/RTCv2/rtc_lld.c index cc1e846e7..f549dc62d 100644 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.c +++ b/os/hal/platforms/STM32/RTCv2/rtc_lld.c @@ -89,7 +89,7 @@ void rtc_lld_init(void){ #define PREDIV_A ((uint32_t)0x7F) /* Add async part to preload value. */ - uint32_t preload = PREDIV_A << 16; + volatile uint32_t preload = PREDIV_A << 16; /* Enables access to BKP registers.*/ PWR->CR |= PWR_CR_DBP; @@ -128,13 +128,12 @@ void rtc_lld_init(void){ /* RTC enabled regardless its previous status.*/ RCC->BDCR |= RCC_BDCR_RTCEN; + /* Disable write protection on RTC registers. */ + RTCD1.id_rtc->WPR = 0xCA; + RTCD1.id_rtc->WPR = 0x53; + /* If calendar not init yet. */ if (!(RTC->ISR & RTC_ISR_INITS)){ - /* Disable write protection on RTC registers. */ - - RTCD1.id_rtc->WPR = 0xCA; - RTCD1.id_rtc->WPR = 0x53; - /* Enter in init mode. */ RTCD1.id_rtc->ISR |= RTC_ISR_INIT; while(!(RTC->ISR & RTC_ISR_INITF)) @@ -146,6 +145,7 @@ void rtc_lld_init(void){ } } + /** * @brief Set current time. * @note Fractional part will be silently ignored. There is no possibility @@ -229,9 +229,9 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, /** * @brief Get alarm time. * - * @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 + * @param[out] alarmspec pointer to a @p RTCAlarm structure * * @notapi */ @@ -255,14 +255,14 @@ void rtc_lld_get_alarm(RTCDriver *rtcp, * @notapi */ void rtc_lld_set_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec){ - chDbgCheck((wakeupspec->wutr != 0) || ((wakeupspec->wucksel & 0x7) != 3), + chDbgCheck((wakeupspec->wakeup != 0x30000), "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->WUTR = wakeupspec->wakeup & 0xFFFF; + rtcp->id_rtc->CR = (wakeupspec->wakeup >> 16) & 0x7; rtcp->id_rtc->CR |= RTC_CR_WUTE; } @@ -271,20 +271,50 @@ void rtc_lld_set_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec){ * * @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 + * @param[in] rtcp pointer to RTC driver structure + * @param[out] 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; + wakeupspec->wakeup = 0; + wakeupspec->wakeup |= rtcp->id_rtc->WUTR; + wakeupspec->wakeup |= (((uint32_t)rtcp->id_rtc->CR) & 0x7) << 16; } +#if RTC_SUPPORTS_CALLBACKS - - +static const EXTConfig rtc_extcfg = { + { + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_RISING_EDGE, NULL}, //17, RTC alarm + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_DISABLED, NULL}, + {EXT_CH_MODE_RISING_EDGE, NULL}, //21 RTC tamper + {EXT_CH_MODE_RISING_EDGE, NULL} //22 RTC wakeup + }, + EXT_MODE_EXTI(0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0) +}; @@ -293,30 +323,44 @@ void rtc_lld_get_periodic_wakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec){ * @details TODO: * * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL + * @param[in] cb_cfg pointer to configuration structure with callbacks * * @notapi */ 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; -// } -} + /* To configure callback we must confugure EXTI interrupt on + * corresponding line. + * And then enable interrupts in RTC CR register. */ + + if (cb_cfg->alarm_cb != NULL){ + rtc_extcfg.channels[STM32_RTC_ALARM_EXTI_CH].cb = cb_cfg->alarm_cb; + rtcp->id_rtc->CR |= RTC_CR_ALRBIE; + rtcp->id_rtc->CR |= RTC_CR_ALRAIE; + } + else{ + extChannelDisable(&EXTD1, STM32_RTC_ALARM_EXTI_CH); + } + + if (cb_cfg->tamper_timestapm_cb != NULL){ + rtc_extcfg.channels[STM32_RTC_TAMPER_TIMESTAMP_EXTI_CH].cb = cb_cfg->tamper_timestapm_cb; + rtcp->id_rtc->CR |= RTC_CR_TSIE; + } + else{ + extChannelDisable(&EXTD1, STM32_RTC_TAMPER_TIMESTAMP_EXTI_CH); + } + + if (cb_cfg->wakeup_cb != NULL){ + rtc_extcfg.channels[STM32_RTC_WAKEUP_EXTI_CH].cb = cb_cfg->wakeup_cb; + rtcp->id_rtc->CR |= RTC_CR_WUTIE; + } + else{ + extChannelDisable(&EXTD1, STM32_RTC_WAKEUP_EXTI_CH); + } + + extStart(&EXTD1, &rtc_extcfg); +} +#endif /* RTC_SUPPORTS_CALLBACKS */ #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 626f236a0..3780945c4 100644 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.h +++ b/os/hal/platforms/STM32/RTCv2/rtc_lld.h @@ -47,6 +47,13 @@ */ #define RTC_ALARMS 2 +/** + * @brief EXTI channel numbers for different RTC events. + */ +#define STM32_RTC_ALARM_EXTI_CH 17 +#define STM32_RTC_TAMPER_TIMESTAMP_EXTI_CH 21 +#define STM32_RTC_WAKEUP_EXTI_CH 22 + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -143,13 +150,13 @@ struct RTCAlarm { */ struct RTCWakeup { /** - * @brief RTC WUTR register. + * @brief RTC WUTR register. + * @details Bits [15:0] contain value of WUTR register + * Bits [18:16] contain value of WUCKSEL bits in CR register + * + * @notes ((WUTR == 0) || (WUCKSEL == 3)) is forbidden combination. */ - uint32_t wutr; - /** - * @brief RTC WUCKSEL bits of CR register. - */ - uint32_t wucksel; + uint32_t wakeup; }; /** diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c index f7ce21529..52e35fd22 100644 --- a/os/hal/src/rtc.c +++ b/os/hal/src/rtc.c @@ -117,8 +117,8 @@ void rtcSetAlarm(RTCDriver *rtcp, * @note If an alarm has not been set then the returned alarm specification * is not meaningful. * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier * @param[out] alarmspec pointer to a @p RTCAlarm structure * * @api @@ -134,12 +134,6 @@ void rtcGetAlarm(RTCDriver *rtcp, } #endif /* RTC_ALARMS > 0 */ - - - - - - /** * @brief Sets periodic wakeup period. */