X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Firq.h;h=c3824556176b647068a5e6913b19c122b102e3a5;hb=dddad4f8940615bcad589c25f15ca920a062a163;hp=4e61f20a41590f3462d3e602f96289a683447f40;hpb=ea1d7ca0efe2315a0785aee1acb51ae79480b87e;p=bertos.git diff --git a/bertos/cpu/irq.h b/bertos/cpu/irq.h index 4e61f20a..c3824556 100644 --- a/bertos/cpu/irq.h +++ b/bertos/cpu/irq.h @@ -44,7 +44,7 @@ #include "detect.h" #include "types.h" -#include +#include /* proc_needPreempt() / proc_preempt() */ #include /* for uintXX_t */ #include "cfg/cfg_proc.h" /* CONFIG_KERN_PREEMPT */ @@ -63,6 +63,147 @@ #define IRQ_RESTORE(x) FIXME #endif /* OS_EMBEDDED */ +#elif CPU_CM3 + /* Cortex-M3 */ + + /* + * Interrupt priority. + * + * NOTE: 0 means that an interrupt is not affected by the global IRQ + * priority settings. + */ + #define IRQ_PRIO 0x80 + #define IRQ_PRIO_MIN 0xf0 + #define IRQ_PRIO_MAX 0 + /* + * To disable interrupts we just raise the system base priority to a + * number lower than the default IRQ priority. In this way, all the + * "normal" interrupt can't be triggered. High-priority interrupt can + * still happen (at the moment only the soft-interrupt svcall uses a + * priority greater than the default IRQ priority). + * + * To enable interrupts we set the system base priority to 0, that + * means IRQ priority mechanism is disabled, and any interrupt can + * happen. + */ + #define IRQ_PRIO_DISABLED 0x40 + #define IRQ_PRIO_ENABLED 0 + + #define IRQ_DISABLE \ + ({ \ + register cpu_flags_t reg = IRQ_PRIO_DISABLED; \ + asm volatile ( \ + "msr basepri, %0" \ + : : "r"(reg) : "memory", "cc"); \ + }) + + #define IRQ_ENABLE \ + ({ \ + register cpu_flags_t reg = IRQ_PRIO_ENABLED; \ + asm volatile ( \ + "msr basepri, %0" \ + : : "r"(reg) : "memory", "cc"); \ + }) + + #define CPU_READ_FLAGS() \ + ({ \ + register cpu_flags_t reg; \ + asm volatile ( \ + "mrs %0, basepri" \ + : "=r"(reg) : : "memory", "cc"); \ + reg; \ + }) + + #define IRQ_SAVE_DISABLE(x) \ + ({ \ + x = CPU_READ_FLAGS(); \ + IRQ_DISABLE; \ + }) + + #define IRQ_RESTORE(x) \ + ({ \ + asm volatile ( \ + "msr basepri, %0" \ + : : "r"(x) : "memory", "cc"); \ + }) + + #define IRQ_ENABLED() (CPU_READ_FLAGS() == IRQ_PRIO_ENABLED) + + INLINE bool irq_running(void) + { + register uint32_t ret; + + /* + * Check if the current stack pointer is the main stack or + * process stack: we use the main stack only in Handler mode, + * so this means we're running inside an ISR. + */ + asm volatile ( + "mrs %0, msp\n\t" + "cmp sp, %0\n\t" + "ite ne\n\t" + "movne %0, #0\n\t" + "moveq %0, #1\n\t" : "=r"(ret) : : "cc"); + return ret; + } + #define IRQ_RUNNING() irq_running() + + #if CONFIG_KERN_PREEMPT + + #define DECLARE_ISR_CONTEXT_SWITCH(func) \ + void func(void); \ + INLINE void __isr_##func(void); \ + void func(void) \ + { \ + __isr_##func(); \ + if (!proc_needPreempt()) \ + return; \ + /* + * Set a PendSV request. + * + * The preemption handler will be called immediately + * after this ISR in tail-chaining mode (without the + * overhead of hardware state saving and restoration + * between interrupts). + */ \ + HWREG(NVIC_INT_CTRL) = NVIC_INT_CTRL_PEND_SV; \ + } \ + INLINE void __isr_##func(void) + + /** + * With task priorities enabled each ISR is used a point to + * check if we need to perform a context switch. + * + * Instead, without priorities a context switch can occur only + * when the running task expires its time quantum. In this last + * case, the context switch can only occur in the timer ISR, + * that must be always declared with the + * DECLARE_ISR_CONTEXT_SWITCH() macro. + */ + #if CONFIG_KERN_PRI + #define DECLARE_ISR(func) \ + DECLARE_ISR_CONTEXT_SWITCH(func) + /** + * Interrupt service routine prototype: can be used for + * forward declarations. + */ + #define ISR_PROTO(func) \ + ISR_PROTO_CONTEXT_SWITCH(func) + #endif /* !CONFIG_KERN_PRI */ + #endif + + #ifndef ISR_PROTO + #define ISR_PROTO(func) void func(void) + #endif + #ifndef DECLARE_ISR + #define DECLARE_ISR(func) void func(void) + #endif + #ifndef DECLARE_ISR_CONTEXT_SWITCH + #define DECLARE_ISR_CONTEXT_SWITCH(func) void func(void) + #endif + #ifndef ISR_PROTO_CONTEXT_SWITCH + #define ISR_PROTO_CONTEXT_SWITCH(func) void func(void) + #endif #elif CPU_ARM @@ -368,7 +509,7 @@ #define DECLARE_ISR_CONTEXT_SWITCH(vect) ISR(vect) #endif #ifndef ISR_PROTO_CONTEXT_SWITCH - #define ISR_PROTO_CONTEXT_SWITCH(func) ISR(vect) + #define ISR_PROTO_CONTEXT_SWITCH(vect) ISR(vect) #endif #else @@ -382,6 +523,7 @@ /// Ensure callee is not running within an interrupt #define ASSERT_USER_CONTEXT() ASSERT(!IRQ_RUNNING()) #else + #define IRQ_RUNNING() false #define ASSERT_USER_CONTEXT() do {} while(0) #define ASSERT_IRQ_CONTEXT() do {} while(0) #endif