1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/7/20 - ROBIN KRENS
8 * Set up of basic exceptions and interrupts. These interrupts
9 * don't do much, except for halting the system.
10 * ivt_set_gate(interrupt nr, function, priority) can be used
11 * later to define more appropriate handling. See timer (timer.c)
12 * or serial or (uart.c) handling for non-trivial examples.
14 * The actual code is not much, but there are a lot of details
15 * to consider. Besides that, in case more control is desired over
16 * entering and exiting interrupts (what is pushed on the stack)
17 * A so-called naked function can be used. See below for more
27 #include <sys/robsys.h>
30 #include <lib/stdio.h>
31 #include <lib/string.h>
32 #include <lib/regfunc.h>
35 * These values are pushed on the stack just before
36 * entering the ISR. Normally, this would require
37 * assembly or inline assembly code. I use a so-called
38 * 'naked function' __attribute__ ((interrupt)) which
39 * gives me a little bit more control over the caller
41 * The following register are pushed to the stack
45 struct interrupt_frame {
58 * Vector table, each entry contains an interrupt
61 * interrupt vector 1-15: processor exceptions
62 * interrupt vector 16-92: irq0 - irq ..
64 * Vector table needs to be aligned in memory.
67 uint32_t __attribute__((aligned(0x100))) ivt[92];
69 /* each message corresponds to each and every exception.
70 * We get the correct message by accessing
71 * exception_message[interrupt_number]
72 * exception_message[0] is not used (=MSP)*/
74 char * exception_message(uint8_t intnr) {
100 if (intnr < 20) // TODO: strlen
101 return messages[intnr];
106 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
108 ivt[num] = (uint32_t) isr;
109 *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
114 /* Dummy interrupt: comment out the comment to use a naked f
117 // __attribute__ ((interrupt))
118 void * dummy_isr(/* struct interrupt_frame * frame */) {
120 uint8_t nr = *SCB_VTOR_ST & 0xFF;
122 cputs("EXCEPTION: ");
123 cputs(exception_message(nr));
124 cputs("\nSYSTEM HALTED\n");
129 /* Initialize interrupt vector */
132 /* clear entire IVT, in SRAM location for SRAM + .data (in .bss section) */
133 memset(&ivt, 0, (sizeof(uint32_t) * 92));
135 // stack top is loaded from the first entry table on boot/reset
136 // don't need to relocate or init this here
137 extern void * reset, * nmi, * hardfault;
139 for (int i = 1; i <= 64 ; i++) {
140 ivt_set_gate(i, dummy_isr, 0);
143 /* The vector table is intially at 0x0. The vector table can be
144 * relocated to other memory locations. We can do this by setting
145 * a register in the NVIC called the vector table offset register */
147 regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, OWRITE);