diff options
Diffstat (limited to 'src/generic/armcm_irq.c')
-rw-r--r-- | src/generic/armcm_irq.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/generic/armcm_irq.c b/src/generic/armcm_irq.c new file mode 100644 index 00000000..64acdd89 --- /dev/null +++ b/src/generic/armcm_irq.c @@ -0,0 +1,58 @@ +// Definitions for irq enable/disable on ARM Cortex-M processors +// +// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net> +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "irq.h" // irqstatus_t +#include "sched.h" // DECL_SHUTDOWN + +void +irq_disable(void) +{ + asm volatile("cpsid i" ::: "memory"); +} + +void +irq_enable(void) +{ + asm volatile("cpsie i" ::: "memory"); +} + +irqstatus_t +irq_save(void) +{ + irqstatus_t flag; + asm volatile("mrs %0, primask" : "=r" (flag) :: "memory"); + irq_disable(); + return flag; +} + +void +irq_restore(irqstatus_t flag) +{ + asm volatile("msr primask, %0" :: "r" (flag) : "memory"); +} + +// Clear the active irq if a shutdown happened in an irq handler +static void +clear_active_irq(void) +{ + uint32_t psr; + asm volatile("mrs %0, psr" : "=r" (psr)); + if (!(psr & 0x1ff)) + // Shutdown did not occur in an irq - nothing to do. + return; + // Clear active irq status + psr = 1<<24; // T-bit + uint32_t temp; + asm volatile( + " push { %1 }\n" + " adr %0, 1f\n" + " push { %0 }\n" + " push { r0, r1, r2, r3, r12, lr }\n" + " bx %2\n" + "1:\n" + : "=&r"(temp) : "r"(psr), "r"(0xfffffff9) : "cc"); +} +DECL_SHUTDOWN(clear_active_irq); |