synth/mbv/hal/interrupts.cc
Paul Mathieu 3db383d461 mbv: now with functioning timer interrupts!
And a few other nice things.
The bootloader now has an embedded wozmon!
If you know its offset, you can jump to it from the app.
2025-06-10 23:46:43 -07:00

53 lines
1.3 KiB
C++

#include <cstdint>
#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));
}