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 enableInterrupt(const uint16_t m, const TargetCPU target, const Sensitivity sensitivity);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
@ -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[];
|
||||
|
||||
|
18
src/gic.cpp
18
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;
|
||||
|
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...");
|
||||
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();
|
||||
|
@ -1,16 +1,23 @@
|
||||
#include <gic.h>
|
||||
#include <interrupt.h>
|
||||
#include <timer.h>
|
||||
#include <dbg.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,23 +1,28 @@
|
||||
#include <dbg.h>
|
||||
#include <interrupt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user