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
14 * The following register are pushed to the stack
18 struct interrupt_frame {
31 * Vector table, each entry contains an interrupt
34 * interrupt vector 1-15: processor exceptions
35 * interrupt vector 16-92: irq0 - irq ..
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)*/
45 char * exception_message(uint8_t intnr) {
71 if (intnr < 20) // TODO: strlen
72 return messages[intnr];
77 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
79 ivt[num] = (uint32_t) isr;
80 *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
86 __attribute__ ((interrupt))
87 void * dummy_isr(struct interrupt_frame * frame) {
89 uint8_t nr = *SCB_VTOR_ST & 0xFF;
91 uart_puts("EXCEPTION: ");
92 uart_puts(exception_message(nr));
93 uart_puts("\nSYSTEM HALTED\n");
98 /* Initialize interrupt vector */
101 /* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */
102 memset(&ivt, 0, (sizeof(uint32_t) * 92));
104 // stack top is loaded from the first entry table on boot/reset
105 // don't need to relocate or init this here
106 extern void * reset, * nmi, * hardfault;
108 for (int i = 1; i <= 6 ; i++) {
109 ivt_set_gate(i, dummy_isr, 0);
112 /* the vector table starts at 0x0. Since the address 0x0 point to
113 * bootcode, it is on ROM or FLASH. The vector table can be
114 * relocated to other memory locations. We can do this by setting
115 * a register in the NVIC called the vector table offset register */
117 //*SCB_VTOR = (volatile uint32_t) &ivt;
118 regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, 0x01);