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 * @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