simulavr  1.1.0
hweeprom.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 "hweeprom.h"
27 #include "avrdevice.h"
28 #include "systemclock.h"
29 #include "irqsystem.h"
30 #include "avrerror.h"
31 #include <assert.h>
32 
33 using namespace std;
34 
36  HWIrqSystem *_irqSystem,
37  unsigned int size,
38  unsigned int irqVec,
39  int devMode):
40  Hardware(_core),
41  Memory(size),
42  TraceValueRegister(_core, "EEPROM"),
43  core(_core),
44  irqSystem(_irqSystem),
45  irqVectorNo(irqVec),
46  eearh_reg(this, "EEARH",
47  this, &HWEeprom::GetEearh, &HWEeprom::SetEearh),
48  eearl_reg(this, "EEARL",
49  this, &HWEeprom::GetEearl, &HWEeprom::SetEearl),
50  eedr_reg(this, "EEDR",
51  this, &HWEeprom::GetEedr, &HWEeprom::SetEedr),
52  eecr_reg(this, "EECR",
53  this, &HWEeprom::GetEecr, &HWEeprom::SetEecr)
54 {
55  if(irqSystem)
57 
58  // in a "fresh" device eeprom is initialized to 0xff like flash too
59  for(unsigned int tt = 0; tt < size; tt++)
60  myMemory[tt] = 0xff;
61 
62  // operation duration, see datasheets for time!
63  if(devMode == DEVMODE_NORMAL) {
64  eraseWriteDelayTime = 8500000LL; // 8.5ms
65  eraseDelayTime = 0LL; // isn't available in this op mode!
66  writeDelayTime = 0LL; // isn't available in this op mode!
67  } else if(devMode == DEVMODE_AT90S) {
68  eraseWriteDelayTime = 4000000LL; // 4.0ms
69  eraseDelayTime = 0LL; // isn't available in this op mode!
70  writeDelayTime = 0LL; // isn't available in this op mode!
71  } else {
72  eraseWriteDelayTime = 3400000LL; // 3.4ms
73  eraseDelayTime = 1800000LL; // 1.8ms
74  writeDelayTime = 1800000LL; // 1.8ms
75  }
76 
77  // in normal mode only erase + write in one operation is available
78  if((devMode == DEVMODE_NORMAL) || (devMode == DEVMODE_AT90S)) {
79  if(irqSystem == NULL)
80  eecr_mask = 0x07; // without operation mode bits and irq enable
81  else
82  eecr_mask = 0x0f; // without operation mode bits
83  } else
84  eecr_mask = 0x3f; // with operation mode bits
85  eecr = 0;
86 
87  eear_mask = (size - 1); // mask out all not significant MSB's, assumes that
88  // size is a 2^n value! This limits also access to
89  // wrong myMemory places.
90  eear = 0;
91 
93 
94  Reset();
95 }
96 
98  eecr &= 0x32; // bit 1 reflect EEPROM statemachine state before reset!
99  // bit 4 and bit 5 are operation modes, which are hold over reset
100  eedr = 0;
101 
102  opEnableCycles = 0;
103  cpuHoldCycles = 0;
104 }
105 
106 
109  myMemory = NULL; // to prevent a double-free error!
110 }
111 
112 void HWEeprom::SetEearl(unsigned char val) {
113  eear = ((eear & 0xff00) + val) & eear_mask;
114  if(core->trace_on == 1)
115  traceOut << "EEAR=0x" << hex << eear << dec;
116 }
117 
118 void HWEeprom::SetEearh(unsigned char val) {
119  if((GetSize() <= 256) && (val != 0))
120  avr_warning("invalid write access: EEARH=0x%02x, EEPROM size <= 256 byte", val);
121  eear = ((eear & 0x00ff) + (val << 8)) & eear_mask;
122  if(core->trace_on == 1)
123  traceOut << "EEAR=0x" << hex << eear << dec;
124 }
125 
126 void HWEeprom::SetEedr(unsigned char val) {
127  eedr = val;
128  if(core->trace_on == 1)
129  traceOut << "EEDR=0x"<< hex << (unsigned int)eedr << dec;
130 }
131 
132 void HWEeprom::SetEecr(unsigned char newval) {
133  if(core->trace_on == 1)
134  traceOut << "EECR=0x" << hex << (unsigned int)newval << dec;
135 
136  eecr = newval & eecr_mask;
137 
138  switch(opState) {
139 
140  default:
141  case OPSTATE_READY:
142  // enable write mode
143  if((eecr & CTRL_ENABLE) == CTRL_ENABLE) {
145  opEnableCycles = 4;
146  core->AddToCycleList(this);
147  }
148  // read will be processed immediately
149  if((eecr & CTRL_READ) == CTRL_READ) {
150  cpuHoldCycles = 4;
151  assert(eear < size);
152  eedr = myMemory[eear];
153  eecr &= ~CTRL_READ; // reset read bit isn't described in document!
154  core->AddToCycleList(this);
155  if(core->trace_on == 1)
156  traceOut << " EEPROM: Read = 0x" << hex << (unsigned int)eedr << dec;
157  }
158  // write will not processed
159  eecr &= ~CTRL_WRITE;
160  break;
161 
162  case OPSTATE_ENABLED:
163  // enable bit will be hold in this state
164  eecr |= CTRL_ENABLE;
165  // read will be processed immediately
166  if((eecr & CTRL_READ) == CTRL_READ) {
167  cpuHoldCycles = 4; // Datasheet: "When the EEPROM is read, the CPU is halted for four cycles"
168  assert(eear < size);
169  eedr = myMemory[eear];
170  eecr &= ~CTRL_READ; // reset read bit isn't described in document!
171  if(core->trace_on == 1)
172  traceOut << " EEPROM: Read = 0x" << hex << (unsigned int)eedr << dec;
173  break; // to ignore possible write request!
174  }
175  // start write operation
176  if((eecr & CTRL_WRITE) == CTRL_WRITE) {
177  cpuHoldCycles = 2; // Datasheet: "When EEWE has been set, the CPU is halted for two cycles"
178  // abort enable state, switch to write state
179  opMode = eecr & CTRL_MODES;
180  opAddr = eear;
181  assert(opAddr < size);
183  opEnableCycles = 0;
184  eecr &= ~CTRL_ENABLE;
185  // start timer ...
187  switch(opMode & CTRL_MODES) {
188  default:
191  break;
192  case CTRL_MODE_ERASE:
193  t = eraseDelayTime;
194  break;
195  case CTRL_MODE_WRITE:
196  t = writeDelayTime;
197  break;
198  }
200  if(core->trace_on == 1)
201  traceOut << " EEPROM: Write start";
202  }
203  break;
204 
205  case OPSTATE_WRITE:
206  // enable write mode, mode change will not happen!
207  if((eecr & CTRL_ENABLE) == CTRL_ENABLE) {
208  opEnableCycles = 4;
209  }
210  // read is ignored here
211  eecr &= ~CTRL_READ;
212  // write is hold
213  eecr |= CTRL_WRITE;
214  break;
215 
216  }
217 }
218 
219 unsigned int HWEeprom::CpuCycle() {
220 
221  // handle enable state and fallback to ready
222  if(opEnableCycles > 0) {
223  opEnableCycles--;
224  if(opEnableCycles == 0) {
225  eecr &= ~CTRL_ENABLE;
226  if(opState == OPSTATE_ENABLED)
228  if(core->trace_on == 1)
229  traceOut << " EEPROM: WriteEnable cleared";
230  }
231  }
232 
233  // handle write state
234  if(opState == OPSTATE_WRITE) {
235  if(SystemClock::Instance().GetCurrentTime() >= writeDoneTime) {
236  // go to ready state
238  // reset write enable bit
239  eecr &= ~CTRL_WRITE;
240  assert(opAddr < size);
241  // process operation
242  switch(opMode & CTRL_MODES) {
243  default:
245  myMemory[opAddr] = eedr;
246  break;
247  case CTRL_MODE_ERASE:
248  myMemory[opAddr] = 0xff;
249  break;
250  case CTRL_MODE_WRITE:
252  break;
253  }
254  if(core->trace_on == 1)
255  traceOut << " EEPROM: Write done";
256  // now raise irq if enabled and available
257  if((irqSystem != NULL) && ((eecr & CTRL_IRQ) == CTRL_IRQ))
259  }
260  }
261 
262  // deactivate engine, if not used
263  if((opState == OPSTATE_READY) && (cpuHoldCycles == 0) && (opEnableCycles == 0))
264  core->RemoveFromCycleList(this);
265 
266  // handle cpu hold state
267  if(cpuHoldCycles > 0) {
268  cpuHoldCycles--;
269  return 1;
270  } else
271  return 0;
272 
273 }
274 
275 void HWEeprom::ClearIrqFlag(unsigned int vector) {
276  if(vector == irqVectorNo)
278 }
279 
280 void HWEeprom::WriteAtAddress(unsigned int addr, unsigned char val) {
281  myMemory[addr] = val;
282 }
283 
284 unsigned char HWEeprom::ReadFromAddress( unsigned int addr) {
285  return myMemory[addr];
286 }
287 
288 void HWEeprom::WriteMem(const unsigned char *src, unsigned int offset, unsigned int secSize) {
289  for(unsigned int tt = 0; tt < secSize; tt++) {
290  if(tt + offset < size) {
291  *(myMemory + tt + offset) = src[tt];
292  }
293  }
294 }
295 
Basic AVR device, contains the core functionality.
Definition: avrdevice.h:66
int opMode
Definition: hweeprom.h:48
unsigned char * myMemory
Definition: memory.h:45
void AddToCycleList(Hardware *hw)
Definition: avrdevice.cpp:51
SystemClockOffset GetCurrentTime() const
Returns the current simulation time.
Definition: systemclock.h:95
unsigned char ReadFromAddress(unsigned int)
Definition: hweeprom.cpp:284
void avr_free(void *ptr)
Free malloc&#39;d memory.
Definition: avrmalloc.cpp:182
unsigned int opAddr
Definition: hweeprom.h:49
SystemClockOffset writeDoneTime
Definition: hweeprom.h:53
int opEnableCycles
Definition: hweeprom.h:45
#define traceOut
Definition: avrerror.h:121
unsigned int irqVectorNo
Definition: hweeprom.h:44
STL namespace.
void ClearIrqFlag(unsigned int vector)
Definition: hweeprom.cpp:275
int opState
Definition: hweeprom.h:47
void WriteAtAddress(unsigned int, unsigned char)
Definition: hweeprom.cpp:280
HWIrqSystem * irqSystem
Definition: hweeprom.h:43
void SetEearh(unsigned char)
Definition: hweeprom.cpp:118
void SetEedr(unsigned char)
Definition: hweeprom.cpp:126
SystemClockOffset writeDelayTime
Definition: hweeprom.h:52
SystemClockOffset eraseDelayTime
Definition: hweeprom.h:51
void WriteMem(const unsigned char *, unsigned int offset, unsigned int size)
Definition: hweeprom.cpp:288
Build a register for TraceValue&#39;s.
Definition: traceval.h:442
void Reset()
Definition: hweeprom.cpp:97
unsigned char eedr
Definition: hweeprom.h:42
static SystemClock & Instance()
Returns the central SystemClock instance for the application.
void SetIrqFlag(Hardware *, unsigned int vector_index)
Definition: irqsystem.cpp:243
unsigned int GetSize()
Definition: memory.h:85
HWEeprom(AvrDevice *core, HWIrqSystem *irqs, unsigned int size, unsigned int irqVec, int devMode=DEVMODE_NORMAL)
Definition: hweeprom.cpp:35
long long SystemClockOffset
unsigned char eecr_mask
Definition: hweeprom.h:41
unsigned int size
Definition: memory.h:41
void SetEecr(unsigned char)
Definition: hweeprom.cpp:132
void SetEearl(unsigned char)
Definition: hweeprom.cpp:112
unsigned int eear_mask
Definition: hweeprom.h:39
unsigned char eecr
Definition: hweeprom.h:40
Hold a memory block and symbol informations.
Definition: memory.h:38
#define avr_warning(...)
Definition: avrerror.h:133
void RemoveFromCycleList(Hardware *hw)
Removes from the cycle list, if possible.
Definition: avrdevice.cpp:56
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
AvrDevice * core
Definition: hweeprom.h:37
int trace_on
Definition: avrdevice.h:90
virtual ~HWEeprom()
Definition: hweeprom.cpp:107
int cpuHoldCycles
Definition: hweeprom.h:46
void ClearIrqFlag(unsigned int vector_index)
Definition: irqsystem.cpp:258
unsigned int eear
Definition: hweeprom.h:38
SystemClockOffset eraseWriteDelayTime
Definition: hweeprom.h:50
virtual unsigned int CpuCycle()
Definition: hweeprom.cpp:219