uart small ping pong receive, update of register functions
[cortex-from-scratch] / ivt.c
1 #include <stdbool.h>
2 #include <stddef.h>
3 #include <stdint.h>
4 #include <stm32.h>
5 #include <mmap.h>
6
7 /* 
8  * These values are pushed on the stack just before
9  * entering the ISR. Normally, this would require
10  * assembly or inline assembly code. I use a so-called
11  * 'naked function' __attribute__ ((interrupt)) which
12  * gives me a little bit more control over the caller
13  *
14  * The following register are pushed to the stack
15  * in reverse order
16  *
17  * */
18 struct interrupt_frame {
19
20         uint32_t r0; // N-32
21         uint32_t r1;
22         uint32_t r2;
23         uint32_t r3;
24         uint32_t r12;
25         uint32_t lr;
26         uint32_t pc;
27         uint32_t psr; // N-4
28 };
29
30 /* 
31  * Vector table, each entry contains an interrupt
32  * service routine:  
33  *
34  * interrupt vector 1-15: processor exceptions
35  * interrupt vector 16-64: irq0 - irq ..
36  * */
37
38 uint32_t ivt[64];
39
40 /* each message corresponds to each and every exception. 
41  * We get the correct message by accessing
42  *  exception_message[interrupt_number] 
43  *  exception_message[0] is not used (=MSP)*/
44 unsigned char *exception_messages[] =
45 {
46     "--",
47     "RESET",
48     "NMI",
49     "HARD FAULT",
50     "MEMMANAGE FAULT",
51     "BUS FAULT",
52     "USAGE FAULT",
53     "RESERVED",
54     "SVC",
55     "DEBUG MONITOR",
56     "RESERVED",
57     "PENDSV",
58     "SYSTICK",
59     "IRQ1",
60     "IRQ2",
61     "IRQ3",
62     "IRQ4",
63     // add more if needed
64 };
65
66 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
67
68         ivt[num] = (uint32_t) isr;
69         *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
70         /* Priorities */
71 }
72
73
74 /* Dummy interrupt */
75 __attribute__ ((interrupt)) 
76 void * dummy_isr(struct interrupt_frame * frame) {
77
78
79         uint32_t * p = (volatile uint32_t *) 0x21000000;
80
81         addrtohex(frame->r0);
82         addrtohex(frame->r1);
83         addrtohex(frame->r2);
84         addrtohex(frame->r3);
85         addrtohex(frame->r12);
86         addrtohex(frame->lr);
87         addrtohex(frame->pc);
88         addrtohex(frame->psr);
89         
90         //__asm__ __volatile__ ("MRS r0, IPSR");
91         //addrtohex(frame->r0);
92         uart_puts("EXCEPTION X: SYSTEM HALTED\n");
93         
94         for(;;);
95 }
96
97 /* Initialize interrupt vector  */
98 void ivt_init() {
99
100         /* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */
101         memset(&ivt, 0, (sizeof(uint32_t) * 87));
102
103         // stack top is loaded from the first entry table on boot/reset
104         // don't need to relocate or init this here
105         extern void * reset,  * nmi, * hardfault;
106
107         for (int i = 1; i < 7; i++) {
108                 ivt_set_gate(i, dummy_isr, 0);
109         }
110
111         /* the vector table starts at 0x0. Since the address 0x0 point to 
112          * bootcode, it is on ROM or FLASH. The vector table can be
113          * relocated to other memory locations. We can do this by setting 
114          * a register in the NVIC called the vector table offset register */
115
116         //*SCB_VTOR = (volatile uint32_t) &ivt; 
117         regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, 0x01);
118
119 }