#pragma once #include /** Reference to the global ISR vector. */ extern char isr_vector; /** Default IRQ handler. This is weakly defined and can be overridden. */ void default_irq_handler(void); /** Weakly defined interrput service routine vectors. These just alias to * default_irq_handler if not overridden. */ void irq_on_reset(void); void irq_on_nmi(void); void irq_on_exc(void); void irq_on_systick(void); void irq_on_swi(void); void irq_on_tmr0(void); void irq_on_gpio_a(void); void irq_on_gpio_b(void); void irq_on_spi0(void); void irq_on_blel(void); void irq_on_bleb(void); void irq_on_usb(void); void irq_on_tmr1(void); void irq_on_tmr2(void); void irq_on_uart0(void); void irq_on_uart1(void); void irq_on_rtc(void); void irq_on_adc(void); void irq_on_pwmx(void); void irq_on_tmr3(void); void irq_on_uart2(void); void irq_on_uart3(void); void irq_on_wdog_bat(void); /* * Macro to define an interrput service routine. */ #define IRQ(name) \ /* Real interrupt service routine. This contains most of the code to handle \ * the interrupt. */ \ static void __attribute__((noinline)) _real__irq_on_##name(void); \ /* The actual routine that's jumped to. It's soley responsible for jumping \ * to the real handler (which requires multiple instructions because it's a \ * long jump). This stub is compiled and linked promimal to the ISR vector. \ */ \ void __attribute__((interrupt)) \ __attribute__((__section__(".isr_vector.routines"))) irq_on_##name(void) \ { \ _real__irq_on_##name(); \ } \ static void __attribute__((noinline)) _real__irq_on_##name(void) inline static void enable_interrupts() { int mstatus; asm volatile ("csrr %0, mstatus" : "=r"(mstatus)); mstatus |= 0x88; asm volatile ("csrw mstatus, %0" : : "r"(mstatus)); } inline static void disable_interrupts() { int mstatus; asm volatile ("csrr %0, mstatus" : "=r"(mstatus)); mstatus &= ~0x88; asm volatile ("csrw mstatus, %0" : : "r"(mstatus)); }