From a00c54e193ff9c2e3451b0e3ac3d3c686369080d Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 20 Nov 2017 13:55:49 +0100 Subject: [PATCH 1/2] Implemented deepsleep, reset_cause and rtc functions memory, string and datetime --- ports/esp32/Makefile | 3 + ports/esp32/esprtcmem.c | 102 +++++++++++++ ports/esp32/esprtcmem.h | 49 +++++++ ports/esp32/machine_rtc.c | 291 ++++++++++++++++++++++++++++++++++++++ ports/esp32/machine_rtc.h | 40 ++++++ ports/esp32/main.c | 1 + ports/esp32/modmachine.c | 100 +++++++++++++ ports/esp32/modmachine.h | 3 + 8 files changed, 589 insertions(+) create mode 100644 ports/esp32/esprtcmem.c create mode 100644 ports/esp32/esprtcmem.h create mode 100644 ports/esp32/machine_rtc.c create mode 100644 ports/esp32/machine_rtc.h diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 48d4b9d5c..0e3e6b51f 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -141,8 +141,10 @@ SRC_C = \ modesp.c \ moduhashlib.c \ espneopixel.c \ + machine_rtc.c \ machine_hw_spi.c \ machine_wdt.c \ + esprtcmem.c \ mpthreadport.c \ $(SRC_MOD) @@ -229,6 +231,7 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ cpu_start.o \ gdbstub.o \ crosscore_int.o \ + sleep_modes.o \ ipc.o \ int_wdt.o \ event_loop.o \ diff --git a/ports/esp32/esprtcmem.c b/ports/esp32/esprtcmem.c new file mode 100644 index 000000000..42f5c3c22 --- /dev/null +++ b/ports/esp32/esprtcmem.c @@ -0,0 +1,102 @@ +/* + * This file is part of the SHA2017 Badge MicroPython project, + * http://micropython.org/ https://badge.sha2017.org + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Renze Nicolai + * Copyright (c) 2017 Anne Jan Brouwer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include + +#include "esprtcmem.h" + +static uint8_t RTC_DATA_ATTR rtcmemcontents[USER_RTC_MEM_SIZE] = { 0 }; + +// @return 0..255 is ok; -1 is error +int +esp_rtcmem_read(uint32_t location) +{ + if (location >= USER_RTC_MEM_SIZE) + { + return -1; + } + + return rtcmemcontents[location]; +} + +// @return 0 is ok; -1 is error +int +esp_rtcmem_write(uint32_t location, uint8_t value) +{ + if (location >= USER_RTC_MEM_SIZE) + { + return -1; + } + + rtcmemcontents[location] = value; + + return 0; +} + +// @return 0 is ok; -1 is error +int +esp_rtcmem_read_string(uint32_t location, char *buffer, size_t *buf_len) +{ + if (location >= USER_RTC_MEM_SIZE) + { + return -1; + } + + size_t maxlen = USER_RTC_MEM_SIZE - location; + size_t len = strnlen((const char *) &rtcmemcontents[location], maxlen); + if (len == maxlen) + { + return -1; + } + + if (*buf_len <= len) + { + return -1; + } + *buf_len = len + 1; + memcpy(buffer, &rtcmemcontents[location], len + 1); + + return 0; +} + +// @return 0 is ok; -1 is error +int +esp_rtcmem_write_string(uint32_t location, const char *buffer) +{ + if (location >= USER_RTC_MEM_SIZE || location + strlen(buffer) >= USER_RTC_MEM_SIZE) + { + return -1; + } + + memcpy(&rtcmemcontents[location], buffer, strlen(buffer)+1); + + return 0; +} diff --git a/ports/esp32/esprtcmem.h b/ports/esp32/esprtcmem.h new file mode 100644 index 000000000..ce986935d --- /dev/null +++ b/ports/esp32/esprtcmem.h @@ -0,0 +1,49 @@ +#ifndef ESPRTCMEM_H +#define ESPRTCMEM_H + +#include + +#include +#include + +#define USER_RTC_MEM_SIZE 1024 + +/** + * Read byte from rtcmem on offset location. + * + * @param location The offset in the rtcmem. + * @return 0..255 is ok; -1 is error + */ +extern int esp_rtcmem_read(uint32_t location); + +/** + * Write byte to rtcmem on offset location. + * + * @param location The offset in the rtcmem + * @param value The value to write to this offset + * @return 0 is ok; -1 is error + */ +extern int esp_rtcmem_write(uint32_t location, uint8_t value); + +/** + * Read zero-terminated string from rtcmem on offset location + * + * @param location The offset in the rtcmem + * @param buffer The destination buffer + * @param buf_len The length of the destination buffer + * on input: the total buffer-length + * on output: the used buffer-length + * @return 0 is ok; -1 is error + */ +extern int esp_rtcmem_read_string(uint32_t location, char *buffer, size_t *buf_len); + +/** + * Write zero-terminated string to rtcmem on offfset location + * + * @param location The offset in the rtcmem + * @param buffer The string to write to this offset + * @return 0 is ok; -1 is error + */ +extern int esp_rtcmem_write_string(uint32_t location, const char *buffer); + +#endif // ESPRTCMEM_H diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c new file mode 100644 index 000000000..c272335c1 --- /dev/null +++ b/ports/esp32/machine_rtc.c @@ -0,0 +1,291 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include "driver/gpio.h" + +#include "py/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "modmachine.h" +#include "machine_rtc.h" +#include "esprtcmem.h" +#include "lib/timeutils/timeutils.h" + + +extern uint64_t system_get_rtc_time(void); + +typedef struct _machine_rtc_obj_t { + mp_obj_base_t base; +} machine_rtc_obj_t; + +const mp_obj_type_t machine_rtc_type; + +#define MACHINE_RTC_VALID_EXT_PINS \ +( \ + (1ll << 0) | \ + (1ll << 2) | \ + (1ll << 4) | \ + (1ll << 12) | \ + (1ll << 13) | \ + (1ll << 14) | \ + (1ll << 15) | \ + (1ll << 25) | \ + (1ll << 26) | \ + (1ll << 27) | \ + (1ll << 32) | \ + (1ll << 33) | \ + (1ll << 34) | \ + (1ll << 35) | \ + (1ll << 36) | \ + (1ll << 37) | \ + (1ll << 38) | \ + (1ll << 39) \ +) + +#define MACHINE_RTC_LAST_EXT_PIN 39 + + +machine_rtc_config_t machine_rtc_config = { 0 }; + +STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + machine_rtc_obj_t *self = m_new_obj(machine_rtc_obj_t); + self->base.type = &machine_rtc_type; + return self; + + +} + +STATIC mp_obj_t machine_rtc_datetime(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // Get time + struct timeval tv; + gettimeofday(&tv, NULL); + + timeutils_struct_time_t tm; + mp_int_t seconds = tv.tv_sec; + + timeutils_seconds_since_2000_to_struct_time(seconds, &tm); + mp_obj_t tuple[8] = { + tuple[0] = mp_obj_new_int(tm.tm_year), + tuple[1] = mp_obj_new_int(tm.tm_mon), + tuple[2] = mp_obj_new_int(tm.tm_mday), + tuple[3] = mp_obj_new_int(tm.tm_hour), + tuple[4] = mp_obj_new_int(tm.tm_min), + tuple[5] = mp_obj_new_int(tm.tm_sec), + tuple[6] = mp_obj_new_int(tm.tm_wday), + tuple[7] = mp_obj_new_int(tm.tm_yday), + }; + return mp_obj_new_tuple(8, tuple); + } else { + // Set time + + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[0], 8, &items); + + mp_uint_t seconds = timeutils_mktime( + mp_obj_get_int(items[0]), + mp_obj_get_int(items[1]), + mp_obj_get_int(items[2]), + mp_obj_get_int(items[3]), + mp_obj_get_int(items[4]), + mp_obj_get_int(items[5])); + struct timeval tv = { + .tv_sec = seconds, + .tv_usec = 0, + }; + settimeofday(&tv, NULL); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(func_machine_rtc_datetime_obj, 0, 1, machine_rtc_datetime); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_rtc_datetime_obj,&func_machine_rtc_datetime_obj); + +STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { + mp_obj_t args[2] = {self_in, date}; + machine_rtc_datetime(2, args); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); + +STATIC mp_obj_t machine_rtc_memory(size_t n_args, const mp_obj_t *args) { + + if (n_args == 1) { + mp_int_t pos = mp_obj_get_int(args[0]); + mp_int_t val = esp_rtcmem_read(pos); + if (val < 0) { + mp_raise_msg(&mp_type_IndexError, "Offset out of range"); + } + return mp_obj_new_int(val); + } else { + mp_int_t pos = mp_obj_get_int(args[0]); + mp_int_t val = mp_obj_get_int(args[1]); + + if (val < 0 || val > 255) { + mp_raise_msg(&mp_type_IndexError, "Value out of range"); + } + int res = esp_rtcmem_write(pos, val); + if (res < 0) { + mp_raise_msg(&mp_type_IndexError, "Offset out of range"); + } + return mp_const_none; + } + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(func_machine_rtc_memory_obj, 1, 2, machine_rtc_memory); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_rtc_memory_obj,&func_machine_rtc_memory_obj); + +STATIC mp_obj_t machine_rtc_string(size_t n_args, const mp_obj_t *args) { + + if (n_args == 1) { + mp_int_t pos = mp_obj_get_int(args[0]); + char str[256]; + size_t str_len = sizeof(str); + int res = esp_rtcmem_read_string(pos, str, &str_len); + if (res < 0) { + mp_raise_msg(&mp_type_IndexError, "Offset out of range"); + } + return mp_obj_new_str(str, str_len-1, true); + } else { + mp_int_t pos = mp_obj_get_int(args[0]); + const char *str = mp_obj_str_get_str(args[1]); + + int res = esp_rtcmem_write_string(pos, str); + if (res < 0) { + mp_raise_msg(&mp_type_IndexError, "Offset out of range"); + } + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(func_machine_rtc_string_obj, 1, 2, machine_rtc_string); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_rtc_string_obj,&func_machine_rtc_string_obj); + + +STATIC mp_obj_t machine_rtc_wake_on_touch(mp_obj_t self_in, const mp_obj_t wake) { + (void)self_in; // unused + + machine_rtc_config.wake_on_touch = mp_obj_is_true(wake); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_wake_on_touch_obj, machine_rtc_wake_on_touch); + +STATIC mp_obj_t machine_rtc_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum {ARG_pin, ARG_level}; + const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} }, + { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_pin].u_obj == mp_const_none) { + machine_rtc_config.ext0_pin = -1; // "None" + } else { + gpio_num_t pin_id = machine_pin_get_id(args[ARG_pin].u_obj); + if (pin_id != machine_rtc_config.ext0_pin) { + if (!((1ll << pin_id) & MACHINE_RTC_VALID_EXT_PINS)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + } + machine_rtc_config.ext0_pin = pin_id; + } + } + + machine_rtc_config.ext0_level = args[ARG_level].u_bool; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rtc_wake_on_ext0_obj, 1, machine_rtc_wake_on_ext0); + +STATIC mp_obj_t machine_rtc_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum {ARG_pins, ARG_level}; + const mp_arg_t allowed_args[] = { + { MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext1_level} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + uint64_t ext1_pins = machine_rtc_config.ext1_pins; + + + // Check that all pins are allowed + if (args[ARG_pins].u_obj != mp_const_none) { + mp_uint_t len = 0; + mp_obj_t *elem; + mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem); + ext1_pins = 0; + + for (int i = 0; i < len; i++) { + + gpio_num_t pin_id = machine_pin_get_id(elem[i]); + // mp_int_t pin = mp_obj_get_int(elem[i]); + uint64_t pin_bit = (1ll << pin_id); + + if (!(pin_bit & MACHINE_RTC_VALID_EXT_PINS)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + break; + } + ext1_pins |= pin_bit; + } + } + + machine_rtc_config.ext1_level = args[ARG_level].u_bool; + machine_rtc_config.ext1_pins = ext1_pins; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rtc_wake_on_ext1_obj, 1, machine_rtc_wake_on_ext1); + + +STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_datetime),MP_ROM_PTR(&machine_rtc_datetime_obj) }, + { MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&machine_rtc_memory_obj) }, + { MP_ROM_QSTR(MP_QSTR_string), MP_ROM_PTR(&machine_rtc_string_obj) }, + // FIXME -- need to enable touch IRQ for this to work, + // doesn't seem possible in the IDF presently. + // { MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_touch), (mp_obj_t)&machine_rtc_wake_on_touch_obj }, + { MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&machine_rtc_wake_on_ext0_obj) }, + { MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&machine_rtc_wake_on_ext1_obj) }, + { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_INT(false) }, + { MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_INT(true) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); + +const mp_obj_type_t machine_rtc_type = { + { &mp_type_type }, + .name = MP_QSTR_RTC, + .make_new = machine_rtc_make_new, + .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, +}; + diff --git a/ports/esp32/machine_rtc.h b/ports/esp32/machine_rtc.h new file mode 100644 index 000000000..200c310ee --- /dev/null +++ b/ports/esp32/machine_rtc.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ESP32_MACINE_RTC_H +#define MICROPY_INCLUDED_ESP32_MACINE_RTC_H + + +typedef struct { + uint64_t ext1_pins; // set bit == pin# + int8_t ext0_pin; // just the pin#, -1 == None + bool wake_on_touch : 1; + bool ext0_level : 1; + bool ext1_level : 1; +} machine_rtc_config_t; + + +#endif diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 091cbddc9..cef94f014 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -65,6 +65,7 @@ void mp_task(void *pvParameter) { mp_thread_init(&mp_task_stack[0], MP_TASK_STACK_LEN); #endif uart_init(); + machine_init(); soft_reset: // initialise the stack pointer for the main thread diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 32c9c5ad5..fdc0d0101 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -34,6 +34,7 @@ #include "freertos/task.h" #include "rom/ets_sys.h" #include "esp_system.h" +#include "rom/rtc.h" #include "py/obj.h" #include "py/runtime.h" @@ -43,9 +44,20 @@ #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" #include "modmachine.h" +#include "machine_rtc.h" +#include "esp_sleep.h" #if MICROPY_PY_MACHINE +extern machine_rtc_config_t machine_rtc_config; + +uint32_t reset_cause; + +void machine_init() { + reset_cause = rtc_get_reset_reason(0); + // TODO do we need CPU_1 info too ?? +} + STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get @@ -64,12 +76,78 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); +STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + enum {ARG_sleep_ms}; + const mp_arg_t allowed_args[] = { + { MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_int_t expiry = args[ARG_sleep_ms].u_int; + + if (expiry != 0) { + esp_sleep_enable_timer_wakeup(expiry * 1000); + } + + if (machine_rtc_config.ext0_pin != -1) { + esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0); + } + + if (machine_rtc_config.ext1_pins != 0) { + esp_sleep_enable_ext1_wakeup( + machine_rtc_config.ext1_pins, + machine_rtc_config.ext1_level ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW); + } + + if (machine_rtc_config.wake_on_touch) { + esp_sleep_enable_touchpad_wakeup(); + } + + esp_deep_sleep_start(); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_deepsleep_obj, 0, machine_deepsleep); + + +STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + enum {ARG_sleep_ms}; + const mp_arg_t allowed_args[] = { + { MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_int_t expiry = args[ARG_sleep_ms].u_int; + + if (expiry != 0) { + esp_sleep_enable_timer_wakeup(expiry * 1000); + } + + esp_light_sleep_start(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_lightsleep_obj, 0, machine_lightsleep); + + STATIC mp_obj_t machine_reset(void) { esp_restart(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); +STATIC mp_obj_t machine_reset_cause(void) { + return mp_obj_new_int(reset_cause); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); + STATIC mp_obj_t machine_unique_id(void) { uint8_t chipid[6]; esp_efuse_mac_get_default(chipid); @@ -105,6 +183,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, @@ -121,9 +202,28 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + + // These are conflated, unfortunately + // https://github.com/espressif/esp-idf/issues/494#issuecomment-291921540 + // + // Per @igrr: + // "ESP32 doesn't have a dedicated reset line, instead CHIP_PU pin is + // used both as a power down pin and a reset pin. So a low pulse on + // CHIP_PU is equivalent to a power off followed by power on. + // This is why an external reset is logged as a power on reset." + + { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(POWERON_RESET) }, + { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(POWERON_RESET) }, + { MP_ROM_QSTR(MP_QSTR_CPU_RESET), MP_ROM_INT(RTCWDT_CPU_RESET) }, + { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(TG0WDT_SYS_RESET) }, + { MP_ROM_QSTR(MP_QSTR_RTC_RESET), MP_ROM_INT(RTCWDT_RTC_RESET) }, + { MP_ROM_QSTR(MP_QSTR_SW_CPU_RESET), MP_ROM_INT(SW_CPU_RESET) }, + { MP_ROM_QSTR(MP_QSTR_EXT_CPU_RESET),MP_ROM_INT(EXT_CPU_RESET) }, + { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(SW_RESET) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 58229007d..88e5492ae 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -3,12 +3,15 @@ #include "py/obj.h" +void machine_init(); + extern const mp_obj_type_t machine_timer_type; extern const mp_obj_type_t machine_wdt_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_touchpad_type; extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_dac_type; +extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_uart_type; From 73834d1c583214f3ea9b50cbd800b9b3629b7ec4 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 20 Nov 2017 19:41:25 +0100 Subject: [PATCH 2/2] ntptime should use the same time tuple as time.localtime() --- ports/esp8266/modules/ntptime.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/esp8266/modules/ntptime.py b/ports/esp8266/modules/ntptime.py index a97e08e60..92c113119 100644 --- a/ports/esp8266/modules/ntptime.py +++ b/ports/esp8266/modules/ntptime.py @@ -31,6 +31,5 @@ def settime(): import machine import utime tm = utime.localtime(t) - tm = tm[0:3] + (0,) + tm[3:6] + (0,) - machine.RTC().datetime(tm) + machine.RTC.datetime(tm) print(utime.localtime())