basic scheduling, basic syscall, (added .data copy)
authorRobin Krens <robin@robinkrens.nl>
Wed, 30 Oct 2019 19:01:52 +0000 (20:01 +0100)
committerRobin Krens <robin@robinkrens.nl>
Wed, 30 Oct 2019 19:01:52 +0000 (20:01 +0100)
13 files changed:
Makefile
include/lib/syscall.h
include/sys/mmap.h
include/sys/process.h [new file with mode: 0644]
include/sys/robsys.h
ivt.c
lib/regfunc.c
lib/syscall.c
link.ld
main.c
start.asm
syscall.c
systick.c

index 6d3ec19..f390d30 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ kernel: $(OBJ) $(DRIVERS) $(LIBS)
        $(LD) -nostartfiles -Map $(BIN)/$@.MAP -T link.ld -o $(BIN)/$@.ELF start.o $^ --print-memory-usage
        @echo "Creating binary..."
        @mkdir -p $(BIN)
-       $(MKIMG) -Obinary -R .data $(BIN)/$@.ELF  $(BIN)/$@.bin
+       $(MKIMG) -Obinary $(BIN)/$@.ELF  $(BIN)/$@.bin
 
 # Run in Qemu; note this is a patched version for stm32-f103c8
 run:
index ddf6882..f1e8c6e 100644 (file)
@@ -1,2 +1,5 @@
 /* syscall.h */
-extern void theos_test();
+extern int theos_test(int, int, int);
+extern int theos_init(uint32_t *);
+extern int theos_switch(uint32_t *, uint32_t *);
+extern int theos_uptime();
index 4ed901d..8a4baa9 100644 (file)
 /* Safety macro's to get the address or value */
 #define MEM_VALUE(addr) *((volatile uint32_t(*) (addr))
 #define MEM_ADDR(addr) ((volatile uint32_t *) (addr))
+#define HW_ADDR(addr) (*((volatile unsigned long *)(addr)))
 
 /* SYSTEM INFO AND DEBUG */
 #define MCU_ID MEM_ADDR(0xE000ED00) 
 #define FLASH_MEM MEM_ADDR(0x1FFFF000)
 
+/* MEMORY PROTECTION UNIT */
+#define MPU_TYPER MEM_ADDR(0xE000ED90)
+#define MPU_CR MEM_ADDR(0xE000ED94)
+#define MPU_RNR MEM_ADDR(0xE000ED98)
+#define MPU_RBAR MEM_ADDR(0xE000ED9C)
+
 /* POWER CONTROL REGISTERS */
 #define PWR_CR MEM_ADDR(0x40007000)
 
 /* SYSTEM CONTROL BLOCK REGISTER */
 #define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
-#define SCB_VTOR_ST MEM_ADDR(0xE000ED04) // STATUS OF VECTOR
+#define SCB_ICSR MEM_ADDR(0xE000ED04) // STATUS OF VECTOR
 #define SCB_CCR MEM_ADDR(0xE000ED14) // SET SOFTWARE TRAPS
+#define SCB_SHCSR MEM_ADDR(0xE000ED24) // ENABLE VARIOUS FAULTS EXCEPTIONS
+#define SCB_CFSR MEM_ADDR(0xE000ED28) // GEN. USAGE FAULT STATUS REGISTER
+#define SCB_HFSR MEM_ADDR(0xE000ED2C) // HARD FAULT STATUS REGISTER
+#define SCB_BFAR MEM_ADDR(0xE000ED38) // BUS FAULT ADDRESS REGISTER
 
 /* NESTED VECTOR INTERRUPT CONTROL REGISTER */
 #define NVIC_ISER0 MEM_ADDR(0xE000E100) // interrupt set enable register
 #define NVIC_ISER1 MEM_ADDR(0xE000E104) // interrupt set enable register
 #define NVIC_ISER2 MEM_ADDR(0xE000E108) // interrupt set enable register
+#define NVIC_STIR MEM_ADDR(0xE000EF00) // Software trigger interrupt
 
 /* SYSTICK REGISTER */
 #define STK_CTRL MEM_ADDR(0xE000E010)
diff --git a/include/sys/process.h b/include/sys/process.h
new file mode 100644 (file)
index 0000000..2d5b351
--- /dev/null
@@ -0,0 +1,6 @@
+typedef struct process process_t;
+struct process {
+       uint32_t id;
+       uint32_t * stackptr;
+       uint32_t reserved;
+};
index 705bd8c..14e9b1f 100644 (file)
@@ -2,6 +2,17 @@
 #define __SYSTEM_H
 
 
+/* Return CONSTANTS */
+
+#define OK 1
+#define MMKAY 0
+#define NOTOK -1
+
+/* RETURN TYPES */
+
+typedef int32_t SYSCALL;
+typedef int32_t PROCESS;
+
 /* CLOCK.C 
  * Board specific clock settings. These boards often come with two 
  * external oscillators: one high speed (8MHz) and one low speed (~30kHz).
diff --git a/ivt.c b/ivt.c
index 0d3b8ff..2cb86e7 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -127,7 +127,7 @@ __attribute__ ((naked)) void * dummy_isr(void) {
 
        memcpy(&frame, current_sp, sizeof(struct interrupt_frame));
 
-       uint8_t nr = *SCB_VTOR_ST & 0xFF;
+       uint8_t nr = *SCB_ICSR & 0xFF;
        printf("EXCEPTION: %s\n", exception_message(nr));
        printf("STACKFRAME:\n");
        printf("R0:%p\n",frame.r0);
@@ -136,9 +136,11 @@ __attribute__ ((naked)) void * dummy_isr(void) {
        printf("R3:%p\n",frame.r3);
        printf("R12:%p\n",frame.r12);
        printf("LR:%p\n",frame.lr);
-       printf("PC:%p\n",frame.pc);
+       printf("PC:%p (<-- last function call)\n",frame.pc);
        printf("PSR:%p\n",frame.psr);
        
+       printf("CPU STATUS:");
+       printf("%x\n", *SCB_CFSR);
        for(;;); 
 }
 
@@ -154,11 +156,24 @@ void ivt_init() {
        *  */
        extern void * reset,  * nmi, * hardfault;
 
-       // set dummy handlers 
+       /* set dummy handlers */
        for (int i = 1; i <= 64 ; i++) {
                ivt_set_gate(i, dummy_isr, 0);
        }
 
+
+       /* Enable memory management, bus and usage fault exceptions handlers
+        * If these are not enabled, the processor treats them as a hard
+        * faults. Unpriviliged access will cause a busfault in case no MPU */
+       rsetbit(SCB_SHCSR, 16); // MPU violation
+       rsetbit(SCB_SHCSR, 17); // Bus faults
+       rsetbit(SCB_SHCSR, 18); // Usage faults
+       
+       /* Enable various other faults */
+       // rsetbit(SCB_CCR, 4); // division by zero, (needed if you write a lot
+       // of assembly, otherwise the compiler probably leave these divisions out
+
+
        /* The vector table is intially at 0x0. The vector table can be
         * relocated to other memory locations. We can do this by setting 
         * a register in the NVIC called the vector table offset register */
index 2928694..38bc23a 100644 (file)
@@ -105,11 +105,9 @@ uint32_t hextoreg(char * a) {
  * 0xFFFF * (1/8,000,000) * 3 = 24.58ms 
  * 0xFFFFFFFF * (1/8MHz) * 3 = 1610ms
  * */
-static void __block(uint32_t count) {
+/* static void __block(uint32_t count) {
 
-       asm volatile("b1: subs %0, %1, #1" "\n\t"
-               "bne b1" : "=r" (count) : "r" (count));
-}
+} */
 
 /* Delay us microsecond
  * Note: delay includes setup time (about 4 clockcycles), so is quite
@@ -117,7 +115,9 @@ static void __block(uint32_t count) {
 void _block(uint32_t us) {
        
        uint32_t count = (us/3) * CLKSPEED_MHZ; // x cycles 
-       __block(count);
+       asm volatile("b1: subs %0, %1, #1" "\n\t"
+               "bne b1" : "=r" (count) : "r" (count));
+       //__block(count);
 
 }
 
index 106c235..d844b43 100644 (file)
@@ -1,4 +1,3 @@
-
 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
  * 
  * $LOG$
 
 #include <lib/syscall.h>
 
+/* Arguments are placed in r0, r1, r2 by convention
+ * And "parsed" to the the kernel
+ * Right after the svc call, r0 contains status
+ * of call (ie. OK, NOTOK */
 
-//__attribute__ ((naked))
-static int theos_syscall(int SYSCALL_N, int SYSCALL_N2) {
+int theos_uptime() {
 
-       asm volatile ("svc 11");
-       
-       return 0;
+       asm volatile("svc 6");
+       int ret;
+       asm volatile("mov %0, r0" : "=r" (ret));        
+       return ret;
 }
 
-//__attribute__ ((naked))
-void theos_test(int dummy, int dummy2) {
+       
+int theos_init(uint32_t * p) {
+       asm volatile("svc 1");
 
-       theos_syscall(0xB1, 0xB2);
+       return -1;
 }
 
-/* void theos_cputs(const char * str, size_t len) {
+__attribute__ ((naked))
+int theos_switch(uint32_t * p1, uint32_t * p2) {
+
+       asm volatile("push {lr}");
+       asm volatile("svc 4");
+       asm volatile("pop {lr}");
+       asm volatile("bx lr");
+       // should not be here
+       for(;;);
+       
+}
 
-       //syscall(#, 0, 0, 0 ..);
-       theos_syscall(22, 44);
-} */
+int theos_test(int arg1, int arg2, int arg3) {
+       
+       asm volatile("svc 11");
+       int ret;
+       asm volatile("mov %0, r0" : "=r" (ret));        
+       return ret;
+}
diff --git a/link.ld b/link.ld
index 5056e38..63f173d 100644 (file)
--- a/link.ld
+++ b/link.ld
@@ -38,13 +38,16 @@ SECTIONS
        {
                /* (.vector_table */
                *(.text)
-               *(.rodata)
+               *(.rodata) 
+               data_lma = .;
        }
         . = 0x20000000;        
-       .data :  
+       data_vma = .;
+       .data : AT (data_lma)
        {
                *(.data)
        } 
+       data_end = .;
        .bss : ALIGN(4) 
        {
                *(.bss)
diff --git a/main.c b/main.c
index 1543a12..ac01416 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,6 +16,7 @@
 
 #include <sys/robsys.h> 
 #include <sys/mmap.h>
+#include <sys/process.h>
 
 #include <lib/regfunc.h>
 #include <lib/pool.h>
 //#include <drivers/mk450_joystick.h>
 #include <drivers/st7735s.h>
 
-
 #include <lib/syscall.h>
 
 
+process_t p1;
+process_t p2;
+
+uint32_t stackp1[500];
+uint32_t stackp2[500];
+
+extern int count;
+
+void switch_usermode() {
+
+       // user mode 
+       //asm volatile ("mov r0, 0x1" "\n\t" 
+       //"msr control, r0" "\n\t"
+       //"isb" "\n\t"); 
+
+       // system init call
+
+}
+
+void process1(void) {
+       
+       while(1) {
+               //uint32_t control = 0xFFFFFFFF;
+               printf("process 1\n");
+               //asm volatile("msr control, %0" "\n\t"
+               //             "dsb" : : "r" (control));
+               //printf("control: %x", control);       
+               //for(;;);
+               _block(100);
+               theos_switch(&p1, &p2);
+       }
+
+}
+void process2(void) {
+       while(1) {
+               printf("process 2\n");
+               _block(100);
+               theos_switch(&p2, &p1);
+       }
+       
+}
+
+int test_data_segment = 99;
+
 void main()
 {
 
+       /* Load .data segment into SRAM */
+       extern uint32_t * data_lma, data_vma, data_end;
+       int size = (&data_end - &data_vma) * 4;
+       memcpy(&data_vma, &data_lma, size);
+
        /* Initialize the clock system, */
        clock_init();
 
@@ -50,11 +99,6 @@ void main()
        /* TFT screen */
        // tft_init();
        
-       /* Cortex M* integrated systick, can be replaced
-        * by the more accurate RTC.
-       systick_init();
-       */
-       
        /* Set up a very small libc library */
        init_printf(NULL, putc);
 
@@ -68,14 +112,42 @@ void main()
        /* On board LEDs*/
        led_init();
 
+
        /* Real time clock */
-       //rtc_init();
+       rtc_init();
+
 
 //     printf("press any key to start\n");
-//     asm volatile ("wfi");
+//     asm volatile ("cpsid f"); // doesn't work in qemu
 
        syscall_init();
-       theos_test(0xA1, 0xA2);
+
+       //int ret;
+       //ret = theos_test(0x1, 0x2, 0x3);
+       //ret = theos_uptime();
+
+       //printf("ret: %d\n", ret);
+
+       int size_stack = sizeof(stackp1);
+       
+       p1.stackptr = ((unsigned int) stackp1) + size_stack - 0x1C;
+       p1.stackptr[6] = (uint32_t) process1;
+       p1.stackptr[7] = 0x01000000;
+       p2.stackptr = ((unsigned int) stackp2) + size_stack - 0x1C;
+       p2.stackptr[6] = (uint32_t) process2;
+       p2.stackptr[7] = 0x01000000;
+       
+       theos_init(&p1);
+
+       /* Cortex M* integrated systick, can be replaced
+        * by the more accurate RTC. */
+       
+//     systick_init();
+
+       //      switch_usermode();      
+
+       //printf("without system call");        
+//     theos_test(0xA1, 0xA2);
 
        /* Eeprom Driver
        eeprom_at24c_init();
index e6d08c6..65b67f5 100644 (file)
--- a/start.asm
+++ b/start.asm
@@ -13,7 +13,7 @@
        .text
        .global _start
        .global reset, nmi, hardfault
-       .global _svc_handler
+       .global pendsv_handler
        .code 16
        .syntax unified
 _start:
@@ -31,6 +31,7 @@ reset:
    (machine somehow has a failure). That's why they are included here.
    Later the interrupt vector will be relocated to SRAM and modified.  */
 
+
 nmi:
        b nmi
 
index 9f33ad5..ba0dc9a 100644 (file)
--- a/syscall.c
+++ b/syscall.c
  * |----------------------------|
  * | SYSTEM CALL       | #     |
  * |--------------------|-------|
- * | THEOS_getenv      |       |
- * | THEOS_killenv     |       |
- * | THEOS_setenv      |       |
- * | THEOS_newenv      |       |
- * | THEOS_cputs       |       |
- * | THEOS_omnigod     |       |
- * | THEOS_brk         |       |
- * | THEOS_time                |       |
- * | THEOS_magic       |       |
+ * | THEOS_INIT                | 1     |
+ * | THEOS_DESTROY     | 2     |
+ * | THEOS_RESCHED     | 3     |
+ * | THEOS_GETC                | 4     |
+ * | THEOS_CPUTS       | 5     |
+ * | THEOS_UPTIME      | 6     |
+ * | THEOS_OMNIGOD     | 7     |
+ * | THEOS_TIME                | 8     |
+ * | THEOS_MAGIC       | 99    |
  * |----------------------------|
  *
  * TODO: include in header enum
  * */
 
-
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 
 #include <sys/robsys.h>
 #include <sys/mmap.h>
+#include <sys/process.h>
 
 #include <lib/stdio.h>
 #include <lib/string.h>
 #include <lib/regfunc.h>
 #include <lib/tinyprintf.h>
 
+enum {
+       THEOS_INIT = 1,
+       THEOS_CREATE,
+       THEOS_DESTROY,
+       THEOS_SWITCH,
+       THEOS_GETC,
+       THEOS_CPUTS,
+       THEOS_UPTIME
+};
+
+
+static int sys_uptime() {
+
+       int uptime = *RTC_CNTL;
+       return uptime;
+}
+
+/* Context switch routine, saves stack pointer of 
+ * the current process, loads the stack pointer
+ * of the next.
+ *
+ * Other registers and flags (i.e. PSR, PC are popped
+ * by exit of this system call.
+ * Precondition: Usage of PSP   */
+int sys_switch(process_t * currp, process_t * newp) {
+
+       uint32_t tmp_stackptr = 0xFFFFFFFF;
+       asm volatile("mrs %0, psp" : "=r" (tmp_stackptr));
+       currp->stackptr = tmp_stackptr; 
+
+       asm volatile("msr psp, %0" : : "r" (newp->stackptr) ); // load new pointer 
+       uint32_t chk_stackptr;
+       asm volatile("mrs %0, psp" : "=r" (chk_stackptr));
+       //asm volatile("isb");
+       printf("OLD: %x\n", currp->stackptr);
+       printf("NEW: %x\n", newp->stackptr);
+       printf("CHK: %x\n", chk_stackptr);
+       //for(;;);
+
+       return 0;
+
+}
+
+int sys_init(process_t * p) {
+
+       asm volatile("msr psp, %0" : : "r" (p->stackptr));      
+       return 0;
+}
+
+static int sys_stub() {
+
+       return 0;
+
+}
 
 /*
  * This is a so-called first interrupt handler
  * The naked attribute makes sure the compiler doesn't
- * places registers on the stack.  */
+ * places registers on the stack */
+
+/* 
+ * SVC is similar to an exception or interrupt
+ * A stack frame is pushed on entry and popped
+ * on exit BY PROCESSOR. Please see in-function command */
 
 __attribute__ ((naked))
 void * _svc_handler(void) {
 
-       uint32_t * current_sp;
+       uint32_t * callee_sp;
 
        /* Test whether system call was invoked from supervisor (use MSP) or
         * user (use PSP) mode */
@@ -53,67 +112,80 @@ void * _svc_handler(void) {
        "tst lr, #4" "\n\t"
        "ite eq" "\n\t"
        "mrseq %0, msp" "\n\t"
-       "mrsne %0, psp" : "=r" (current_sp));
+       "mrsne %0, psp" "\n\t"
+       "push {lr}" "\n\t"
+       "push {r4-r11}" : "=r" (callee_sp));
 
        /* An exception (or interrupt) before entering this handler
         * places the following on the stack 
         * 
-        * R0
-        * R1
-        * R2
+        * R0 <- args[0]
+        * R1 <- args[1]
+        * R2 
         * R3
         * R12
-        * LR
-        * PC <- placed at current_sp[6]
-        * PSR 
+        * LR <- Not a real LR, A certain 'mask'
+        * PC <- placed at callee_sp[6], see description below
+        * PSR <- Status of processor before call
         *
         * PC contains the return address that will continue after this SVC handler
         * is finised. The previous address (the svc # call) is at PC - 2, the
         * first byte contains the svc number.
         * */
 
-       uint8_t svc_nr = ((char *) current_sp[6])[-2];
-
-       printf("SYSTEM CALL NR: %d", svc_nr);
+       uint8_t svc_nr = ((char *) callee_sp[6])[-2];
+       int ret = -1;
 
-       for (;;);
+       switch(svc_nr) {
+               case THEOS_INIT:
+                       sys_init((process_t *) callee_sp[0]);
+                       asm volatile (
+                               "ldr r0, =0xFFFFFFFD" "\n\t"
+                               "mov lr, r0" "\n\t"
+                               "bx lr");
+                       break;
+               case THEOS_SWITCH:
+                       sys_switch((process_t *) callee_sp[0], (process_t *) callee_sp[1]);
+                       //asm volatile (
+                       //      "ldr r0, =0xFFFFFFFD" "\n\t"
+                       //      "mov lr, r0" "\n\t"
+                       //      "bx lr");
+                       
+                       break;
+               case THEOS_CPUTS:  
+                       break;
+               case THEOS_GETC:
+                       break;
+               case THEOS_UPTIME:
+                       ret = sys_uptime();
+                       break;
+               default:
+                       break;
+       }
 
-}
+       //printf("SYSTEM CALL NR: %d\n", svc_nr);
+       /* Check arguments, placed in r0, r1, r2 
+        * (can get more if you save the stack) */
+       //uint32_t arg1 = callee_sp[0];
+       //uint32_t arg2 = callee_sp[1];
+       //uint32_t arg3 = callee_sp[2];
+       //printf("ARGUMENTS: %x, %x, %x\n", arg1, arg2, arg3);
 
-void syscall(unsigned int * args) {
+       /* Return value in r0 for callee */
+       callee_sp[0] = ret;
 
-       uint32_t svc_number = 99;
-       printf("SYSCALL NR: %x", svc_number);
+       asm volatile ("pop {r4-r11}");
+       /* exception return, 0xFFFFFFFX (<-- last value is flag
+        * and gives the processor information to return to what */
+       asm volatile ("pop {lr}"); 
+       asm volatile ("bx lr");
 
-       for(;;);
-       /* switch(SYSCALL_NO) {
-               case THEOS_cputs:
-                       kernel_cputs(a1, a2);
-                       break;
-               default:
-                       for (;;);
-       } */
 
 }
 
 void syscall_init() {
-
        /* SVC is located at position 11 in the interrupt vector table  */
        ivt_set_gate(11, _svc_handler, 0);
-
 }
 
-static void kernel_cputs(char * s, size_t l) {
-
-       // TODO
-}
-
-
-void kernel_omnigod() {
-
-       /* */
-
-}
-
-
 
index 589e286..2c49820 100644 (file)
--- a/systick.c
+++ b/systick.c
 #include <lib/regfunc.h>
 #include <lib/tinyprintf.h>
 
+#define NUMB_TASKS 3
+
+int count;
+int next_task;
+int curr_task;
+uint32_t currentp;
+uint32_t nextp;
+
+//struct proces {
+//     int32_t nr;
+//     uint32_t *stack_ptr;
+//     uint32_t mask;
+//};
+//
+//struct proces p1, p2, p3;
+//
+//
+//     uint32_t oldpsp;
+//     uint32_t newpsp;
+//
+//uint32_t task0_stack[50];
+//uint32_t task1_stack[50];
+//uint32_t task2_stack[50];
+//uint32_t PSP_array[3];
+
 struct interrupt_frame {
 
         uint32_t r0; // N-32
@@ -36,12 +61,63 @@ struct interrupt_frame {
 //__attribute__ ((interrupt))
 void * systick_handler(/* struct interrupt_frame * frame */) {
 
-       printf("Ticking...\n");
+       //printf("Ticking...\n");
+       //printf("Current task: %d", curr_task);
+       //count++;
+
+
+
+
+       //switch(curr_task) {
+       //      case(0): next_task = 1; break;
+       //      case(1): next_task = 2; break;
+       //      case(2): next_task = 0; break;
+       //      default: next_task = 0; break;
+       //} 
+
+       //if (curr_task != next_task) {
+       
+               
+       
+       //} 
+
 }
 
 
+__attribute__ ((naked))
+               void * pendsv_handler_c(void) {
+//
+//     asm volatile ("push {r0-r11, lr}");
+//     asm volatile ("mrs %0, psp" : "=r" (oldpsp));
+//     asm volatile ("push {lr}");
+//
+//     //asm volatile ("push {lr}");
+//     
+//     //printf("FROM MSP %x", oldpsp);
+//     //PSP_array[curr_task] = oldpsp;
+//     //curr_task = next_task;
+//     //newpsp = PSP_array[next_task];        
+//
+//     asm volatile ("msr psp, %0" : : "r" (newpsp)); 
+//
+//     asm volatile("pop {lr}");
+//     //asm volatile ("pop {r0-r12}");
+//     asm volatile("bx lr"); // return
+}
+
+uint32_t set_psp(uint32_t) __attribute__( ( naked ) );
+uint32_t set_psp(uint32_t stackie) {
+  
+       asm volatile ("msr psp, r0" "\n\t"
+                 "bx lr");
+}
+
 void systick_init() {
 
+//     count = 0;
+//     curr_task = 0;
+//     next_task = 1;
+
        /* Every time the counter counts down to zero
         * a systick exception is invoked. Systick has
         * exception number 15. in the vector table  */
@@ -50,7 +126,7 @@ void systick_init() {
        /* Get calibration and set this to 1 sec
         * !Most boards have a 1 ms or 10 ms 
         * calibration value */
-       int calib = (*STK_CALIB << 0) * 500;
+       int calib = (*STK_CALIB << 0) * 200;
 
        /* The counter reload registers counts down to zero
         * and then it is restores the value */
@@ -61,5 +137,56 @@ void systick_init() {
        rsetbit(STK_CTRL, 0);
        rsetbit(STK_CTRL, 1);
 
+//     extern void task0(void), task1(void), task2(void);
+//
+//     int size_stack = sizeof(task0_stack);
+//     
+//     p1.stack_ptr  = ((unsigned int) task0_stack) + size_stack - 0x1C;
+//     p1.stack_ptr[6] = (uint32_t) task0;
+//     p1.stack_ptr[7] = 0x01000000;
+//     p2.stack_ptr  = ((unsigned int) task0_stack) + size_stack - 0x1C;
+//     p2.stack_ptr[6] = (uint32_t) task1;
+//     p2.stack_ptr[7] = 0x01000000;
+//     p3.stack_ptr  = ((unsigned int) task0_stack) + size_stack - 0x1C;
+//     p3.stack_ptr[6] = (uint32_t) task2;
+//     p3.stack_ptr[7] = 0x01000000;
+//
+//     set_psp(p1.stack_ptr[-7]);
+//
+//     for(;;);        
+
+       /* Initialize processes */
+       //PSP_array[0] = ((unsigned int) task0_stack) + sizeof(task0_stack) - 32*4;
+       //HW_ADDR(PSP_array[0] + 0x18) = (unsigned long) task0;
+        //HW_ADDR(PSP_array[0] + 0x1C) = 0x01000000;   
+       //PSP_array[1] = ((unsigned int) task1_stack) + sizeof(task1_stack) - 32*4;
+       //HW_ADDR(PSP_array[1] + 0x18) = (unsigned long) task1;
+        //HW_ADDR(PSP_array[1] + 0x1C) = 0x01000000;   
+       //PSP_array[2] = ((unsigned int) task2_stack) + sizeof(task2_stack) - 32*4;
+       //HW_ADDR(PSP_array[2] + 0x18) = (unsigned long) task2;
+        //HW_ADDR(PSP_array[2] + 0x1C) = 0x01000000;   
+
+       //extern void pendsv_handler;
+
+       ivt_set_gate(14, pendsv_handler_c, 0);
+
+       //set_psp((PSP_array[curr_task] + 32*4 ));
+       
+       //int startpsp = PSP_array[curr_task] + 16*4;
+
+       //asm volatile ("msr psp, %0" : : "r" (startpsp));
+       
+       
+       //asm volatile ("mov r0, 0x3" "\n\t" 
+       //"msr control, r0" "\n\t"
+       //"isb" "\n\t"); 
+
+       //for(;;);
+
+       //set current PSP
+       //printf("0: %x\n", PSP_array[0]);
+       //printf("1: %x", PSP_array[0]);
+
+       //task0();
 
 }