Commit e5cbb703 authored by Damien George's avatar Damien George
Browse files

stmhal: Make enable_irq and disable_irq inline functions.

These functions are generally 1 machine instruction, and are used in
critical code, so makes sense to have them inline.

Also leave these functions uninverted (ie 0 means enable, 1 means
disable) and provide macro constants if you really need to distinguish
the states.  This makes for smaller code as well (combined with
inlining).

Applied to teensy port as well.
parent 9480138f
...@@ -88,10 +88,10 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { ...@@ -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 // Update the 2 variables atomically so that an interrupt can't occur
// between the assignments. // 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_size = size;
mp_emergency_exception_buf = buf; mp_emergency_exception_buf = buf;
MICROPY_END_ATOMIC_SECTION(enabled); MICROPY_END_ATOMIC_SECTION(irq_state);
if (old_buf != NULL) { if (old_buf != NULL) {
m_free(old_buf, old_size); m_free(old_buf, old_size);
......
...@@ -33,17 +33,6 @@ ...@@ -33,17 +33,6 @@
#include MICROPY_HAL_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() /// \function wfi()
/// Wait for an interrupt. /// Wait for an interrupt.
/// This executies a `wfi` instruction which reduces power consumption /// This executies a `wfi` instruction which reduces power consumption
...@@ -56,19 +45,22 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); ...@@ -56,19 +45,22 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi);
/// \function disable_irq() /// \function disable_irq()
/// Disable interrupt requests. /// 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) { 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); MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq);
/// \function enable_irq() /// \function enable_irq(state=True)
/// Enable interrupt requests. /// 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) { STATIC mp_obj_t pyb_enable_irq(uint n_args, const mp_obj_t *arg) {
mp_int_t enabled = true; enable_irq((n_args == 0 || mp_obj_is_true(arg[0])) ? IRQ_STATE_ENABLED : IRQ_STATE_DISABLED);
if (n_args > 0) {
enabled = mp_obj_is_true(arg[0]);
}
enable_irq(enabled);
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq);
...@@ -24,12 +24,11 @@ ...@@ -24,12 +24,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
// The prototypes for disable_irq/enable_irq are in mpconfigport.h // these states correspond to values from enable_irq and disable_irq
// Once we switch around to using traitional #include headers, then they #define IRQ_STATE_DISABLED (0x00000001)
// can be move back into here. #define IRQ_STATE_ENABLED (0x00000000)
// mp_int_t disable_irq(void); // enable_irq and disable_irq are defined inline in mpconfigport.h
// void enable_irq(mp_int_t enabled);
MP_DECLARE_CONST_FUN_OBJ(pyb_wfi_obj); MP_DECLARE_CONST_FUN_OBJ(pyb_wfi_obj);
MP_DECLARE_CONST_FUN_OBJ(pyb_disable_irq_obj); MP_DECLARE_CONST_FUN_OBJ(pyb_disable_irq_obj);
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#ifndef __INCLUDED_MPCONFIGPORT_H
#define __INCLUDED_MPCONFIGPORT_H
// options to control how Micro Python is built // options to control how Micro Python is built
#define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_ALLOC_PATH_MAX (128)
...@@ -96,11 +100,28 @@ typedef unsigned int mp_uint_t; // must be pointer size ...@@ -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 void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_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); // We have inlined IRQ functions for efficiency (they are generally
void enable_irq(mp_int_t enable); // 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);
}
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_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
// There is no classical C heap in bare-metal ports, only Python // There is no classical C heap in bare-metal ports, only Python
// garbage-collected heap. For completeness, emulate C heap via // garbage-collected heap. For completeness, emulate C heap via
...@@ -121,3 +142,5 @@ void enable_irq(mp_int_t enable); ...@@ -121,3 +142,5 @@ void enable_irq(mp_int_t enable);
#define MICROPY_HAL_H "mphal.h" #define MICROPY_HAL_H "mphal.h"
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stmhal.h" #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stmhal.h"
#endif // __INCLUDED_MPCONFIGPORT_H
...@@ -51,11 +51,40 @@ typedef unsigned int mp_uint_t; // must be pointer size ...@@ -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 void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_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); // We have inlined IRQ functions for efficiency (they are generally
void enable_irq(mp_int_t enable); // 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_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(enable) enable_irq(enable) #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
// There is no classical C heap in bare-metal ports, only Python // There is no classical C heap in bare-metal ports, only Python
// garbage-collected heap. For completeness, emulate C heap via // garbage-collected heap. For completeness, emulate C heap via
......
...@@ -119,19 +119,6 @@ __attribute__(( always_inline )) static inline void __WFI(void) ...@@ -119,19 +119,6 @@ __attribute__(( always_inline )) static inline void __WFI(void)
__asm volatile ("wfi"); __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); uint32_t HAL_GetTick(void);
void HAL_Delay(uint32_t Delay); void HAL_Delay(uint32_t Delay);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment