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.
63 lines
1.1 KiB
C++
63 lines
1.1 KiB
C++
#include "intc.h"
|
|
|
|
#include "pol0.h"
|
|
|
|
namespace {
|
|
|
|
struct IntC {
|
|
volatile uint32_t ISR;
|
|
volatile uint32_t IPR;
|
|
volatile uint32_t IER;
|
|
volatile uint32_t IAR;
|
|
volatile uint32_t SIE;
|
|
volatile uint32_t CIE;
|
|
volatile uint32_t IVR;
|
|
volatile uint32_t MER;
|
|
volatile uint32_t IMR;
|
|
volatile uint32_t ILR;
|
|
|
|
// the rest is not enabled
|
|
};
|
|
|
|
IntC* intc = reinterpret_cast<IntC*>(INTC_BASE);
|
|
Isr isrs[NIRQ] = {};
|
|
|
|
}
|
|
|
|
bool SetIrqEnabled(uint8_t irqn, bool enabled) {
|
|
uint32_t mask = 1 << irqn;
|
|
uint32_t ier = intc->IER;
|
|
bool was_enabled = (ier & (~mask)) > 0;
|
|
if (enabled) {
|
|
intc->IER = ier | mask;
|
|
} else {
|
|
intc->IER = ier & (~mask);
|
|
}
|
|
|
|
return was_enabled;
|
|
}
|
|
|
|
void SetIsr(uint8_t irqn, Isr isr) {
|
|
isrs[irqn] = isr;
|
|
}
|
|
|
|
void EnableInterrupts() {
|
|
intc->MER = 0x3;
|
|
}
|
|
|
|
void InterruptHandler() {
|
|
uint32_t ipr = intc->IPR;
|
|
|
|
for (int i = 0; i < NIRQ; i++) {
|
|
uint32_t mask = 1 << i;
|
|
|
|
if ((ipr & mask) > 0) {
|
|
// interrupt pending
|
|
if (isrs[i] != nullptr) {
|
|
isrs[i]();
|
|
}
|
|
intc->IAR = mask; // ack
|
|
}
|
|
}
|
|
}
|