55 lines
1.7 KiB
C++
55 lines
1.7 KiB
C++
#include <gic.h>
|
|
#include <interrupt.h>
|
|
#include <timer.h>
|
|
#include <dbg.h>
|
|
|
|
namespace Timer {
|
|
|
|
Timer timer[6] = { Timer(0), Timer(1), Timer(2), Timer(3), Timer(4), Timer(5) };
|
|
|
|
Timer::Timer(uint8_t n) {
|
|
this->n = 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;
|
|
|
|
/* Set controls: mode, prescaler and source */
|
|
module->TMR_CTLR_REG = (mode << 7) | (prescaler << 4) | (source << 2);
|
|
|
|
/* Set timer value */
|
|
module->TMR_INTV_VALUE_REG = interval;
|
|
|
|
/* 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) {
|
|
/* Reload interval value and start */
|
|
module->TMR_CTLR_REG = module->TMR_CTLR_REG | 0x3;
|
|
}
|
|
|
|
void Timer::stop(void) {
|
|
/* Clear stop/pause bit */
|
|
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);
|
|
}
|
|
|
|
}
|