/*
* 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
uint32_t lr;
uint32_t pc;
uint32_t psr; // N-4
-};
+} frame;
/*
* Vector table, each entry contains an interrupt
* */
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[] = {
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(;;);
}
#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;
}
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);
}