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 "flashprog.h"
00027 #include "avrdevice.h"
00028 #include "systemclock.h"
00029 #include "avrmalloc.h"
00030 #include "flash.h"
00031
00032
00033
00034
00035 void FlashProgramming::ClearOperationBits(void) {
00036 spmcr_val &= ~spmcr_opr_bits;
00037 action = SPM_ACTION_NOOP;
00038 spm_opr = SPM_OPS_NOOP;
00039 }
00040
00041 void FlashProgramming::SetRWWLock(unsigned int addr) {
00042
00043 if(!isATMega)
00044 return;
00045
00046 if(addr < (nrww_addr * 2)) {
00047 spmcr_val |= 0x40;
00048 core->Flash->SetRWWLock(nrww_addr * 2);
00049 }
00050 }
00051
00052 FlashProgramming::FlashProgramming(AvrDevice *c,
00053 unsigned int pgsz,
00054 unsigned int nrww,
00055 int mode):
00056 Hardware(c),
00057 core(c),
00058 pageSize(pgsz),
00059 nrww_addr(nrww),
00060 spmcr_reg(c, "SPMCR",
00061 this, &FlashProgramming::GetSpmcr, &FlashProgramming::SetSpmcr)
00062 {
00063
00064 tempBuffer = avr_new(unsigned char, pgsz * 2);
00065 for(int i = 0; i < (pageSize * 2); i++)
00066 tempBuffer[i] = 0xff;
00067
00068
00069 isATMega = (mode & SPM_MEGA_MODE) == SPM_MEGA_MODE;
00070 spmcr_opr_bits = 0x1f;
00071 if((mode & SPM_SIG_OPR) == SPM_SIG_OPR)
00072
00073 spmcr_opr_bits |= 0x20;
00074 spmcr_valid_bits = spmcr_opr_bits;
00075 if(isATMega)
00076
00077 spmcr_valid_bits |= 0x80;
00078
00079
00080 Reset();
00081
00082
00083 core->AddToCycleList(this);
00084 }
00085
00086 FlashProgramming::~FlashProgramming() {
00087 avr_free(tempBuffer);
00088 }
00089
00090 unsigned int FlashProgramming::CpuCycle() {
00091
00092 if(opr_enable_count > 0) {
00093 opr_enable_count--;
00094 if(opr_enable_count == 0)
00095 ClearOperationBits();
00096 }
00097
00098 if(action == SPM_ACTION_LOCKCPU) {
00099 if(SystemClock::Instance().GetCurrentTime() < timeout)
00100 return 1;
00101 ClearOperationBits();
00102 }
00103 return 0;
00104 }
00105
00106 void FlashProgramming::Reset() {
00107 spmcr_val = 0;
00108 opr_enable_count = 0;
00109 action = SPM_ACTION_NOOP;
00110 spm_opr = SPM_OPS_NOOP;
00111 timeout = 0;
00112 }
00113
00114 unsigned char FlashProgramming::LPM_action(unsigned int xaddr, unsigned int addr) {
00115 return 0;
00116 }
00117
00118 int FlashProgramming::SPM_action(unsigned int data, unsigned int xaddr, unsigned int addr) {
00119
00120
00121 unsigned int pc = core->PC;
00122 if(pc < nrww_addr)
00123 return 0;
00124
00125
00126 addr = (addr & 0xffff) + (xaddr << 16);
00127
00128
00129 if(action == SPM_ACTION_PREPARE) {
00130 opr_enable_count = 0;
00131 if(spm_opr == SPM_OPS_UNLOCKRWW) {
00132 ClearOperationBits();
00133 spmcr_val &= ~0x40;
00134 core->Flash->SetRWWLock(0);
00135
00136 return 0;
00137 }
00138 if(spm_opr == SPM_OPS_STOREBUFFER) {
00139
00140 addr = addr & 0xfffe;
00141 addr &= (pageSize * 2) - 1;
00142
00143 tempBuffer[addr] = data & 0xff;
00144 tempBuffer[addr + 1] = (data >> 8) & 0xff;
00145
00146 ClearOperationBits();
00147
00148 return 2;
00149 }
00150 if(spm_opr == SPM_OPS_WRITEBUFFER) {
00151
00152 addr &= ~((pageSize * 2) - 1);
00153
00154 core->Flash->WriteMem(tempBuffer, addr, pageSize * 2);
00155
00156 timeout = SystemClock::Instance().GetCurrentTime() + FlashProgramming::SPM_TIMEOUT;
00157
00158 action = SPM_ACTION_LOCKCPU;
00159
00160 SetRWWLock(addr);
00161
00162 return 0;
00163 }
00164 if(spm_opr == SPM_OPS_ERASE) {
00165
00166 addr &= ~((pageSize * 2) - 1);
00167
00168 for(int i = 0; i < (pageSize * 2); i++)
00169 tempBuffer[i] = 0xff;
00170 core->Flash->WriteMem(tempBuffer, addr, pageSize * 2);
00171
00172 timeout = SystemClock::Instance().GetCurrentTime() + FlashProgramming::SPM_TIMEOUT;
00173
00174 action = SPM_ACTION_LOCKCPU;
00175
00176 SetRWWLock(addr);
00177
00178 return 0;
00179 }
00180
00181 ClearOperationBits();
00182 }
00183 return 0;
00184 }
00185
00186 void FlashProgramming::SetSpmcr(unsigned char v) {
00187 spmcr_val = (spmcr_val & ~spmcr_valid_bits) + (v & spmcr_valid_bits);
00188
00189
00190 if(action == SPM_ACTION_NOOP) {
00191 opr_enable_count = 4;
00192 action = SPM_ACTION_PREPARE;
00193 switch(spmcr_val & spmcr_opr_bits) {
00194 case 0x1:
00195 spm_opr = SPM_OPS_STOREBUFFER;
00196 break;
00197
00198 case 0x3:
00199 spm_opr = SPM_OPS_ERASE;
00200 break;
00201
00202 case 0x5:
00203 spm_opr = SPM_OPS_WRITEBUFFER;
00204 break;
00205
00206 case 0x9:
00207 spm_opr = SPM_OPS_LOCKBITS;
00208 break;
00209
00210 case 0x11:
00211 if(isATMega)
00212 spm_opr = SPM_OPS_UNLOCKRWW;
00213 else
00214 spm_opr = SPM_OPS_CLEARBUFFER;
00215 break;
00216
00217 case 0x21:
00218 spm_opr = SPM_OPS_READSIG;
00219 break;
00220
00221 default:
00222 spm_opr = SPM_OPS_NOOP;
00223 if(!(spmcr_val & 0x1)) {
00224 opr_enable_count = 0;
00225 action = SPM_ACTION_NOOP;
00226 }
00227 break;
00228 }
00229 }
00230
00231 }
00232
00233