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