Fixed problem in DeviceSettings::strParam, returned wrong string
[avr-sim.git] / src / Flash.cpp
blobfec51a594af9b2ffd58110cc5982d38d99b025dd
1 /*
2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "Flash.h"
20 #include "Instruction.h"
21 #include "Registers.h"
22 #include "Bus.h"
23 #include "AccessViolation.h"
24 #include "RuntimeException.h"
26 #include <algorithm>
27 #include <string.h>
29 enum {
30 NONE = 0,
31 PGERASE = 1 << 1 | 1,
32 RWWSRE = 1 << 4 | 1,
33 BLBSET = 1 << 3 | 1,
34 FILL = 1,
35 PGWRITE = 1 << 2 | 1,
36 BUSY = 1<<6
39 #define SPMCSR_LOWERBITS 0x1f
40 #define BUFFERSIZE 1<<pagebits
41 #define DEFAULT_VALUE 0xff
42 #define setBusy() spmcsr->set( *spmcsr | BUSY );
44 // TODO these are cycles for 8Mhz!
45 #define ERASE_CYCLES 36000
46 #define WRITE_CYCLES 36000
47 #define RESET_CYCLES 4
49 namespace avr {
51 static unsigned int log2Int(unsigned int v) {
52 // find the log base 2 of 32-bit v
54 static const int MultiplyDeBruijnBitPosition[32] = {
55 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
56 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
59 v |= v >> 1; // first round down to power of 2
60 v |= v >> 2;
61 v |= v >> 4;
62 v |= v >> 8;
63 v |= v >> 16;
64 v = (v >> 1) + 1;
66 return MultiplyDeBruijnBitPosition[(v * 0x077CB531UL) >> 27];
69 Flash::Flash(Bus & bus, unsigned int size, int pagesize)
70 : Hardware(bus), Memory(size) {
72 pagebits = log2Int(pagesize);
74 Memory::fill(DEFAULT_VALUE);
75 pagemask = (0xffffffff >> (31 - (pagebits)));
77 buffer = new unsigned char[BUFFERSIZE];
78 memset(buffer, DEFAULT_VALUE, BUFFERSIZE);
80 spmcsr = 0;
83 Flash::~Flash() {
84 if( buffer != 0 )
85 delete [] buffer;
88 void Flash::fill(unsigned int offset, byte val, unsigned int size) {
89 if( offset + size > siz )
90 throw AccessViolation("Flash::fill: writing too much to memory");
92 memset( mem + offset, val, size );
95 bool Flash::attachReg(const char *name, IORegister *reg) {
96 if( strcmp(name, "spmcsr") == 0 )
97 spmcsr = reg;
98 else
99 return false;
101 reg->registerHW(this);
102 return true;
105 bool Flash::finishBuild() {
106 return ( spmcsr != 0 );
109 void Flash::regChanged( IORegister *reg ) {
110 if( reg == spmcsr ) {
111 bus.setBreakDelta(RESET_CYCLES, this);
115 void Flash::storeProgramMemory(dword Z, byte r0, byte r1) {
116 pageoffset = (Z & pagemask);
117 pagenum = Z >> pagebits;
119 state = *spmcsr;
120 switch ( state ) {
121 case PGERASE:
122 setBusy();
123 bus.reassignBreakDelta(ERASE_CYCLES, this);
124 break;
126 case RWWSRE:
127 resetRWW();
128 bus.clearBreak(this);
129 break;
131 case BLBSET:
132 bus.clearBreak(this);
133 break;
135 case FILL:
136 if( pageoffset >= BUFFERSIZE )
137 throw AccessViolation("Tried to write beyond RWW buffer boundaries");
139 buffer[pageoffset] = r0;
140 buffer[pageoffset+1] = r1;
141 spmcsr->set( *spmcsr & ~SPMCSR_LOWERBITS );
142 bus.clearBreak(this);
143 break;
145 case PGWRITE:
146 setBusy();
147 bus.reassignBreakDelta(WRITE_CYCLES, this);
148 break;
152 void Flash::resetRWW() {
153 if( (*spmcsr & BUSY) == 0 )
154 spmcsr->set( *spmcsr & ~(BUSY|SPMCSR_LOWERBITS) );
157 void Flash::pageErase() {
158 int size = BUFFERSIZE;
159 int addr = pagenum * size;
160 fill( addr, DEFAULT_VALUE, size );
163 void Flash::pageWrite() {
164 int size = BUFFERSIZE;
165 int addr = pagenum * size;
166 write( addr, buffer, size );
169 void Flash::step() {
170 switch ( state ) {
171 case NONE:
172 break;
174 case PGERASE:
175 pageErase();
176 break;
178 case PGWRITE:
179 pageWrite();
180 break;
182 default:
183 throw util::RuntimeException("Flash::step: invalid state");
186 memset(buffer, DEFAULT_VALUE, BUFFERSIZE);
187 spmcsr->set( *spmcsr & ~(SPMCSR_LOWERBITS) );