diff options
Diffstat (limited to 'kernel/task/mcu')
-rw-r--r-- | kernel/task/mcu/atmega2560/context.c | 98 | ||||
-rw-r--r-- | kernel/task/mcu/atmega2560/include/mcu/task/context.h | 137 | ||||
-rw-r--r-- | kernel/task/mcu/atmega2560/include/mcu/task/task.h | 11 |
3 files changed, 246 insertions, 0 deletions
diff --git a/kernel/task/mcu/atmega2560/context.c b/kernel/task/mcu/atmega2560/context.c new file mode 100644 index 0000000..bcc2130 --- /dev/null +++ b/kernel/task/mcu/atmega2560/context.c @@ -0,0 +1,98 @@ +#include "mcu/task/context.h" + +char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args) { + char* sp = (char*) mem_high; + unsigned long address = (unsigned long) entry; + + // pattern for debugging purposes + *sp = (char) 0x1; + sp--; + *sp = (char) 0x2; + sp--; + *sp = (char) 0x1; + sp--; + *sp = (char) 0x2; + sp--; + + // put return address on stack + *sp = (char) ( address & (unsigned short) 0x00ff ); + sp--; + + *sp = (char) ( (address >> 8) & ( unsigned short ) 0x00ff ); + sp--; + + *sp = (char) ( (address >> 16) & ( unsigned short ) 0x00ff ); + sp--; + + // save registers + *sp = (char) 0x00; //r0 + sp--; + *sp = (char) 0x80; //SREG, enable interrupts when task starts + sp--; + *sp = ( char ) 0x00; //r1 + sp--; + *sp = ( char ) 0x00; //r2 + sp--; + *sp = ( char ) 0x00; //r3 + sp--; + *sp = ( char ) 0x00; //r4 + sp--; + *sp = ( char ) 0x00; //r5 + sp--; + *sp = ( char ) 0x00; //r6 + sp--; + *sp = ( char ) 0x00; //r7 + sp--; + *sp = ( char ) 0x00; //r8 + sp--; + *sp = ( char ) 0x00; //r9 + sp--; + *sp = ( char ) 0x00; //r10 + sp--; + *sp = ( char ) 0x00; //r11 + sp--; + *sp = ( char ) 0x00; //r12 + sp--; + *sp = ( char ) 0x00; //r13 + sp--; + *sp = ( char ) 0x00; //r14 + sp--; + *sp = ( char ) 0x00; //r15 + sp--; + *sp = ( char ) 0x00; //r16 + sp--; + *sp = ( char ) 0x00; //r17 + sp--; + *sp = ( char ) 0x00; //r18 + sp--; + *sp = ( char ) 0x00; //r19 + sp--; + *sp = ( char ) 0x00; //r20 + sp--; + *sp = ( char ) 0x00; //r21 + sp--; + *sp = ( char ) 0x00; //r22 + sp--; + *sp = ( char ) 0x00; //r23 + sp--; + + *sp = (char) ( args ); //place first argument in register 24 + sp--; + + *sp = ( char ) 0x00; //r25 + sp--; + *sp = ( char ) 0x00; //r26 + sp--; + *sp = ( char ) 0x00; //r27 + sp--; + *sp = ( char ) 0x00; //r28 + sp--; + *sp = ( char ) 0x00; //r29 + sp--; + *sp = ( char ) 0x00; //r30 + sp--; + *sp = ( char ) 0x00; //r31 + sp--; + + return sp; +} diff --git a/kernel/task/mcu/atmega2560/include/mcu/task/context.h b/kernel/task/mcu/atmega2560/include/mcu/task/context.h new file mode 100644 index 0000000..b717991 --- /dev/null +++ b/kernel/task/mcu/atmega2560/include/mcu/task/context.h @@ -0,0 +1,137 @@ +#ifndef CONTEXT_H +#define CONTEXT_H + +#include <avr/interrupt.h> +#define ret() asm volatile ( "ret" ) + +/* + * 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" \ + "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" \ + "lds r26, kstack \n\t" \ + "lds r27, kstack + 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" \ + ) + + +/** + * Restore context to memory location specified by first two chars of + * a symbol named 'current'. + */ +#define context_restore() \ + asm volatile ( \ + "lds r26, kstack \n\t" \ + "lds r27, kstack +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" \ + "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); + +/** Initialize the given memory addresses to contain a valid, initial stackframe. */ +static inline void kstack_init(void **kstack) { + //this sets the kernel stack to the default stack location + //of this mcu, namely the top (stacks of tasks will typically + //be contained in memory allocated on the head and thus should + //overflow with the kernel stack) + *kstack = (void*) SP; +} + +#endif diff --git a/kernel/task/mcu/atmega2560/include/mcu/task/task.h b/kernel/task/mcu/atmega2560/include/mcu/task/task.h new file mode 100644 index 0000000..d9823af --- /dev/null +++ b/kernel/task/mcu/atmega2560/include/mcu/task/task.h @@ -0,0 +1,11 @@ +#ifndef MCU_TASK_H +#define MACU_TASK_H + + +/** 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 + +#endif
\ No newline at end of file |