diff --git a/include/gic.h b/include/gic.h index 4296625..34386b5 100644 --- a/include/gic.h +++ b/include/gic.h @@ -39,6 +39,7 @@ namespace GIC { }; void enable(void); + void enableInterrupt(const uint16_t m, const TargetCPU target, const Sensitivity sensitivity); } #endif diff --git a/include/interrupt.h b/include/interrupt.h index 4f31bcf..a76ff86 100644 --- a/include/interrupt.h +++ b/include/interrupt.h @@ -3,10 +3,10 @@ #include -extern "C" void setVectorBAR(void); -extern "C" address_t* getVectorBAR(void); - extern "C" void fireswi(void); +namespace interrupt { + extern void (*handler[])(const uint8_t cpuID, const uint16_t interruptID); +} #endif diff --git a/include/timer.h b/include/timer.h index d7b55d0..f240271 100644 --- a/include/timer.h +++ b/include/timer.h @@ -43,8 +43,9 @@ namespace Timer { class Timer { private: - uint8_t n; - TimerModule* module; + uint8_t n; /* Timer module number (0-5) */ + uint16_t src; /* Timer interrupt source line (54-57, 99-100) */ + TimerModule* module; /* Timer module MMIO config registers */ public: /* Initialize class instance as timer n * where n is found on Allwinner datasheet */ @@ -57,6 +58,9 @@ namespace Timer { void stop(void); }; + /* Interrupt handler */ + extern void handler(const uint8_t cpuID, const uint16_t interruptID); + /* Vector of system's timers */ extern Timer timer[]; diff --git a/src/gic.cpp b/src/gic.cpp index b7b976d..650b76e 100644 --- a/src/gic.cpp +++ b/src/gic.cpp @@ -27,25 +27,9 @@ namespace GIC { cpuInterface[1] = 0xff; } - void printDistributorStatus(void) { - for (short i = 0; i < 1024; ++i) { - printk("Distributor "); printk(itoa(i * 4)); printk(" : "); - printkl(itoa(distributor[i])); - } - } - void printCPUInterfaceStatus(void) { - for (short i = 0; i < 64; ++i) { - printk("CPUInterface "); printk(itoa(i * 4)); printk(" : "); - printkl(itoa(cpuInterface[i])); - } - } - void enable(void) { - - enableInterrupt(54, CPU0T, EDGE); /* Timer0 */ - /* Enable distributor and CPU interfaces - * Do this always at the end, + * Call this function always at the end, * since writing on GIC registers is not allowed when it is enabled */ distributor[0] = distributor[GICD_CTLR] | 0x1; cpuInterface[0] = cpuInterface[GICC_CTLR] | 0x1; diff --git a/src/interrupt.cpp b/src/interrupt.cpp new file mode 100644 index 0000000..2edb4e7 --- /dev/null +++ b/src/interrupt.cpp @@ -0,0 +1,6 @@ +#include + +namespace interrupt { + void (*handler[128])(const uint8_t cpuID, const uint16_t interruptID); +} + diff --git a/src/kernel.cpp b/src/kernel.cpp index a8b7098..ed79749 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -15,12 +15,14 @@ extern "C" int main(int argc, char** argv) { printkl("Now firing test software interrupt..."); fireswi(); - printkl("Now enabling GIC interrupts..."); - GIC::enable(); - printkl("Now enabling timer..."); - Timer::timer[0].set(0x80, Timer::CONTINUOUS, Timer::PRESCALER_128, Timer::LS_OSC); + Timer::timer[0].set(0x100, Timer::CONTINUOUS, Timer::PRESCALER_128, Timer::LS_OSC); Timer::timer[0].start(); + Timer::timer[5].set(0x100, Timer::CONTINUOUS, Timer::PRESCALER_16, Timer::LS_OSC); + Timer::timer[5].start(); + + printkl("Now enabling GIC..."); + GIC::enable(); printkl("Now going user..."); go_usr(); diff --git a/src/timer.cpp b/src/timer.cpp index 691032b..8dbd98a 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -1,16 +1,23 @@ +#include +#include #include #include namespace Timer { - Timer timer[3] = { Timer(0), Timer(1), Timer(2) }; + Timer timer[6] = { Timer(0), Timer(1), Timer(2), Timer(3), Timer(4), Timer(5) }; Timer::Timer(uint8_t n) { this->n = n; - module = (TimerModule*)(TMR_MODULE_BASE + n); + if (n >= 0 && n <= 3) this->src = 54 + n; + if (n >= 4 && n <= 5) this->src = 99 - 4 + n; + module = (TimerModule*)(TMR_MODULE_BASE + n * 4); } void Timer::set(uint32_t interval, Mode mode, Prescaler prescaler, ClockSource source) { + /* attach interrupt handler */ + interrupt::handler[src] = handler; + /* zero fill control registers */ module->TMR_CTLR_REG = 0; module->TMR_CUR_VALUE_REG = 0; @@ -21,9 +28,9 @@ namespace Timer { /* Set timer value */ module->TMR_INTV_VALUE_REG = interval; - /* Enable interrupt */ + /* Enable interrupt in GIC and set interrupt handler */ + GIC::enableInterrupt(src, GIC::CPU0T, GIC::EDGE); peripheral->TMR_IRQ_EN_REG = peripheral->TMR_IRQ_EN_REG | (1 << n); - } void Timer::start(void) { @@ -36,4 +43,12 @@ namespace Timer { module->TMR_CTLR_REG = module->TMR_CTLR_REG & 0xfffffffe; } + void handler(const uint8_t cpuID, const uint16_t interruptID) { + uint16_t n; + if (interruptID >= 54 && interruptID <= 57) n = interruptID - 54; + if (interruptID >= 99 && interruptID <= 100) n = interruptID - 99 + 4; + + peripheral->TMR_IRQ_STA_REG = peripheral->TMR_IRQ_STA_REG | (1 << n); + } + } diff --git a/src/vectab.cpp b/src/vectab.cpp index 905ff89..36ed04f 100644 --- a/src/vectab.cpp +++ b/src/vectab.cpp @@ -1,23 +1,28 @@ #include +#include #include extern "C" uint32_t c_irq_handler(uint32_t iar) { uint8_t cpuID = (iar >> 10) & 0x7; uint16_t interruptID = iar & 0x3ff; + printk("Serving IRQ #"); printkl(itoa(interruptID)); + + void (*handler)(const uint8_t, const uint16_t); + if (cpuID == 0) { /* for * SPI - Shared Peripheral Interrupt * PPI - Private Peripheral Interrupt */ - switch (interruptID) { - case 54: /* timer 0 */ /* TODO: improve this ugliness */ - uint32_t* const TMR_IRQ_STA_REG = (uint32_t* const)(0x01c20c04); - *TMR_IRQ_STA_REG = *TMR_IRQ_STA_REG | 0x1; - printk("Serving IRQ #"); - printkl(itoa(interruptID)); + switch (interruptID) { /* Choose proper interrupt handler */ + case 54: case 55: case 56: case 57: case 99: case 100: + handler = interrupt::handler[interruptID]; break; } + + /* Call interrupt handler */ + handler(cpuID, interruptID); } else { /* for