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.
AVR910.cpp
00001 //****************************************************************************/ 00002 // Description: 00003 // 00004 // Program AVR chips with the AVR910 ISP (in-system programming) protocol, 00005 // using an mbed. 00006 // 00007 // AVR Application Note: 00008 // 00009 // http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf 00010 //****************************************************************************/ 00011 00012 //****************************************************************************/ 00013 // Includes 00014 //****************************************************************************/ 00015 #include "AVR910.h" 00016 00017 Serial debug(USBTX, USBRX); 00018 00019 AVR910::AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset) { 00020 00021 spi_ = new SPI(mosi, miso, sclk); 00022 spi_->frequency(32000); 00023 spi_->format(8, 1); 00024 nReset_ = new DigitalOut(nReset); 00025 00026 } 00027 00028 int AVR910::program(FILE* binary) { 00029 00030 int response = 0; 00031 00032 debug.printf("mbed AVR910 Programmer starting\n"); 00033 00034 //Enter serial programming mode by pulling reset line low. 00035 *nReset_ = 0; 00036 00037 //Wait 20ms before issuing first command. 00038 wait_ms(20); 00039 00040 //Issue a programming enable command. 00041 response = enableProgramming(); 00042 00043 if (response < 0) { 00044 debug.printf("Enable programming command not successful\n"); 00045 } else { 00046 debug.printf("Enable programming command successful\n"); 00047 } 00048 00049 //Read vendor code, part family and part number. 00050 response = readVendorCode(); 00051 00052 if (response == ATMEL_VENDOR_CODE) { 00053 debug.printf("Microcontroller is an Atmel [0x%02x]\n", response); 00054 } else if (response == DEVICE_LOCKED) { 00055 debug.printf("Device is locked\n"); 00056 } else { 00057 debug.printf("Microcontroller is not an Atmel\n"); 00058 } 00059 00060 response = readPartFamilyAndFlashSize(); 00061 00062 if (response == 0xFF) { 00063 debug.printf("Device code erased or target missing\n"); 00064 } else if (response == 0x01) { 00065 debug.printf("Device locked\n"); 00066 } else { 00067 debug.printf("Part family and flash size code is: 0x%02x\n", response); 00068 } 00069 00070 response = readPartNumber(); 00071 00072 if (response == 0xFF) { 00073 debug.printf("Device code erased or target missing\n"); 00074 } else if (response == 0x02) { 00075 debug.printf("Device locked\n"); 00076 } else { 00077 debug.printf("Part number code is: 0x%02x\n", response); 00078 } 00079 00080 //Clear memory contents. 00081 chipErase(); 00082 00083 char pageOffset = 0; 00084 int pageNumber = 0; 00085 int c = 0; 00086 int highLow = 0; 00087 00088 while ((c = getc(binary)) != EOF) { 00089 00090 //Page is fully loaded, time to write it to flash. 00091 if (pageOffset == (PAGE_SIZE)) { 00092 writeFlashMemoryPage(pageNumber); 00093 debug.printf("Page %i written\n", pageNumber); 00094 pageNumber++; 00095 pageOffset = 0; 00096 } 00097 00098 //Write low byte. 00099 if (highLow == 0) { 00100 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c); 00101 highLow = 1; 00102 } 00103 //Write high byte. 00104 else { 00105 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c); 00106 highLow = 0; 00107 pageOffset++; 00108 } 00109 00110 } 00111 00112 //We might have partially filled up a page. 00113 writeFlashMemoryPage(pageNumber); 00114 00115 int success = -1; 00116 success = checkMemory(pageNumber, binary); 00117 00118 //Leave serial programming mode by pulling reset line high. 00119 *nReset_ = 1; 00120 00121 return success; 00122 00123 } 00124 00125 void AVR910::setFrequency(int frequency){ 00126 00127 spi_->frequency(frequency); 00128 00129 } 00130 00131 int AVR910::enableProgramming(void) { 00132 00133 int response = 0; 00134 int error = 0; 00135 00136 //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00 00137 //Byte two echo'd back in byte three. 00138 spi_->write(0xAC); 00139 00140 spi_->write(0x53); 00141 00142 response = spi_->write(0x00); 00143 00144 if (response == 0x53) { 00145 error = 0; 00146 } else { 00147 error = -1; 00148 } 00149 00150 spi_->write(0x00); 00151 00152 return error; 00153 00154 } 00155 00156 void AVR910::poll(void) { 00157 00158 int response = 0; 00159 00160 do { 00161 spi_->write(0xF0); 00162 spi_->write(0x00); 00163 spi_->write(0x00); 00164 response = spi_->write(0x00); 00165 } while ((response & 0x01) != 0); 00166 00167 } 00168 00169 int AVR910::readVendorCode(void) { 00170 00171 int response = 0; 00172 00173 //Issue read signature byte command. 00174 //Address 0x00 is vendor code. 00175 spi_->write(0x30); 00176 spi_->write(0x00); 00177 spi_->write(0x00); 00178 response = spi_->write(0x00); 00179 00180 return response; 00181 00182 } 00183 00184 int AVR910::readPartFamilyAndFlashSize(void) { 00185 00186 int response = 0; 00187 00188 //Issue read signature byte command. 00189 //Address 0x01 is part family and flash size code. 00190 spi_->write(0x30); 00191 spi_->write(0x00); 00192 spi_->write(0x01); 00193 response = spi_->write(0x00); 00194 00195 return response; 00196 00197 } 00198 00199 int AVR910::readPartNumber(void) { 00200 00201 int response = 0; 00202 00203 //Issue read signature byte command. 00204 //Address 0x02 is part number code. 00205 spi_->write(0x30); 00206 spi_->write(0x00); 00207 spi_->write(0x02); 00208 response = spi_->write(0x00); 00209 00210 return response; 00211 00212 } 00213 00214 void AVR910::chipErase(void) { 00215 00216 //Issue chip erase command. 00217 spi_->write(0xAC); 00218 spi_->write(0x80); 00219 spi_->write(0x00); 00220 spi_->write(0x00); 00221 00222 poll(); 00223 00224 //Temporarily release reset line. 00225 *nReset_ = 1; 00226 *nReset_ = 0; 00227 00228 } 00229 00230 void AVR910::loadMemoryPage(int highLow, char address, char data) { 00231 00232 spi_->write(highLow); 00233 spi_->write(0x00); 00234 spi_->write(address & 0x3F); 00235 spi_->write(data); 00236 00237 poll(); 00238 00239 } 00240 00241 void AVR910::writeFlashMemoryPage(char pageNumber) { 00242 00243 spi_->write(0x4C); 00244 spi_->write((pageNumber >> 2) & 0x3F); 00245 spi_->write((pageNumber & 0x03) << 6); 00246 spi_->write(0x00); 00247 00248 poll(); 00249 00250 } 00251 00252 char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset) { 00253 00254 int response = 0; 00255 00256 spi_->write(highLow); 00257 spi_->write((pageNumber >> 2) & 0x3F); 00258 spi_->write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F)); 00259 response = spi_->write(0x00); 00260 00261 poll(); 00262 00263 return response; 00264 00265 } 00266 00267 int AVR910::checkMemory(int numPages, FILE* binary){ 00268 00269 int success = 0; 00270 int response = 0; 00271 char c = 0; 00272 00273 //Go back to the beginning of the binary file. 00274 fseek(binary, 0, SEEK_SET); 00275 00276 for(int i = 0; i < numPages; i++){ 00277 for (int j = 0; j < PAGE_SIZE; j++) { 00278 c = getc(binary); 00279 //Read program memory low byte. 00280 response = readProgramMemory(READ_LOW_BYTE, i, j); 00281 //debug.printf("Low byte: 0x%02x\n", response); 00282 if( c != response ){ 00283 debug.printf("page %i low byte %i: 0x%02x\n", i, j, response); 00284 debug.printf("correct byte is 0x%02x\n", c); 00285 success = -1; 00286 } 00287 00288 c = getc(binary); 00289 //Read program memory high byte. 00290 response = readProgramMemory(READ_HIGH_BYTE, i, j); 00291 //debug.printf("High byte: 0x%02x\n", response); 00292 if( c != response ){ 00293 debug.printf("page %i high byte %i: 0x%02x\n", i, j, response); 00294 debug.printf("correct byte is 0x%02x\n", c); 00295 success = -1; 00296 } 00297 } 00298 } 00299 00300 return success; 00301 00302 }
Generated on Wed Jul 20 2022 19:55:29 by
1.7.2