From f868cc5dd02319957500180541281f41ec0d0573 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 24 Nov 2020 23:36:59 -0500 Subject: [PATCH] some API renaming and bug fixes; fix docs --- main.c | 48 ++++++++++++--------- shared-bindings/alarm/__init__.c | 4 +- shared-bindings/alarm/pin/PinAlarm.c | 34 +++++++-------- shared-bindings/alarm/time/DurationAlarm.c | 6 +-- shared-bindings/microcontroller/Processor.c | 4 +- shared-bindings/supervisor/RunReason.c | 2 +- shared-bindings/supervisor/Runtime.c | 2 +- shared-bindings/supervisor/__init__.c | 37 ++++++++-------- 8 files changed, 72 insertions(+), 65 deletions(-) diff --git a/main.c b/main.c index b2e527ddef..10066bd92f 100755 --- a/main.c +++ b/main.c @@ -98,7 +98,7 @@ #endif // How long to wait for host to enumerate (secs). -#define CIRCUITPY_USB_ENUMERATION_DELAY 1 +#define CIRCUITPY_USB_ENUMERATION_DELAY 5 // How long to flash errors on the RGB status LED before going to sleep (secs) #define CIRCUITPY_FLASH_ERROR_PERIOD 10 @@ -319,26 +319,28 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { bool ok = result.return_code != PYEXEC_EXCEPTION; ESP_LOGI("main", "common_hal_alarm_enable_deep_sleep_alarms()"); - // Decide whether to deep sleep. #if CIRCUITPY_ALARM // Enable pin or time alarms before sleeping. common_hal_alarm_enable_deep_sleep_alarms(); #endif - // Normally we won't deep sleep if there was an error or if we are connected to a host - // but either of those can be enabled. - // *********DON'T SLEEP IF USB HASN'T HAD TIME TO ENUMERATE. - bool will_deep_sleep = - (ok || supervisor_workflow_get_allow_deep_sleep_on_error()) && - (!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected()); - ESP_LOGI("main", "ok %d", will_deep_sleep); - ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error()); - ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active()); - ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected()); - will_deep_sleep = false; prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { + // Normally we won't deep sleep if there was an error or if we are connected to a host + // but either of those can be enabled. + // It's ok to deep sleep if we're not connected to a host, but we need to make sure + // we're giving enough time for USB enumeration to happen. + bool deep_sleep_allowed = + (ok || supervisor_workflow_get_allow_deep_sleep_on_error()) && + (!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected()) && + (supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024); + + ESP_LOGI("main", "ok %d", deep_sleep_allowed); + ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error()); + ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active()); + ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected()); + ESP_LOGI("main", "supervisor_ticks_ms64() %lld", supervisor_ticks_ms64()); RUN_BACKGROUND_TASKS; if (reload_requested) { supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD); @@ -360,7 +362,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { print_code_py_status_message(safe_mode); } // We won't be going into the REPL if we're going to sleep. - if (!will_deep_sleep) { + if (!deep_sleep_allowed) { print_safe_mode_message(safe_mode); serial_write("\n"); serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload.")); @@ -379,27 +381,31 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { #endif bool animation_done = false; - if (will_deep_sleep && ok) { + + if (deep_sleep_allowed && ok) { // Skip animation if everything is OK. animation_done = true; } else { animation_done = tick_rgb_status_animation(&animation); } // Do an error animation only once before deep-sleeping. - if (animation_done && will_deep_sleep) { - int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64(); - // If USB isn't enumerated then deep sleep after our waiting period. - if (ok && remaining_enumeration_wait < 0) { + if (animation_done) { + if (deep_sleep_allowed) { common_hal_mcu_deep_sleep(); // Does not return. } + // Wake up every so often to flash the error code. if (!ok) { port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024); } else { - port_interrupt_after_ticks(remaining_enumeration_wait); + int64_t remaining_enumeration_wait = + CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64(); + if (remaining_enumeration_wait > 0) { + port_interrupt_after_ticks(remaining_enumeration_wait); + } + port_sleep_until_interrupt(); } - port_sleep_until_interrupt(); } } } diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 22b2e7f6ab..b6b86c8354 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -38,7 +38,7 @@ //| //| Light sleep leaves the CPU and RAM powered so that CircuitPython can resume where it left off //| after being woken up. CircuitPython automatically goes into a light sleep when `time.sleep()` is -//| called. To light sleep until a non-time alarm use `alarm.sleep_until_alarm()`. Any active +//| called. To light sleep until a non-time alarm use `alarm.sleep_until_alarms()`. Any active //| peripherals, such as I2C, are left on. //| //| Deep sleep shuts down power to nearly all of the chip including the CPU and RAM. This can save @@ -51,7 +51,7 @@ //| //| An error includes an uncaught exception, or sys.exit() called with a non-zero argument //| -//| To set alarms for deep sleep use `alarm.restart_on_alarm()` they will apply to next deep sleep only.""" +//| To set alarms for deep sleep use `alarm.set_deep_sleep_alarms()` they will apply to next deep sleep only.""" //| //| wake_alarm: Alarm //| """The most recent alarm to wake us up from a sleep (light or deep.)""" diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index a2d2e0ab7a..bb48b93c42 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -38,26 +38,26 @@ //| """Trigger an alarm when a pin changes state.""" //| //| def __init__(self, *pins: microcontroller.Pin, value: bool, all_same_value: bool = False, edge: bool = False, pull: bool = False) -> None: -//| """Create an alarm triggered by a `~microcontroller.Pin` level. The alarm is not active -//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or -//| `alarm.restart_on_alarm()`. +//| """Create an alarm triggered by a `microcontroller.Pin` level. The alarm is not active +//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or +//| `alarm.set_deep_sleep_alarms()`. //| -//| :param pins: The pins to monitor. On some ports, the choice of pins -//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. +//| :param microcontroller.Pin \*pins: The pins to monitor. On some ports, the choice of pins +//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. //| :param bool value: When active, trigger when the pin value is high (``True``) or low (``False``). -//| On some ports, multiple `PinAlarm` objects may need to have coordinated values -//| for deep-sleep alarms. -//| :param bool all_same_value: If ``True``, all pins listed must be at `value` to trigger the alarm. -//| If ``False``, any one of the pins going to `value` will trigger the alarm. +//| On some ports, multiple `PinAlarm` objects may need to have coordinated values +//| for deep-sleep alarms. +//| :param bool all_same_value: If ``True``, all pins listed must be at ``value`` to trigger the alarm. +//| If ``False``, any one of the pins going to ``value`` will trigger the alarm. //| :param bool edge: If ``True``, trigger only when there is a transition to the specified -//| value of `value`. If ``True``, if the alarm becomes active when the pin value already -//| matches `value`, the alarm is not triggered: the pin must transition from ``not value`` -//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available, -//| particularly for deep-sleep alarms. -//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to value opposite -//| opposite that of `value`. For instance, if `value` is set to ``True``, setting `pull` -//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal -//| pulls it high. +//| value of ``value``. If ``True``, if the alarm becomes active when the pin value already +//| matches ``value``, the alarm is not triggered: the pin must transition from ``not value`` +//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available, +//| particularly for deep-sleep alarms. +//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to the level opposite +//| opposite that of ``value``. For instance, if ``value`` is set to ``True``, setting ``pull`` +//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal +//| pulls it high. //| """ //| ... //| diff --git a/shared-bindings/alarm/time/DurationAlarm.c b/shared-bindings/alarm/time/DurationAlarm.c index c105bbebf7..6831aba5db 100644 --- a/shared-bindings/alarm/time/DurationAlarm.c +++ b/shared-bindings/alarm/time/DurationAlarm.c @@ -37,10 +37,10 @@ //| """Trigger an alarm at a specified interval from now.""" //| //| def __init__(self, secs: float) -> None: -//| """Create an alarm that will be triggered in `secs` seconds from the time +//| """Create an alarm that will be triggered in ``secs`` seconds from the time //| sleep starts. The alarm is not active until it is listed in an -//| `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or -//| `alarm.restart_on_alarm()`. +//| `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or +//| `alarm.set_deep_sleep_alarms()`. //| """ //| ... //| diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index ea43688213..90cc02fe39 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -67,8 +67,8 @@ const mp_obj_property_t mcu_processor_frequency_obj = { }, }; -//| reset_reason: `microcontroller.ResetReason` -//| """The reason the microcontroller started up from reset state.""" +//| reset_reason: microcontroller.ResetReason +//| """The reason the microcontroller started up from reset state.""" //| STATIC mp_obj_t mcu_processor_get_reset_reason(mp_obj_t self) { return cp_enum_find(&mcu_reset_reason_type, common_hal_mcu_processor_get_reset_reason()); diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index 73f62fed6d..a2a5fe13ef 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -37,7 +37,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| """The reason that CircuitPython started running.""" //| //| STARTUP: object -//| """CircuitPython started the microcontroller started up. See `microcontroller.cpu.reset_reason` +//| """CircuitPython started the microcontroller started up. See `microcontroller.Processor.reset_reason` //| for more detail on why the microcontroller was started.""" //| //| AUTO_RELOAD: object diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 1a283b35c0..8e0259a3b3 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -98,7 +98,7 @@ const mp_obj_property_t supervisor_serial_bytes_available_obj = { //| run_reason: RunReason -//| """Returns why CircuitPython started running this particular time. +//| """Returns why CircuitPython started running this particular time.""" //| STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) { return cp_enum_find(&supervisor_run_reason_type, _run_reason); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index c13b19e48e..9a7890a87d 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -47,18 +47,19 @@ //| This object is the sole instance of `supervisor.Runtime`.""" //| -//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False): -//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur -//| after a program has finished running or when `supervisor.deep_sleep_now()` is called. +//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False) -> None: +//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur +//| after a program has finished running or when `supervisor.exit_and_deep_sleep()` is called. //| -//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep -//| when a program finishes, even if it is connected to a host computer over USB or other means. -//| It will disconnect from the host before sleeping. -//| If ``False``, deep sleep will not be entered if connected. -//| :param bool on_error: If ``True``, deep sleep will be entered if even a program -//| terminated due to an exception or fatal error. If ``False``, an error will cause -//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available. -//| ... +//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep +//| when a program finishes, even if it is connected to a host computer over USB or other means. +//| It will disconnect from the host before sleeping. +//| If ``False``, deep sleep will not be entered if connected. +//| :param bool on_error: If ``True``, deep sleep will be entered if even a program +//| terminated due to an exception or fatal error. If ``False``, an error will cause +//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available. +//| """ +//| ... //| STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_when_connected, ARG_on_error }; @@ -77,16 +78,16 @@ STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_a } MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_allow_deep_sleep_obj, 0, supervisor_allow_deep_sleep); -//| def deep_sleep(): -> None +//| def exit_and_deep_sleep() -> None: //| """Go into deep sleep mode immediately, if not connected to a host computer. -//| But if connected and `supervisor.runtime.allow_deep_sleep(when_connected=true)` -//| has not been called, simply restart. -//| +//| But if connected and ``supervisor.allow_deep_sleep(when_connected=true)`` +//| has not been called, simply restart.""" +//| ... -STATIC mp_obj_t supervisor_deep_sleep(void) { +STATIC mp_obj_t supervisor_exit_and_deep_sleep(void) { common_hal_mcu_deep_sleep(); } -MP_DEFINE_CONST_FUN_OBJ_0(supervisor_deep_sleep_obj, supervisor_deep_sleep); +MP_DEFINE_CONST_FUN_OBJ_0(supervisor_exit_and_deep_sleep_obj, supervisor_exit_and_deep_sleep); //| def enable_autoreload() -> None: //| """Enable autoreload based on USB file write activity.""" @@ -156,7 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_next_stack_limit_obj, supervisor_set_ne STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) }, { MP_ROM_QSTR(MP_QSTR_allow_deep_sleep), MP_ROM_PTR(&supervisor_allow_deep_sleep_obj) }, - { MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&supervisor_deep_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep), MP_ROM_PTR(&supervisor_exit_and_deep_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) }, { MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },