Browse Source

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.
pull/824/head
Damien George 10 years ago
parent
commit
e5cbb70328
  1. 4
      py/objexcept.c
  2. 28
      stmhal/irq.c
  3. 9
      stmhal/irq.h
  4. 31
      stmhal/mpconfigport.h
  5. 37
      teensy/mpconfigport.h
  6. 13
      teensy/teensy_hal.h

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

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

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

31
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

37
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

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

Loading…
Cancel
Save