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
This commit is contained in:
barthess 2012-01-11 20:07:19 +00:00
parent bff048984e
commit 7f333ab456
4 changed files with 75 additions and 30 deletions

View File

@ -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 * @notapi
*/ */
static void rtc_lld_wait_write(void) { static void rtc_lld_acquire(void) {
/* Waits registers write completion.*/ /* Waits registers write completion.*/
BEGIN:
while ((RTC->CRL & RTC_CRL_RTOFF) == 0) 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. */ /* Driver interrupt handlers. */
/*===========================================================================*/ /*===========================================================================*/
@ -130,21 +143,26 @@ void rtc_lld_init(void){
while (!(RTC->CRL & RTC_CRL_RSF)) 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) + if (STM32_RTCCLK != (((uint32_t)(RTC->PRLH)) << 16) +
((uint32_t)RTC->PRLL) + 1) { ((uint32_t)RTC->PRLL) + 1) {
/* Enters configuration mode and writes PRLx registers then leaves the /* Enters configuration mode and writes PRLx registers then leaves the
configuration mode.*/ configuration mode.*/
rtc_lld_wait_write(); rtc_lld_acquire();
RTC->CRL |= RTC_CRL_CNF; RTC->CRL |= RTC_CRL_CNF;
RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16); RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16);
RTC->PRLL = (uint16_t)((STM32_RTCCLK - 1) & 0xFFFF); RTC->PRLL = (uint16_t)((STM32_RTCCLK - 1) & 0xFFFF);
RTC->CRL &= ~RTC_CRL_CNF; RTC->CRL &= ~RTC_CRL_CNF;
rtc_lld_release();
} }
/* All interrupts initially disabled.*/ /* All interrupts initially disabled.*/
RTC->CRH = 0; if (RTC->CRH != 0){
rtc_lld_acquire();
RTC->CRH = 0;
rtc_lld_release();
}
/* Callback initially disabled.*/ /* Callback initially disabled.*/
RTCD1.callback = NULL; RTCD1.callback = NULL;
@ -164,11 +182,12 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) {
(void)rtcp; (void)rtcp;
rtc_lld_wait_write(); rtc_lld_acquire();
RTC->CRL |= RTC_CRL_CNF; RTC->CRL |= RTC_CRL_CNF;
RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16); RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16);
RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF); RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF);
RTC->CRL &= ~RTC_CRL_CNF; 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 /* Enters configuration mode and writes ALRHx registers then leaves the
configuration mode.*/ configuration mode.*/
rtc_lld_wait_write(); rtc_lld_acquire();
RTC->CRL |= RTC_CRL_CNF; RTC->CRL |= RTC_CRL_CNF;
if (alarmspec != NULL) { if (alarmspec != NULL) {
RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16);
@ -227,6 +246,7 @@ void rtc_lld_set_alarm(RTCDriver *rtcp,
RTC->ALRL = 0; RTC->ALRL = 0;
} }
RTC->CRL &= ~RTC_CRL_CNF; 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) { void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
rtc_lld_acquire();
if (callback != NULL) { if (callback != NULL) {
rtcp->callback = callback; rtcp->callback = callback;
@ -276,9 +297,10 @@ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
} }
else { else {
nvicDisableVector(RTC_IRQn); nvicDisableVector(RTC_IRQn);
RTC->CRL = 0; RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF);
RTC->CRH = 0; RTC->CRH &= ~(RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE);
} }
rtc_lld_release();
} }
#endif /* HAL_USE_RTC */ #endif /* HAL_USE_RTC */

View File

@ -72,9 +72,6 @@ static void hal_lld_backup_domain_init(void) {
RCC->BDCR |= RCC_BDCR_RTCEN; RCC->BDCR |= RCC_BDCR_RTCEN;
} }
#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ #endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */
/* Backup domain access disabled for operations safety.*/
PWR->CR &= ~PWR_CR_DBP;
} }
/*===========================================================================*/ /*===========================================================================*/

View File

@ -24,17 +24,23 @@
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
static void my_cb(RTCDriver *rtcp, rtcevent_t event) {
(void)rtcp;
(void)event;
return;
}
/* sleep indicator thread */ /* sleep indicator thread */
static WORKING_AREA(blinkWA, 128); static WORKING_AREA(blinkWA, 128);
static msg_t blink_thd(void *arg){ static msg_t blink_thd(void *arg){
(void)arg; (void)arg;
while (TRUE) { while (TRUE) {
chThdSleepMilliseconds(100); chThdSleepMilliseconds(100);
palTogglePad(IOPORT3, GPIOC_LED); palTogglePad(GPIOC, GPIOC_LED);
} }
return 0; return 0;
} }
@ -45,24 +51,32 @@ 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(&timespec); rtcGetTime(&RTCD1, &timespec);
alarmspec.tv_sec = timespec.tv_sec + 60; alarmspec.tv_sec = timespec.tv_sec + 30;
rtcSetAlarm(&alarmspec); rtcSetAlarm(&RTCD1, 0, &alarmspec);
/* Needed just to switch interrupts on.*/
rtcSetCallback(&RTCD1, my_cb);
while (TRUE){ while (TRUE){
chThdSleepSeconds(10); chThdSleepSeconds(10);
chSysLock(); chSysLock();
/* going to anabiosis*/ /* going to anabiosis*/
PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF); PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF);
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__WFI(); __WFI();
} }
return 0; return 0;
} }
#else /* TEST_ALARM_WAKEUP */ #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) { static void my_cb(RTCDriver *rtcp, rtcevent_t event) {
(void)rtcp; (void)rtcp;
@ -76,24 +90,36 @@ static void my_cb(RTCDriver *rtcp, rtcevent_t event) {
break; break;
case RTC_EVENT_ALARM: case RTC_EVENT_ALARM:
palTogglePad(GPIOC, GPIOC_LED); palTogglePad(GPIOC, GPIOC_LED);
rtcGetTime(&RTCD1, &timespec); chBSemSignalI(&alarm_sem);
alarmspec.tv_sec = timespec.tv_sec + 10;
rtcSetAlarm(&RTCD1, 0, &alarmspec);
break; break;
} }
} }
int main(void) { int main(void) {
msg_t status = RDY_TIMEOUT;
halInit(); halInit();
chSysInit(); chSysInit();
chBSemInit(&alarm_sem, TRUE);
rtcGetTime(&RTCD1, &timespec); rtcGetTime(&RTCD1, &timespec);
alarmspec.tv_sec = timespec.tv_sec + 10; alarmspec.tv_sec = timespec.tv_sec + RTC_ALARMPERIOD;
rtcSetAlarm(&RTCD1, 0, &alarmspec); rtcSetAlarm(&RTCD1, 0, &alarmspec);
rtcSetCallback(&RTCD1, my_cb); rtcSetCallback(&RTCD1, my_cb);
while (TRUE){ 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, &timespec);
alarmspec.tv_sec = timespec.tv_sec + RTC_ALARMPERIOD;
rtcSetAlarm(&RTCD1, 0, &alarmspec);
}
} }
return 0; return 0;
} }

View File

@ -38,7 +38,7 @@
#define STM32_HSI_ENABLED TRUE #define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED FALSE #define STM32_LSI_ENABLED FALSE
#define STM32_HSE_ENABLED TRUE #define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE #define STM32_LSE_ENABLED TRUE
#define STM32_SW STM32_SW_PLL #define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE #define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 #define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
@ -50,7 +50,7 @@
#define STM32_USB_CLOCK_REQUIRED TRUE #define STM32_USB_CLOCK_REQUIRED TRUE
#define STM32_USBPRE STM32_USBPRE_DIV1P5 #define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK #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_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0 #define STM32_PLS STM32_PLS_LEV0