aboutsummaryrefslogtreecommitdiff
path: root/kernel/mcu/atmega2560/include/mcu/context.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/mcu/atmega2560/include/mcu/context.h')
-rw-r--r--kernel/mcu/atmega2560/include/mcu/context.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/kernel/mcu/atmega2560/include/mcu/context.h b/kernel/mcu/atmega2560/include/mcu/context.h
new file mode 100644
index 0000000..5f6e947
--- /dev/null
+++ b/kernel/mcu/atmega2560/include/mcu/context.h
@@ -0,0 +1,123 @@
+#ifndef MCU_CONTEXT_H
+#define MCU_CONTEXT_H
+
+#include <avr/interrupt.h>
+#define ret() asm volatile ( "ret" )
+
+/** Default stack size, you may use this definition for declaring tasks. */
+#define DEFAULT_STACK_SIZE 256
+
+/** Stack size to be allocated for the idle task. */
+#define IDLE_STACK_SIZE 64
+
+/*
+ * The macros save_context(), restore_context() as well as the code contained in
+ * init_stack is adapted from the FreeRTOS kernel (http://www.freertos.org/).
+ * Here by copyright, credits attributed to wherever they belong.
+ */
+
+/**
+ * Save context to memory location specified by first two chars of
+ * a symbol named 'current' (this is why 'sp' has to be the first element of
+ * of task control blocks). After executing this macro, the stack pointer will
+ * be set to the address contained in 'kstack'.
+ */
+#define context_save() \
+ asm volatile ( \
+ "push r0 \n\t" \
+ "in r0, __SREG__ \n\t" \
+ "cli \n\t" \
+ "push r0 \n\t" \
+ "push r1 \n\t" \
+ "clr r1 \n\t" \
+ "push r2 \n\t" \
+ "push r3 \n\t" \
+ "push r4 \n\t" \
+ "push r5 \n\t" \
+ "push r6 \n\t" \
+ "push r7 \n\t" \
+ "push r8 \n\t" \
+ "push r9 \n\t" \
+ "push r10 \n\t" \
+ "push r11 \n\t" \
+ "push r12 \n\t" \
+ "push r13 \n\t" \
+ "push r14 \n\t" \
+ "push r15 \n\t" \
+ "push r16 \n\t" \
+ "push r17 \n\t" \
+ "push r18 \n\t" \
+ "push r19 \n\t" \
+ "push r20 \n\t" \
+ "push r21 \n\t" \
+ "push r22 \n\t" \
+ "push r23 \n\t" \
+ "push r24 \n\t" \
+ "push r25 \n\t" \
+ "push r26 \n\t" \
+ "push r27 \n\t" \
+ "push r28 \n\t" \
+ "push r29 \n\t" \
+ "push r30 \n\t" \
+ "push r31 \n\t" \
+ "lds r26, current \n\t" \
+ "lds r27, current +1 \n\t" \
+ "in r0, __SP_L__ \n\t" \
+ "st x+, r0 \n\t" \
+ "in r0, __SP_H__ \n\t" \
+ "st x+, r0 \n\t" \
+ )
+
+
+/**
+ * Restore context to memory location specified by first two chars of
+ * a symbol named 'current'.
+ */
+#define context_restore() \
+ asm volatile ( \
+ "lds r26, current \n\t" \
+ "lds r27, current + 1 \n\t" \
+ "ld r28, x+ \n\t" \
+ "out __SP_L__, r28 \n\t" \
+ "ld r29, x+ \n\t" \
+ "out __SP_H__, r29 \n\t" \
+ "pop r31 \n\t" \
+ "pop r30 \n\t" \
+ "pop r29 \n\t" \
+ "pop r28 \n\t" \
+ "pop r27 \n\t" \
+ "pop r26 \n\t" \
+ "pop r25 \n\t" \
+ "pop r24 \n\t" \
+ "pop r23 \n\t" \
+ "pop r22 \n\t" \
+ "pop r21 \n\t" \
+ "pop r20 \n\t" \
+ "pop r19 \n\t" \
+ "pop r18 \n\t" \
+ "pop r17 \n\t" \
+ "pop r16 \n\t" \
+ "pop r15 \n\t" \
+ "pop r14 \n\t" \
+ "pop r13 \n\t" \
+ "pop r12 \n\t" \
+ "pop r11 \n\t" \
+ "pop r10 \n\t" \
+ "pop r9 \n\t" \
+ "pop r8 \n\t" \
+ "pop r7 \n\t" \
+ "pop r6 \n\t" \
+ "pop r5 \n\t" \
+ "pop r4 \n\t" \
+ "pop r3 \n\t" \
+ "pop r2 \n\t" \
+ "pop r1 \n\t" \
+ "pop r0 \n\t" \
+ "out __SREG__, r0 \n\t" \
+ "pop r0 \n\t" \
+ )
+
+/** Initialize the given memory addresses to contain a valid, initial stackframe. */
+char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args);
+
+#endif