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.
This commit is contained in:
Damien George 2015-01-07 23:38:50 +00:00
parent 7a0636e80a
commit 3b51b3e90f
16 changed files with 142 additions and 138 deletions

View File

@ -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 <alloca.h>

View File

@ -28,8 +28,6 @@
#include <stddef.h>
#include <string.h>
#include <stm32f4xx_hal.h>
#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);

View File

@ -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);

View File

@ -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
}

View File

@ -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) {

View File

@ -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"));
}

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -29,6 +29,7 @@
#include <string.h>
#include <errno.h>
#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();
}

View File

@ -28,8 +28,7 @@
#include <stdint.h>
#include <string.h>
#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;

View File

@ -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.

View File

@ -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) {

View File

@ -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));
}
}

View File

@ -26,8 +26,6 @@
#include <stdio.h>
#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);

View File

@ -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)