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:
parent
bff048984e
commit
7f333ab456
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
|
@ -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(×pec);
|
rtcGetTime(&RTCD1, ×pec);
|
||||||
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, ×pec);
|
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, ×pec);
|
rtcGetTime(&RTCD1, ×pec);
|
||||||
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, ×pec);
|
||||||
|
alarmspec.tv_sec = timespec.tv_sec + RTC_ALARMPERIOD;
|
||||||
|
rtcSetAlarm(&RTCD1, 0, &alarmspec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue