SYSCALL cleanup and ivt rewrite
authorRobin Krens <robin@robinkrens.nl>
Tue, 22 Oct 2019 20:31:43 +0000 (22:31 +0200)
committerRobin Krens <robin@robinkrens.nl>
Tue, 22 Oct 2019 20:31:43 +0000 (22:31 +0200)
ivt.c
main.c
syscall.c

diff --git a/ivt.c b/ivt.c
index 0e2d1f2..0d3b8ff 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -34,9 +34,8 @@
 
 /* 
  * These values are pushed on the stack just before
- * entering the ISR. Normally, this would require
- * assembly or inline assembly code. I use a so-called
- * 'naked function' __attribute__ ((interrupt)) which
+ * entering the ISR. I use a so-called
+ * 'naked function' __attribute__ ((naked)) which
  * gives me a little bit more control over the caller
  *
  * The following register are pushed to the stack
@@ -53,7 +52,7 @@ struct interrupt_frame {
        uint32_t lr;
        uint32_t pc;
        uint32_t psr; // N-4
-};
+} frame;
 
 /* 
  * Vector table, each entry contains an interrupt
@@ -64,7 +63,7 @@ struct interrupt_frame {
  * */
 uint32_t __attribute__((aligned(0x100))) ivt[92];
 
-/* Each message corresponds to each and every exception. */
+/* Each message corresponds to an exception in the vector table. */
 char * exception_message(uint8_t intnr) {
 
 char * messages[] = {
@@ -98,70 +97,47 @@ if (intnr < 20) // TODO: strlen
        return messages[intnr];
 
 return "UNKNOWN";
+
 }
 
+/* Function to set entries of the interrupt vector table 
+ * */
 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 
        ivt[num] = (uint32_t) isr;
-//     if (num <= 32)
-//             *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
+       //if (num <= 32)
+       //*NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
        /* TODO: Priorities */
 }
 
 
-/* Dummy interrupt: comment out the comment to use a naked
- * function */
+/* Dummy interrupt: shows the saved stack registers and then
+ * halts */
+__attribute__ ((naked)) void * dummy_isr(void) {
 
-struct interrupt_frame * frame;
+       uint32_t * current_sp;
 
-//__attribute__ ((interrupt)) 
-void * dummy_isr( struct interrupt_frame * f ) {
+       /* Test whether system call was invoked from supervisor (use MSP) or
+        * user (use PSP) mode */
+       asm volatile (
+       "tst lr, #4" "\n\t"
+       "ite eq" "\n\t"
+       "mrseq %0, msp" "\n\t"
+       "mrsne %0, psp" : "=r" (current_sp));
 
-       //uint32_t link_register = 0;
-       //asm ("mov %0, #33" : "=r" (lp));
-       
-       /* Check Link Register:
-        * If you ever need to debug these: here are the most common
-        * values
-        * 0xFFFFFFF1: return to handler mode (nested interrupts
-        * 0xFFFFFFF9: return to thread mode using main stack
-        * 0xFFFFFFFD: return to thread mode using process stack */
-       // asm ("mov %0, lr" : "=r" (link_register));
-       // printf("%x\n", link_register);
-       // for(;;);
-
-//     asm volatile ("push {r0-r12}"); 
-//     int * stack;
-//     asm volatile ("tst lr, #4" "\n\t" 
-//     "ite eq" "\n\t"
-//     "mrseq %0, msp" "\n\t" 
-//     "mrsne r0, psp" : "=r" (stack));
-//     
-//     printf("STACK:  %x, %x,  %x, %x, %x", stack[32], stack[28], stack[24], stack[20], stack[16]);
-
-//     asm volatile ("CPSID f");
-
-//     uint32_t tmp = args[0];
-//     uint32_t tmp2 = args[1];
-//     printf("%x, %x\n", tmp, tmp2); 
-//     uint32_t tmp3 = args[2];
-//     uint32_t tmp4 = args[3];
-//     printf("%x, %x\n", tmp3, tmp4); 
-
-       struct interrupt_frame * frame = (struct interrupt_frame * )kalloc(get_kheap());
-       memcpy(frame, f, sizeof(struct interrupt_frame));
+       memcpy(&frame, current_sp, sizeof(struct interrupt_frame));
 
        uint8_t nr = *SCB_VTOR_ST & 0xFF;
        printf("EXCEPTION: %s\n", exception_message(nr));
-       printf("STACK TRACE:\n");
-       printf("R0:%p\n",frame->r0);
-       printf("R1:%p\n",frame->r1);
-       printf("R2:%p\n",frame->r2);
-       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("PSR:%p\n",frame->psr);
+       printf("STACKFRAME:\n");
+       printf("R0:%p\n",frame.r0);
+       printf("R1:%p\n",frame.r1);
+       printf("R2:%p\n",frame.r2);
+       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("PSR:%p\n",frame.psr);
        
        for(;;); 
 }
diff --git a/main.c b/main.c
index e87131a..1543a12 100644 (file)
--- a/main.c
+++ b/main.c
 
 #include <lib/syscall.h>
 
-int test3(int i, int j) {
-
-       volatile uint32_t * sp = get_msp();
-       
-       /* asm volatile (
-       "tst lr, #4" "\n\t" 
-       "ite eq" "\n\t"
-       "mrseq %0, msp" "\n\t" 
-       "mrsne r0, psp" : "=r" (sp) ); */
-
-       for (int i = 0; (sp + i) < 0x20010000; i++) {
-               printf("ADDRESS: %p, VALUE: %x\n", (sp + i), *(sp + i));
-       }
-
-       for(;;);
-       return 0xCC;
-
-}
-int test2(int i, int j) {
-
-       int x = i * j;
-       test3(0x3A, 0x3B); 
-       
-
-}
-int test(int i, int j) {
-
-       test2(0x2A, 0x2B);
-       
-       return 0xAA;
-}
 
 void main()
 {
index f6e1cba..9f33ad5 100644 (file)
--- a/syscall.c
+++ b/syscall.c
 #include <lib/tinyprintf.h>
 
 
-/* the function gets called for 
- * */
+/*
+ * This is a so-called first interrupt handler
+ * The naked attribute makes sure the compiler doesn't
+ * places registers on the stack.  */
+
 __attribute__ ((naked))
-void * __svc_handler__(int x) {
+void * _svc_handler(void) {
 
-       uint8_t svc_nr;
+       uint32_t * current_sp;
 
+       /* Test whether system call was invoked from supervisor (use MSP) or
+        * user (use PSP) mode */
        asm volatile (
        "tst lr, #4" "\n\t"
        "ite eq" "\n\t"
-       "mrseq r0, msp" "\n\t"
-       "mrsne r0, psp" "\n\t"
-       "ldr r0, [r0, #24]" "\n\t"
-       "ldrb %0, [r0, #-2]" : "=r" (svc_nr) );
+       "mrseq %0, msp" "\n\t"
+       "mrsne %0, psp" : "=r" (current_sp));
+
+       /* An exception (or interrupt) before entering this handler
+        * places the following on the stack 
+        * 
+        * R0
+        * R1
+        * R2
+        * R3
+        * R12
+        * LR
+        * PC <- placed at current_sp[6]
+        * PSR 
+        *
+        * 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);
 
-       for(;;);
-
-       volatile uint32_t * sp;
-       
-       asm volatile (
-       "tst lr, #4" "\n\t" 
-       "ite eq" "\n\t"
-       "mrseq %0, msp" "\n\t" 
-       "mrsne r0, psp" : "=r" (sp) );
-
-
-       for (int i = 0; (sp + i) < 0x20010000; i++) {
-               printf("ADDRESS: %p, VALUE: %x\n", (sp + i), *(sp + i));
-       }
-
-       for (;;);       
-       //asm ("mov %0, pc" : "=r" (link_register));
-       //printf("%x\n", link_register);
-       
-       volatile uint32_t * svc_number = (uint32_t *) 0x20022222;
-       *svc_number = sp[-6];
-       //              = sp[6];
-       //uint8_t tmp  = link_register[-2];
-       printf("SVC nr: %x", *svc_number);
-       //printf("%d, %d, %d, %d, %d, %d\n", msp[6], msp[0], msp[1], msp[2], msp[3], msp[4]);
-       
        for (;;);
-       //return NULL;  
-       return 0;
 
 }
 
@@ -104,13 +98,8 @@ void syscall(unsigned int * args) {
 
 void syscall_init() {
 
-
        /* SVC is located at position 11 in the interrupt vector table  */
-//     extern void * _syscall;
-       extern void * hardfault;
-
-       ivt_set_gate(11, __svc_handler__, 0);
-
+       ivt_set_gate(11, _svc_handler, 0);
 
 }