From e1a4d569933c2a58966126cad57dec99f3bbaa7b Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 26 Mar 2022 11:55:56 +0000 Subject: [PATCH 1/4] Badger2040: Read the button state and enable 3v3 before initializing crystal --- micropython/modules/badger2040/badger2040.cpp | 27 ++++++--------- micropython/modules/badger2040/badgerinit.S | 34 +++++++++++++++++++ .../modules/badger2040/micropython.cmake | 3 +- 3 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 micropython/modules/badger2040/badgerinit.S diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index 3bc58031..de2f902d 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -4,41 +4,34 @@ #define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) +extern "C" uint32_t badger_gpio_on_wake; + namespace { struct Badger2040_WakeUpInit { Badger2040_WakeUpInit() - : state(gpio_get_all() & (0x1f << pimoroni::Badger2040::DOWN)) // Record state of front buttons { - gpio_set_function(pimoroni::Badger2040::ENABLE_3V3, GPIO_FUNC_SIO); - gpio_set_dir(pimoroni::Badger2040::ENABLE_3V3, GPIO_OUT); - gpio_put(pimoroni::Badger2040::ENABLE_3V3, 1); - - gpio_set_function(pimoroni::Badger2040::LED, GPIO_FUNC_SIO); - gpio_set_dir(pimoroni::Badger2040::LED, GPIO_OUT); - gpio_put(pimoroni::Badger2040::LED, 1); + // Only keep the front buttons + badger_gpio_on_wake &= 0x1f << pimoroni::Badger2040::DOWN; } bool any() const { - return state > 0; + return badger_gpio_on_wake > 0; } bool get(uint32_t pin) const { - return state & (0b1 << pin); + return badger_gpio_on_wake & (0b1 << pin); } bool get_once(uint32_t pin) { uint32_t mask = 0b1 << pin; - bool value = state & mask; - state &= ~mask; + bool value = badger_gpio_on_wake & mask; + badger_gpio_on_wake &= ~mask; return value; } - void clear() { state = 0; } - - private: - uint32_t state; + void clear() { badger_gpio_on_wake = 0; } }; - Badger2040_WakeUpInit button_wake_state __attribute__ ((init_priority (101))); + Badger2040_WakeUpInit button_wake_state; }; extern "C" { diff --git a/micropython/modules/badger2040/badgerinit.S b/micropython/modules/badger2040/badgerinit.S new file mode 100644 index 00000000..4a79d737 --- /dev/null +++ b/micropython/modules/badger2040/badgerinit.S @@ -0,0 +1,34 @@ + +.syntax unified +.cpu cortex-m0plus +.thumb + +#include "pico/asm_helper.S" + +__pre_init __badger_init, 00003 + +.section .data.badger_init +.global badger_gpio_on_wake +.align 4 +badger_gpio_on_wake: +.word 0x00000000 + +.section .text +.thumb_func +__badger_init: + // Read GPIO state and store + movs r3, 0xd0 + lsls r3, r3, 24 + ldr r1, [r3, 4] + ldr r2, =badger_gpio_on_wake + str r1, [r2] + + // Enable 3v3 pin on the badger + ldr r1, =0x40014054 // GPIO control register 10 + movs r2, 5 // SIO function + str r2, [r1] // Set Enable 3v3 to SIO + str r2, [r1, 120] // Also set LED (25) to SIO + ldr r2, =0x02000400 // Pins 25 and 10 + str r2, [r3, 36] // Enable pins out + str r2, [r3, 20] // Set pins high + bx lr diff --git a/micropython/modules/badger2040/micropython.cmake b/micropython/modules/badger2040/micropython.cmake index 79def714..4ae063de 100644 --- a/micropython/modules/badger2040/micropython.cmake +++ b/micropython/modules/badger2040/micropython.cmake @@ -5,6 +5,7 @@ add_library(usermod_${MOD_NAME} INTERFACE) target_sources(usermod_${MOD_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/badgerinit.S ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/badger2040/badger2040.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/uc8151/uc8151.cpp ) @@ -19,4 +20,4 @@ target_compile_definitions(usermod_${MOD_NAME} INTERFACE MODULE_BADGER2040_ENABLED=1 ) -target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) From 7720bbe6029931cc1689bac238b0805b5717a656 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 26 Mar 2022 12:45:25 +0000 Subject: [PATCH 2/4] Simplify Badger Wake on the C++ side, tidy up X_to_wake on the python interface --- micropython/examples/badger2040/launcher.py | 1 - micropython/modules/badger2040/badger2040.c | 4 -- micropython/modules/badger2040/badger2040.cpp | 63 +++++++------------ micropython/modules/badger2040/badger2040.h | 2 - micropython/modules/badger2040/badgerinit.S | 13 ++-- 5 files changed, 29 insertions(+), 54 deletions(-) diff --git a/micropython/examples/badger2040/launcher.py b/micropython/examples/badger2040/launcher.py index f003a940..2741f45c 100644 --- a/micropython/examples/badger2040/launcher.py +++ b/micropython/examples/badger2040/launcher.py @@ -17,7 +17,6 @@ woken_by_button = badger2040.woken_by_button() # Must be done before we clear_p if badger2040.pressed_to_wake(badger2040.BUTTON_A) and badger2040.pressed_to_wake(badger2040.BUTTON_C): # Pressing A and C together at start quits app exited_to_launcher = badger_os.state_clear_running() - badger2040.clear_pressed_to_wake() else: # Otherwise restore previously running app badger_os.state_launch() diff --git a/micropython/modules/badger2040/badger2040.c b/micropython/modules/badger2040/badger2040.c index 2b42a96a..aa81c828 100644 --- a/micropython/modules/badger2040/badger2040.c +++ b/micropython/modules/badger2040/badger2040.c @@ -16,7 +16,6 @@ MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pen_obj, Badger2040_pen); MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_thickness_obj, Badger2040_thickness); MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pressed_obj, Badger2040_pressed); -MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pressed_to_wake2_obj, Badger2040_pressed_to_wake2); MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_clear_obj, Badger2040_clear); MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_pixel_obj, Badger2040_pixel); MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_line_obj, 4, Badger2040_line); @@ -34,7 +33,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_measure_glyph_obj, 2, Badger2040_measure_g MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_command_obj, Badger2040_command); MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_pressed_to_wake_obj, Badger2040_pressed_to_wake); -MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_clear_pressed_to_wake_obj, Badger2040_clear_pressed_to_wake); MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_halt_obj, Badger2040_halt); MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_woken_by_button_obj, Badger2040_woken_by_button); @@ -55,7 +53,6 @@ STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_thickness), MP_ROM_PTR(&Badger2040_thickness_obj) }, { MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&Badger2040_pressed_obj) }, - { MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake2_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&Badger2040_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&Badger2040_pixel_obj) }, @@ -92,7 +89,6 @@ STATIC const mp_rom_map_elem_t badger2040_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_Badger2040), (mp_obj_t)&Badger2040_type }, { MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake_obj) }, - { MP_ROM_QSTR(MP_QSTR_clear_pressed_to_wake), MP_ROM_PTR(&Badger2040_clear_pressed_to_wake_obj) }, { MP_ROM_QSTR(MP_QSTR_woken_by_button), MP_ROM_PTR(&Badger2040_woken_by_button_obj) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_NORMAL), MP_ROM_INT(0) }, diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index de2f902d..20e7af9e 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -4,41 +4,29 @@ #define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) -extern "C" uint32_t badger_gpio_on_wake; - -namespace { - struct Badger2040_WakeUpInit { - Badger2040_WakeUpInit() - { - // Only keep the front buttons - badger_gpio_on_wake &= 0x1f << pimoroni::Badger2040::DOWN; - } - - bool any() const { - return badger_gpio_on_wake > 0; - } - - bool get(uint32_t pin) const { - return badger_gpio_on_wake & (0b1 << pin); - } - - bool get_once(uint32_t pin) { - uint32_t mask = 0b1 << pin; - bool value = badger_gpio_on_wake & mask; - badger_gpio_on_wake &= ~mask; - return value; - } - void clear() { badger_gpio_on_wake = 0; } - }; - - Badger2040_WakeUpInit button_wake_state; -}; - extern "C" { #include "badger2040.h" #include "py/builtin.h" #include "py/mpthread.h" +extern uint32_t badger_buttons_on_wake; + +bool Badger2040_wake_state_any() { + return badger_buttons_on_wake > 0; +} + +bool Badger2040_wake_state_get(uint32_t pin) { + return badger_buttons_on_wake & (0b1 << pin); +} + +bool Badger2040_wake_state_get_once(uint32_t pin) { + uint32_t mask = 0b1 << pin; + bool value = badger_buttons_on_wake & mask; + badger_buttons_on_wake &= ~mask; + return value; +} + + std::string mp_obj_to_string_r(const mp_obj_t &obj) { if(mp_obj_is_str_or_bytes(obj)) { GET_STR_DATA_LEN(obj, str, str_len); @@ -207,7 +195,7 @@ MICROPY_EVENT_POLL_HOOK } mp_obj_t Badger2040_woken_by_button() { - return button_wake_state.any() ? mp_const_true : mp_const_false; + return Badger2040_wake_state_any() ? mp_const_true : mp_const_false; } mp_obj_t Badger2040_halt(mp_obj_t self_in) { @@ -262,25 +250,16 @@ mp_obj_t Badger2040_thickness(mp_obj_t self_in, mp_obj_t thickness) { mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button) { _Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t); self->badger2040->update_button_states(); - bool wake_state = button_wake_state.get_once(mp_obj_get_int(button)); + bool wake_state = Badger2040_wake_state_get_once(mp_obj_get_int(button)); bool state = self->badger2040->pressed(mp_obj_get_int(button)); return (state || wake_state) ? mp_const_true : mp_const_false; } mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button) { - bool state = button_wake_state.get(mp_obj_get_int(button)); + bool state = Badger2040_wake_state_get(mp_obj_get_int(button)); return state ? mp_const_true : mp_const_false; } -mp_obj_t Badger2040_pressed_to_wake2(mp_obj_t self_in, mp_obj_t button) { - return Badger2040_pressed_to_wake(button); -} - -mp_obj_t Badger2040_clear_pressed_to_wake() { - button_wake_state.clear(); - return mp_const_none; -} - // pressed // pressed_to_wake // wait_for_press - implement in terms of MicroPython! diff --git a/micropython/modules/badger2040/badger2040.h b/micropython/modules/badger2040/badger2040.h index ae08294a..0b6fac44 100644 --- a/micropython/modules/badger2040/badger2040.h +++ b/micropython/modules/badger2040/badger2040.h @@ -24,7 +24,6 @@ extern mp_obj_t Badger2040_pen(mp_obj_t self_in, mp_obj_t color); extern mp_obj_t Badger2040_thickness(mp_obj_t self_in, mp_obj_t thickness); extern mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button); -extern mp_obj_t Badger2040_pressed_to_wake2(mp_obj_t self_in, mp_obj_t button); extern mp_obj_t Badger2040_clear(mp_obj_t self_in); extern mp_obj_t Badger2040_pixel(mp_obj_t self_in, mp_obj_t x, mp_obj_t y); @@ -43,5 +42,4 @@ extern mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data); extern mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button); -extern mp_obj_t Badger2040_clear_pressed_to_wake(); extern mp_obj_t Badger2040_woken_by_button(); diff --git a/micropython/modules/badger2040/badgerinit.S b/micropython/modules/badger2040/badgerinit.S index 4a79d737..dcd49666 100644 --- a/micropython/modules/badger2040/badgerinit.S +++ b/micropython/modules/badger2040/badgerinit.S @@ -8,19 +8,22 @@ __pre_init __badger_init, 00003 .section .data.badger_init -.global badger_gpio_on_wake +.global badger_buttons_on_wake .align 4 -badger_gpio_on_wake: +badger_buttons_on_wake: .word 0x00000000 .section .text .thumb_func __badger_init: - // Read GPIO state and store + // Read GPIO state for front buttons and store movs r3, 0xd0 lsls r3, r3, 24 - ldr r1, [r3, 4] - ldr r2, =badger_gpio_on_wake + ldr r1, [r3, 4] // Read all GPIOs + movs r2, 0b11111 // Mask the front buttons (pins 15-11) + lsls r2, 11 + ands r1, r1, r2 + ldr r2, =badger_buttons_on_wake str r1, [r2] // Enable 3v3 pin on the badger From 4061b446b3f5cb363573d7734fada8fb0524a157 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 26 Mar 2022 12:51:55 +0000 Subject: [PATCH 3/4] Badger2040: Make wake state access methods static --- micropython/modules/badger2040/badger2040.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index 20e7af9e..d928b193 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -11,15 +11,15 @@ extern "C" { extern uint32_t badger_buttons_on_wake; -bool Badger2040_wake_state_any() { +static bool Badger2040_wake_state_any() { return badger_buttons_on_wake > 0; } -bool Badger2040_wake_state_get(uint32_t pin) { +static bool Badger2040_wake_state_get(uint32_t pin) { return badger_buttons_on_wake & (0b1 << pin); } -bool Badger2040_wake_state_get_once(uint32_t pin) { +static bool Badger2040_wake_state_get_once(uint32_t pin) { uint32_t mask = 0b1 << pin; bool value = badger_buttons_on_wake & mask; badger_buttons_on_wake &= ~mask; From 0a11a9f5556f92d450025b02ef37caafaa25da0c Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 26 Mar 2022 12:58:36 +0000 Subject: [PATCH 4/4] Comment why this works --- micropython/modules/badger2040/badgerinit.S | 1 + 1 file changed, 1 insertion(+) diff --git a/micropython/modules/badger2040/badgerinit.S b/micropython/modules/badger2040/badgerinit.S index dcd49666..82142929 100644 --- a/micropython/modules/badger2040/badgerinit.S +++ b/micropython/modules/badger2040/badgerinit.S @@ -5,6 +5,7 @@ #include "pico/asm_helper.S" +// This macro tells the pico runtime to call __badger_init very early in boot __pre_init __badger_init, 00003 .section .data.badger_init