summaryrefslogtreecommitdiff
path: root/interrupt/fault.cpp
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2012-08-07 16:50:46 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2012-08-07 16:50:46 +0200
commite586c178073b9a0fee90d5fc8e795d266ebd7b7d (patch)
treeca9a9c40bab37d5af440c80833755223e2bdd946 /interrupt/fault.cpp
Initial import.
Most sources are split off from suzumebachi project revision 2fc77d2 as is with some path changes. New build rules introduced.
Diffstat (limited to 'interrupt/fault.cpp')
-rw-r--r--interrupt/fault.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/interrupt/fault.cpp b/interrupt/fault.cpp
new file mode 100644
index 0000000..016b74b
--- /dev/null
+++ b/interrupt/fault.cpp
@@ -0,0 +1,41 @@
+#include "interrupt.h"
+#include <os/thread.h>
+#include <os/time.h>
+
+inline void __attribute__((naked)) switch_context() {
+ asm volatile ("cpsid i");
+
+ // Save unsaved registers.
+ asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" ::: "memory");
+
+ // Store stack pointer for old thread.
+ asm volatile ("str sp, [%0]" :: "r" (&Thread::active_thread->sp));
+
+ // Update running thread.
+ Thread::active_thread = Thread::active_thread->next;
+
+ // Fetch stack pointer for new thread.
+ asm volatile ("ldr sp, [%0]" :: "r" (&Thread::active_thread->sp));
+
+ asm volatile ("cpsie i");
+
+ // Load registers and return.
+ asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" ::: "memory");
+}
+
+template<>
+void interrupt<Interrupt::SVCall>() {
+ switch_context();
+}
+
+template<>
+void interrupt<Interrupt::SysTick>() {
+ Time::tick();
+}
+
+template<> void interrupt<Interrupt::NMI>() { while(1); }
+template<> void interrupt<Interrupt::HardFault>() { while(1); }
+template<> void interrupt<Interrupt::MemManage>() { while(1); }
+template<> void interrupt<Interrupt::BusFault>() { while(1); }
+template<> void interrupt<Interrupt::UsageFault>() { while(1); }
+template<> void interrupt<Interrupt::PendSV>() { while(1); }