From 9480138f0c917b2400991066e94636f7d8076a4c Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Sun, 24 Aug 2014 12:21:12 -0700 Subject: [PATCH] Add save/restore_irq Factored irq functions into a separate file. --- py/objexcept.c | 4 +-- stmhal/Makefile | 1 + stmhal/irq.c | 74 +++++++++++++++++++++++++++++++++++++++++++ stmhal/irq.h | 36 +++++++++++++++++++++ stmhal/main.c | 8 ----- stmhal/modpyb.c | 27 +--------------- stmhal/mpconfigport.h | 12 +++---- teensy/Makefile | 1 + teensy/modpyb.c | 33 ++----------------- teensy/mpconfigport.h | 6 ++++ teensy/teensy_hal.h | 14 ++++++++ 11 files changed, 144 insertions(+), 72 deletions(-) create mode 100644 stmhal/irq.c create mode 100644 stmhal/irq.h diff --git a/py/objexcept.c b/py/objexcept.c index cddc77bfeb..7f9b219d56 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -88,10 +88,10 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { // Update the 2 variables atomically so that an interrupt can't occur // between the assignments. - MICROPY_BEGIN_ATOMIC_SECTION(); + mp_int_t enabled = MICROPY_BEGIN_ATOMIC_SECTION(); mp_emergency_exception_buf_size = size; mp_emergency_exception_buf = buf; - MICROPY_END_ATOMIC_SECTION(); + MICROPY_END_ATOMIC_SECTION(enabled); if (old_buf != NULL) { m_free(old_buf, old_size); diff --git a/stmhal/Makefile b/stmhal/Makefile index 75f080587f..ba965481a3 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -70,6 +70,7 @@ SRC_C = \ usbd_desc_cdc_msc.c \ usbd_cdc_interface.c \ usbd_msc_storage.c \ + irq.c \ pendsv.c \ systick.c \ timer.c \ diff --git a/stmhal/irq.c b/stmhal/irq.c new file mode 100644 index 0000000000..2d6a990beb --- /dev/null +++ b/stmhal/irq.c @@ -0,0 +1,74 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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 "mpconfig.h" +#include "misc.h" +#include "nlr.h" +#include "qstr.h" +#include "obj.h" +#include "irq.h" + +#include MICROPY_HAL_H + +void enable_irq(mp_int_t enable) { + // With __set_PRIMASK 1 = disable, 0 = enable + __set_PRIMASK(!enable); +} + +mp_int_t disable_irq(void) { + mp_int_t enabled = !__get_PRIMASK(); + __disable_irq(); + return enabled; +} + +/// \function wfi() +/// Wait for an interrupt. +/// This executies a `wfi` instruction which reduces power consumption +/// of the MCU until an interrupt occurs, at which point execution continues. +STATIC mp_obj_t pyb_wfi(void) { + __WFI(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); + +/// \function disable_irq() +/// Disable interrupt requests. +STATIC mp_obj_t pyb_disable_irq(void) { + return MP_BOOL(disable_irq()); +} +MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq); + +/// \function enable_irq() +/// Enable interrupt requests. +STATIC mp_obj_t pyb_enable_irq(uint n_args, const mp_obj_t *arg) { + mp_int_t enabled = true; + if (n_args > 0) { + enabled = mp_obj_is_true(arg[0]); + } + enable_irq(enabled); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq); diff --git a/stmhal/irq.h b/stmhal/irq.h new file mode 100644 index 0000000000..9903a02fa4 --- /dev/null +++ b/stmhal/irq.h @@ -0,0 +1,36 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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. + */ + +// The prototypes for disable_irq/enable_irq are in mpconfigport.h +// Once we switch around to using traitional #include headers, then they +// can be move back into here. + +// mp_int_t disable_irq(void); +// void enable_irq(mp_int_t enabled); + +MP_DECLARE_CONST_FUN_OBJ(pyb_wfi_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_disable_irq_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_enable_irq_obj); diff --git a/stmhal/main.c b/stmhal/main.c index b735f49bca..a34ffab325 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -119,14 +119,6 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c } #endif -void enable_irq(void) { - __enable_irq(); -} - -void disable_irq(void) { - __disable_irq(); -} - STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL; diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index a075cf2c32..de7eac4024 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -36,6 +36,7 @@ #include "obj.h" #include "gc.h" #include "gccollect.h" +#include "irq.h" #include "systick.h" #include "pyexec.h" #include "led.h" @@ -216,32 +217,6 @@ STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay); -/// \function wfi() -/// Wait for an interrupt. -/// This executies a `wfi` instruction which reduces power consumption -/// of the MCU until an interrupt occurs, at which point execution continues. -STATIC mp_obj_t pyb_wfi(void) { - __WFI(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); - -/// \function disable_irq() -/// Disable interrupt requests. -STATIC mp_obj_t pyb_disable_irq(void) { - __disable_irq(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq); - -/// \function enable_irq() -/// Enable interrupt requests. -STATIC mp_obj_t pyb_enable_irq(void) { - __enable_irq(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_enable_irq_obj, pyb_enable_irq); - #if 0 STATIC void SYSCLKConfig_STOP(void) { /* After wake-up from STOP reconfigure the system clock */ diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 5ace34ff18..805d74f996 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -57,12 +57,6 @@ #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) -void enable_irq(void); -void disable_irq(void); - -#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() -#define MICROPY_END_ATOMIC_SECTION() enable_irq() - // extra built in names to add to the global namespace extern const struct _mp_obj_fun_builtin_t mp_builtin_help_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj; @@ -102,6 +96,12 @@ typedef unsigned int mp_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size +mp_int_t disable_irq(void); +void enable_irq(mp_int_t enable); + +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) + // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via // GC heap. Note that MicroPython core never uses malloc() and friends, diff --git a/teensy/Makefile b/teensy/Makefile index c627f2fa60..09bee1dbcd 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -61,6 +61,7 @@ SRC_C = \ STM_SRC_C = $(addprefix stmhal/,\ gccollect.c \ input.c \ + irq.c \ pin.c \ pin_named_pins.c \ printf.c \ diff --git a/teensy/modpyb.c b/teensy/modpyb.c index 81149d89bf..518b93be8f 100644 --- a/teensy/modpyb.c +++ b/teensy/modpyb.c @@ -38,6 +38,7 @@ #include "obj.h" #include "gc.h" #include "gccollect.h" +#include "irq.h" #include "systick.h" #include "pyexec.h" #include "led.h" @@ -181,45 +182,17 @@ STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay); -/// \function wfi() -/// Wait for an interrupt. -/// This executies a `wfi` instruction which reduces power consumption -/// of the MCU until an interrupt occurs, at which point execution continues. -STATIC mp_obj_t pyb_wfi(void) { - __WFI(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); - -/// \function disable_irq() -/// Disable interrupt requests. -STATIC mp_obj_t pyb_disable_irq(void) { - __disable_irq(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq); - -/// \function enable_irq() -/// Enable interrupt requests. -STATIC mp_obj_t pyb_enable_irq(void) { - __enable_irq(); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(pyb_enable_irq_obj, pyb_enable_irq); - STATIC mp_obj_t pyb_stop(void) { printf("stop not currently implemented\n"); return mp_const_none; } - -MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop); STATIC mp_obj_t pyb_standby(void) { printf("standby not currently implemented\n"); return mp_const_none; } - -MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby); /// \function have_cdc() /// Return True if USB is connected as a serial device, False otherwise. diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h index 697106378e..ec68c9b5bc 100644 --- a/teensy/mpconfigport.h +++ b/teensy/mpconfigport.h @@ -51,6 +51,12 @@ typedef unsigned int mp_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size +mp_int_t disable_irq(void); +void enable_irq(mp_int_t enable); + +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) + // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via // GC heap. Note that MicroPython core never uses malloc() and friends, diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h index 9c9e628424..ffbb70bcc3 100644 --- a/teensy/teensy_hal.h +++ b/teensy/teensy_hal.h @@ -1,3 +1,4 @@ +#include #ifdef USE_FULL_ASSERT #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) @@ -118,6 +119,19 @@ __attribute__(( always_inline )) static inline void __WFI(void) __asm volatile ("wfi"); } +__attribute__(( always_inline )) static inline uint32_t __get_PRIMASK(void) +{ + uint32_t result; + __asm volatile ("MRS %0, primask" : "=r" (result)); + return(result); +} + +__attribute__(( always_inline )) static inline void __set_PRIMASK(uint32_t priMask) +{ + __asm volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + uint32_t HAL_GetTick(void); void HAL_Delay(uint32_t Delay);