summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/objexcept.c4
-rw-r--r--stmhal/irq.c28
-rw-r--r--stmhal/irq.h9
-rw-r--r--stmhal/mpconfigport.h31
-rw-r--r--teensy/mpconfigport.h37
-rw-r--r--teensy/teensy_hal.h13
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);