stmhal: Add rtc.wakeup method, to set wakeup timer.
This allows to wake from low-power modes at a regular interval. This method is preliminary, pending testing and API overhaul.
This commit is contained in:
parent
1ef26b35c1
commit
dac79324b5
|
@ -121,6 +121,7 @@ Q(recv)
|
|||
Q(RTC)
|
||||
Q(info)
|
||||
Q(datetime)
|
||||
Q(wakeup)
|
||||
|
||||
// for Pin class
|
||||
Q(Pin)
|
||||
|
|
114
stmhal/rtc.c
114
stmhal/rtc.c
|
@ -372,9 +372,123 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
|
||||
|
||||
// wakeup(None)
|
||||
// wakeup(ms, callback=None)
|
||||
// wakeup(wucksel, wut, callback)
|
||||
mp_obj_t pyb_rtc_wakeup(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// wut is wakeup counter start value, wucksel is clock source
|
||||
// counter is decremented at wucksel rate, and wakes the MCU when it gets to 0
|
||||
// wucksel=0b000 is RTC/16 (RTC runs at 32768Hz)
|
||||
// wucksel=0b001 is RTC/8
|
||||
// wucksel=0b010 is RTC/4
|
||||
// wucksel=0b011 is RTC/2
|
||||
// wucksel=0b100 is 1Hz clock
|
||||
// wucksel=0b110 is 1Hz clock with 0x10000 added to wut
|
||||
// so a 1 second wakeup could be wut=2047, wucksel=0b000, or wut=4095, wucksel=0b001, etc
|
||||
|
||||
// disable wakeup IRQ while we configure it
|
||||
HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
|
||||
|
||||
bool enable = false;
|
||||
mp_int_t wucksel;
|
||||
mp_int_t wut;
|
||||
mp_obj_t callback = mp_const_none;
|
||||
if (n_args <= 3) {
|
||||
if (args[1] == mp_const_none) {
|
||||
// disable wakeup
|
||||
} else {
|
||||
// time given in ms
|
||||
mp_int_t ms = mp_obj_get_int(args[1]);
|
||||
mp_int_t div = 2;
|
||||
wucksel = 3;
|
||||
while (div <= 16 && ms > 2000 * div) {
|
||||
div *= 2;
|
||||
wucksel -= 1;
|
||||
}
|
||||
if (div <= 16) {
|
||||
wut = 32768 / div * ms / 1000;
|
||||
} else {
|
||||
wucksel = 4;
|
||||
wut = ms / 1000;
|
||||
if (ms > 0x10000) {
|
||||
wucksel = 5;
|
||||
ms -= 0x10000;
|
||||
if (ms > 0x10000) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "wakeup value too large"));
|
||||
}
|
||||
}
|
||||
}
|
||||
wut -= 1;
|
||||
enable = true;
|
||||
}
|
||||
if (n_args == 3) {
|
||||
callback = args[2];
|
||||
}
|
||||
} else {
|
||||
// config values given directly
|
||||
wucksel = mp_obj_get_int(args[1]);
|
||||
wut = mp_obj_get_int(args[2]);
|
||||
callback = args[3];
|
||||
enable = true;
|
||||
}
|
||||
|
||||
// set the callback
|
||||
MP_STATE_PORT(pyb_extint_callback)[22] = callback;
|
||||
|
||||
// disable register write protection
|
||||
RTC->WPR = 0xca;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
// clear WUTE
|
||||
RTC->CR &= ~(1 << 10);
|
||||
|
||||
// wait until WUTWF is set
|
||||
while (!(RTC->ISR & (1 << 2))) {
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
// program WUT
|
||||
RTC->WUTR = wut;
|
||||
|
||||
// set WUTIE to enable wakeup interrupts
|
||||
// set WUTE to enable wakeup
|
||||
// program WUCKSEL
|
||||
RTC->CR |= (1 << 14) | (1 << 10) | (wucksel & 7);
|
||||
|
||||
// enable register write protection
|
||||
RTC->WPR = 0xff;
|
||||
|
||||
// enable external interrupts on line 22
|
||||
EXTI->IMR |= 1 << 22;
|
||||
EXTI->RTSR |= 1 << 22;
|
||||
|
||||
// clear interrupt flags
|
||||
RTC->ISR &= ~(1 << 10);
|
||||
EXTI->PR = 1 << 22;
|
||||
|
||||
HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0x0f, 0x0f);
|
||||
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
||||
|
||||
//printf("wut=%d wucksel=%d\n", wut, wucksel);
|
||||
} else {
|
||||
// clear WUTIE to disable interrupts
|
||||
RTC->CR &= ~(1 << 14);
|
||||
|
||||
// enable register write protection
|
||||
RTC->WPR = 0xff;
|
||||
|
||||
// disable external interrupts on line 22
|
||||
EXTI->IMR &= ~(1 << 22);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_wakeup_obj, 2, 4, pyb_rtc_wakeup);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_rtc_info_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_wakeup), (mp_obj_t)&pyb_rtc_wakeup_obj },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
|
||||
|
||||
|
|
|
@ -341,7 +341,8 @@ void TAMP_STAMP_IRQHandler(void) {
|
|||
}
|
||||
|
||||
void RTC_WKUP_IRQHandler(void) {
|
||||
Handle_EXTI_Irq(EXTI_RTC_WAKEUP);
|
||||
RTC->ISR &= ~(1 << 10); // clear wakeup interrupt flag
|
||||
Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback
|
||||
}
|
||||
|
||||
void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||
|
|
Loading…
Reference in New Issue