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
This commit is contained in:
parent
4a5c4e2ae0
commit
9a52743e90
|
@ -320,6 +320,7 @@
|
||||||
|
|
||||||
/* RTC attributes.*/
|
/* RTC attributes.*/
|
||||||
#define STM32_HAS_RTC TRUE
|
#define STM32_HAS_RTC TRUE
|
||||||
|
#define RTC_HAS_SUBSECONDS TRUE
|
||||||
|
|
||||||
/* SDIO attributes.*/
|
/* SDIO attributes.*/
|
||||||
#define STM32_HAS_SDIO TRUE
|
#define STM32_HAS_SDIO TRUE
|
||||||
|
|
|
@ -31,6 +31,24 @@
|
||||||
|
|
||||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
#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. */
|
/* Driver exported variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -65,7 +83,11 @@ RTCDriver RTCD1;
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void rtc_lld_init(void){
|
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.*/
|
/* Enables access to BKP registers.*/
|
||||||
PWR->CR |= PWR_CR_DBP;
|
PWR->CR |= PWR_CR_DBP;
|
||||||
|
@ -77,35 +99,35 @@ void rtc_lld_init(void){
|
||||||
}
|
}
|
||||||
|
|
||||||
#if STM32_RTC == STM32_RTC_LSE
|
#if STM32_RTC == STM32_RTC_LSE
|
||||||
|
#define RTC_CLK STM32_LSECLK
|
||||||
if (!(RCC->BDCR & RCC_BDCR_LSEON)) {
|
if (!(RCC->BDCR & RCC_BDCR_LSEON)) {
|
||||||
RCC->BDCR |= RCC_BDCR_LSEON;
|
RCC->BDCR |= RCC_BDCR_LSEON;
|
||||||
while (!(RCC->BDCR & RCC_BDCR_LSERDY))
|
while (!(RCC->BDCR & RCC_BDCR_LSERDY))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
preload = STM32_LSECLK - 1;
|
|
||||||
#elif STM32_RTC == STM32_RTC_LSI
|
#elif STM32_RTC == STM32_RTC_LSI
|
||||||
|
#define RTC_CLK STM32_LSICLK
|
||||||
/* TODO: Move the LSI clock initialization in the HAL low level driver.*/
|
/* TODO: Move the LSI clock initialization in the HAL low level driver.*/
|
||||||
RCC->CSR |= RCC_CSR_LSION;
|
RCC->CSR |= RCC_CSR_LSION;
|
||||||
while (!(RCC->CSR & RCC_CSR_LSIRDY))
|
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
|
#elif STM32_RTC == STM32_RTC_HSE
|
||||||
preload = (STM32_HSICLK / 128) - 1;
|
#define RTC_CLK (STM32_HSICLK / 31)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Add sync part to preload value. */
|
||||||
|
preload |= ((RTC_CLK / (PREDIV_A + 1)) - 1) & 0x7FFF;
|
||||||
|
|
||||||
/* Selects clock source (previously enabled and stabilized).*/
|
/* Selects clock source (previously enabled and stabilized).*/
|
||||||
RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | STM32_RTC;
|
RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | STM32_RTC;
|
||||||
|
|
||||||
/* RTC enabled regardless its previous status.*/
|
/* RTC enabled regardless its previous status.*/
|
||||||
RCC->BDCR |= RCC_BDCR_RTCEN;
|
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. */
|
/* Disable write protection on RTC registers. */
|
||||||
RTC->WPR = 0xCA;
|
RTC->WPR = 0xCA;
|
||||||
RTC->WPR = 0x53;
|
RTC->WPR = 0x53;
|
||||||
|
@ -115,13 +137,9 @@ void rtc_lld_init(void){
|
||||||
while(!(RTC->ISR & RTC_ISR_INITF))
|
while(!(RTC->ISR & RTC_ISR_INITF))
|
||||||
;
|
;
|
||||||
/* Prescaler registers must be written in by two separate writes. */
|
/* Prescaler registers must be written in by two separate writes. */
|
||||||
RTC->PRER = 0x007F00FF;
|
RTC->PRER = preload;
|
||||||
RTC->PRER = 0x007F00FF;
|
RTC->PRER = preload;
|
||||||
RTC->ISR &= ~RTC_ISR_INIT;
|
RTC->ISR &= ~RTC_ISR_INIT;
|
||||||
|
|
||||||
/* Wait until calendar data will updated. */
|
|
||||||
while(!(RTC->ISR & RTC_ISR_RSF))
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback initially disabled.*/
|
/* Callback initially disabled.*/
|
||||||
|
@ -147,10 +165,6 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) {
|
||||||
RTC->TR = timespec->tv_time;
|
RTC->TR = timespec->tv_time;
|
||||||
RTC->DR = timespec->tv_date;
|
RTC->DR = timespec->tv_date;
|
||||||
RTC->ISR &= ~RTC_ISR_INIT;
|
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’ .*/
|
* the frequency of RTCCLK, BYPSHAD must be set to ‘1’ .*/
|
||||||
|
|
||||||
/* Wait until calendar data will updated. */
|
/* 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_time = RTC->TR;
|
||||||
timespec->tv_date = RTC->DR;
|
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.
|
* @brief Set alarm time.
|
||||||
*
|
*
|
||||||
|
@ -189,7 +209,6 @@ void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) {
|
||||||
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
||||||
rtcalarm_t alarm,
|
rtcalarm_t alarm,
|
||||||
const RTCAlarm *alarmspec) {
|
const RTCAlarm *alarmspec) {
|
||||||
|
|
||||||
(void)rtcp;
|
(void)rtcp;
|
||||||
(void)alarm;
|
(void)alarm;
|
||||||
(void)alarmspec;
|
(void)alarmspec;
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#define RTC_SUPPORTS_CALLBACKS TRUE
|
#define RTC_SUPPORTS_CALLBACKS TRUE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief One alarm comparator available.
|
* @brief Two alarm comparators available on STM32F4x.
|
||||||
*/
|
*/
|
||||||
#define RTC_ALARMS 2
|
#define RTC_ALARMS 2
|
||||||
|
|
||||||
|
@ -62,6 +62,10 @@
|
||||||
#error "invalid source selected for RTC clock"
|
#error "invalid source selected for RTC clock"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if RTC_SUPPORTS_CALLBACKS && !(HAL_USE_EXT)
|
||||||
|
#error "interrupts from STM32 RTC works only through EXTI"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver data structures and types. */
|
/* Driver data structures and types. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -97,13 +101,18 @@ typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
|
||||||
*/
|
*/
|
||||||
struct RTCTime {
|
struct RTCTime {
|
||||||
/**
|
/**
|
||||||
* @brief RTC date register in BCD format.
|
* @brief RTC date register in STM32 BCD format.
|
||||||
*/
|
*/
|
||||||
uint32_t tv_date;
|
uint32_t tv_date;
|
||||||
/**
|
/**
|
||||||
* @brief RTC time register in BCD format.
|
* @brief RTC time register in STM32 BCD format.
|
||||||
*/
|
*/
|
||||||
uint32_t tv_time;
|
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 {
|
struct RTCAlarm {
|
||||||
/**
|
/**
|
||||||
* @brief Date and time of alarm in BCD.
|
* @brief Date and time of alarm in STM32 BCD.
|
||||||
*/
|
*/
|
||||||
uint32_t tv_datetime;
|
uint32_t tv_datetime;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
RTCTime timespec;
|
RTCTime timespec;
|
||||||
RTCAlarm alarmspec;
|
RTCAlarm alarmspec;
|
||||||
|
|
||||||
#define TEST_ALARM_WAKEUP FALSE
|
#define TEST_ALARM_WAKEUP TRUE
|
||||||
|
|
||||||
#if TEST_ALARM_WAKEUP
|
#if TEST_ALARM_WAKEUP
|
||||||
|
|
||||||
|
@ -45,9 +45,9 @@ int main(void) {
|
||||||
|
|
||||||
chThdCreateStatic(blinkWA, sizeof(blinkWA), NORMALPRIO, blink_thd, NULL);
|
chThdCreateStatic(blinkWA, sizeof(blinkWA), NORMALPRIO, blink_thd, NULL);
|
||||||
/* set alarm in near future */
|
/* set alarm in near future */
|
||||||
rtcGetTime(×pec);
|
rtcGetTime(&RTCD1, ×pec);
|
||||||
alarmspec.tv_sec = timespec.tv_sec + 60;
|
alarmspec.tv_sec = timespec.tv_sec + 60;
|
||||||
rtcSetAlarm(&alarmspec);
|
rtcSetAlarm(&RTCD1, 0, &alarmspec);
|
||||||
|
|
||||||
while (TRUE){
|
while (TRUE){
|
||||||
chThdSleepSeconds(10);
|
chThdSleepSeconds(10);
|
||||||
|
|
Loading…
Reference in New Issue