From 3b51b3e90f1d513031ad2c6b6a2a0d5d391f753d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 7 Jan 2015 23:38:50 +0000 Subject: [PATCH] stmhal: Collect all root pointers together in 1 place. A GC in stmhal port now only scans true root pointers, not entire BSS. This reduces base GC time from 1700ms to 900ms. --- esp8266/mpconfigport.h | 5 +++++ stmhal/extint.c | 49 ++++++++++++++++-------------------------- stmhal/extint.h | 4 ++-- stmhal/gccollect.c | 33 ++++++++++++---------------- stmhal/main.c | 21 ++++++++---------- stmhal/modpyb.c | 9 ++++---- stmhal/mpconfigport.h | 28 ++++++++++++++++++++++++ stmhal/pendsv.c | 5 ++++- stmhal/pin.c | 22 +++++++++---------- stmhal/pybstdio.c | 16 ++++++-------- stmhal/readline.c | 21 ++++++++---------- stmhal/timer.c | 12 +++++------ stmhal/uart.c | 21 ++++++++---------- stmhal/usb.c | 9 ++++---- stmhal/usrsw.c | 17 +++++---------- teensy/mpconfigport.h | 8 +++++++ 16 files changed, 142 insertions(+), 138 deletions(-) diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index fbf77f645c..7d1d6e1b7b 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -61,6 +61,11 @@ extern const struct _mp_obj_module_t pyb_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; + // We need to provide a declaration/definition of alloca() #include diff --git a/stmhal/extint.c b/stmhal/extint.c index 78bc17be0f..40254ac4dd 100644 --- a/stmhal/extint.c +++ b/stmhal/extint.c @@ -28,8 +28,6 @@ #include #include -#include - #include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" @@ -101,13 +99,7 @@ typedef struct { mp_int_t line; } extint_obj_t; -typedef struct { - mp_obj_t callback_obj; - void *param; - uint32_t mode; -} extint_vector_t; - -STATIC extint_vector_t extint_vector[EXTI_NUM_VECTORS]; +STATIC uint32_t pyb_extint_mode[EXTI_NUM_VECTORS]; #if !defined(ETH) #define ETH_WKUP_IRQn 62 // The 405 doesn't have ETH, but we want a value to put in our table @@ -123,10 +115,7 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { // Set override_callback_obj to true if you want to unconditionally set the // callback function. -// -// NOTE: param is for C callers. Python can use closure to get an object bound -// with the function. -uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj, void *param) { +uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj) { const pin_obj_t *pin = NULL; uint v_line; @@ -159,22 +148,21 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid ExtInt Pull: %d", pull)); } - extint_vector_t *v = &extint_vector[v_line]; - if (!override_callback_obj && v->callback_obj != mp_const_none && callback_obj != mp_const_none) { + mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[v_line]; + if (!override_callback_obj && *cb != mp_const_none && callback_obj != mp_const_none) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ExtInt vector %d is already in use", v_line)); } - // We need to update callback and param atomically, so we disable the line + // We need to update callback atomically, so we disable the line // before we update anything. extint_disable(v_line); - v->callback_obj = callback_obj; - v->param = param; - v->mode = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 + *cb = callback_obj; + pyb_extint_mode[v_line] = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 EXTI_Mode_Interrupt : EXTI_Mode_Event; - if (v->callback_obj != mp_const_none) { + if (*cb != mp_const_none) { GPIO_InitTypeDef exti; exti.Pin = pin->pin_mask; @@ -199,7 +187,7 @@ void extint_enable(uint line) { // Since manipulating IMR/EMR is a read-modify-write, and we want this to // be atomic, we use the bit-band area to just affect the bit we're // interested in. - EXTI_MODE_BB(extint_vector[line].mode, line) = 1; + EXTI_MODE_BB(pyb_extint_mode[line], line) = 1; } void extint_disable(uint line) { @@ -303,7 +291,7 @@ STATIC mp_obj_t extint_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_ extint_obj_t *self = m_new_obj(extint_obj_t); self->base.type = type_in; - self->line = extint_register(vals[0].u_obj, vals[1].u_int, vals[2].u_int, vals[3].u_obj, false, NULL); + self->line = extint_register(vals[0].u_obj, vals[1].u_int, vals[2].u_int, vals[3].u_obj, false); return self; } @@ -343,11 +331,10 @@ const mp_obj_type_t extint_type = { }; void extint_init0(void) { - for (extint_vector_t *v = extint_vector; v < &extint_vector[EXTI_NUM_VECTORS]; v++) { - v->callback_obj = mp_const_none; - v->param = NULL; - v->mode = EXTI_Mode_Interrupt; - } + for (int i = 0; i < PYB_EXTI_NUM_VECTORS; i++) { + MP_STATE_PORT(pyb_extint_callback)[i] = mp_const_none; + pyb_extint_mode[i] = EXTI_Mode_Interrupt; + } } // Interrupt handler @@ -355,18 +342,18 @@ void Handle_EXTI_Irq(uint32_t line) { if (__HAL_GPIO_EXTI_GET_FLAG(1 << line)) { __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); if (line < EXTI_NUM_VECTORS) { - extint_vector_t *v = &extint_vector[line]; - if (v->callback_obj != mp_const_none) { + mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; + if (*cb != mp_const_none) { // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_call_function_1(v->callback_obj, MP_OBJ_NEW_SMALL_INT(line)); + mp_call_function_1(*cb, MP_OBJ_NEW_SMALL_INT(line)); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. - v->callback_obj = mp_const_none; + *cb = mp_const_none; extint_disable(line); printf("Uncaught exception in ExtInt interrupt handler line %lu\n", line); mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); diff --git a/stmhal/extint.h b/stmhal/extint.h index cae23959cf..6eb2137414 100644 --- a/stmhal/extint.h +++ b/stmhal/extint.h @@ -37,7 +37,7 @@ #define EXTI_RTC_TIMESTAMP (21) #define EXTI_RTC_WAKEUP (22) -#define EXTI_NUM_VECTORS (23) +#define EXTI_NUM_VECTORS (PYB_EXTI_NUM_VECTORS) #define EXTI_MODE_INTERRUPT (offsetof(EXTI_TypeDef, IMR)) #define EXTI_MODE_EVENT (offsetof(EXTI_TypeDef, EMR)) @@ -48,7 +48,7 @@ void extint_init0(void); -uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj, void *param); +uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj); void extint_enable(uint line); void extint_disable(uint line); diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c index fcbe10fec1..de76b71ac1 100644 --- a/stmhal/gccollect.c +++ b/stmhal/gccollect.c @@ -30,24 +30,19 @@ #include "py/obj.h" #include "py/gc.h" #include "gccollect.h" -#include MICROPY_HAL_H +#include "systick.h" mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs); -// obsolete -// void gc_helper_get_regs_and_clean_stack(mp_uint_t *regs, mp_uint_t heap_end); - void gc_collect(void) { // get current time, in case we want to time the GC - uint32_t start = HAL_GetTick(); + #if 0 + uint32_t start = sys_tick_get_microseconds(); + #endif // start the GC gc_collect_start(); - // We need to scan everything in RAM that can hold a pointer. - // The data segment is used, but should not contain pointers, so we just scan the bss. - gc_collect_root((void**)&_sbss, ((uint32_t)&_ebss - (uint32_t)&_sbss) / sizeof(uint32_t)); - // get the registers and the sp mp_uint_t regs[10]; mp_uint_t sp = gc_helper_get_regs_and_sp(regs); @@ -58,14 +53,14 @@ void gc_collect(void) { // end the GC gc_collect_end(); - if (0) { - // print GC info - uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly - gc_info_t info; - gc_info(&info); - printf("GC@%lu %lums\n", start, ticks); - printf(" " UINT_FMT " total\n", info.total); - printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); - printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); - } + #if 0 + // print GC info + uint32_t ticks = sys_tick_get_microseconds() - start; + gc_info_t info; + gc_info(&info); + printf("GC@%lu %lums\n", start, ticks); + printf(" " UINT_FMT " total\n", info.total); + printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); + printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); + #endif } diff --git a/stmhal/main.c b/stmhal/main.c index ae5c94b531..d78e5529f0 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -112,12 +112,9 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c } #endif -STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; -STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL; - STATIC mp_obj_t pyb_main(mp_obj_t main) { if (MP_OBJ_IS_STR(main)) { - pyb_config_main = main; + MP_STATE_PORT(pyb_config_main) = main; } return mp_const_none; } @@ -125,7 +122,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main); STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) { if (MP_OBJ_IS_STR(usb_mode)) { - pyb_config_usb_mode = usb_mode; + MP_STATE_PORT(pyb_config_usb_mode) = usb_mode; } return mp_const_none; } @@ -303,7 +300,7 @@ soft_reset: pyb_stdio_uart = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args); } #else - pyb_stdio_uart = NULL; + MP_STATE_PORT(pyb_stdio_uart) = NULL; #endif // Initialise low-level sub-systems. Here we need to very basic things like @@ -444,8 +441,8 @@ soft_reset: #endif // reset config variables; they should be set by boot.py - pyb_config_main = MP_OBJ_NULL; - pyb_config_usb_mode = MP_OBJ_NULL; + MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL; + MP_STATE_PORT(pyb_config_usb_mode) = MP_OBJ_NULL; // run boot.py, if it exists // TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py @@ -479,8 +476,8 @@ soft_reset: // USB device usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC; // if we are not in reset_mode==1, this config variable will always be NULL - if (pyb_config_usb_mode != MP_OBJ_NULL) { - if (strcmp(mp_obj_str_get_str(pyb_config_usb_mode), "CDC+HID") == 0) { + if (MP_STATE_PORT(pyb_config_usb_mode) != MP_OBJ_NULL) { + if (strcmp(mp_obj_str_get_str(MP_STATE_PORT(pyb_config_usb_mode)), "CDC+HID") == 0) { usb_mode = USB_DEVICE_MODE_CDC_HID; } } @@ -509,10 +506,10 @@ soft_reset: // Run the main script from the current directory. if (reset_mode == 1 && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { const char *main_py; - if (pyb_config_main == MP_OBJ_NULL) { + if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) { main_py = "main.py"; } else { - main_py = mp_obj_str_get_str(pyb_config_main); + main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } FRESULT res = f_stat(main_py, NULL); if (res == FR_OK) { diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 91b9464713..64712ad300 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -29,6 +29,7 @@ #include "stm32f4xx_hal.h" +#include "py/mpstate.h" #include "py/nlr.h" #include "py/obj.h" #include "py/gc.h" @@ -475,16 +476,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc); /// Get or set the UART object that the REPL is repeated on. STATIC mp_obj_t pyb_repl_uart(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 0) { - if (pyb_stdio_uart == NULL) { + if (MP_STATE_PORT(pyb_stdio_uart) == NULL) { return mp_const_none; } else { - return pyb_stdio_uart; + return MP_STATE_PORT(pyb_stdio_uart); } } else { if (args[0] == mp_const_none) { - pyb_stdio_uart = NULL; + MP_STATE_PORT(pyb_stdio_uart) = NULL; } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) { - pyb_stdio_uart = args[0]; + MP_STATE_PORT(pyb_stdio_uart) = args[0]; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "need a UART object")); } diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index d75102df36..15d84e85fd 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -122,6 +122,34 @@ extern const struct _mp_obj_module_t mp_module_network; { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_stm), (mp_obj_t)&stm_module }, \ +#define PYB_EXTI_NUM_VECTORS (23) + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; \ + \ + mp_obj_t mp_const_vcp_interrupt; \ + \ + mp_obj_t pyb_config_main; \ + mp_obj_t pyb_config_usb_mode; \ + \ + mp_obj_t pyb_switch_callback; \ + \ + mp_obj_t pin_class_mapper; \ + mp_obj_t pin_class_map_dict; \ + \ + mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ + \ + /* Used to do callbacks to Python code on interrupt */ \ + struct _pyb_timer_obj_t *pyb_timer_obj_all[14]; \ + \ + /* stdio is repeated on this UART object if it's not null */ \ + struct _pyb_uart_obj_t *pyb_stdio_uart; \ + \ + /* pointers to all UART objects (if they have been created) */ \ + struct _pyb_uart_obj_t *pyb_uart_obj_all[6]; \ + // type definitions for the specific machine #define BYTES_PER_WORD (4) diff --git a/stmhal/pendsv.c b/stmhal/pendsv.c index d7104d8518..68455b2752 100644 --- a/stmhal/pendsv.c +++ b/stmhal/pendsv.c @@ -31,7 +31,10 @@ #include "py/runtime.h" #include "pendsv.h" -static void *pendsv_object = NULL; +// Note: this can contain point to the heap but is not traced by GC. +// This is okay because we only ever set it to mp_const_vcp_interrupt +// which is in the root-pointer set. +STATIC void *pendsv_object; void pendsv_init(void) { // set PendSV interrupt at lowest priority diff --git a/stmhal/pin.c b/stmhal/pin.c index 91d5d916da..0d28ffd54d 100644 --- a/stmhal/pin.c +++ b/stmhal/pin.c @@ -91,13 +91,11 @@ /// how a particular object gets mapped to a pin. // Pin class variables -STATIC mp_obj_t pin_class_mapper; -STATIC mp_obj_t pin_class_map_dict; STATIC bool pin_class_debug; void pin_init0(void) { - pin_class_mapper = mp_const_none; - pin_class_map_dict = mp_const_none; + MP_STATE_PORT(pin_class_mapper) = mp_const_none; + MP_STATE_PORT(pin_class_map_dict) = mp_const_none; pin_class_debug = false; } @@ -116,8 +114,8 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { return pin_obj; } - if (pin_class_mapper != mp_const_none) { - pin_obj = mp_call_function_1(pin_class_mapper, user_obj); + if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) { + pin_obj = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj); if (pin_obj != mp_const_none) { if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object")); @@ -135,8 +133,8 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { // other lookup methods. } - if (pin_class_map_dict != mp_const_none) { - mp_map_t *pin_map_map = mp_obj_dict_get_map(pin_class_map_dict); + if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) { + mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict)); mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); if (elem != NULL && elem->value != NULL) { pin_obj = elem->value; @@ -266,10 +264,10 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, /// Get or set the pin mapper function. STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { - pin_class_mapper = args[1]; + MP_STATE_PORT(pin_class_mapper) = args[1]; return mp_const_none; } - return pin_class_mapper; + return MP_STATE_PORT(pin_class_mapper); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun_obj); @@ -278,10 +276,10 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun /// Get or set the pin mapper dictionary. STATIC mp_obj_t pin_map_dict(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { - pin_class_map_dict = args[1]; + MP_STATE_PORT(pin_class_map_dict) = args[1]; return mp_const_none; } - return pin_class_map_dict; + return MP_STATE_PORT(pin_class_map_dict); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj); diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c index 5597bbd689..d8ccc1be0a 100644 --- a/stmhal/pybstdio.c +++ b/stmhal/pybstdio.c @@ -29,6 +29,7 @@ #include #include +#include "py/mpstate.h" #include "py/obj.h" #include "py/stream.h" #include "usb.h" @@ -40,16 +41,13 @@ // be changed by Python code. This requires some changes, as these // objects are in a read-only module (py/modsys.c). -// stdio is repeated on this UART object if it's not null -pyb_uart_obj_t *pyb_stdio_uart = NULL; - void stdout_tx_str(const char *str) { stdout_tx_strn(str, strlen(str)); } void stdout_tx_strn(const char *str, mp_uint_t len) { - if (pyb_stdio_uart != PYB_UART_NONE) { - uart_tx_strn(pyb_stdio_uart, str, len); + if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { + uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); } #if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_strn(str, len); @@ -61,8 +59,8 @@ void stdout_tx_strn(const char *str, mp_uint_t len) { void stdout_tx_strn_cooked(const char *str, mp_uint_t len) { // send stdout to UART and USB CDC VCP - if (pyb_stdio_uart != PYB_UART_NONE) { - uart_tx_strn_cooked(pyb_stdio_uart, str, len); + if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { + uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len); } if (usb_vcp_is_enabled()) { usb_vcp_send_strn_cooked(str, len); @@ -84,8 +82,8 @@ int stdin_rx_chr(void) { byte c; if (usb_vcp_recv_byte(&c) != 0) { return c; - } else if (pyb_stdio_uart != PYB_UART_NONE && uart_rx_any(pyb_stdio_uart)) { - return uart_rx_char(pyb_stdio_uart); + } else if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { + return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } __WFI(); } diff --git a/stmhal/readline.c b/stmhal/readline.c index aa9194a035..ee2e8ebdae 100644 --- a/stmhal/readline.c +++ b/stmhal/readline.c @@ -28,8 +28,7 @@ #include #include -#include "py/mpconfig.h" -#include "py/misc.h" +#include "py/mpstate.h" #include "readline.h" #include "pybstdio.h" @@ -40,14 +39,12 @@ #define DEBUG_printf(...) (void)0 #endif -#define READLINE_HIST_SIZE (8) - -static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +#define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist))) enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O }; void readline_init0(void) { - memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char*)); + memset(MP_STATE_PORT(readline_hist), 0, READLINE_HIST_SIZE * sizeof(const char*)); } STATIC char *str_dup_maybe(const char *str) { @@ -89,15 +86,15 @@ int readline(vstr_t *line, const char *prompt) { } else if (c == '\r') { // newline stdout_tx_str("\r\n"); - if (line->len > orig_line_len && (readline_hist[0] == NULL || strcmp(readline_hist[0], line->buf + orig_line_len) != 0)) { + if (line->len > orig_line_len && (MP_STATE_PORT(readline_hist)[0] == NULL || strcmp(MP_STATE_PORT(readline_hist)[0], line->buf + orig_line_len) != 0)) { // a line which is not empty and different from the last one // so update the history char *most_recent_hist = str_dup_maybe(line->buf + orig_line_len); if (most_recent_hist != NULL) { for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { - readline_hist[i] = readline_hist[i - 1]; + MP_STATE_PORT(readline_hist)[i] = MP_STATE_PORT(readline_hist)[i - 1]; } - readline_hist[0] = most_recent_hist; + MP_STATE_PORT(readline_hist)[0] = most_recent_hist; } } return 0; @@ -139,12 +136,12 @@ int readline(vstr_t *line, const char *prompt) { escape_seq = ESEQ_NONE; if (c == 'A') { // up arrow - if (hist_cur + 1 < READLINE_HIST_SIZE && readline_hist[hist_cur + 1] != NULL) { + if (hist_cur + 1 < READLINE_HIST_SIZE && MP_STATE_PORT(readline_hist)[hist_cur + 1] != NULL) { // increase hist num hist_cur += 1; // set line to history line->len = orig_line_len; - vstr_add_str(line, readline_hist[hist_cur]); + vstr_add_str(line, MP_STATE_PORT(readline_hist)[hist_cur]); // set redraw parameters redraw_step_back = cursor_pos - orig_line_len; redraw_from_cursor = true; @@ -158,7 +155,7 @@ int readline(vstr_t *line, const char *prompt) { // set line to history vstr_cut_tail_bytes(line, line->len - orig_line_len); if (hist_cur >= 0) { - vstr_add_str(line, readline_hist[hist_cur]); + vstr_add_str(line, MP_STATE_PORT(readline_hist)[hist_cur]); } // set redraw parameters redraw_step_back = cursor_pos - orig_line_len; diff --git a/stmhal/timer.c b/stmhal/timer.c index 7adb98c826..87239a5b8f 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -145,9 +145,7 @@ TIM_HandleTypeDef TIM6_Handle; // Used to divide down TIM3 and periodically call the flash storage IRQ STATIC uint32_t tim3_counter = 0; -// Used to do callbacks to Python code on interrupt -STATIC pyb_timer_obj_t *pyb_timer_obj_all[14]; -#define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(pyb_timer_obj_all) +#define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(MP_STATE_PORT(pyb_timer_obj_all)) STATIC uint32_t timer_get_source_freq(uint32_t tim_id); STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in); @@ -157,14 +155,14 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback); void timer_init0(void) { tim3_counter = 0; for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { - pyb_timer_obj_all[i] = NULL; + MP_STATE_PORT(pyb_timer_obj_all)[i] = NULL; } } // unregister all interrupt sources void timer_deinit(void) { for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { - pyb_timer_obj_t *tim = pyb_timer_obj_all[i]; + pyb_timer_obj_t *tim = MP_STATE_PORT(pyb_timer_obj_all)[i]; if (tim != NULL) { pyb_timer_deinit(tim); } @@ -659,7 +657,7 @@ STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t // set the global variable for interrupt callbacks if (tim->tim_id - 1 < PYB_TIMER_OBJ_ALL_NUM) { - pyb_timer_obj_all[tim->tim_id - 1] = tim; + MP_STATE_PORT(pyb_timer_obj_all)[tim->tim_id - 1] = tim; } return (mp_obj_t)tim; @@ -1253,7 +1251,7 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o void timer_irq_handler(uint tim_id) { if (tim_id - 1 < PYB_TIMER_OBJ_ALL_NUM) { // get the timer object - pyb_timer_obj_t *tim = pyb_timer_obj_all[tim_id - 1]; + pyb_timer_obj_t *tim = MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1]; if (tim == NULL) { // Timer object has not been set, so we can't do anything. diff --git a/stmhal/uart.c b/stmhal/uart.c index 98be745938..23eba45b87 100644 --- a/stmhal/uart.c +++ b/stmhal/uart.c @@ -90,21 +90,18 @@ struct _pyb_uart_obj_t { byte *read_buf; // byte or uint16_t, depending on char size }; -// pointers to all UART objects (if they have been created) -STATIC pyb_uart_obj_t *pyb_uart_obj_all[6]; - STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in); void uart_init0(void) { - for (int i = 0; i < MP_ARRAY_SIZE(pyb_uart_obj_all); i++) { - pyb_uart_obj_all[i] = NULL; + for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) { + MP_STATE_PORT(pyb_uart_obj_all)[i] = NULL; } } // unregister all interrupt sources void uart_deinit(void) { - for (int i = 0; i < MP_ARRAY_SIZE(pyb_uart_obj_all); i++) { - pyb_uart_obj_t *uart_obj = pyb_uart_obj_all[i]; + for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) { + pyb_uart_obj_t *uart_obj = MP_STATE_PORT(pyb_uart_obj_all)[i]; if (uart_obj != NULL) { pyb_uart_deinit(uart_obj); } @@ -302,7 +299,7 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) { // this IRQ handler is set up to handle RXNE interrupts only void uart_irq_handler(mp_uint_t uart_id) { // get the uart object - pyb_uart_obj_t *self = pyb_uart_obj_all[uart_id - 1]; + pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; if (self == NULL) { // UART object has not been set, so we can't do anything, not @@ -502,21 +499,21 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t } } else { uart_id = mp_obj_get_int(args[0]); - if (uart_id < 1 || uart_id > MP_ARRAY_SIZE(pyb_uart_obj_all)) { + if (uart_id < 1 || uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all))) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id)); } } pyb_uart_obj_t *self; - if (pyb_uart_obj_all[uart_id - 1] == NULL) { + if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) { // create new UART object self = m_new0(pyb_uart_obj_t, 1); self->base.type = &pyb_uart_type; self->uart_id = uart_id; - pyb_uart_obj_all[uart_id - 1] = self; + MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] = self; } else { // reference existing UART object - self = pyb_uart_obj_all[uart_id - 1]; + self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; } if (n_args > 1 || n_kw > 0) { diff --git a/stmhal/usb.c b/stmhal/usb.c index 50a5a7420d..0bda0aaeb2 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -45,12 +45,11 @@ USBD_HandleTypeDef hUSBDDevice; #endif STATIC int dev_is_enabled = 0; -STATIC mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL; void pyb_usb_init0(void) { // create an exception object for interrupting by VCP - mp_const_vcp_interrupt = mp_obj_new_exception(&mp_type_KeyboardInterrupt); - USBD_CDC_SetInterrupt(-1, mp_const_vcp_interrupt); + MP_STATE_PORT(mp_const_vcp_interrupt) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); + USBD_CDC_SetInterrupt(-1, MP_STATE_PORT(mp_const_vcp_interrupt)); } void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) { @@ -102,9 +101,9 @@ bool usb_vcp_is_connected(void) { void usb_vcp_set_interrupt_char(int c) { if (dev_is_enabled) { if (c != -1) { - mp_obj_exception_clear_traceback(mp_const_vcp_interrupt); + mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_const_vcp_interrupt)); } - USBD_CDC_SetInterrupt(c, mp_const_vcp_interrupt); + USBD_CDC_SetInterrupt(c, MP_STATE_PORT(mp_const_vcp_interrupt)); } } diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c index 69a636ceac..b6320054a1 100644 --- a/stmhal/usrsw.c +++ b/stmhal/usrsw.c @@ -26,8 +26,6 @@ #include -#include "stm32f4xx_hal.h" - #include "py/runtime.h" #include "extint.h" #include "pin.h" @@ -73,10 +71,9 @@ int switch_get(void) { typedef struct _pyb_switch_obj_t { mp_obj_base_t base; - mp_obj_t callback; } pyb_switch_obj_t; -STATIC pyb_switch_obj_t pyb_switch_obj; +STATIC const pyb_switch_obj_t pyb_switch_obj = {{&pyb_switch_type}}; void pyb_switch_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, "Switch()"); @@ -88,9 +85,6 @@ STATIC mp_obj_t pyb_switch_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_ // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); - // init the switch object - pyb_switch_obj.base.type = &pyb_switch_type; - // No need to clear the callback member: if it's already been set and registered // with extint then we don't want to reset that behaviour. If it hasn't been set, // then no extint will be called until it is set via the callback method. @@ -108,8 +102,8 @@ mp_obj_t pyb_switch_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, con } STATIC mp_obj_t switch_callback(mp_obj_t line) { - if (pyb_switch_obj.callback != mp_const_none) { - mp_call_function_0(pyb_switch_obj.callback); + if (MP_STATE_PORT(pyb_switch_callback) != mp_const_none) { + mp_call_function_0(MP_STATE_PORT(pyb_switch_callback)); } return mp_const_none; } @@ -119,8 +113,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(switch_callback_obj, switch_callback); /// Register the given function to be called when the switch is pressed down. /// If `fun` is `None`, then it disables the callback. mp_obj_t pyb_switch_callback(mp_obj_t self_in, mp_obj_t callback) { - pyb_switch_obj_t *self = self_in; - self->callback = callback; + MP_STATE_PORT(pyb_switch_callback) = callback; // Init the EXTI each time this function is called, since the EXTI // may have been disabled by an exception in the interrupt, or the // user disabling the line explicitly. @@ -128,7 +121,7 @@ mp_obj_t pyb_switch_callback(mp_obj_t self_in, mp_obj_t callback) { MICROPY_HW_USRSW_EXTI_MODE, MICROPY_HW_USRSW_PULL, callback == mp_const_none ? mp_const_none : (mp_obj_t)&switch_callback_obj, - true, NULL); + true); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_switch_callback_obj, pyb_switch_callback); diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h index efe51fecda..63f0ee7b70 100644 --- a/teensy/mpconfigport.h +++ b/teensy/mpconfigport.h @@ -44,6 +44,14 @@ extern const struct _mp_obj_module_t time_module; #define MICROPY_PORT_CONSTANTS \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; \ + mp_obj_t pin_class_mapper; \ + mp_obj_t pin_class_map_dict; \ + struct _pyb_uart_obj_t *pyb_stdio_uart; \ + // type definitions for the specific machine #define BYTES_PER_WORD (4)