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.
53 lines
1.3 KiB
C++
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));
|
|
}
|