Aaron Berk
/
mAVRISP
Program an AVR microcontroller using mbed.
Embed:
(wiki syntax)
Show/hide line numbers
AVR910.cpp
00001 /** 00002 * @author Aaron Berk 00003 * 00004 * @section LICENSE 00005 * 00006 * Copyright (c) 2010 Aaron Berk 00007 * 00008 * Permission is hereby granted, free of charge, to any person obtaining a copy 00009 * of this software and associated documentation files (the "Software"), to deal 00010 * in the Software without restriction, including without limitation the rights 00011 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00012 * copies of the Software, and to permit persons to whom the Software is 00013 * furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be included in 00016 * all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00023 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00024 * THE SOFTWARE. 00025 * 00026 * @section DESCRIPTION 00027 * 00028 * Program AVR chips with the AVR910 ISP (in-system programming) protocol, 00029 * using an mbed. 00030 * 00031 * AVR910 Application Note: 00032 * 00033 * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf 00034 */ 00035 00036 /** 00037 * Includes 00038 */ 00039 #include "AVR910.h" 00040 00041 Serial debug(USBTX, USBRX); 00042 00043 AVR910::AVR910(PinName mosi, 00044 PinName miso, 00045 PinName sclk, 00046 PinName nReset) : spi_(mosi, miso, sclk), nReset_(nReset) { 00047 00048 //Slow frequency as default to ensure no errors from 00049 //trying to run it too fast. Increase as appropriate. 00050 spi_.frequency(32000); 00051 spi_.format(8, 0); 00052 00053 int response = 0; 00054 00055 //Enter serial programming mode by pulling reset line low. 00056 nReset_ = 0; 00057 00058 //Wait 20ms before issuing first command. 00059 wait_ms(20); 00060 00061 //Issue a programming enable command. 00062 response = enableProgramming(); 00063 00064 //Simple debugging to see if we get trapped 00065 //in an infinite loop. 00066 DigitalOut working(LED1); 00067 working = 1; 00068 00069 //TODO: introduce a timeout. 00070 while (response < 0) { 00071 00072 //Give nReset a positive pulse. 00073 nReset_ = 1; 00074 wait_ms(20); 00075 nReset_ = 0; 00076 wait_ms(20); 00077 00078 //Issue another programming enable. 00079 response = enableProgramming(); 00080 00081 } 00082 00083 working = 0; 00084 00085 } 00086 00087 int AVR910::program(FILE* binary, int pageSize, int numPages) { 00088 00089 //Clear memory contents. 00090 chipErase(); 00091 00092 char pageOffset = 0; 00093 int pageNumber = 0; 00094 int address = 0; 00095 int c = 0; 00096 int highLow = 0; 00097 00098 //We're dealing with paged memory. 00099 if (numPages > 1) { 00100 00101 while ((c = getc(binary)) != EOF) { 00102 00103 //Page is fully loaded, time to write it to flash. 00104 if (pageOffset == (pageSize)) { 00105 writeFlashMemoryPage(pageNumber); 00106 00107 pageNumber++; 00108 if (pageNumber > numPages) { 00109 break; 00110 } 00111 pageOffset = 0; 00112 } 00113 00114 //Write low byte. 00115 if (highLow == 0) { 00116 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c); 00117 highLow = 1; 00118 } 00119 //Write high byte. 00120 else { 00121 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c); 00122 highLow = 0; 00123 pageOffset++; 00124 } 00125 00126 } 00127 00128 } 00129 //We're dealing with non-paged memory. 00130 else { 00131 00132 while ((c = getc(binary)) != EOF) { 00133 00134 //Write low byte. 00135 if (highLow == 0) { 00136 writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c); 00137 highLow = 1; 00138 } 00139 //Write high byte. 00140 else { 00141 writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c); 00142 highLow = 0; 00143 address++; 00144 00145 //Page size is our memory size in the non-paged memory case. 00146 //Therefore if we've gone beyond our size break because we 00147 //don't have any more room. 00148 if (address > pageSize) { 00149 break; 00150 } 00151 00152 } 00153 00154 } 00155 00156 } 00157 00158 //We might have partially filled up a page. 00159 writeFlashMemoryPage(pageNumber); 00160 00161 int success = -1; 00162 success = checkMemory(pageNumber, binary); 00163 00164 //Leave serial programming mode by pulling reset line high. 00165 nReset_ = 1; 00166 00167 return success; 00168 00169 } 00170 00171 void AVR910::setFrequency(int frequency) { 00172 00173 spi_.frequency(frequency); 00174 00175 } 00176 00177 int AVR910::enableProgramming(void) { 00178 00179 int response = 0; 00180 int error = 0; 00181 00182 //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00 00183 //Byte two echo'd back in byte three. 00184 spi_.write(0xAC); 00185 00186 spi_.write(0x53); 00187 00188 response = spi_.write(0x00); 00189 00190 if (response == 0x53) { 00191 error = 0; 00192 } else { 00193 error = -1; 00194 } 00195 00196 spi_.write(0x00); 00197 00198 return error; 00199 00200 } 00201 00202 void AVR910::poll(void) { 00203 00204 int response = 0; 00205 00206 do { 00207 spi_.write(0xF0); 00208 spi_.write(0x00); 00209 spi_.write(0x00); 00210 response = spi_.write(0x00); 00211 } while ((response & 0x01) != 0); 00212 00213 } 00214 00215 int AVR910::readVendorCode(void) { 00216 00217 int response = 0; 00218 00219 //Issue read signature byte command. 00220 //Address 0x00 is vendor code. 00221 spi_.write(0x30); 00222 spi_.write(0x00); 00223 spi_.write(0x00); 00224 response = spi_.write(0x00); 00225 00226 return response; 00227 00228 } 00229 00230 int AVR910::readPartFamilyAndFlashSize(void) { 00231 00232 int response = 0; 00233 00234 //Issue read signature byte command. 00235 //Address 0x01 is part family and flash size code. 00236 spi_.write(0x30); 00237 spi_.write(0x00); 00238 spi_.write(0x01); 00239 response = spi_.write(0x00); 00240 00241 return response; 00242 00243 } 00244 00245 int AVR910::readPartNumber(void) { 00246 00247 int response = 0; 00248 00249 //Issue read signature byte command. 00250 //Address 0x02 is part number code. 00251 spi_.write(0x30); 00252 spi_.write(0x00); 00253 spi_.write(0x02); 00254 response = spi_.write(0x00); 00255 00256 return response; 00257 00258 } 00259 00260 void AVR910::chipErase(void) { 00261 00262 //Issue chip erase command. 00263 spi_.write(0xAC); 00264 spi_.write(0x80); 00265 spi_.write(0x00); 00266 spi_.write(0x00); 00267 00268 poll(); 00269 00270 //Temporarily release reset line. 00271 nReset_ = 1; 00272 nReset_ = 0; 00273 00274 } 00275 00276 void AVR910::loadMemoryPage(int highLow, char address, char data) { 00277 00278 spi_.write(highLow); 00279 spi_.write(0x00); 00280 spi_.write(address & 0x3F); 00281 spi_.write(data); 00282 00283 poll(); 00284 00285 } 00286 00287 void AVR910::writeFlashMemoryByte(int highLow, int address, char data) { 00288 00289 spi_.write(highLow); 00290 spi_.write(address & 0xFF00 >> 8); 00291 spi_.write(address & 0x00FF); 00292 spi_.write(data); 00293 00294 } 00295 00296 void AVR910::writeFlashMemoryPage(char pageNumber) { 00297 00298 spi_.write(0x4C); 00299 spi_.write((pageNumber >> 2) & 0x3F); 00300 spi_.write((pageNumber & 0x03) << 6); 00301 spi_.write(0x00); 00302 00303 poll(); 00304 00305 } 00306 00307 char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset) { 00308 00309 int response = 0; 00310 00311 spi_.write(highLow); 00312 spi_.write((pageNumber >> 2) & 0x3F); 00313 spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F)); 00314 response = spi_.write(0x00); 00315 00316 poll(); 00317 00318 return response; 00319 00320 } 00321 00322 int AVR910::checkMemory(int numPages, FILE* binary) { 00323 00324 int success = 0; 00325 int response = 0; 00326 char c = 0; 00327 00328 //Go back to the beginning of the binary file. 00329 fseek(binary, 0, SEEK_SET); 00330 00331 for (int i = 0; i < numPages; i++) { 00332 for (int j = 0; j < PAGE_SIZE; j++) { 00333 c = getc(binary); 00334 //Read program memory low byte. 00335 response = readProgramMemory(READ_LOW_BYTE, i, j); 00336 //debug.printf("Low byte: 0x%02x\n", response); 00337 if ( c != response ) { 00338 debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response); 00339 debug.printf("Correct byte is 0x%02x\n", c); 00340 success = -1; 00341 } 00342 00343 c = getc(binary); 00344 //Read program memory high byte. 00345 response = readProgramMemory(READ_HIGH_BYTE, i, j); 00346 //debug.printf("High byte: 0x%02x\n", response); 00347 if ( c != response ) { 00348 debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response); 00349 debug.printf("Correct byte is 0x%02x\n", c); 00350 success = -1; 00351 } 00352 } 00353 } 00354 00355 return success; 00356 00357 }
Generated on Tue Jul 12 2022 14:07:14 by 1.7.2