new wait-until-alarm design, don't use System OFF.
This commit is contained in:
parent
7bb789625e
commit
3fab9f8b1b
1
main.c
1
main.c
@ -435,6 +435,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
#else
|
||||
port_idle_until_interrupt();
|
||||
#endif
|
||||
return false; // to go REPL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
#include "common-hal/alarm/SleepMemory.h"
|
||||
#include "nrf_power.h"
|
||||
|
||||
@ -35,14 +36,15 @@ extern void dbg_dump_RAMreg(void);
|
||||
#include "supervisor/serial.h" // dbg_printf()
|
||||
#endif
|
||||
|
||||
#define RTC_DATA_ATTR __attribute__((section(".uninitialized")))
|
||||
static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH];
|
||||
static RTC_DATA_ATTR uint32_t _sleep_mem_magicnum;
|
||||
__attribute__((section(".uninitialized"))) static uint8_t _sleepmem[SLEEP_MEMORY_LENGTH];
|
||||
__attribute__((section(".uninitialized"))) uint8_t sleepmem_wakeup_event;
|
||||
__attribute__((section(".uninitialized"))) uint8_t sleepmem_wakeup_pin;
|
||||
__attribute__((section(".uninitialized"))) static uint32_t _sleepmem_magicnum;
|
||||
#define SLEEP_MEMORY_DATA_GUARD 0xad0000af
|
||||
#define SLEEP_MEMORY_DATA_GUARD_MASK 0xff0000ff
|
||||
|
||||
static int is_sleep_memory_valid(void) {
|
||||
if ((_sleep_mem_magicnum & SLEEP_MEMORY_DATA_GUARD_MASK)
|
||||
if ((_sleepmem_magicnum & SLEEP_MEMORY_DATA_GUARD_MASK)
|
||||
== SLEEP_MEMORY_DATA_GUARD) {
|
||||
return 1;
|
||||
}
|
||||
@ -75,14 +77,16 @@ void set_memory_retention(void) {
|
||||
}
|
||||
|
||||
static void initialize_sleep_memory(void) {
|
||||
memset((uint8_t *)_sleep_mem, 0, SLEEP_MEMORY_LENGTH);
|
||||
memset((uint8_t *)_sleepmem, 0, SLEEP_MEMORY_LENGTH);
|
||||
sleepmem_wakeup_event = 0;
|
||||
sleepmem_wakeup_pin = 0;
|
||||
|
||||
set_memory_retention();
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
//dbg_dump_RAMreg();
|
||||
#endif
|
||||
|
||||
_sleep_mem_magicnum = SLEEP_MEMORY_DATA_GUARD;
|
||||
_sleepmem_magicnum = SLEEP_MEMORY_DATA_GUARD;
|
||||
}
|
||||
|
||||
void alarm_sleep_memory_reset(void) {
|
||||
@ -95,21 +99,21 @@ void alarm_sleep_memory_reset(void) {
|
||||
}
|
||||
|
||||
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
|
||||
return sizeof(_sleep_mem);
|
||||
return sizeof(_sleepmem);
|
||||
}
|
||||
|
||||
bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t* values, uint32_t len) {
|
||||
if (start_index + len > sizeof(_sleep_mem)) {
|
||||
if (start_index + len > sizeof(_sleepmem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *) (_sleep_mem + start_index), values, len);
|
||||
memcpy((uint8_t *) (_sleepmem + start_index), values, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t* values, uint32_t len) {
|
||||
if (start_index + len > sizeof(_sleep_mem)) {
|
||||
if (start_index + len > sizeof(_sleepmem)) {
|
||||
return;
|
||||
}
|
||||
memcpy(values, (uint8_t *) (_sleep_mem + start_index), len);
|
||||
memcpy(values, (uint8_t *) (_sleepmem + start_index), len);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} alarm_sleep_memory_obj_t;
|
||||
|
||||
extern void set_memory_retention(void);
|
||||
extern void alarm_sleep_memory_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
||||
|
@ -37,10 +37,13 @@
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/alarm/touch/TouchAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/serial.h" // serial_connected()
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
#include "supervisor/serial.h" // dbg_printf()
|
||||
extern int dbg_check_RTCprescaler(void);
|
||||
#endif
|
||||
|
||||
#include "nrf.h"
|
||||
@ -113,6 +116,23 @@ bool alarm_woken_from_sleep(void) {
|
||||
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD);
|
||||
}
|
||||
|
||||
nrf_sleep_source_t alarm_woken_from_sleep_2(void) {
|
||||
nrf_sleep_source_t cause = _get_wakeup_cause();
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
if (cause != NRF_SLEEP_WAKEUP_UNDEFINED) {
|
||||
//print_wakeup_cause(cause);
|
||||
}
|
||||
#endif
|
||||
if (cause == NRF_SLEEP_WAKEUP_GPIO ||
|
||||
cause == NRF_SLEEP_WAKEUP_TIMER ||
|
||||
cause == NRF_SLEEP_WAKEUP_TOUCHPAD) {
|
||||
return cause;
|
||||
}
|
||||
else {
|
||||
return NRF_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
nrf_sleep_source_t cause = _get_wakeup_cause();
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
@ -146,19 +166,74 @@ STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t
|
||||
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
|
||||
}
|
||||
|
||||
STATIC void _idle_until_alarm(void) {
|
||||
nrf_sleep_source_t system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
|
||||
bool have_timeout = false;
|
||||
uint64_t start_tick = 0, end_tick = 0;
|
||||
|
||||
if (timediff_ms != -1) {
|
||||
have_timeout = true;
|
||||
#if 0
|
||||
int64_t now = common_hal_time_monotonic_ms();
|
||||
dbg_printf("now_ms=%ld timediff_ms=%ld\r\n", (long)now, (long)timediff_ms);
|
||||
#endif
|
||||
if (timediff_ms < 0) timediff_ms = 0;
|
||||
int64_t tickdiff;
|
||||
if (prescaler == 0) {
|
||||
// 1 tick = 1/1024 sec = 1000/1024 ms
|
||||
// -> 1 ms = 1024/1000 ticks
|
||||
tickdiff = (mp_uint_t)(timediff_ms * 1024 / 1000); // ms -> ticks
|
||||
}
|
||||
else {
|
||||
// 1 tick = prescaler/1024 sec = prescaler*1000/1024 ms
|
||||
// -> 1ms = 1024/(1000*prescaler) ticks
|
||||
tickdiff = (mp_uint_t)(timediff_ms * 1024 / (1000 * prescaler));
|
||||
}
|
||||
start_tick = port_get_raw_ticks(NULL);
|
||||
end_tick = start_tick + tickdiff;
|
||||
}
|
||||
#if 0
|
||||
dbg_printf("start_tick=%ld end_tick=%ld have_timeout=%c\r\n", (long)start_tick, (long)end_tick, have_timeout ? 'T' : 'F');
|
||||
#endif
|
||||
|
||||
int64_t remaining;
|
||||
nrf_sleep_source_t wakeup_cause = NRF_SLEEP_WAKEUP_UNDEFINED;
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE;
|
||||
sleepmem_wakeup_pin = WAKEUP_PIN_UNDEF;
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
int ct = 40;
|
||||
char reason = '?';
|
||||
#define WAKEUP_REASON(x) reason = (x)
|
||||
#else
|
||||
#define WAKEUP_REASON(x)
|
||||
#endif
|
||||
reset_reason_saved = 0;
|
||||
// Poll for alarms.
|
||||
while (!mp_hal_is_interrupted()) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
// Allow ctrl-C interrupt.
|
||||
if (alarm_woken_from_sleep()) {
|
||||
alarm_save_wake_alarm();
|
||||
return;
|
||||
|
||||
while(1) {
|
||||
if (mp_hal_is_interrupted()) {
|
||||
WAKEUP_REASON('I');
|
||||
break;
|
||||
}
|
||||
if (serial_connected() && serial_bytes_available()) {
|
||||
WAKEUP_REASON('S');
|
||||
break;
|
||||
}
|
||||
RUN_BACKGROUND_TASKS;
|
||||
wakeup_cause = alarm_woken_from_sleep_2();
|
||||
if (wakeup_cause != NRF_SLEEP_WAKEUP_UNDEFINED) {
|
||||
WAKEUP_REASON('0'+wakeup_cause);
|
||||
break;
|
||||
}
|
||||
if (have_timeout) {
|
||||
remaining = end_tick - port_get_raw_ticks(NULL);
|
||||
// We break a bit early so we don't risk setting the alarm before the time when we call
|
||||
// sleep.
|
||||
if (remaining < 1) {
|
||||
WAKEUP_REASON('t');
|
||||
break;
|
||||
}
|
||||
port_interrupt_after_ticks(remaining);
|
||||
}
|
||||
// Idle until an interrupt happens.
|
||||
port_idle_until_interrupt();
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
if (ct > 0) {
|
||||
@ -166,17 +241,39 @@ STATIC void _idle_until_alarm(void) {
|
||||
--ct;
|
||||
}
|
||||
#endif
|
||||
if (have_timeout) {
|
||||
remaining = end_tick - port_get_raw_ticks(NULL);
|
||||
if (remaining <= 0) {
|
||||
wakeup_cause = NRF_SLEEP_WAKEUP_TIMER;
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_TIMER;
|
||||
WAKEUP_REASON('T');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("%c\r\n", reason);
|
||||
#endif
|
||||
return wakeup_cause;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
mp_obj_t r_obj = mp_const_none;
|
||||
alarm_time_timealarm_clear_wakeup_time();
|
||||
_setup_sleep_alarms(false, n_alarms, alarms);
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("\r\nsleep...");
|
||||
dbg_printf("\r\nlight sleep...");
|
||||
#endif
|
||||
|
||||
_idle_until_alarm();
|
||||
int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms();
|
||||
nrf_sleep_source_t cause = system_on_idle_until_alarm(timediff_ms, 0);
|
||||
(void)cause;
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
//dbg_printf("wakeup! ");
|
||||
print_wakeup_cause(cause);
|
||||
#endif
|
||||
|
||||
if (mp_hal_is_interrupted()) {
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
@ -192,29 +289,47 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
|
||||
}
|
||||
|
||||
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
alarm_time_timealarm_clear_wakeup_time();
|
||||
_setup_sleep_alarms(true, n_alarms, alarms);
|
||||
}
|
||||
|
||||
extern void set_memory_retention(void);
|
||||
#if defined(MICROPY_QSPI_CS)
|
||||
extern void qspi_disable(void);
|
||||
#endif
|
||||
|
||||
#define PRESCALER_VALUE_IN_DEEP_SLEEP (1024)
|
||||
extern void _debug_uart_init(void);
|
||||
extern void _debug_uart_uninit(void);
|
||||
|
||||
void NORETURN alarm_enter_deep_sleep(void) {
|
||||
alarm_pin_pinalarm_prepare_for_deep_sleep();
|
||||
alarm_touch_touchalarm_prepare_for_deep_sleep();
|
||||
alarm_time_timealarm_prepare_for_deep_sleep();
|
||||
|
||||
uint8_t sd_enabled;
|
||||
sd_softdevice_is_enabled(&sd_enabled);
|
||||
|
||||
set_memory_retention();
|
||||
#if defined(MICROPY_QSPI_CS)
|
||||
qspi_disable();
|
||||
#endif
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("go system off.. %d\r\n", sd_enabled);
|
||||
dbg_printf("\r\ndeep sleep...");
|
||||
#endif
|
||||
if (sd_enabled) {
|
||||
sd_power_system_off();
|
||||
}
|
||||
else {
|
||||
NRF_POWER->SYSTEMOFF = 1;
|
||||
}
|
||||
int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms();
|
||||
tick_set_prescaler(PRESCALER_VALUE_IN_DEEP_SLEEP -1);
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_dump_RTCreg(); //XXX
|
||||
dbg_check_RTCprescaler(); //XXX
|
||||
#endif
|
||||
nrf_sleep_source_t cause;
|
||||
cause = system_on_idle_until_alarm(timediff_ms,
|
||||
PRESCALER_VALUE_IN_DEEP_SLEEP);
|
||||
(void)cause;
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("wakeup! ");
|
||||
print_wakeup_cause(cause);
|
||||
dbg_printf("RESET...\r\n\r\n");
|
||||
#endif
|
||||
|
||||
reset_cpu();
|
||||
|
||||
// should not reach here..
|
||||
while(1) ;
|
||||
@ -222,12 +337,23 @@ void NORETURN alarm_enter_deep_sleep(void) {
|
||||
|
||||
void alarm_pretending_deep_sleep(void) {
|
||||
alarm_pin_pinalarm_prepare_for_deep_sleep();
|
||||
alarm_touch_touchalarm_prepare_for_deep_sleep();
|
||||
alarm_time_timealarm_prepare_for_deep_sleep();
|
||||
|
||||
port_idle_until_interrupt();
|
||||
if (alarm_woken_from_sleep()) {
|
||||
alarm_reset();
|
||||
}
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("\r\npretending to deep sleep...");
|
||||
#endif
|
||||
|
||||
int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms();
|
||||
nrf_sleep_source_t cause = system_on_idle_until_alarm(timediff_ms, 0);
|
||||
(void)cause;
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
dbg_printf("wakeup! ");
|
||||
print_wakeup_cause(cause);
|
||||
dbg_printf("continue..\r\n");
|
||||
#endif
|
||||
|
||||
alarm_reset();
|
||||
}
|
||||
|
||||
void common_hal_alarm_gc_collect(void) {
|
||||
|
@ -41,6 +41,15 @@ typedef enum {
|
||||
|
||||
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
|
||||
|
||||
enum {
|
||||
SLEEPMEM_WAKEUP_BY_NONE = 0,
|
||||
SLEEPMEM_WAKEUP_BY_PIN = 1,
|
||||
SLEEPMEM_WAKEUP_BY_TIMER = 2,
|
||||
};
|
||||
#define WAKEUP_PIN_UNDEF 0xFF
|
||||
extern uint8_t sleepmem_wakeup_event;
|
||||
extern uint8_t sleepmem_wakeup_pin;
|
||||
|
||||
extern void alarm_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
|
||||
#include "nrfx.h"
|
||||
#include "nrf_gpio.h"
|
||||
@ -43,8 +44,6 @@
|
||||
|
||||
#define WPIN_UNUSED 0xFF
|
||||
volatile char _pinhandler_gpiote_count;
|
||||
volatile nrfx_gpiote_pin_t _pinhandler_ev_pin;
|
||||
#define MYGPIOTE_EV_PIN_UNDEF 0xFF
|
||||
static bool pins_configured = false;
|
||||
|
||||
extern uint32_t reset_reason_saved;
|
||||
@ -81,11 +80,13 @@ bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
|
||||
|
||||
static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
++_pinhandler_gpiote_count;
|
||||
_pinhandler_ev_pin = pin;
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_PIN;
|
||||
sleepmem_wakeup_pin = pin & 0xFF;
|
||||
}
|
||||
|
||||
bool alarm_pin_pinalarm_woke_us_up(void) {
|
||||
return (_pinhandler_gpiote_count > 0 && _pinhandler_ev_pin != MYGPIOTE_EV_PIN_UNDEF);
|
||||
return (sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_PIN &&
|
||||
sleepmem_wakeup_pin != WAKEUP_PIN_UNDEF);
|
||||
}
|
||||
|
||||
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
@ -95,7 +96,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
|
||||
continue;
|
||||
}
|
||||
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
if (alarm->pin->number == _pinhandler_ev_pin) {
|
||||
if (alarm->pin->number == sleepmem_wakeup_pin) {
|
||||
return alarms[i];
|
||||
}
|
||||
}
|
||||
@ -105,7 +106,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
|
||||
// Map the pin number back to a pin object.
|
||||
for (size_t i = 0; i < mcu_pin_globals.map.used; i++) {
|
||||
const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value);
|
||||
if ((size_t) pin_obj->number == _pinhandler_ev_pin) {
|
||||
if ((size_t) pin_obj->number == sleepmem_wakeup_pin) {
|
||||
alarm->pin = mcu_pin_globals.map.table[i].value;
|
||||
break;
|
||||
}
|
||||
@ -147,7 +148,6 @@ static void configure_pins_for_sleep(void) {
|
||||
(void)err; // to suppress unused warning
|
||||
|
||||
_pinhandler_gpiote_count = 0;
|
||||
_pinhandler_ev_pin = MYGPIOTE_EV_PIN_UNDEF;
|
||||
|
||||
nrfx_gpiote_in_config_t cfg = {
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
|
@ -30,6 +30,7 @@
|
||||
//#include "supervisor/esp_port.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
@ -56,17 +57,31 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *
|
||||
}
|
||||
|
||||
bool alarm_time_timealarm_woke_us_up(void) {
|
||||
return rtc_woke_up_counter;
|
||||
return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_TIMER;
|
||||
}
|
||||
|
||||
int64_t wakeup_time_saved =0;
|
||||
|
||||
int64_t alarm_time_timealarm_get_wakeup_timediff_ms(void) {
|
||||
if (wakeup_time_saved == 0) {
|
||||
return -1;
|
||||
}
|
||||
return wakeup_time_saved - common_hal_time_monotonic_ms();
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_clear_wakeup_time(void) {
|
||||
wakeup_time_saved = 0;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_reset(void) {
|
||||
port_disable_interrupt_after_ticks_ch(1);
|
||||
rtc_woke_up_counter = 0;
|
||||
wakeup_time_saved = 0;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
bool timealarm_set = false;
|
||||
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
|
||||
wakeup_time_saved = 0;
|
||||
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
|
||||
@ -82,17 +97,8 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute how long to actually sleep, considering the time now.
|
||||
mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f;
|
||||
mp_float_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
|
||||
int wsecs = (int)(wakeup_in_secs);
|
||||
// timealarm is implemented by RTC, which is a 24bit counter
|
||||
// running at 32768Hz. So, 2^24 / 32768 = 512sec is an upper limit.
|
||||
if (wsecs >= 512) {
|
||||
mp_raise_ValueError(translate("Alarm time must be < 512 seconds."));
|
||||
}
|
||||
|
||||
uint32_t wakeup_in_ticks = (uint32_t)(wakeup_in_secs * 1024.0f);
|
||||
port_interrupt_after_ticks_ch(1, wakeup_in_ticks);
|
||||
rtc_woke_up_counter = 0;
|
||||
wakeup_time_saved = (int64_t)(timealarm->monotonic_time * 1000.0f);
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_prepare_for_deep_sleep(void) {
|
||||
}
|
||||
|
@ -42,3 +42,9 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *
|
||||
bool alarm_time_timealarm_woke_us_up(void);
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_time_timealarm_reset(void);
|
||||
|
||||
extern void alarm_time_timealarm_prepare_for_deep_sleep(void);
|
||||
extern int64_t alarm_time_timealarm_get_wakeup_timediff_ms(void);
|
||||
extern void alarm_time_timealarm_clear_wakeup_time(void);
|
||||
extern void dbg_dump_RTCreg(void);
|
||||
extern void tick_set_prescaler(uint32_t prescaler_val);
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include "nrfx_rtc.h"
|
||||
#include "supervisor/serial.h" // dbg_printf()
|
||||
#include "shared-bindings/microcontroller/Processor.h"
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
|
||||
extern const nrfx_rtc_t rtc_instance; // port.c
|
||||
extern volatile int rtc_woke_up_counter; // port.c
|
||||
extern uint32_t reset_reason_saved;
|
||||
|
||||
const nrfx_uarte_t _dbg_uart_inst = NRFX_UARTE_INSTANCE(1);
|
||||
@ -31,6 +31,16 @@ static int _dbg_uart_initialized = 0;
|
||||
#define DBG_PBUF_LEN 80
|
||||
static char _dbg_pbuf[DBG_PBUF_LEN+1];
|
||||
|
||||
void _debug_uart_uninit(void) {
|
||||
nrf_gpio_cfg(DEBUG_UART_TXPIN,
|
||||
NRF_GPIO_PIN_DIR_INPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
nrfx_uarte_uninit(&_dbg_uart_inst);
|
||||
}
|
||||
|
||||
void _debug_uart_init(void) {
|
||||
//if (_dbg_uart_initialized) return;
|
||||
nrfx_uarte_config_t config = {
|
||||
@ -55,6 +65,16 @@ void _debug_uart_init(void) {
|
||||
NRF_GPIO_PIN_H0H1, // orig=S0S1
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
_dbg_uart_initialized = 1;
|
||||
#if 1 //XXX
|
||||
#define DBGPIN 6+32
|
||||
nrf_gpio_cfg(DBGPIN,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_H0H1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
nrf_gpio_pin_write(DBGPIN, 1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -97,7 +117,15 @@ void dbg_dump_RTCreg(void) {
|
||||
dbg_printf("EVTENSET=%08X\r\n", (int)r->EVTENSET);
|
||||
dbg_printf("EVENTS_COMPARE[0..3]=%X,%X,%X,%X ", (int)r->EVENTS_COMPARE[0], (int)r->EVENTS_COMPARE[1], (int)r->EVENTS_COMPARE[2], (int)r->EVENTS_COMPARE[3]);
|
||||
dbg_printf("CC[0..3]=%08X,%08X,%08X,%08X\r\n", (int)r->CC[0], (int)r->CC[1], (int)r->CC[2], (int)r->CC[3]);
|
||||
dbg_printf("woke_up=%d\r\n", rtc_woke_up_counter);
|
||||
}
|
||||
|
||||
int dbg_check_RTCprescaler(void) {
|
||||
NRF_RTC_Type *r = rtc_instance.p_reg;
|
||||
if ((int)r->PRESCALER == 0) {
|
||||
dbg_printf("****** PRESCALER == 0\r\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbg_dump_RAMreg(void) {
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "common-hal/rtc/RTC.h"
|
||||
#include "common-hal/neopixel_write/__init__.h"
|
||||
#include "common-hal/watchdog/WatchDogTimer.h"
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/rtc/__init__.h"
|
||||
@ -75,13 +76,13 @@ static void power_warning_handler(void) {
|
||||
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
extern void _debug_uart_init(void);
|
||||
#define DBGPIN 6+32 //XXX P1_06 = TP1
|
||||
#endif
|
||||
|
||||
uint32_t reset_reason_saved = 0;
|
||||
const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(2);
|
||||
volatile int rtc_woke_up_counter = 0;
|
||||
|
||||
const nrfx_rtc_config_t rtc_config = {
|
||||
nrfx_rtc_config_t rtc_config = {
|
||||
.prescaler = RTC_FREQ_TO_PRESCALER(0x8000),
|
||||
.reliable = 0,
|
||||
.tick_latency = 0,
|
||||
@ -97,6 +98,11 @@ static volatile struct {
|
||||
} overflow_tracker __attribute__((section(".uninitialized")));
|
||||
|
||||
void rtc_handler(nrfx_rtc_int_type_t int_type) {
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
if (int_type == NRFX_RTC_INT_TICK) {
|
||||
nrf_gpio_pin_toggle(DBGPIN); //XXX
|
||||
}
|
||||
#endif
|
||||
if (int_type == NRFX_RTC_INT_OVERFLOW) {
|
||||
// Our RTC is 24 bits and we're clocking it at 32.768khz which is 32 (2 ** 5) subticks per
|
||||
// tick.
|
||||
@ -108,7 +114,7 @@ void rtc_handler(nrfx_rtc_int_type_t int_type) {
|
||||
nrfx_rtc_cc_set(&rtc_instance, 0, 0, false);
|
||||
} else if (int_type == NRFX_RTC_INT_COMPARE1) {
|
||||
// used in light sleep
|
||||
++rtc_woke_up_counter;
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_TIMER;
|
||||
nrfx_rtc_cc_set(&rtc_instance, 1, 0, false);
|
||||
}
|
||||
}
|
||||
@ -134,6 +140,22 @@ void tick_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void tick_uninit(void) {
|
||||
nrfx_rtc_counter_clear(&rtc_instance);
|
||||
nrfx_rtc_disable(&rtc_instance);
|
||||
nrfx_rtc_uninit(&rtc_instance);
|
||||
}
|
||||
|
||||
void tick_set_prescaler(uint32_t prescaler_val) {
|
||||
tick_uninit();
|
||||
// update of prescaler value sometimes fails if we skip this delay..
|
||||
NRFX_DELAY_US(1000);
|
||||
uint16_t prescaler_saved = rtc_config.prescaler;
|
||||
rtc_config.prescaler = prescaler_val;
|
||||
tick_init();
|
||||
rtc_config.prescaler = prescaler_saved;
|
||||
}
|
||||
|
||||
safe_mode_t port_init(void) {
|
||||
nrf_peripherals_clocks_init();
|
||||
|
||||
@ -166,6 +188,10 @@ safe_mode_t port_init(void) {
|
||||
reset_reason_saved = NRF_POWER->RESETREAS;
|
||||
// clear all RESET reason bits
|
||||
NRF_POWER->RESETREAS = reset_reason_saved;
|
||||
// clear wakeup event/pin when reset by reset-pin
|
||||
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE;
|
||||
}
|
||||
|
||||
// If the board was reset by the WatchDogTimer, we may
|
||||
// need to boot into safe mode. Reset the RESETREAS bit
|
||||
|
Loading…
x
Reference in New Issue
Block a user