simulavr  1.1.0
timerirq.cpp
Go to the documentation of this file.
1 /*
2  ****************************************************************************
3  *
4  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
5  * Copyright (C) 2001, 2002, 2003 Klaus Rudolph
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  ****************************************************************************
22  *
23  * $Id$
24  */
25 
26 #include "hwtimer/timerirq.h"
27 #include "helper.h"
28 #include "avrerror.h"
29 
31  irqvector(-1),
32  name("") {
33  irqreg = NULL; // set unregistered state
34 }
35 
36 IRQLine::IRQLine(const std::string& n, int irqvec):
37  irqvector(irqvec),
38  name(n) {
39  irqreg = NULL; // set unregistered state
40 }
41 
43  return irqvector != -1;
44 }
45 
48 }
49 
50 static const std::string __hlp2name(const std::string s, int i) {
51  // if i == -2, then precede name with "E", for example "ETIMSK"
52  if(i == -2)
53  return "E" + s;
54  // if then i < 0, let the name unchanged
55  if(i < 0)
56  return s;
57  // in all other cases append i as number
58  return s + int2str(i);
59 }
60 
61 static const std::string __hlp2scope(const std::string p, int i) {
62  // if i == -2, then append "X"
63  if(i == -2)
64  return p + "X";
65  // if then i < 0, let the name unchanged
66  if(i < 0)
67  return p;
68  // in all other cases append i as number
69  return p + int2str(i);
70 }
71 
73  HWIrqSystem* irqsys,
74  int regidx):
75  Hardware(c),
76  TraceValueRegister(c, __hlp2scope("TMRIRQ", regidx)),
77  irqsystem(irqsys),
78  lines(8),
79  timsk_reg(this, __hlp2name("TIMSK", regidx)),
80  tifr_reg(this, __hlp2name("TIFR", regidx))
81 {
84  bitmask = 0;
85  Reset();
86 }
87 
90  // no check, if idx is in right range!
91  irq->irqreg = this;
92  lines[idx] = *irq;
93  vector2line[irq->irqvector] = idx;
94  name2line[irq->name] = idx;
95  bitmask |= 1 << idx;
96 }
97 
98 void TimerIRQRegister::registerLine(int idx, const IRQLine& irq) {
99  IRQLine i = irq;
101  // no check, if idx is in right range!
102  i.irqreg = this;
103  lines[idx] = i;
104  vector2line[i.irqvector] = idx;
105  name2line[i.name] = idx;
106  bitmask |= 1 << idx;
107 }
108 
109 IRQLine* TimerIRQRegister::getLine(const std::string& n) {
110  std::map<std::string, int>::iterator cur = name2line.find(n);
111  if(cur == name2line.end())
112  avr_error("IRQ line '%s' not found", n.c_str());
113  return &lines[name2line[n]];
114 }
115 
116 void TimerIRQRegister::fireInterrupt(int irqvector) {
117  int idx = vector2line[irqvector];
118  irqflags |= (1 << idx);
120  if(irqmask & (1 << idx)) // check irq mask
121  irqsystem->SetIrqFlag(this, irqvector);
122 }
123 
124 void TimerIRQRegister::ClearIrqFlag(unsigned int vector) {
125  int idx = vector2line[vector];
126  irqflags &= ~(1 << idx);
128  irqsystem->ClearIrqFlag(vector);
129 }
130 
132  irqmask = 0;
133  timsk_reg.Reset();
134  irqflags = 0;
135  tifr_reg.Reset();
136 }
137 
138 unsigned char TimerIRQRegister::set_from_reg(const IOSpecialReg* reg, unsigned char nv) {
139  if(reg == &timsk_reg) {
140  // mask register: trigger interrupt, if mask bit is new set and flag is true
141  unsigned int idx = 0;
142  unsigned char m = 1;
143  nv &= bitmask;
144  for(; idx < lines.size(); idx++, m <<= 1) {
145  if(((nv & m) != 0) &&
146  ((irqmask & m) == 0) &&
147  ((irqflags & m) != 0) &&
148  (lines[idx].active()))
149  irqsystem->SetIrqFlag(this, lines[idx].irqvector);
150  }
151  irqmask = nv;
152  } else {
153  // Get all interrupt flags that are actually cleared with this instruction.
154  unsigned char reset = nv & bitmask & irqflags;
155 
156  // reset flag, if written with 1
157  irqflags ^= reset;
158  // Walk through resetting flags beginning with the LSB ...
159  for(unsigned char idx = 0; idx < lines.size(); ++idx)
160  if(reset & (1<<idx))
161  // ... and remove there pending calls from the irq system.
162  ClearIrqFlag(lines[idx].irqvector);
163  }
164 
165  return nv;
166 }
167 
168 unsigned char TimerIRQRegister::get_from_client(const IOSpecialReg* reg, unsigned char v) {
169  // don't use v in this case, all bits under control of TimerIRQRegister
170  // unused bits return 0
171  if(reg == &timsk_reg)
172  return irqmask;
173  else
174  return irqflags;
175 }
176 
Basic AVR device, contains the core functionality.
Definition: avrdevice.h:66
static const std::string __hlp2name(const std::string s, int i)
Definition: timerirq.cpp:50
unsigned char bitmask
mask for used bits in registers
Definition: timerirq.h:70
void hardwareChange(unsigned char val)
Definition: rwmem.h:439
std::vector< IRQLine > lines
list with IRQ lines
Definition: timerirq.h:65
virtual void ClearIrqFlag(unsigned int vector)
Definition: timerirq.cpp:124
virtual unsigned char get_from_client(const IOSpecialReg *reg, unsigned char v)
Definition: timerirq.cpp:168
HWIrqSystem * irqsystem
pointer to irq system
Definition: timerirq.h:64
virtual void Reset(void)
Definition: timerirq.cpp:131
std::map< int, int > vector2line
mapping IRQ vector to index
Definition: timerirq.h:67
int irqvector
the IRQ vector number in interrupt table, starting with 0
Definition: timerirq.h:47
unsigned char irqmask
mask register value;
Definition: timerirq.h:68
Represents a timer interrupt line, Frontend for timer interrupts.
Definition: timerirq.h:42
void Reset(void)
Register reset functionality, sets internal register value to 0.
Definition: rwmem.h:432
std::string name
name of this IRQ line
Definition: timerirq.h:48
void connectSRegClient(IOSpecialRegClient *c)
Registers a client to this IO register to inform this client on read or write access.
Definition: rwmem.h:429
virtual unsigned char set_from_reg(const IOSpecialReg *reg, unsigned char nv)
Definition: timerirq.cpp:138
IOSpecialReg tifr_reg
the TIFRx register
Definition: timerirq.h:74
TimerIRQRegister * irqreg
pointer to irq registers, where this line is hold
Definition: timerirq.h:49
void fireInterrupt(int irqvector)
Definition: timerirq.cpp:116
#define avr_error(...)
Definition: avrerror.h:135
Build a register for TraceValue&#39;s.
Definition: traceval.h:442
IRQLine()
Definition: timerirq.cpp:30
void SetIrqFlag(Hardware *, unsigned int vector_index)
Definition: irqsystem.cpp:243
void fireInterrupt(void)
inform interrupt system, that an interrupt occured
Definition: timerirq.cpp:46
std::string int2str(int i)
Convert an int into a string.
Definition: helper.cpp:59
static const std::string __hlp2scope(const std::string p, int i)
Definition: timerirq.cpp:61
void registerLine(int idx, IRQLine *irq)
Definition: timerirq.cpp:88
unsigned char irqflags
flag register value;
Definition: timerirq.h:69
void DebugVerifyInterruptVector(unsigned int vector_index, const Hardware *source)
In datasheets RESET vector is index 1 but we use 0! And not a byte address.
Definition: irqsystem.cpp:297
IRQLine * getLine(const std::string &name)
Definition: timerirq.cpp:109
void ClearIrqFlag(unsigned int vector_index)
Definition: irqsystem.cpp:258
TimerIRQRegister(AvrDevice *core, HWIrqSystem *irqsys, int regidx=-1)
Definition: timerirq.cpp:72
bool active()
Definition: timerirq.cpp:42
std::map< std::string, int > name2line
mapping IRQ line name to index
Definition: timerirq.h:66
IOSpecialReg timsk_reg
the TIMSKx register
Definition: timerirq.h:73