diff options
-rw-r--r-- | py/objexcept.c | 4 | ||||
-rw-r--r-- | stmhal/irq.c | 28 | ||||
-rw-r--r-- | stmhal/irq.h | 9 | ||||
-rw-r--r-- | stmhal/mpconfigport.h | 31 | ||||
-rw-r--r-- | teensy/mpconfigport.h | 37 | ||||
-rw-r--r-- | teensy/teensy_hal.h | 13 |
6 files changed, 76 insertions, 46 deletions
diff --git a/py/objexcept.c b/py/objexcept.c index 7f9b219d56..cb01fd6e85 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. - mp_int_t enabled = MICROPY_BEGIN_ATOMIC_SECTION(); + mp_uint_t irq_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_emergency_exception_buf_size = size; mp_emergency_exception_buf = buf; - MICROPY_END_ATOMIC_SECTION(enabled); + MICROPY_END_ATOMIC_SECTION(irq_state); if (old_buf != NULL) { m_free(old_buf, old_size); diff --git a/stmhal/irq.c b/stmhal/irq.c index 2d6a990beb..c08f2fe094 100644 --- a/stmhal/irq.c +++ b/stmhal/irq.c @@ -33,17 +33,6 @@ #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 @@ -56,19 +45,22 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); /// \function disable_irq() /// Disable interrupt requests. +/// Returns the previous IRQ state: `False`/`True` for disabled/enabled IRQs +/// respectively. This return value can be passed to enable_irq to restore +/// the IRQ to its original state. STATIC mp_obj_t pyb_disable_irq(void) { - return MP_BOOL(disable_irq()); + return MP_BOOL(disable_irq() == IRQ_STATE_ENABLED); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq); -/// \function enable_irq() +/// \function enable_irq(state=True) /// Enable interrupt requests. +/// If `state` is `True` (the default value) then IRQs are enabled. +/// If `state` is `False` then IRQs are disabled. The most common use of +/// this function is to pass it the value returned by `disable_irq` to +/// exit a critical section. 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); + enable_irq((n_args == 0 || mp_obj_is_true(arg[0])) ? IRQ_STATE_ENABLED : IRQ_STATE_DISABLED); 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 index 9903a02fa4..ef595b7446 100644 --- a/stmhal/irq.h +++ b/stmhal/irq.h @@ -24,12 +24,11 @@ * 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. +// these states correspond to values from enable_irq and disable_irq +#define IRQ_STATE_DISABLED (0x00000001) +#define IRQ_STATE_ENABLED (0x00000000) -// mp_int_t disable_irq(void); -// void enable_irq(mp_int_t enabled); +// enable_irq and disable_irq are defined inline in mpconfigport.h MP_DECLARE_CONST_FUN_OBJ(pyb_wfi_obj); MP_DECLARE_CONST_FUN_OBJ(pyb_disable_irq_obj); diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 805d74f996..f9142eea43 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -24,6 +24,10 @@ * THE SOFTWARE. */ +#pragma once +#ifndef __INCLUDED_MPCONFIGPORT_H +#define __INCLUDED_MPCONFIGPORT_H + // options to control how Micro Python is built #define MICROPY_ALLOC_PATH_MAX (128) @@ -96,11 +100,28 @@ 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); +// We have inlined IRQ functions for efficiency (they are generally +// 1 machine instruction). +// +// Note on IRQ state: you should not need to know the specific +// value of the state variable, but rather just pass the return +// value from disable_irq back to enable_irq. If you really need +// to know the machine-specific values, see irq.h. + +#include <stm32f4xx_hal.h> + +static inline void enable_irq(mp_uint_t state) { + __set_PRIMASK(state); +} -#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() -#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) +static inline mp_uint_t disable_irq(void) { + mp_uint_t state = __get_PRIMASK(); + __disable_irq(); + return state; +} + +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via @@ -121,3 +142,5 @@ void enable_irq(mp_int_t enable); #define MICROPY_HAL_H "mphal.h" #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stmhal.h" + +#endif // __INCLUDED_MPCONFIGPORT_H diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h index ec68c9b5bc..5e4b5129be 100644 --- a/teensy/mpconfigport.h +++ b/teensy/mpconfigport.h @@ -51,11 +51,40 @@ 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); +// We have inlined IRQ functions for efficiency (they are generally +// 1 machine instruction). +// +// Note on IRQ state: you should not need to know the specific +// value of the state variable, but rather just pass the return +// value from disable_irq back to enable_irq. If you really need +// to know the machine-specific values, see irq.h. + +#ifndef __disable_irq +#define __disable_irq() __asm__ volatile("CPSID i"); +#endif + +__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"); +} + +__attribute__(( always_inline )) static inline void enable_irq(mp_uint_t state) { + __set_PRIMASK(state); +} + +__attribute__(( always_inline )) static inline mp_uint_t disable_irq(void) { + mp_uint_t state = __get_PRIMASK(); + __disable_irq(); + return state; +} -#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() -#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h index ffbb70bcc3..d7589975c7 100644 --- a/teensy/teensy_hal.h +++ b/teensy/teensy_hal.h @@ -119,19 +119,6 @@ __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); |