Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
AVRISP.cpp
00001 #include "AVRISP.h" 00002 00003 // constructor 00004 AVRISP::AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset, uint32_t targetClk, uint16_t pageSize, PRGCB pCB ) 00005 : spiPort(mosi, miso, sclk ) 00006 , resetPin(reset) 00007 , mPageSize(pageSize) 00008 , progressCB(pCB) 00009 { 00010 spiPort.frequency(targetClk>>2);//1/4 th of the clock frequency of the unit 00011 spiPort.format(8,0); 00012 } 00013 00014 AVRISP::~AVRISP() 00015 { 00016 } 00017 00018 //A function to poll BSY to prevent loading a new instruction prematurely 00019 void AVRISP::StillProgramming() 00020 { 00021 uint8_t check = 1; 00022 while(check & 0x1){//check LSB only 00023 spiPort.write(0xF0); 00024 spiPort.write(0x00); 00025 spiPort.write(0x00); 00026 check = spiPort.write(0x00); //read data byte out 00027 } 00028 } 00029 00030 // enable programming mode 00031 bool AVRISP::EnableProgrammingMode() 00032 { 00033 int failed = 0; 00034 00035 resetPin = 1; 00036 wait(0.02); 00037 resetPin = 0; 00038 wait(0.02); 00039 00040 while(failed < 5) //loop to try to enable programming mode 5 times 00041 { 00042 spiPort.write(0xAC); 00043 spiPort.write(0x53); 00044 int echoBack= spiPort.write(0x00); 00045 if(echoBack == 0x53) 00046 { //if data read on 3rd byte load is 0x53 00047 spiPort.write(0x00); //programming mode was enabled...good job! 00048 return true; 00049 } 00050 else 00051 { 00052 failed++; 00053 resetPin = 1; //pulse reset and try again 00054 resetPin = 0; 00055 wait(0.5); 00056 } 00057 } 00058 return false; //Bummer... 00059 } 00060 00061 void AVRISP::LeaveProgrammingMode() 00062 { 00063 resetPin = 1; 00064 wait(0.02); 00065 } 00066 00067 // read chip signature byte 00068 uint8_t AVRISP::ReadChipSignatureByte(SignatureByte Nr) 00069 { 00070 spiPort.write(0x30); 00071 spiPort.write(0x00); 00072 spiPort.write(Nr); 00073 return spiPort.write(0x00); 00074 } 00075 00076 // erase chip 00077 void AVRISP::ChipErase() 00078 { 00079 spiPort.write(0xAC); 00080 spiPort.write(0x80); 00081 spiPort.write(0x00); 00082 spiPort.write(0x00); 00083 StillProgramming(); 00084 resetPin = 1; 00085 wait(0.02); 00086 resetPin = 0; 00087 wait(0.02); 00088 EnableProgrammingMode(); 00089 } 00090 00091 // write fuse byte 00092 void AVRISP::WriteFuse(FuseType Typ, uint8_t fuse) 00093 { 00094 spiPort.write(0xAC); 00095 switch ( Typ ){ 00096 case eFTLo: 00097 spiPort.write(0xA0); break; 00098 case eFTHi: 00099 spiPort.write(0xA8); break; 00100 case eFTEx: 00101 spiPort.write(0xA4); break; 00102 case eFTLock: 00103 spiPort.write(0xE0); break; 00104 default: 00105 spiPort.write(0x00); break; 00106 }; 00107 spiPort.write(0x00); 00108 spiPort.write(fuse&0xff); 00109 StillProgramming(); 00110 } 00111 00112 // read fuse byte 00113 uint8_t AVRISP::ReadFuse(FuseType Typ) 00114 { 00115 switch (Typ){ 00116 case eFTLo: 00117 spiPort.write(0x50); 00118 spiPort.write(0x00); 00119 break; 00120 case eFTHi: 00121 spiPort.write(0x58); 00122 spiPort.write(0x08); 00123 break; 00124 case eFTEx: 00125 spiPort.write(0x50); 00126 spiPort.write(0x08); 00127 break; 00128 case eFTLock: 00129 spiPort.write(0x58); 00130 spiPort.write(0x00); 00131 break; 00132 default: 00133 spiPort.write(0x00); 00134 spiPort.write(0x00); 00135 break; 00136 } 00137 spiPort.write(0x00); 00138 return spiPort.write(0x00); 00139 } 00140 #define LSB(I) ((I) & 0xFF) 00141 #define MSB(I) (((I) & 0xF00) >> 8) 00142 // write program page 00143 void AVRISP::WriteProgramPage(uint16_t addr) 00144 { 00145 //write program memory page 00146 spiPort.write(0x4C); 00147 spiPort.write(MSB(addr)); 00148 spiPort.write(LSB(addr)); 00149 spiPort.write(0x00); 00150 00151 StillProgramming(); //make sure the operation worked 00152 } 00153 00154 00155 //function to load and write program memory 00156 //args: addr is the 12 bit address of the memory location 00157 // low_data and high_data are the values to write to that location 00158 void AVRISP::LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData)//int addr_MSB, 00159 { 00160 //load program memory low byte (little endian) 00161 spiPort.write(0x40); 00162 spiPort.write(0x00); 00163 spiPort.write(LSB(addr)); 00164 spiPort.write(lowData); 00165 00166 //load program memory high byte 00167 spiPort.write(0x48); 00168 spiPort.write(0x00); 00169 spiPort.write(LSB(addr)); 00170 spiPort.write(highData); 00171 } 00172 00173 inline uint8_t AVRISP::ReadByte(FILE *file) 00174 { 00175 char ascii_char[2]; 00176 fread(&ascii_char, 1, 2, file); 00177 return (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4) 00178 | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55)); 00179 } 00180 00181 uint8_t AVRISP::ReadProgramFlash(uint16_t addr, bool highByte) 00182 { 00183 spiPort.write(highByte ? 0x28: 0x20 ); 00184 spiPort.write(MSB(addr)); 00185 spiPort.write(LSB(addr)); 00186 return spiPort.write(0x00); 00187 } 00188 #define AT_BOUNDARY(addr,size) ((addr % size) == (size -1)) 00189 // program flash 00190 00191 //TODO: Implement address gaps in the hex file format 00192 bool AVRISP::ProgramFlash(FILE *hexFile) 00193 { 00194 int flag = 0; 00195 if(hexFile != NULL) 00196 { 00197 uint16_t address = 0; 00198 char temp; 00199 temp = fgetc(hexFile); 00200 while(flag == 0) 00201 { 00202 if(temp == ':') 00203 { 00204 uint8_t length = ReadByte(hexFile); 00205 if(length == 0) 00206 { 00207 flag = 1; 00208 } 00209 else 00210 { 00211 fseek(hexFile,6,SEEK_CUR); //2 if reading address 00212 00213 for(uint8_t i=0;i<length;i+=2) 00214 { 00215 uint8_t lowData = ReadByte(hexFile); 00216 uint8_t highData = ReadByte(hexFile); 00217 00218 //load data bytes here 00219 LoadProgramPage(address,lowData,highData); 00220 00221 if (AT_BOUNDARY(address, mPageSize)) // write page if 32 words have now been written 00222 { 00223 WriteProgramPage(address); 00224 if( progressCB ) (*progressCB)(); //activity callback 00225 } 00226 00227 address++; 00228 } 00229 while((temp = fgetc(hexFile)) != ':'); 00230 } 00231 } 00232 else flag = 1; 00233 } 00234 WriteProgramPage(address);//write the last part 00235 } 00236 else 00237 { 00238 return false; 00239 } 00240 return true; 00241 } 00242 00243 //TODO: Implement address gaps in the hex file format 00244 bool AVRISP::VerifyFlash(FILE* hexFile) 00245 { 00246 int flag = 0; 00247 bool Error = false; 00248 if(hexFile != NULL) 00249 { 00250 uint16_t address = 0; 00251 char temp; 00252 temp = fgetc(hexFile); 00253 while(flag == 0) 00254 { 00255 if(temp == ':') 00256 { 00257 uint8_t length = ReadByte(hexFile); 00258 if(length == 0) 00259 { 00260 flag = 1; 00261 } 00262 else 00263 { 00264 fseek(hexFile,6,SEEK_CUR); //2 if reading address 00265 00266 for(uint8_t i=0;i<length;i+=2) 00267 { 00268 uint8_t lowData = ReadByte(hexFile); 00269 uint8_t highData = ReadByte(hexFile); 00270 uint8_t lowDataF = ReadProgramFlash(address, false); 00271 uint8_t highDataF = ReadProgramFlash(address, true); 00272 00273 if( lowData != lowDataF || highData != highDataF ) 00274 { 00275 printf( "\n@%04x src %02x,%02x != %02x,%02x\n", address, lowData, highData, lowDataF,highDataF); 00276 Error = true; 00277 } 00278 00279 if (AT_BOUNDARY(address, mPageSize)) 00280 { 00281 if( progressCB ) (*progressCB)(); //activity callback 00282 } 00283 address++; 00284 } 00285 while((temp = fgetc(hexFile)) != ':'); 00286 } 00287 } 00288 else flag = 1; 00289 } 00290 if(Error) 00291 return false; 00292 } 00293 else 00294 { 00295 return false; 00296 } 00297 00298 return true; 00299 }
Generated on Sat Jul 16 2022 08:05:38 by
1.7.2