X-Git-Url: https://robinkrens.nl/gitweb/?a=blobdiff_plain;f=ivt.c;h=a2714871d175f47ad78cf7ae36888a1491d88a14;hb=b530a9c3f72545035278db2c90bc26870d1a38d9;hp=b3854f18c7e50fb085b5463565f7d340e02e1730;hpb=41d25ed67df8b6acd6126c41c8b0882586db0b0d;p=cortex-from-scratch diff --git a/ivt.c b/ivt.c index b3854f1..a271487 100644 --- a/ivt.c +++ b/ivt.c @@ -5,14 +5,32 @@ * Initial version * * $DESCRIPTION$ + * Set up of basic exceptions and interrupts. These interrupts + * don't do much, except for halting the system. + * ivt_set_gate(interrupt nr, function, priority) can be used + * later to define more appropriate handling. See timer (timer.c) + * or serial or (uart.c) handling for non-trivial examples. + * + * The actual code is not much, but there are a lot of details + * to consider. Besides that, in case more control is desired over + * entering and exiting interrupts (what is pushed on the stack) + * A so-called naked function can be used. See below for more + * details. * + * * */ #include #include #include -#include -#include + +#include +#include + +#include +#include +#include +#include /* * These values are pushed on the stack just before @@ -22,7 +40,7 @@ * gives me a little bit more control over the caller * * The following register are pushed to the stack - * in reverse order + * in reverse order: * * */ struct interrupt_frame { @@ -39,68 +57,72 @@ struct interrupt_frame { /* * Vector table, each entry contains an interrupt - * service routine: - * + * service routine: * interrupt vector 1-15: processor exceptions * interrupt vector 16-92: irq0 - irq .. + * Vector table needs to be aligned in memory. * */ - uint32_t __attribute__((aligned(0x100))) ivt[92]; -/* each message corresponds to each and every exception. - * We get the correct message by accessing - * exception_message[interrupt_number] - * exception_message[0] is not used (=MSP)*/ - +/* Each message corresponds to each and every exception. */ char * exception_message(uint8_t intnr) { - char * messages[] = { - "--", - "RESET", - "NMI", - "HARD FAULT", - "MEMMANAGE FAULT", - "BUS FAULT", - "USAGE FAULT", - "RESERVED", - "SVC", - "DEBUG MONITOR", - "RESERVED", - "RESERVED", - "RESERVED", - "RESERVED", - "PENDSV", - "SYSTICK", - "IRQ1", - "IRQ2", - "IRQ3", - "IRQ4", - // add more if needed - }; - - if (intnr < 20) // TODO: strlen - return messages[intnr]; - - return NULL; +char * messages[] = { + "--", + "RESET", + "NMI", + "HARD FAULT", + "MEMMANAGE FAULT", + "BUS FAULT", + "USAGE FAULT", + "RESERVED", + "SVC", + "DEBUG MONITOR", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "PENDSV", + "SYSTICK", + "IRQ1", + "IRQ2", + "IRQ3", + "IRQ4", + // add more if needed +}; + +if (intnr < 20) // TODO: strlen + return messages[intnr]; + +return "UNKNOWN"; } void ivt_set_gate(unsigned char num, void * isr(), short pri) { ivt[num] = (uint32_t) isr; - *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F)); - /* Priorities */ +// if (num <= 32) +// *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F)); + /* TODO: Priorities */ } -/* Dummy interrupt */ -// __attribute__ ((interrupt)) -void * dummy_isr(/* struct interrupt_frame * frame */) { +/* Dummy interrupt: comment out the comment to use a naked + * function */ + +__attribute__ ((interrupt)) +void * dummy_isr( struct interrupt_frame * frame ) { uint8_t nr = *SCB_VTOR_ST & 0xFF; - - uart_puts("EXCEPTION: "); - uart_puts(exception_message(nr)); - uart_puts("\nSYSTEM HALTED\n"); + 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); for(;;); } @@ -108,24 +130,24 @@ void * dummy_isr(/* struct interrupt_frame * frame */) { /* Initialize interrupt vector */ void ivt_init() { - /* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */ + /* clear entire IVT location in memory */ memset(&ivt, 0, (sizeof(uint32_t) * 92)); - // stack top is loaded from the first entry table on boot/reset - // don't need to relocate or init this here + /* The reset, NMI and hardfault handlers are originally + * defined in the assembly start up and can be + * reused or overwritten. + * */ extern void * reset, * nmi, * hardfault; + // set dummy handlers for (int i = 1; i <= 64 ; i++) { ivt_set_gate(i, dummy_isr, 0); } - - /* the vector table starts at 0x0. Since the address 0x0 point to - * bootcode, it is on ROM or FLASH. The vector table can be + /* The vector table is intially at 0x0. The vector table can be * relocated to other memory locations. We can do this by setting * a register in the NVIC called the vector table offset register */ - //*SCB_VTOR = (volatile uint32_t) &ivt; - regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, OWRITE); + rwrite(SCB_VTOR, (uint32_t) &ivt); }