Aaron Berk
/
mbedAvrProgrammer
AVR910 In-System Programming
Embed:
(wiki syntax)
Show/hide line numbers
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 Thu Jul 14 2022 22:49:47 by 1.7.2