Proper interrupt handlers
Proper interrupt handlers for timers (and new peripherals can use them too). Improved interrupt enabling. Improved timer interrupts and fixed minor bugs.
This commit is contained in:
parent
06f000e19a
commit
92e1e261e7
@ -39,6 +39,7 @@ namespace GIC {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void enable(void);
|
void enable(void);
|
||||||
|
void enableInterrupt(const uint16_t m, const TargetCPU target, const Sensitivity sensitivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern "C" void setVectorBAR(void);
|
|
||||||
extern "C" address_t* getVectorBAR(void);
|
|
||||||
|
|
||||||
extern "C" void fireswi(void);
|
extern "C" void fireswi(void);
|
||||||
|
|
||||||
|
namespace interrupt {
|
||||||
|
extern void (*handler[])(const uint8_t cpuID, const uint16_t interruptID);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,8 +43,9 @@ namespace Timer {
|
|||||||
|
|
||||||
class Timer {
|
class Timer {
|
||||||
private:
|
private:
|
||||||
uint8_t n;
|
uint8_t n; /* Timer module number (0-5) */
|
||||||
TimerModule* module;
|
uint16_t src; /* Timer interrupt source line (54-57, 99-100) */
|
||||||
|
TimerModule* module; /* Timer module MMIO config registers */
|
||||||
public:
|
public:
|
||||||
/* Initialize class instance as timer n
|
/* Initialize class instance as timer n
|
||||||
* where n is found on Allwinner datasheet */
|
* where n is found on Allwinner datasheet */
|
||||||
@ -57,6 +58,9 @@ namespace Timer {
|
|||||||
void stop(void);
|
void stop(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Interrupt handler */
|
||||||
|
extern void handler(const uint8_t cpuID, const uint16_t interruptID);
|
||||||
|
|
||||||
/* Vector of system's timers */
|
/* Vector of system's timers */
|
||||||
extern Timer timer[];
|
extern Timer timer[];
|
||||||
|
|
||||||
|
18
src/gic.cpp
18
src/gic.cpp
@ -27,25 +27,9 @@ namespace GIC {
|
|||||||
cpuInterface[1] = 0xff;
|
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) {
|
void enable(void) {
|
||||||
|
|
||||||
enableInterrupt(54, CPU0T, EDGE); /* Timer0 */
|
|
||||||
|
|
||||||
/* Enable distributor and CPU interfaces
|
/* 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 */
|
* since writing on GIC registers is not allowed when it is enabled */
|
||||||
distributor[0] = distributor[GICD_CTLR] | 0x1;
|
distributor[0] = distributor[GICD_CTLR] | 0x1;
|
||||||
cpuInterface[0] = cpuInterface[GICC_CTLR] | 0x1;
|
cpuInterface[0] = cpuInterface[GICC_CTLR] | 0x1;
|
||||||
|
6
src/interrupt.cpp
Normal file
6
src/interrupt.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace interrupt {
|
||||||
|
void (*handler[128])(const uint8_t cpuID, const uint16_t interruptID);
|
||||||
|
}
|
||||||
|
|
@ -15,12 +15,14 @@ extern "C" int main(int argc, char** argv) {
|
|||||||
printkl("Now firing test software interrupt...");
|
printkl("Now firing test software interrupt...");
|
||||||
fireswi();
|
fireswi();
|
||||||
|
|
||||||
printkl("Now enabling GIC interrupts...");
|
|
||||||
GIC::enable();
|
|
||||||
|
|
||||||
printkl("Now enabling timer...");
|
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[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...");
|
printkl("Now going user...");
|
||||||
go_usr();
|
go_usr();
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
|
#include <gic.h>
|
||||||
|
#include <interrupt.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <dbg.h>
|
#include <dbg.h>
|
||||||
|
|
||||||
namespace Timer {
|
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) {
|
Timer::Timer(uint8_t n) {
|
||||||
this->n = 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) {
|
void Timer::set(uint32_t interval, Mode mode, Prescaler prescaler, ClockSource source) {
|
||||||
|
/* attach interrupt handler */
|
||||||
|
interrupt::handler[src] = handler;
|
||||||
|
|
||||||
/* zero fill control registers */
|
/* zero fill control registers */
|
||||||
module->TMR_CTLR_REG = 0;
|
module->TMR_CTLR_REG = 0;
|
||||||
module->TMR_CUR_VALUE_REG = 0;
|
module->TMR_CUR_VALUE_REG = 0;
|
||||||
@ -21,9 +28,9 @@ namespace Timer {
|
|||||||
/* Set timer value */
|
/* Set timer value */
|
||||||
module->TMR_INTV_VALUE_REG = interval;
|
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);
|
peripheral->TMR_IRQ_EN_REG = peripheral->TMR_IRQ_EN_REG | (1 << n);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::start(void) {
|
void Timer::start(void) {
|
||||||
@ -36,4 +43,12 @@ namespace Timer {
|
|||||||
module->TMR_CTLR_REG = module->TMR_CTLR_REG & 0xfffffffe;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,28 @@
|
|||||||
#include <dbg.h>
|
#include <dbg.h>
|
||||||
|
#include <interrupt.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern "C" uint32_t c_irq_handler(uint32_t iar) {
|
extern "C" uint32_t c_irq_handler(uint32_t iar) {
|
||||||
uint8_t cpuID = (iar >> 10) & 0x7;
|
uint8_t cpuID = (iar >> 10) & 0x7;
|
||||||
uint16_t interruptID = iar & 0x3ff;
|
uint16_t interruptID = iar & 0x3ff;
|
||||||
|
|
||||||
|
printk("Serving IRQ #"); printkl(itoa(interruptID));
|
||||||
|
|
||||||
|
void (*handler)(const uint8_t, const uint16_t);
|
||||||
|
|
||||||
if (cpuID == 0) {
|
if (cpuID == 0) {
|
||||||
/* for
|
/* for
|
||||||
* SPI - Shared Peripheral Interrupt
|
* SPI - Shared Peripheral Interrupt
|
||||||
* PPI - Private Peripheral Interrupt
|
* PPI - Private Peripheral Interrupt
|
||||||
*/
|
*/
|
||||||
switch (interruptID) {
|
switch (interruptID) { /* Choose proper interrupt handler */
|
||||||
case 54: /* timer 0 */ /* TODO: improve this ugliness */
|
case 54: case 55: case 56: case 57: case 99: case 100:
|
||||||
uint32_t* const TMR_IRQ_STA_REG = (uint32_t* const)(0x01c20c04);
|
handler = interrupt::handler[interruptID];
|
||||||
*TMR_IRQ_STA_REG = *TMR_IRQ_STA_REG | 0x1;
|
|
||||||
printk("Serving IRQ #");
|
|
||||||
printkl(itoa(interruptID));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Call interrupt handler */
|
||||||
|
handler(cpuID, interruptID);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* for
|
/* for
|
||||||
|
Loading…
Reference in New Issue
Block a user