00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "timerirq.h"
00027 #include "helper.h"
00028 #include "avrerror.h"
00029
00030 IRQLine::IRQLine(const std::string& n, int irqvec):
00031 irqvector(irqvec),
00032 name(n) {
00033 irqreg = NULL;
00034 }
00035
00036 void IRQLine::fireInterrupt(void) {
00037 if(irqreg) irqreg->fireInterrupt(irqvector);
00038 }
00039
00040 static const std::string __hlp2name(const std::string s, int i) {
00041
00042 if(i == -2)
00043 return "E" + s;
00044
00045 if(i < 0)
00046 return s;
00047
00048 return s + int2str(i);
00049 }
00050
00051 static const std::string __hlp2scope(const std::string p, int i) {
00052
00053 if(i == -2)
00054 return p + "X";
00055
00056 if(i < 0)
00057 return p;
00058
00059 return p + int2str(i);
00060 }
00061
00062 TimerIRQRegister::TimerIRQRegister(AvrDevice* c,
00063 HWIrqSystem* irqsys,
00064 int regidx):
00065 Hardware(c),
00066 TraceValueRegister(c, __hlp2scope("TMRIRQ", regidx)),
00067 core(c),
00068 irqsystem(irqsys),
00069 lines(8),
00070 timsk_reg(this, __hlp2name("TIMSK", regidx)),
00071 tifr_reg(this, __hlp2name("TIFR", regidx))
00072 {
00073 timsk_reg.connectSRegClient(this);
00074 tifr_reg.connectSRegClient(this);
00075 bitmask = 0;
00076 Reset();
00077 }
00078
00079 void TimerIRQRegister::registerLine(int idx, IRQLine* irq) {
00080 irqsystem->DebugVerifyInterruptVector(irq->irqvector, this);
00081
00082 irq->irqreg = this;
00083 lines[idx] = irq;
00084 vector2line[irq->irqvector] = idx;
00085 name2line[irq->name] = idx;
00086 bitmask |= 1 << idx;
00087 }
00088
00089 IRQLine* TimerIRQRegister::getLine(const std::string& n) {
00090 std::map<std::string, int>::iterator cur = name2line.find(n);
00091 if(cur == name2line.end())
00092 avr_error("IRQ line '%s' not found", n.c_str());
00093 return lines[name2line[n]];
00094 }
00095
00096 void TimerIRQRegister::fireInterrupt(int irqvector) {
00097 int idx = vector2line[irqvector];
00098 irqflags |= (1 << idx);
00099 tifr_reg.hardwareChange(irqflags);
00100 if(irqmask & (1 << idx))
00101 irqsystem->SetIrqFlag(this, irqvector);
00102 }
00103
00104 void TimerIRQRegister::ClearIrqFlag(unsigned int vector) {
00105 int idx = vector2line[vector];
00106 irqflags &= ~(1 << idx);
00107 tifr_reg.hardwareChange(irqflags);
00108 irqsystem->ClearIrqFlag(vector);
00109 }
00110
00111 void TimerIRQRegister::Reset(void) {
00112 irqmask = 0;
00113 timsk_reg.Reset();
00114 irqflags = 0;
00115 tifr_reg.Reset();
00116 }
00117
00118 unsigned char TimerIRQRegister::set_from_reg(const IOSpecialReg* reg, unsigned char nv) {
00119 if(reg == &timsk_reg) {
00120
00121 int idx = 0;
00122 unsigned char m = 1;
00123 nv &= bitmask;
00124 for(; idx < lines.size(); idx++, m <<= 1) {
00125 if(((nv & m) != 0) &&
00126 ((irqmask & m) == 0) &&
00127 ((irqflags & m) != 0) &&
00128 (lines[idx] != NULL))
00129 irqsystem->SetIrqFlag(this, lines[idx]->irqvector);
00130 }
00131 irqmask = nv;
00132 } else {
00133
00134 unsigned char reset = nv & bitmask & irqflags;
00135
00136
00137 irqflags ^= reset;
00138
00139 for(unsigned char idx = 0; idx < lines.size(); ++idx)
00140 if(reset & (1<<idx))
00141
00142 ClearIrqFlag(lines[idx]->irqvector);
00143 }
00144
00145 return nv;
00146 }
00147
00148 unsigned char TimerIRQRegister::get_from_client(const IOSpecialReg* reg, unsigned char v) {
00149
00150
00151 if(reg == &timsk_reg)
00152 return irqmask;
00153 else
00154 return irqflags;
00155 }
00156