From 7f333ab4563c75d4e32f86c01db51a75fe07ed65 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 11 Jan 2012 20:07:19 +0000 Subject: RTC. Fixed some bugs and added locks into write functions. Haltest updated. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3790 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/RTCv1/rtc_lld.c | 40 +++++++++++++++++------ os/hal/platforms/STM32F1xx/hal_lld.c | 3 -- testhal/STM32F1xx/RTC/main.c | 58 ++++++++++++++++++++++++---------- testhal/STM32F1xx/RTC/mcuconf.h | 4 +-- 4 files changed, 75 insertions(+), 30 deletions(-) diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.c b/os/hal/platforms/STM32/RTCv1/rtc_lld.c index 3bac2e05b..f133f4970 100644 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.c +++ b/os/hal/platforms/STM32/RTCv1/rtc_lld.c @@ -80,17 +80,30 @@ static void rtc_lld_serve_interrupt(RTCDriver *rtcp) { } /** - * @brief Waits for the previous registers write to finish. + * @brief Acquire atomic write access to RTC registers. * * @notapi */ -static void rtc_lld_wait_write(void) { +static void rtc_lld_acquire(void) { /* Waits registers write completion.*/ +BEGIN: while ((RTC->CRL & RTC_CRL_RTOFF) == 0) ; + chSysLock(); + if ((RTC->CRL & RTC_CRL_RTOFF) == 0){ + chSysUnlock(); + goto BEGIN; + } } +/** + * @brief Release atomic write access to RTC registers. + * + * @notapi + */ +#define rtc_lld_release() {chSysUnlock();} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -130,21 +143,26 @@ void rtc_lld_init(void){ while (!(RTC->CRL & RTC_CRL_RSF)) ; - /* Write preload register only if its value differs.*/ + /* Write preload register only if its value is not equal to desired value.*/ if (STM32_RTCCLK != (((uint32_t)(RTC->PRLH)) << 16) + ((uint32_t)RTC->PRLL) + 1) { /* Enters configuration mode and writes PRLx registers then leaves the configuration mode.*/ - rtc_lld_wait_write(); + rtc_lld_acquire(); RTC->CRL |= RTC_CRL_CNF; RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16); RTC->PRLL = (uint16_t)((STM32_RTCCLK - 1) & 0xFFFF); RTC->CRL &= ~RTC_CRL_CNF; + rtc_lld_release(); } /* All interrupts initially disabled.*/ - RTC->CRH = 0; + if (RTC->CRH != 0){ + rtc_lld_acquire(); + RTC->CRH = 0; + rtc_lld_release(); + } /* Callback initially disabled.*/ RTCD1.callback = NULL; @@ -164,11 +182,12 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { (void)rtcp; - rtc_lld_wait_write(); + rtc_lld_acquire(); 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; + rtc_lld_release(); } /** @@ -216,7 +235,7 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, /* Enters configuration mode and writes ALRHx registers then leaves the configuration mode.*/ - rtc_lld_wait_write(); + rtc_lld_acquire(); RTC->CRL |= RTC_CRL_CNF; if (alarmspec != NULL) { RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); @@ -227,6 +246,7 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, RTC->ALRL = 0; } RTC->CRL &= ~RTC_CRL_CNF; + rtc_lld_release(); } /** @@ -264,6 +284,7 @@ void rtc_lld_get_alarm(RTCDriver *rtcp, */ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + rtc_lld_acquire(); if (callback != NULL) { rtcp->callback = callback; @@ -276,9 +297,10 @@ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { } else { nvicDisableVector(RTC_IRQn); - RTC->CRL = 0; - RTC->CRH = 0; + RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); + RTC->CRH &= ~(RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE); } + rtc_lld_release(); } #endif /* HAL_USE_RTC */ diff --git a/os/hal/platforms/STM32F1xx/hal_lld.c b/os/hal/platforms/STM32F1xx/hal_lld.c index 0112d7eaa..936aec4d2 100644 --- a/os/hal/platforms/STM32F1xx/hal_lld.c +++ b/os/hal/platforms/STM32F1xx/hal_lld.c @@ -72,9 +72,6 @@ static void hal_lld_backup_domain_init(void) { RCC->BDCR |= RCC_BDCR_RTCEN; } #endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ - - /* Backup domain access disabled for operations safety.*/ - PWR->CR &= ~PWR_CR_DBP; } /*===========================================================================*/ diff --git a/testhal/STM32F1xx/RTC/main.c b/testhal/STM32F1xx/RTC/main.c index 84df3c109..2b3bb7be8 100644 --- a/testhal/STM32F1xx/RTC/main.c +++ b/testhal/STM32F1xx/RTC/main.c @@ -24,17 +24,23 @@ RTCTime timespec; RTCAlarm alarmspec; -#define TEST_ALARM_WAKEUP FALSE +#define TEST_ALARM_WAKEUP TRUE #if TEST_ALARM_WAKEUP +static void my_cb(RTCDriver *rtcp, rtcevent_t event) { + (void)rtcp; + (void)event; + return; +} + /* sleep indicator thread */ static WORKING_AREA(blinkWA, 128); static msg_t blink_thd(void *arg){ (void)arg; while (TRUE) { chThdSleepMilliseconds(100); - palTogglePad(IOPORT3, GPIOC_LED); + palTogglePad(GPIOC, GPIOC_LED); } return 0; } @@ -45,24 +51,32 @@ int main(void) { chThdCreateStatic(blinkWA, sizeof(blinkWA), NORMALPRIO, blink_thd, NULL); /* set alarm in near future */ - rtcGetTime(×pec); - alarmspec.tv_sec = timespec.tv_sec + 60; - rtcSetAlarm(&alarmspec); + rtcGetTime(&RTCD1, ×pec); + alarmspec.tv_sec = timespec.tv_sec + 30; + rtcSetAlarm(&RTCD1, 0, &alarmspec); + + /* Needed just to switch interrupts on.*/ + rtcSetCallback(&RTCD1, my_cb); while (TRUE){ - chThdSleepSeconds(10); - chSysLock(); + chThdSleepSeconds(10); + chSysLock(); - /* going to anabiosis*/ - PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF); - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - __WFI(); + /* going to anabiosis*/ + PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF); + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + __WFI(); } return 0; } #else /* TEST_ALARM_WAKEUP */ +/* Manually reloaded test alarm period.*/ +#define RTC_ALARMPERIOD 10 + +BinarySemaphore alarm_sem; + static void my_cb(RTCDriver *rtcp, rtcevent_t event) { (void)rtcp; @@ -76,24 +90,36 @@ static void my_cb(RTCDriver *rtcp, rtcevent_t event) { break; case RTC_EVENT_ALARM: palTogglePad(GPIOC, GPIOC_LED); - rtcGetTime(&RTCD1, ×pec); - alarmspec.tv_sec = timespec.tv_sec + 10; - rtcSetAlarm(&RTCD1, 0, &alarmspec); + chBSemSignalI(&alarm_sem); break; } } int main(void) { + msg_t status = RDY_TIMEOUT; + halInit(); chSysInit(); + chBSemInit(&alarm_sem, TRUE); rtcGetTime(&RTCD1, ×pec); - alarmspec.tv_sec = timespec.tv_sec + 10; + alarmspec.tv_sec = timespec.tv_sec + RTC_ALARMPERIOD; rtcSetAlarm(&RTCD1, 0, &alarmspec); rtcSetCallback(&RTCD1, my_cb); while (TRUE){ - chThdSleepMilliseconds(500); + + /* Wait until alarm callback signaled semaphore.*/ + status = chBSemWaitTimeout(&alarm_sem, S2ST(RTC_ALARMPERIOD + 5)); + + if (status == RDY_TIMEOUT){ + chSysHalt(); + } + else{ + rtcGetTime(&RTCD1, ×pec); + alarmspec.tv_sec = timespec.tv_sec + RTC_ALARMPERIOD; + rtcSetAlarm(&RTCD1, 0, &alarmspec); + } } return 0; } diff --git a/testhal/STM32F1xx/RTC/mcuconf.h b/testhal/STM32F1xx/RTC/mcuconf.h index 1a38f9876..e43e31d12 100644 --- a/testhal/STM32F1xx/RTC/mcuconf.h +++ b/testhal/STM32F1xx/RTC/mcuconf.h @@ -38,7 +38,7 @@ #define STM32_HSI_ENABLED TRUE #define STM32_LSI_ENABLED FALSE #define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE +#define STM32_LSE_ENABLED TRUE #define STM32_SW STM32_SW_PLL #define STM32_PLLSRC STM32_PLLSRC_HSE #define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 @@ -50,7 +50,7 @@ #define STM32_USB_CLOCK_REQUIRED TRUE #define STM32_USBPRE STM32_USBPRE_DIV1P5 #define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_RTCSEL STM32_RTCSEL_HSEDIV +#define STM32_RTCSEL STM32_RTCSEL_LSE #define STM32_PVD_ENABLE FALSE #define STM32_PLS STM32_PLS_LEV0 -- cgit v1.2.3