Skip to content

Commit dac7932

Browse files
committed
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.
1 parent 1ef26b3 commit dac7932

3 files changed

Lines changed: 117 additions & 1 deletion

File tree

stmhal/qstrdefsport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ Q(recv)
121121
Q(RTC)
122122
Q(info)
123123
Q(datetime)
124+
Q(wakeup)
124125

125126
// for Pin class
126127
Q(Pin)

stmhal/rtc.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,123 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
372372
}
373373
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
374374

375+
// wakeup(None)
376+
// wakeup(ms, callback=None)
377+
// wakeup(wucksel, wut, callback)
378+
mp_obj_t pyb_rtc_wakeup(mp_uint_t n_args, const mp_obj_t *args) {
379+
// wut is wakeup counter start value, wucksel is clock source
380+
// counter is decremented at wucksel rate, and wakes the MCU when it gets to 0
381+
// wucksel=0b000 is RTC/16 (RTC runs at 32768Hz)
382+
// wucksel=0b001 is RTC/8
383+
// wucksel=0b010 is RTC/4
384+
// wucksel=0b011 is RTC/2
385+
// wucksel=0b100 is 1Hz clock
386+
// wucksel=0b110 is 1Hz clock with 0x10000 added to wut
387+
// so a 1 second wakeup could be wut=2047, wucksel=0b000, or wut=4095, wucksel=0b001, etc
388+
389+
// disable wakeup IRQ while we configure it
390+
HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
391+
392+
bool enable = false;
393+
mp_int_t wucksel;
394+
mp_int_t wut;
395+
mp_obj_t callback = mp_const_none;
396+
if (n_args <= 3) {
397+
if (args[1] == mp_const_none) {
398+
// disable wakeup
399+
} else {
400+
// time given in ms
401+
mp_int_t ms = mp_obj_get_int(args[1]);
402+
mp_int_t div = 2;
403+
wucksel = 3;
404+
while (div <= 16 && ms > 2000 * div) {
405+
div *= 2;
406+
wucksel -= 1;
407+
}
408+
if (div <= 16) {
409+
wut = 32768 / div * ms / 1000;
410+
} else {
411+
wucksel = 4;
412+
wut = ms / 1000;
413+
if (ms > 0x10000) {
414+
wucksel = 5;
415+
ms -= 0x10000;
416+
if (ms > 0x10000) {
417+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "wakeup value too large"));
418+
}
419+
}
420+
}
421+
wut -= 1;
422+
enable = true;
423+
}
424+
if (n_args == 3) {
425+
callback = args[2];
426+
}
427+
} else {
428+
// config values given directly
429+
wucksel = mp_obj_get_int(args[1]);
430+
wut = mp_obj_get_int(args[2]);
431+
callback = args[3];
432+
enable = true;
433+
}
434+
435+
// set the callback
436+
MP_STATE_PORT(pyb_extint_callback)[22] = callback;
437+
438+
// disable register write protection
439+
RTC->WPR = 0xca;
440+
RTC->WPR = 0x53;
441+
442+
// clear WUTE
443+
RTC->CR &= ~(1 << 10);
444+
445+
// wait until WUTWF is set
446+
while (!(RTC->ISR & (1 << 2))) {
447+
}
448+
449+
if (enable) {
450+
// program WUT
451+
RTC->WUTR = wut;
452+
453+
// set WUTIE to enable wakeup interrupts
454+
// set WUTE to enable wakeup
455+
// program WUCKSEL
456+
RTC->CR |= (1 << 14) | (1 << 10) | (wucksel & 7);
457+
458+
// enable register write protection
459+
RTC->WPR = 0xff;
460+
461+
// enable external interrupts on line 22
462+
EXTI->IMR |= 1 << 22;
463+
EXTI->RTSR |= 1 << 22;
464+
465+
// clear interrupt flags
466+
RTC->ISR &= ~(1 << 10);
467+
EXTI->PR = 1 << 22;
468+
469+
HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0x0f, 0x0f);
470+
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
471+
472+
//printf("wut=%d wucksel=%d\n", wut, wucksel);
473+
} else {
474+
// clear WUTIE to disable interrupts
475+
RTC->CR &= ~(1 << 14);
476+
477+
// enable register write protection
478+
RTC->WPR = 0xff;
479+
480+
// disable external interrupts on line 22
481+
EXTI->IMR &= ~(1 << 22);
482+
}
483+
484+
return mp_const_none;
485+
}
486+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_wakeup_obj, 2, 4, pyb_rtc_wakeup);
487+
375488
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
376489
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_rtc_info_obj },
377490
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
491+
{ MP_OBJ_NEW_QSTR(MP_QSTR_wakeup), (mp_obj_t)&pyb_rtc_wakeup_obj },
378492
};
379493
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
380494

stmhal/stm32f4xx_it.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ void TAMP_STAMP_IRQHandler(void) {
341341
}
342342

343343
void RTC_WKUP_IRQHandler(void) {
344-
Handle_EXTI_Irq(EXTI_RTC_WAKEUP);
344+
RTC->ISR &= ~(1 << 10); // clear wakeup interrupt flag
345+
Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback
345346
}
346347

347348
void TIM1_BRK_TIM9_IRQHandler(void) {

0 commit comments

Comments
 (0)