safe mode fix.

This commit is contained in:
jun2sak 2021-02-21 00:47:07 +09:00
parent cf2427c561
commit 26f8f532f1
9 changed files with 175 additions and 50 deletions

6
.gitignore vendored
View File

@ -86,3 +86,9 @@ TAGS
####################
.venv
.env
1FILES
2FILES
TAG
ports/nrf/LOG*.txt
ports/nrf/boards/pg8c

15
main.c
View File

@ -214,7 +214,7 @@ STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec
decompress(compressed, decompressed);
mp_hal_stdout_tx_str(decompressed);
pyexec_file(filename, exec_result);
dbg_printf("pyexec_file end result=(code=%d, line=%d)\r\n", exec_result->return_code, exec_result->exception_line);
//dbg_printf("pyexec_file end result=(code=%d, line=%d)\r\n", exec_result->return_code, exec_result->exception_line);
return true;
}
@ -260,7 +260,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
}
STATIC bool run_code_py(safe_mode_t safe_mode) {
dbg_printf("run_code_py (%d)\r\n", (int)safe_mode);
//dbg_printf("run_code_py (%d)\r\n", (int)safe_mode);
bool serial_connected_at_start = serial_connected();
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
serial_write("\n");
@ -436,7 +436,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
FIL* boot_output_file;
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
dbg_printf("run_boot_py (%d)\r\n", (int)safe_mode);
//dbg_printf("run_boot_py (%d)\r\n", (int)safe_mode);
// If not in safe mode, run boot before initing USB and capture output in a
// file.
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
@ -583,6 +583,15 @@ int __attribute__((used)) main(void) {
// Start serial and HID after giving boot.py a chance to tweak behavior.
serial_init();
#if 0 //XXX
int rr = (int)common_hal_mcu_processor_get_reset_reason();
const char* rrstr[] = {
"POWER_ON", "BROWNOUT", "SOFTWARE", "DEEPSLEEPALARM",
"RESET_PIN", "WATCHDOG", "UNKNOWN"
};
dbg_printf("reset_reason=%s\r\n", rrstr[rr]);
#endif
#if CIRCUITPY_BLEIO
supervisor_start_bluetooth();
#endif

View File

@ -26,23 +26,84 @@
*/
#include <string.h>
#ifdef MY_DEBUGUART
#include "supervisor/serial.h" // dbg_printf()
#endif
#include "py/runtime.h"
#include "common-hal/alarm/SleepMemory.h"
//static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH];
#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;
#define SLEEP_MEMORY_DATA_GUARD 0xad0000af
#define SLEEP_MEMORY_DATA_GUARD_MASK 0xff0000ff
void alarm_sleep_memory_reset(void) {
static int is_sleep_memory_valid(void) {
if ((_sleep_mem_magicnum & SLEEP_MEMORY_DATA_GUARD_MASK)
== SLEEP_MEMORY_DATA_GUARD) {
return 1;
}
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
return 0;
}
static void dumpRAMreg(void) {
#ifdef MY_DEBUGUART
int i;
for(i = 0; i <= 8; ++i) {
dbg_printf(" RAM%d:%08X", i, (int)(NRF_POWER->RAM[i].POWER));
if (i==4) dbg_printf("\r\n");
}
dbg_printf("\r\n");
#endif
}
static void initialize_sleep_memory(void) {
memset((uint8_t *)_sleep_mem, 0, SLEEP_MEMORY_LENGTH);
// also, set RAM[n].POWER register for RAM retention
// nRF52840 has RAM[0..7].Section[0..1] and RAM[8].Section[0..5]
// nRF52833 has RAM[0..7].Section[0..1] and RAM[8].Section[0,1]
dumpRAMreg();
for(int ram = 0; ram <= 7; ++ram) {
NRF_POWER->RAM[ram].POWERSET = 0x00030000; // RETENTION for section 0,1
};
#ifdef NRF52840
NRF_POWER->RAM[8].POWERSET = 0x001F0000; // RETENTION for section 0..5
#endif
#ifdef NRF52833
NRF_POWER->RAM[8].POWERSET = 0x00030000; // RETENTION for section 0,1
#endif
dumpRAMreg();
_sleep_mem_magicnum = SLEEP_MEMORY_DATA_GUARD;
}
void alarm_sleep_memory_reset(void) {
if (!is_sleep_memory_valid()) {
initialize_sleep_memory();
#ifdef MY_DEBUGUART
dbg_printf("_sleep_mem[] initialized\r\n");
#endif
}
}
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
return sizeof(_sleep_mem);
}
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)) {
return false;
}
memcpy((uint8_t *) (_sleep_mem + 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)) {
return;
}
memcpy(values, (uint8_t *) (_sleep_mem + start_index), len);
}

View File

@ -42,14 +42,15 @@
//#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/port.h"
#ifdef MY_DEBUGUART
#include "supervisor/serial.h" // dbg_printf()
#endif
#include "nrf.h"
#include "nrf_power.h"
#include "nrfx.h"
#include "nrfx_gpiote.h"
extern void _debug_print(const char* s);
extern void _xxx_dumpRTC(void);//XXXX
#define DEBUG_LED_PIN (NRF_GPIO_PIN_MAP(1, 11)) // P1_11 = LED
void _debug_led_init(void) {
@ -68,14 +69,14 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
};
void alarm_reset(void) {
//alarm_sleep_memory_reset();
alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset();
//alarm_touch_touchalarm_reset();
}
extern uint32_t reset_reason_saved;
STATIC uint32_t _get_wakeup_cause(void) {
STATIC nrf_sleep_source_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
return NRF_SLEEP_WAKEUP_GPIO;
}
@ -101,17 +102,30 @@ STATIC uint32_t _get_wakeup_cause(void) {
}
bool alarm_woken_from_sleep(void) {
uint32_t cause = _get_wakeup_cause();
nrf_sleep_source_t cause = _get_wakeup_cause();
return (cause == NRF_SLEEP_WAKEUP_GPIO || cause == NRF_SLEEP_WAKEUP_TIMER
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD
|| cause == NRF_SLEEP_WAKEUP_RESETPIN);
}
#ifdef MY_DEBUGUART
static const char* cause_str[] = {
"UNDEFINED",
"GPIO",
"TIMER",
"TOUCHPAD",
"VBUS",
"RESETPIN",
};
#endif
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
uint32_t cause = _get_wakeup_cause();
if (cause & 0x80000000) {
printf("wakeup cause = 0x%08X\r\n", (int)cause);
nrf_sleep_source_t cause = _get_wakeup_cause();
#if 0
if (cause >= 0 && cause < NRF_SLEEP_WAKEUP_ZZZ) {
printf("wakeup cause = NRF_SLEEP_WAKEUP_%s\r\n", cause_str[(int)cause]);
}
#endif
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
@ -122,13 +136,14 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
case NRF_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
}
default:
break;
}
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
mp_obj_t obj = _get_wake_alarm(0, NULL);
//_xxx_dumpRTC();//XXX
return obj;
}
@ -139,11 +154,12 @@ STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t
#if 0
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
#endif
//_xxx_dumpRTC();
}
STATIC void _idle_until_alarm(void) {
#ifdef MY_DEBUGUART
int ct = 40;
#endif
reset_reason_saved = 0;
// Poll for alarms.
while (!mp_hal_is_interrupted()) {
@ -151,26 +167,35 @@ STATIC void _idle_until_alarm(void) {
// Allow ctrl-C interrupt.
if (alarm_woken_from_sleep()) {
alarm_save_wake_alarm();
#ifdef MY_DEBUGUART
int cause = _get_wakeup_cause();
printf("wakeup(%d)\r\n", cause); //XXX
printf("wakeup(%d)\r\n", cause);
#endif
return;
}
port_idle_until_interrupt();
#ifdef MY_DEBUGUART
if (ct > 0) {
printf("_"); --ct;
printf("_");
--ct;
}
#endif
}
}
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;
_setup_sleep_alarms(false, n_alarms, alarms);
_debug_print("\r\nsleep...");
#ifdef MY_DEBUGUART
dbg_printf("\r\nsleep...");
#endif
_idle_until_alarm();
if (mp_hal_is_interrupted()) {
_debug_print("mp_hal_is_interrupted\r\n");
#ifdef MY_DEBUGUART
dbg_printf("mp_hal_is_interrupted\r\n");
#endif
r_obj = mp_const_none;
}
else {
@ -185,7 +210,9 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
}
void nrf_deep_sleep_start(void) {
_debug_print("go system off..\r\n");
#ifdef MY_DEBUGUART
dbg_printf("go system off..\r\n");
#endif
sd_power_system_off();
}

View File

@ -36,6 +36,7 @@ typedef enum {
NRF_SLEEP_WAKEUP_TOUCHPAD,
NRF_SLEEP_WAKEUP_VBUS,
NRF_SLEEP_WAKEUP_RESETPIN,
NRF_SLEEP_WAKEUP_ZZZ
} nrf_sleep_source_t;
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;

View File

@ -146,30 +146,40 @@ void _setup2(void) {
};
for(size_t i = 0; i < 64; ++i) {
uint64_t mask = 1ull << i;
#ifdef MY_DEBUGUART
int pull = 0;
int sense = 0;
#endif
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
continue;
}
if (((high_alarms & mask) != 0) && ((low_alarms & mask) == 0)) {
cfg.sense = NRF_GPIOTE_POLARITY_LOTOHI;
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
#ifdef MY_DEBUGUART
pull = -1; sense = 1;
#endif
}
else
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
cfg.sense = NRF_GPIOTE_POLARITY_HITOLO;
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
#ifdef MY_DEBUGUART
pull = 1; sense = -1;
#endif
}
else {
cfg.sense = NRF_GPIOTE_POLARITY_TOGGLE;
cfg.pull = NRF_GPIO_PIN_NOPULL;
#ifdef MY_DEBUGUART
sense = 9;
#endif
}
nrfx_gpiote_in_init((nrfx_gpiote_pin_t)i, &cfg, pinalarm_gpiote_handler);
nrfx_gpiote_in_event_enable((nrfx_gpiote_pin_t)i, true);
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
#ifdef MY_DEBUGUART
dbg_printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
#endif
}
}
@ -188,7 +198,9 @@ void _setup_pin1_for_deepsleep(void) {
for(size_t i = 0; i < 64; ++i) {
uint64_t mask = 1ull << i;
int pull = 0;
#ifdef MY_DEBUGUART
int sense = 0;
#endif
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
continue;
}
@ -196,16 +208,22 @@ void _setup_pin1_for_deepsleep(void) {
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_HIGH);
#ifdef MY_DEBUGUART
sense = NRF_GPIO_PIN_SENSE_HIGH;
#endif
}
else
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_LOW);
#ifdef MY_DEBUGUART
sense = NRF_GPIO_PIN_SENSE_LOW;
#endif
}
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
#ifdef MY_DEBUGUART
dbg_printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
#endif
}
#if 0
uint32_t pin_number = 2;
@ -230,7 +248,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
pin_number = alarm->pin->number;
dbg_printf("alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull);
//dbg_printf("alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull);
if (alarm->value) {
high_alarms |= 1ull << pin_number;
high_count++;
@ -251,7 +269,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
}
}
else {
dbg_printf("alarm_pin_pinalarm_set_alarms() no valid pins\r\n");
//dbg_printf("alarm_pin_pinalarm_set_alarms() no valid pins\r\n");
}
}

View File

@ -122,6 +122,26 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
}
extern uint32_t reset_reason_saved;
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
return RESET_REASON_UNKNOWN;
mcu_reset_reason_t r = RESET_REASON_UNKNOWN;
if (reset_reason_saved == 0) {
r = RESET_REASON_POWER_ON;
}
else if (reset_reason_saved & POWER_RESETREAS_RESETPIN_Msk) {
r = RESET_REASON_RESET_PIN;
}
else if (reset_reason_saved & POWER_RESETREAS_DOG_Msk) {
r = RESET_REASON_WATCHDOG;
}
else if (reset_reason_saved & POWER_RESETREAS_SREQ_Msk) {
r = RESET_REASON_SOFTWARE;
}
else if ((reset_reason_saved & POWER_RESETREAS_OFF_Msk) ||
(reset_reason_saved & POWER_RESETREAS_LPCOMP_Msk) ||
(reset_reason_saved & POWER_RESETREAS_NFC_Msk) ||
(reset_reason_saved & POWER_RESETREAS_VBUS_Msk)) {
r = RESET_REASON_DEEP_SLEEP_ALARM;
}
return r;
}

View File

@ -114,7 +114,8 @@ void rtc_handler(nrfx_rtc_int_type_t int_type) {
}
}
void _xxx_dumpRTC(void) {
#ifdef MY_DEBUGUART
void dbg_dumpRTC(void) {
dbg_printf("\r\nRTC2\r\n");
NRF_RTC_Type *r = rtc_instance.p_reg;
dbg_printf("PRESCALER=%08X, ", (int)r->PRESCALER);
@ -125,6 +126,7 @@ void _xxx_dumpRTC(void) {
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);
}
#endif
void tick_init(void) {
if (!nrf_clock_lf_is_running(NRF_CLOCK)) {
@ -178,12 +180,14 @@ safe_mode_t port_init(void) {
#endif
reset_reason_saved = NRF_POWER->RESETREAS;
// clear all RESET reason bits
NRF_POWER->RESETREAS = reset_reason_saved;
// If the board was reset by the WatchDogTimer, we may
// need to boot into safe mode. Reset the RESETREAS bit
// for the WatchDogTimer so we don't encounter this the
// next time we reboot.
if (NRF_POWER->RESETREAS & POWER_RESETREAS_DOG_Msk) {
if (reset_reason_saved & POWER_RESETREAS_DOG_Msk) {
NRF_POWER->RESETREAS = POWER_RESETREAS_DOG_Msk;
uint32_t usb_reg = NRF_POWER->USBREGSTATUS;

View File

@ -74,22 +74,6 @@ void _debug_uart_init(void) {
return;
}
void _debug_printbuf(char* data) {
int siz, l;
while((l = strlen(data)) != 0) {
if (l <= DBG_PBUF_LEN) {
siz = l;
}
else {
siz = DBG_PBUF_LEN;
}
memcpy(_dbg_pbuf, data, siz);
_dbg_pbuf[siz] = 0;
nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const*)_dbg_pbuf, siz);
data += siz;
}
}
void _debug_print_substr(const char* text, uint32_t length) {
char* data = (char*)text;
int siz;
@ -108,10 +92,6 @@ void _debug_print_substr(const char* text, uint32_t length) {
}
}
void _debug_print(const char* s) {
_debug_printbuf((char*)s);
}
void _debug_uart_deinit(void) {
nrfx_uarte_uninit(&_dbg_uart_inst);
}
@ -164,7 +144,6 @@ void serial_early_init(void) {
#ifdef MY_DEBUGUART
_debug_uart_init();
_debug_led_init();
_debug_print("\r\ndebug_uart start\r\n");
#endif
}