#include #include "interrupts.h" namespace { constexpr uint32_t kMstatusMieMask = 1 << 3; constexpr uint32_t kMieExternalInterruptMask = 1 << 11; constexpr uint32_t kExternalInterruptCause = 0x0b; constexpr uint32_t kInterruptCauseMask = 0xff; Isr external_handler = nullptr; __attribute__((interrupt)) void TrapHandler() { uint32_t mcause; uint32_t mip; asm volatile("csrr %0, mcause" : "=r"(mcause)); asm volatile("csrr %0, mip" : "=r"(mip)); // check for external interrupt if ((mcause & kInterruptCauseMask) == kExternalInterruptCause) { if (external_handler != nullptr) { external_handler(); } mip &= ~(kMieExternalInterruptMask); asm volatile("csrw mip, %0" :: "r"(mip)); } } } void SetExternalInterruptHandler(Isr handler) { external_handler = handler; } void EnableExternalInterrupts() { uint32_t mstatus; uint32_t mie; Isr trap = TrapHandler; asm volatile("csrr %0, mstatus" : "=r"(mstatus)); asm volatile("csrr %0, mie" : "=r"(mie)); asm volatile("csrw mtvec, %0" :: "r"(trap)); mie |= kMieExternalInterruptMask; asm volatile("csrw mie, %0" :: "r"(mie)); mstatus |= kMstatusMieMask; asm volatile("csrw mstatus, %0" :: "r"(mstatus)); }