diff options
-rw-r--r-- | os/hal/include/rtc.h | 9 | ||||
-rw-r--r-- | os/hal/platforms/STM32/RTCv1/rtc_lld.c | 2 | ||||
-rw-r--r-- | os/hal/platforms/STM32/RTCv1/rtc_lld.h | 24 | ||||
-rw-r--r-- | os/hal/platforms/STM32/RTCv2/rtc_lld.c | 151 | ||||
-rw-r--r-- | os/hal/platforms/STM32/RTCv2/rtc_lld.h | 73 | ||||
-rw-r--r-- | os/hal/src/rtc.c | 42 |
6 files changed, 234 insertions, 67 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;
@@ -91,6 +97,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.
*/
struct RTCTime {
@@ -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,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
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 */
/** @} */
|