Merge pull request #148 from martinayotte/master
make PeriodicWakeup and AlarmA/AlarmB working
This commit is contained in:
commit
f6769ee64f
|
@ -38,6 +38,10 @@ static rtc_dev rtc = {
|
||||||
|
|
||||||
rtc_dev *RTC = &rtc;
|
rtc_dev *RTC = &rtc;
|
||||||
|
|
||||||
|
voidFuncPtr handlerAlarmA = NULL;
|
||||||
|
voidFuncPtr handlerAlarmB = NULL;
|
||||||
|
voidFuncPtr handlerPeriodicWakeup = NULL;
|
||||||
|
|
||||||
|
|
||||||
RTClock::RTClock() {
|
RTClock::RTClock() {
|
||||||
RTClock(RTCSEL_HSE, 7999, 124);
|
RTClock(RTCSEL_HSE, 7999, 124);
|
||||||
|
@ -50,33 +54,33 @@ RTClock::RTClock(rtc_clk_src src) {
|
||||||
RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler) {
|
RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler) {
|
||||||
uint32 t = 0;
|
uint32 t = 0;
|
||||||
RCC_BASE->APB1ENR |= RCC_APB1RSTR_PWRRST;
|
RCC_BASE->APB1ENR |= RCC_APB1RSTR_PWRRST;
|
||||||
dbg_printf("RCC_BASE->APB1ENR = %08X\r\n", RCC_BASE->APB1ENR);
|
rtc_debug_printf("RCC_BASE->APB1ENR = %08X\r\n", RCC_BASE->APB1ENR);
|
||||||
dbg_printf("before bkp_init\r\n");
|
rtc_debug_printf("before bkp_init\r\n");
|
||||||
bkp_init(); // turn on peripheral clocks to PWR and BKP and reset the backup domain via RCC registers.
|
bkp_init(); // turn on peripheral clocks to PWR and BKP and reset the backup domain via RCC registers.
|
||||||
// (we reset the backup domain here because we must in order to change the rtc clock source).
|
// (we reset the backup domain here because we must in order to change the rtc clock source).
|
||||||
dbg_printf("before bkp_disable_writes\r\n");
|
rtc_debug_printf("before bkp_disable_writes\r\n");
|
||||||
bkp_disable_writes();
|
bkp_disable_writes();
|
||||||
dbg_printf("before bkp_enable_writes\r\n");
|
rtc_debug_printf("before bkp_enable_writes\r\n");
|
||||||
bkp_enable_writes(); // enable writes to the backup registers and the RTC registers via the DBP bit in the PWR control register
|
bkp_enable_writes(); // enable writes to the backup registers and the RTC registers via the DBP bit in the PWR control register
|
||||||
dbg_printf("RCC_BASE->CFGR = %08X\r\n", RCC_BASE->CFGR);
|
rtc_debug_printf("RCC_BASE->CFGR = %08X\r\n", RCC_BASE->CFGR);
|
||||||
RCC_BASE->CFGR |= (0x08 << 16); // Set the RTCPRE to HSE / 8.
|
RCC_BASE->CFGR |= (0x08 << 16); // Set the RTCPRE to HSE / 8.
|
||||||
dbg_printf("RCC_BASE->CFGR = %08X\r\n", RCC_BASE->CFGR);
|
rtc_debug_printf("RCC_BASE->CFGR = %08X\r\n", RCC_BASE->CFGR);
|
||||||
|
|
||||||
switch (src) {
|
switch (src) {
|
||||||
case RTCSEL_LSE :
|
case RTCSEL_LSE :
|
||||||
dbg_printf("Preparing RTC for LSE mode\r\n");
|
rtc_debug_printf("Preparing RTC for LSE mode\r\n");
|
||||||
if ((RCC_BASE->BDCR & 0x00000300) != 0x0100)
|
if ((RCC_BASE->BDCR & 0x00000300) != 0x0100)
|
||||||
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
||||||
RCC_BASE->BDCR = 0x00008101;
|
RCC_BASE->BDCR = 0x00008101;
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
while (!(RCC_BASE->BDCR & 0x00000002)) {
|
while (!(RCC_BASE->BDCR & 0x00000002)) {
|
||||||
if (++t > 1000000) {
|
if (++t > 1000000) {
|
||||||
dbg_printf("RCC_BASE->BDCR.LSERDY Timeout !\r\n");
|
rtc_debug_printf("RCC_BASE->BDCR.LSERDY Timeout !\r\n");
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
if (sync_prescaler == 0 && async_prescaler == 0)
|
if (sync_prescaler == 0 && async_prescaler == 0)
|
||||||
RTC_BASE->PRER = 255 | (127 << 16);
|
RTC_BASE->PRER = 255 | (127 << 16);
|
||||||
|
@ -84,20 +88,20 @@ RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler)
|
||||||
RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16);
|
RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16);
|
||||||
break;
|
break;
|
||||||
case RTCSEL_LSI :
|
case RTCSEL_LSI :
|
||||||
dbg_printf("Preparing RTC for LSI mode\r\n");
|
rtc_debug_printf("Preparing RTC for LSI mode\r\n");
|
||||||
if ((RCC_BASE->BDCR & 0x00000300) != 0x0200)
|
if ((RCC_BASE->BDCR & 0x00000300) != 0x0200)
|
||||||
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
||||||
RCC_BASE->BDCR = 0x00008204;
|
RCC_BASE->BDCR = 0x00008204;
|
||||||
RCC_BASE->CSR |= 0x00000001;
|
RCC_BASE->CSR |= 0x00000001;
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
while (!(RCC_BASE->CSR & 0x00000002)) {
|
while (!(RCC_BASE->CSR & 0x00000002)) {
|
||||||
if (++t > 1000000) {
|
if (++t > 1000000) {
|
||||||
dbg_printf("RCC_BASE->CSR.LSIRDY Timeout !\r\n");
|
rtc_debug_printf("RCC_BASE->CSR.LSIRDY Timeout !\r\n");
|
||||||
dbg_printf("RCC_BASE->CSR = %08X\r\n", RCC_BASE->CSR);
|
rtc_debug_printf("RCC_BASE->CSR = %08X\r\n", RCC_BASE->CSR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
if (sync_prescaler == 0 && async_prescaler == 0)
|
if (sync_prescaler == 0 && async_prescaler == 0)
|
||||||
RTC_BASE->PRER = 249 | (127 << 16);
|
RTC_BASE->PRER = 249 | (127 << 16);
|
||||||
|
@ -106,11 +110,11 @@ RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler)
|
||||||
break;
|
break;
|
||||||
case RTCSEL_DEFAULT:
|
case RTCSEL_DEFAULT:
|
||||||
case RTCSEL_HSE :
|
case RTCSEL_HSE :
|
||||||
dbg_printf("Preparing RTC for HSE mode\r\n");
|
rtc_debug_printf("Preparing RTC for HSE mode\r\n");
|
||||||
if ((RCC_BASE->BDCR & 0x00000300) != 0x0300)
|
if ((RCC_BASE->BDCR & 0x00000300) != 0x0300)
|
||||||
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
||||||
RCC_BASE->BDCR = 0x00008304;
|
RCC_BASE->BDCR = 0x00008304;
|
||||||
dbg_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
rtc_debug_printf("RCC_BASE->BDCR = %08X\r\n", RCC_BASE->BDCR);
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
if (sync_prescaler == 0 && async_prescaler == 0)
|
if (sync_prescaler == 0 && async_prescaler == 0)
|
||||||
RTC_BASE->PRER = 7999 | (124 << 16);
|
RTC_BASE->PRER = 7999 | (124 << 16);
|
||||||
|
@ -118,7 +122,7 @@ RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler)
|
||||||
RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16);
|
RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16);
|
||||||
break;
|
break;
|
||||||
case RTCSEL_NONE:
|
case RTCSEL_NONE:
|
||||||
dbg_printf("Preparing RTC for NONE mode\r\n");
|
rtc_debug_printf("Preparing RTC for NONE mode\r\n");
|
||||||
if ((RCC_BASE->BDCR & 0x00000300) != 0x0000)
|
if ((RCC_BASE->BDCR & 0x00000300) != 0x0000)
|
||||||
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
RCC_BASE->BDCR = 0x00010000; // Reset the entire Backup domain
|
||||||
RCC_BASE->BDCR = RCC_BDCR_RTCSEL_NONE;
|
RCC_BASE->BDCR = RCC_BDCR_RTCSEL_NONE;
|
||||||
|
@ -126,12 +130,12 @@ RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
RCC_BASE->CR |= 0x00000040; // Turn to 24hrs mode
|
RCC_BASE->CR |= 0x00000040; // Turn to 24hrs mode
|
||||||
// dbg_printf("before rtc_clear_sync\r\n");
|
// rtc_debug_printf("before rtc_clear_sync\r\n");
|
||||||
// rtc_clear_sync();
|
// rtc_clear_sync();
|
||||||
// dbg_printf("before rtc_wait_sync\r\n");
|
// rtc_debug_printf("before rtc_wait_sync\r\n");
|
||||||
// rtc_wait_sync();
|
// rtc_wait_sync();
|
||||||
rtc_exit_config_mode();
|
rtc_exit_config_mode();
|
||||||
dbg_printf("end of rtc_init\r\n");
|
rtc_debug_printf("end of rtc_init\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -192,6 +196,9 @@ void RTClock::setTime (time_t time_stamp) {
|
||||||
|
|
||||||
void RTClock::setTime (struct tm* tm_ptr) {
|
void RTClock::setTime (struct tm* tm_ptr) {
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
|
if (tm_ptr->tm_year > 99)
|
||||||
|
tm_ptr->tm_year = tm_ptr->tm_year % 100;
|
||||||
|
tm_ptr->tm_wday = tm_ptr->tm_wday & 0x7;
|
||||||
RTC_BASE->TR = ((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
RTC_BASE->TR = ((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
||||||
((tm_ptr->tm_min / 10) << 12) | ((tm_ptr->tm_min % 10) << 8) |
|
((tm_ptr->tm_min / 10) << 12) | ((tm_ptr->tm_min % 10) << 8) |
|
||||||
((tm_ptr->tm_sec / 10) << 4) | (tm_ptr->tm_sec % 10);
|
((tm_ptr->tm_sec / 10) << 4) | (tm_ptr->tm_sec % 10);
|
||||||
|
@ -202,12 +209,14 @@ void RTClock::setTime (struct tm* tm_ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t RTClock::getTime() {
|
time_t RTClock::getTime() {
|
||||||
int years = 10 * ((RTC_BASE->DR & 0x00F00000) >> 20) + ((RTC_BASE->DR & 0x000F0000) >> 16);
|
uint32 dr_reg = RTC_BASE->DR;
|
||||||
int months = 10 * ((RTC_BASE->DR & 0x00001000) >> 12) + ((RTC_BASE->DR & 0x00000F00) >> 8);
|
uint32 tr_reg = RTC_BASE->TR;
|
||||||
int days = 10 * ((RTC_BASE->DR & 0x00000030) >> 4) + (RTC_BASE->DR & 0x000000F);
|
int years = 10 * ((dr_reg & 0x00F00000) >> 20) + ((dr_reg & 0x000F0000) >> 16);
|
||||||
int hours = 10 * ((RTC_BASE->TR & 0x00300000) >> 20) + ((RTC_BASE->TR & 0x000F0000) >> 16);
|
int months = 10 * ((dr_reg & 0x00001000) >> 12) + ((dr_reg & 0x00000F00) >> 8);
|
||||||
int mins = 10 * ((RTC_BASE->TR & 0x00007000) >> 12) + ((RTC_BASE->TR & 0x0000F00) >> 8);
|
int days = 10 * ((dr_reg & 0x00000030) >> 4) + (dr_reg & 0x000000F);
|
||||||
int secs = 10 * ((RTC_BASE->TR & 0x00000070) >> 4) + (RTC_BASE->TR & 0x0000000F);
|
int hours = 10 * ((tr_reg & 0x00300000) >> 20) + ((tr_reg & 0x000F0000) >> 16);
|
||||||
|
int mins = 10 * ((tr_reg & 0x00007000) >> 12) + ((tr_reg & 0x0000F00) >> 8);
|
||||||
|
int secs = 10 * ((tr_reg & 0x00000070) >> 4) + (tr_reg & 0x0000000F);
|
||||||
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
||||||
time_t t = (years + 30) * SECS_PER_DAY * 365;
|
time_t t = (years + 30) * SECS_PER_DAY * 365;
|
||||||
for (int i = 0; i < years; i++) {
|
for (int i = 0; i < years; i++) {
|
||||||
|
@ -228,34 +237,19 @@ time_t RTClock::getTime() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm* RTClock::getTime(struct tm* tm_ptr) {
|
struct tm* RTClock::getTime(struct tm* tm_ptr) {
|
||||||
tm_ptr->tm_year = 10 * ((RTC_BASE->DR & 0x00F00000) >> 20) + ((RTC_BASE->DR & 0x000F0000) >> 16);
|
uint32 dr_reg = RTC_BASE->DR;
|
||||||
tm_ptr->tm_mon = 10 * ((RTC_BASE->DR & 0x00001000) >> 12) + ((RTC_BASE->DR & 0x00000F00) >> 8);
|
uint32 tr_reg = RTC_BASE->TR;
|
||||||
tm_ptr->tm_mday = 10 * ((RTC_BASE->DR & 0x00000030) >> 4) + (RTC_BASE->DR & 0x000000F);
|
tm_ptr->tm_year = 10 * ((dr_reg & 0x00F00000) >> 20) + ((dr_reg & 0x000F0000) >> 16);
|
||||||
tm_ptr->tm_hour = 10 * ((RTC_BASE->TR & 0x00300000) >> 20) + ((RTC_BASE->TR & 0x000F0000) >> 16);
|
tm_ptr->tm_mon = 10 * ((dr_reg & 0x00001000) >> 12) + ((dr_reg & 0x00000F00) >> 8);
|
||||||
tm_ptr->tm_min = 10 * ((RTC_BASE->TR & 0x00007000) >> 12) + ((RTC_BASE->TR & 0x0000F00) >> 8);
|
tm_ptr->tm_mday = 10 * ((dr_reg & 0x00000030) >> 4) + (dr_reg & 0x000000F);
|
||||||
tm_ptr->tm_sec = 10 * ((RTC_BASE->TR & 0x00000070) >> 4) + (RTC_BASE->TR & 0x0000000F);
|
tm_ptr->tm_hour = 10 * ((tr_reg & 0x00300000) >> 20) + ((tr_reg & 0x000F0000) >> 16);
|
||||||
|
tm_ptr->tm_min = 10 * ((tr_reg & 0x00007000) >> 12) + ((tr_reg & 0x0000F00) >> 8);
|
||||||
|
tm_ptr->tm_sec = 10 * ((tr_reg & 0x00000070) >> 4) + (tr_reg & 0x0000000F);
|
||||||
return tm_ptr;
|
return tm_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTClock::createAlarm(voidFuncPtr function, time_t alarm_time_t) {
|
|
||||||
// rtc_set_alarm(alarm_time_t); //must be int... for standardization sake.
|
|
||||||
// rtc_attach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RTClock::createAlarm(voidFuncPtr function, tm* alarm_tm) {
|
|
||||||
// time_t alarm = mktime(alarm_tm);//convert to time_t
|
|
||||||
// createAlarm(function, alarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RTClock::attachSecondsInterrupt(voidFuncPtr function) {
|
|
||||||
// rtc_attach_interrupt(RTC_SECONDS_INTERRUPT, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RTClock::detachSecondsInterrupt() {
|
|
||||||
// rtc_detach_interrupt(RTC_SECONDS_INTERRUPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
|
void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
|
||||||
|
uint32 t = 0;
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) |
|
unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) |
|
||||||
((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
||||||
|
@ -265,9 +259,21 @@ void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, boo
|
||||||
if (!hours_match) bits |= (1 << 23);
|
if (!hours_match) bits |= (1 << 23);
|
||||||
if (!mins_match) bits |= (1 << 15);
|
if (!mins_match) bits |= (1 << 15);
|
||||||
if (!secs_match) bits |= (1 << 7);
|
if (!secs_match) bits |= (1 << 7);
|
||||||
|
RTC_BASE->CR &= ~(1 << RTC_CR_ALRAE_BIT);
|
||||||
|
while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRAWF_BIT))) {
|
||||||
|
if (++t > 1000000) {
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR.ALRAWF Timeout !\r\n");
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
RTC_BASE->ALRMAR = bits;
|
RTC_BASE->ALRMAR = bits;
|
||||||
|
RTC_BASE->CR |= (1 << RTC_CR_ALRAE_BIT);
|
||||||
RTC_BASE->CR |= (1 << RTC_CR_ALRAIE_BIT); // turn on ALRAIE
|
RTC_BASE->CR |= (1 << RTC_CR_ALRAIE_BIT); // turn on ALRAIE
|
||||||
rtc_exit_config_mode();
|
rtc_exit_config_mode();
|
||||||
|
nvic_irq_enable(NVIC_RTCALARM);
|
||||||
|
nvic_irq_enable(NVIC_RTC);
|
||||||
|
rtc_enable_alarm_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,6 +291,7 @@ void RTClock::turnOffAlarmA() {
|
||||||
|
|
||||||
|
|
||||||
void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
|
void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
|
||||||
|
uint32 t = 0;
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) |
|
unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) |
|
||||||
((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) |
|
||||||
|
@ -294,9 +301,21 @@ void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, boo
|
||||||
if (!hours_match) bits |= (1 << 23);
|
if (!hours_match) bits |= (1 << 23);
|
||||||
if (!mins_match) bits |= (1 << 15);
|
if (!mins_match) bits |= (1 << 15);
|
||||||
if (!secs_match) bits |= (1 << 7);
|
if (!secs_match) bits |= (1 << 7);
|
||||||
|
RTC_BASE->CR &= ~(1 << RTC_CR_ALRBE_BIT);
|
||||||
|
while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRBWF_BIT))) {
|
||||||
|
if (++t > 1000000) {
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR.ALRBWF Timeout !\r\n");
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
RTC_BASE->ALRMBR = bits;
|
RTC_BASE->ALRMBR = bits;
|
||||||
|
RTC_BASE->CR |= (1 << RTC_CR_ALRBE_BIT);
|
||||||
RTC_BASE->CR |= (1 << RTC_CR_ALRBIE_BIT); // turn on ALRBIE
|
RTC_BASE->CR |= (1 << RTC_CR_ALRBIE_BIT); // turn on ALRBIE
|
||||||
rtc_exit_config_mode();
|
rtc_exit_config_mode();
|
||||||
|
nvic_irq_enable(NVIC_RTCALARM);
|
||||||
|
nvic_irq_enable(NVIC_RTC);
|
||||||
|
rtc_enable_alarm_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -314,32 +333,98 @@ void RTClock::turnOffAlarmB() {
|
||||||
|
|
||||||
|
|
||||||
void RTClock::setPeriodicWakeup(uint16 period) {
|
void RTClock::setPeriodicWakeup(uint16 period) {
|
||||||
|
uint32 t = 0;
|
||||||
rtc_enter_config_mode();
|
rtc_enter_config_mode();
|
||||||
dbg_printf("before setting RTC_BASE->WUTR\r\n");
|
RTC_BASE->CR &= ~(1 << RTC_CR_WUTE_BIT);
|
||||||
|
while (!(RTC_BASE->ISR & (1 << RTC_ISR_WUTWF_BIT))) {
|
||||||
|
if (++t > 1000000) {
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR.WUTWF Timeout !\r\n");
|
||||||
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rtc_debug_printf("before setting RTC_BASE->WUTR\r\n");
|
||||||
RTC_BASE->WUTR = period; // set the period
|
RTC_BASE->WUTR = period; // set the period
|
||||||
dbg_printf("before setting RTC_BASE->CR.WUCKSEL\r\n");
|
rtc_debug_printf("RTC_BASE->WUTR = %08X\r\n", RTC_BASE->WUTR);
|
||||||
|
rtc_debug_printf("before setting RTC_BASE->CR.WUCKSEL\r\n");
|
||||||
RTC_BASE->CR &= ~(3); RTC_BASE->CR |= 4; // Set the WUCKSEL to 1Hz (0x00000004)
|
RTC_BASE->CR &= ~(3); RTC_BASE->CR |= 4; // Set the WUCKSEL to 1Hz (0x00000004)
|
||||||
|
RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
|
||||||
|
RTC_BASE->CR |= (1 << RTC_CR_WUTE_BIT);
|
||||||
if (period == 0)
|
if (period == 0)
|
||||||
RTC_BASE->CR &= ~(1 << RTC_CR_WUTIE_BIT); // if period is 0, turn off periodic wakeup interrupt.
|
RTC_BASE->CR &= ~(1 << RTC_CR_WUTIE_BIT); // if period is 0, turn off periodic wakeup interrupt.
|
||||||
else {
|
else {
|
||||||
dbg_printf("before turn ON RTC_BASE->CR.WUTIE\r\n");
|
rtc_debug_printf("before turn ON RTC_BASE->CR.WUTIE\r\n");
|
||||||
RTC_BASE->CR |= (1 << RTC_CR_WUTIE_BIT); // turn on WUTIE
|
RTC_BASE->CR |= (1 << RTC_CR_WUTIE_BIT); // turn on WUTIE
|
||||||
}
|
}
|
||||||
dbg_printf("RCC_BASE->CR = %08X\r\n", RCC_BASE->CR);
|
rtc_debug_printf("RCC_BASE->CR = %08X\r\n", RCC_BASE->CR);
|
||||||
rtc_exit_config_mode();
|
rtc_exit_config_mode();
|
||||||
rtc_enable_wakeup_event();
|
rtc_enable_wakeup_event();
|
||||||
nvic_irq_enable(NVIC_RTC);
|
nvic_irq_enable(NVIC_RTC);
|
||||||
nvic_irq_enable(NVIC_RTCALARM);
|
rtc_debug_printf("setPeriodicWakeup() done !\r\n");
|
||||||
dbg_printf("setPeriodicWakeup() done !\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RTClock::attachAlarmAInterrupt(voidFuncPtr function) {
|
||||||
|
handlerAlarmA = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTClock::detachAlarmAInterrupt() {
|
||||||
|
handlerAlarmA = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTClock::attachAlarmBInterrupt(voidFuncPtr function) {
|
||||||
|
handlerAlarmB = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTClock::detachAlarmBInterrupt() {
|
||||||
|
handlerAlarmB = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTClock::attachPeriodicWakeupInterrupt(voidFuncPtr function) {
|
||||||
|
handlerPeriodicWakeup = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTClock::detachPeriodicWakeupInterrupt() {
|
||||||
|
handlerPeriodicWakeup = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void __irq_rtc(void) {
|
void __irq_rtc(void) {
|
||||||
dbg_printf("__irq_rtc() called !\r\n");
|
rtc_debug_printf("__irq_rtc() called !\r\n");
|
||||||
*bb_perip(&EXTI_BASE->PR, EXTI_RTC_WAKEUP_BIT) = 1;
|
rtc_enter_config_mode();
|
||||||
}
|
RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
|
||||||
void __irq_rtcalarm(void) {
|
rtc_exit_config_mode();
|
||||||
dbg_printf("__irq_rtcalarm() called !\r\n");
|
*bb_perip(&EXTI_BASE->PR, EXTI_RTC_WAKEUP_BIT) = 1;
|
||||||
*bb_perip(&EXTI_BASE->PR, EXTI_RTC_ALARM_BIT) = 1;
|
if (handlerPeriodicWakeup != NULL) {
|
||||||
}
|
handlerPeriodicWakeup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __irq_rtcalarm(void) {
|
||||||
|
bool isAlarmA = false;
|
||||||
|
bool isAlarmB = false;
|
||||||
|
rtc_debug_printf("__irq_rtcalarm() called !\r\n");
|
||||||
|
rtc_enter_config_mode();
|
||||||
|
if (RTC_BASE->ISR & (1 << RTC_ISR_ALRAF_BIT)) {
|
||||||
|
isAlarmA = true;
|
||||||
|
rtc_debug_printf("AlarmA !\r\n");
|
||||||
|
RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRAF_BIT);
|
||||||
|
}
|
||||||
|
if (RTC_BASE->ISR & (1 << RTC_ISR_ALRBF_BIT)) {
|
||||||
|
isAlarmB = true;
|
||||||
|
rtc_debug_printf("AlarmB !\r\n");
|
||||||
|
RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRBF_BIT);
|
||||||
|
}
|
||||||
|
rtc_exit_config_mode();
|
||||||
|
*bb_perip(&EXTI_BASE->PR, EXTI_RTC_ALARM_BIT) = 1;
|
||||||
|
if (isAlarmA && handlerAlarmA != NULL) {
|
||||||
|
handlerAlarmA();
|
||||||
|
}
|
||||||
|
if (isAlarmB && handlerAlarmB != NULL) {
|
||||||
|
handlerAlarmB();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,17 @@
|
||||||
#ifndef _RTCLOCK_H_
|
#ifndef _RTCLOCK_H_
|
||||||
#define _RTCLOCK_H_
|
#define _RTCLOCK_H_
|
||||||
|
|
||||||
|
//#define RTC_DEBUG
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
extern void dbg_printf(const char *fmt, ... );
|
#ifdef RTC_DEBUG
|
||||||
|
extern void dbg_printf(const char *fmt, ... );
|
||||||
|
#define rtc_debug_printf(fmt, ...) dbg_printf(fmt, ##__VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define rtc_debug_printf(...)
|
||||||
|
#endif
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -91,12 +97,25 @@ typedef enum rtc_clk_src {
|
||||||
#define RTC_CR_WUTIE_BIT 14
|
#define RTC_CR_WUTIE_BIT 14
|
||||||
#define RTC_CR_ALRBIE_BIT 13
|
#define RTC_CR_ALRBIE_BIT 13
|
||||||
#define RTC_CR_ALRAIE_BIT 12
|
#define RTC_CR_ALRAIE_BIT 12
|
||||||
|
#define RTC_CR_TSE_BIT 11
|
||||||
|
#define RTC_CR_WUTE_BIT 10
|
||||||
|
#define RTC_CR_ALRBE_BIT 9
|
||||||
|
#define RTC_CR_ALRAE_BIT 8
|
||||||
|
|
||||||
/* Initialization and Status Register */
|
/* Initialization and Status Register */
|
||||||
|
#define RTC_ISR_TSOVF_BIT 12
|
||||||
|
#define RTC_ISR_TSF_BIT 11
|
||||||
|
#define RTC_ISR_WUTF_BIT 10
|
||||||
|
#define RTC_ISR_ALRBF_BIT 9
|
||||||
|
#define RTC_ISR_ALRAF_BIT 8
|
||||||
#define RTC_ISR_INIT_BIT 7
|
#define RTC_ISR_INIT_BIT 7
|
||||||
#define RTC_ISR_INITF_BIT 6
|
#define RTC_ISR_INITF_BIT 6
|
||||||
#define RTC_ISR_RSF_BIT 5
|
#define RTC_ISR_RSF_BIT 5
|
||||||
#define RTC_ISR_INITS_BIT 4
|
#define RTC_ISR_INITS_BIT 4
|
||||||
|
#define RTC_ISR_SHPF_BIT 3
|
||||||
|
#define RTC_ISR_WUTWF_BIT 2
|
||||||
|
#define RTC_ISR_ALRBWF_BIT 1
|
||||||
|
#define RTC_ISR_ALRAWF_BIT 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,12 +132,6 @@ class RTClock {
|
||||||
struct tm* getTime(struct tm* tm_ptr);
|
struct tm* getTime(struct tm* tm_ptr);
|
||||||
time_t getTime();
|
time_t getTime();
|
||||||
|
|
||||||
void createAlarm(voidFuncPtr function, time_t alarm_time_t);
|
|
||||||
void createAlarm(voidFuncPtr function, struct tm* alarm_tm);
|
|
||||||
|
|
||||||
void attachSecondsInterrupt(voidFuncPtr function);
|
|
||||||
void detachSecondsInterrupt();
|
|
||||||
|
|
||||||
void setAlarmATime (tm * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false);
|
void setAlarmATime (tm * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false);
|
||||||
void setAlarmATime (time_t alarm_time, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false);
|
void setAlarmATime (time_t alarm_time, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false);
|
||||||
void turnOffAlarmA();
|
void turnOffAlarmA();
|
||||||
|
@ -127,6 +140,15 @@ class RTClock {
|
||||||
void turnOffAlarmB();
|
void turnOffAlarmB();
|
||||||
|
|
||||||
void setPeriodicWakeup(uint16 period);
|
void setPeriodicWakeup(uint16 period);
|
||||||
|
|
||||||
|
void attachPeriodicWakeupInterrupt(voidFuncPtr function);
|
||||||
|
void detachPeriodicWakeupInterrupt();
|
||||||
|
|
||||||
|
void attachAlarmAInterrupt(voidFuncPtr function);
|
||||||
|
void detachAlarmAInterrupt();
|
||||||
|
void attachAlarmBInterrupt(voidFuncPtr function);
|
||||||
|
void detachAlarmBInterrupt();
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
|
|
||||||
} ;
|
} ;
|
||||||
|
@ -145,15 +167,15 @@ static inline void rtc_clear_sync() {
|
||||||
*/
|
*/
|
||||||
static inline void rtc_wait_sync() {
|
static inline void rtc_wait_sync() {
|
||||||
uint32 t = 0;
|
uint32 t = 0;
|
||||||
dbg_printf("entering rtc_wait_sync\r\n");
|
rtc_debug_printf("entering rtc_wait_sync\r\n");
|
||||||
while (*bb_perip(&(RTC->regs)->ISR, RTC_ISR_RSF_BIT) == 0) {
|
while (*bb_perip(&(RTC->regs)->ISR, RTC_ISR_RSF_BIT) == 0) {
|
||||||
if (++t > 1000000) {
|
if (++t > 1000000) {
|
||||||
dbg_printf("RTC_BASE->ISR.RSF Timeout !\r\n");
|
rtc_debug_printf("RTC_BASE->ISR.RSF Timeout !\r\n");
|
||||||
dbg_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg_printf("finished rtc_wait_sync\r\n");
|
rtc_debug_printf("finished rtc_wait_sync\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,15 +187,15 @@ static inline void rtc_enter_config_mode() {
|
||||||
RTC_BASE->WPR = 0xCA;
|
RTC_BASE->WPR = 0xCA;
|
||||||
RTC_BASE->WPR = 0x53;
|
RTC_BASE->WPR = 0x53;
|
||||||
*bb_perip(&(RTC->regs)->ISR, RTC_ISR_INIT_BIT) = 1;
|
*bb_perip(&(RTC->regs)->ISR, RTC_ISR_INIT_BIT) = 1;
|
||||||
dbg_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
while (!(RTC_BASE->ISR & 0x00000040)) {
|
while (!(RTC_BASE->ISR & 0x00000040)) {
|
||||||
if (++t > 1000000) {
|
if (++t > 1000000) {
|
||||||
dbg_printf("RTC_BASE->ISR.INITF Timeout !\r\n");
|
rtc_debug_printf("RTC_BASE->ISR.INITF Timeout !\r\n");
|
||||||
dbg_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
rtc_debug_printf("RTC_BASE->ISR = %08X\r\n", RTC_BASE->ISR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbg_printf("rtc_enter_config_mode done !\r\n");
|
rtc_debug_printf("rtc_enter_config_mode done !\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,7 +203,7 @@ static inline void rtc_enter_config_mode() {
|
||||||
*/
|
*/
|
||||||
static inline void rtc_exit_config_mode() {
|
static inline void rtc_exit_config_mode() {
|
||||||
*bb_perip(&(RTC->regs)->ISR, RTC_ISR_INIT_BIT) = 0;
|
*bb_perip(&(RTC->regs)->ISR, RTC_ISR_INIT_BIT) = 0;
|
||||||
dbg_printf("rtc_exit_config_mode done !\r\n");
|
rtc_debug_printf("rtc_exit_config_mode done !\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue