AVR910 In-System Programming

Dependencies:   mbed

Committer:
aberk
Date:
Wed Jun 16 13:10:04 2010 +0000
Revision:
0:56d5a7ca509d

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aberk 0:56d5a7ca509d 1 //****************************************************************************/
aberk 0:56d5a7ca509d 2 // Description:
aberk 0:56d5a7ca509d 3 //
aberk 0:56d5a7ca509d 4 // Program AVR chips with the AVR910 ISP (in-system programming) protocol,
aberk 0:56d5a7ca509d 5 // using an mbed.
aberk 0:56d5a7ca509d 6 //
aberk 0:56d5a7ca509d 7 // AVR Application Note:
aberk 0:56d5a7ca509d 8 //
aberk 0:56d5a7ca509d 9 // http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
aberk 0:56d5a7ca509d 10 //****************************************************************************/
aberk 0:56d5a7ca509d 11
aberk 0:56d5a7ca509d 12 //****************************************************************************/
aberk 0:56d5a7ca509d 13 // Includes
aberk 0:56d5a7ca509d 14 //****************************************************************************/
aberk 0:56d5a7ca509d 15 #include "AVR910.h"
aberk 0:56d5a7ca509d 16
aberk 0:56d5a7ca509d 17 Serial debug(USBTX, USBRX);
aberk 0:56d5a7ca509d 18
aberk 0:56d5a7ca509d 19 AVR910::AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset) {
aberk 0:56d5a7ca509d 20
aberk 0:56d5a7ca509d 21 spi_ = new SPI(mosi, miso, sclk);
aberk 0:56d5a7ca509d 22 spi_->frequency(32000);
aberk 0:56d5a7ca509d 23 spi_->format(8, 1);
aberk 0:56d5a7ca509d 24 nReset_ = new DigitalOut(nReset);
aberk 0:56d5a7ca509d 25
aberk 0:56d5a7ca509d 26 }
aberk 0:56d5a7ca509d 27
aberk 0:56d5a7ca509d 28 int AVR910::program(FILE* binary) {
aberk 0:56d5a7ca509d 29
aberk 0:56d5a7ca509d 30 int response = 0;
aberk 0:56d5a7ca509d 31
aberk 0:56d5a7ca509d 32 debug.printf("mbed AVR910 Programmer starting\n");
aberk 0:56d5a7ca509d 33
aberk 0:56d5a7ca509d 34 //Enter serial programming mode by pulling reset line low.
aberk 0:56d5a7ca509d 35 *nReset_ = 0;
aberk 0:56d5a7ca509d 36
aberk 0:56d5a7ca509d 37 //Wait 20ms before issuing first command.
aberk 0:56d5a7ca509d 38 wait_ms(20);
aberk 0:56d5a7ca509d 39
aberk 0:56d5a7ca509d 40 //Issue a programming enable command.
aberk 0:56d5a7ca509d 41 response = enableProgramming();
aberk 0:56d5a7ca509d 42
aberk 0:56d5a7ca509d 43 if (response < 0) {
aberk 0:56d5a7ca509d 44 debug.printf("Enable programming command not successful\n");
aberk 0:56d5a7ca509d 45 } else {
aberk 0:56d5a7ca509d 46 debug.printf("Enable programming command successful\n");
aberk 0:56d5a7ca509d 47 }
aberk 0:56d5a7ca509d 48
aberk 0:56d5a7ca509d 49 //Read vendor code, part family and part number.
aberk 0:56d5a7ca509d 50 response = readVendorCode();
aberk 0:56d5a7ca509d 51
aberk 0:56d5a7ca509d 52 if (response == ATMEL_VENDOR_CODE) {
aberk 0:56d5a7ca509d 53 debug.printf("Microcontroller is an Atmel [0x%02x]\n", response);
aberk 0:56d5a7ca509d 54 } else if (response == DEVICE_LOCKED) {
aberk 0:56d5a7ca509d 55 debug.printf("Device is locked\n");
aberk 0:56d5a7ca509d 56 } else {
aberk 0:56d5a7ca509d 57 debug.printf("Microcontroller is not an Atmel\n");
aberk 0:56d5a7ca509d 58 }
aberk 0:56d5a7ca509d 59
aberk 0:56d5a7ca509d 60 response = readPartFamilyAndFlashSize();
aberk 0:56d5a7ca509d 61
aberk 0:56d5a7ca509d 62 if (response == 0xFF) {
aberk 0:56d5a7ca509d 63 debug.printf("Device code erased or target missing\n");
aberk 0:56d5a7ca509d 64 } else if (response == 0x01) {
aberk 0:56d5a7ca509d 65 debug.printf("Device locked\n");
aberk 0:56d5a7ca509d 66 } else {
aberk 0:56d5a7ca509d 67 debug.printf("Part family and flash size code is: 0x%02x\n", response);
aberk 0:56d5a7ca509d 68 }
aberk 0:56d5a7ca509d 69
aberk 0:56d5a7ca509d 70 response = readPartNumber();
aberk 0:56d5a7ca509d 71
aberk 0:56d5a7ca509d 72 if (response == 0xFF) {
aberk 0:56d5a7ca509d 73 debug.printf("Device code erased or target missing\n");
aberk 0:56d5a7ca509d 74 } else if (response == 0x02) {
aberk 0:56d5a7ca509d 75 debug.printf("Device locked\n");
aberk 0:56d5a7ca509d 76 } else {
aberk 0:56d5a7ca509d 77 debug.printf("Part number code is: 0x%02x\n", response);
aberk 0:56d5a7ca509d 78 }
aberk 0:56d5a7ca509d 79
aberk 0:56d5a7ca509d 80 //Clear memory contents.
aberk 0:56d5a7ca509d 81 chipErase();
aberk 0:56d5a7ca509d 82
aberk 0:56d5a7ca509d 83 char pageOffset = 0;
aberk 0:56d5a7ca509d 84 int pageNumber = 0;
aberk 0:56d5a7ca509d 85 int c = 0;
aberk 0:56d5a7ca509d 86 int highLow = 0;
aberk 0:56d5a7ca509d 87
aberk 0:56d5a7ca509d 88 while ((c = getc(binary)) != EOF) {
aberk 0:56d5a7ca509d 89
aberk 0:56d5a7ca509d 90 //Page is fully loaded, time to write it to flash.
aberk 0:56d5a7ca509d 91 if (pageOffset == (PAGE_SIZE)) {
aberk 0:56d5a7ca509d 92 writeFlashMemoryPage(pageNumber);
aberk 0:56d5a7ca509d 93 debug.printf("Page %i written\n", pageNumber);
aberk 0:56d5a7ca509d 94 pageNumber++;
aberk 0:56d5a7ca509d 95 pageOffset = 0;
aberk 0:56d5a7ca509d 96 }
aberk 0:56d5a7ca509d 97
aberk 0:56d5a7ca509d 98 //Write low byte.
aberk 0:56d5a7ca509d 99 if (highLow == 0) {
aberk 0:56d5a7ca509d 100 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
aberk 0:56d5a7ca509d 101 highLow = 1;
aberk 0:56d5a7ca509d 102 }
aberk 0:56d5a7ca509d 103 //Write high byte.
aberk 0:56d5a7ca509d 104 else {
aberk 0:56d5a7ca509d 105 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
aberk 0:56d5a7ca509d 106 highLow = 0;
aberk 0:56d5a7ca509d 107 pageOffset++;
aberk 0:56d5a7ca509d 108 }
aberk 0:56d5a7ca509d 109
aberk 0:56d5a7ca509d 110 }
aberk 0:56d5a7ca509d 111
aberk 0:56d5a7ca509d 112 //We might have partially filled up a page.
aberk 0:56d5a7ca509d 113 writeFlashMemoryPage(pageNumber);
aberk 0:56d5a7ca509d 114
aberk 0:56d5a7ca509d 115 int success = -1;
aberk 0:56d5a7ca509d 116 success = checkMemory(pageNumber, binary);
aberk 0:56d5a7ca509d 117
aberk 0:56d5a7ca509d 118 //Leave serial programming mode by pulling reset line high.
aberk 0:56d5a7ca509d 119 *nReset_ = 1;
aberk 0:56d5a7ca509d 120
aberk 0:56d5a7ca509d 121 return success;
aberk 0:56d5a7ca509d 122
aberk 0:56d5a7ca509d 123 }
aberk 0:56d5a7ca509d 124
aberk 0:56d5a7ca509d 125 void AVR910::setFrequency(int frequency){
aberk 0:56d5a7ca509d 126
aberk 0:56d5a7ca509d 127 spi_->frequency(frequency);
aberk 0:56d5a7ca509d 128
aberk 0:56d5a7ca509d 129 }
aberk 0:56d5a7ca509d 130
aberk 0:56d5a7ca509d 131 int AVR910::enableProgramming(void) {
aberk 0:56d5a7ca509d 132
aberk 0:56d5a7ca509d 133 int response = 0;
aberk 0:56d5a7ca509d 134 int error = 0;
aberk 0:56d5a7ca509d 135
aberk 0:56d5a7ca509d 136 //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
aberk 0:56d5a7ca509d 137 //Byte two echo'd back in byte three.
aberk 0:56d5a7ca509d 138 spi_->write(0xAC);
aberk 0:56d5a7ca509d 139
aberk 0:56d5a7ca509d 140 spi_->write(0x53);
aberk 0:56d5a7ca509d 141
aberk 0:56d5a7ca509d 142 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 143
aberk 0:56d5a7ca509d 144 if (response == 0x53) {
aberk 0:56d5a7ca509d 145 error = 0;
aberk 0:56d5a7ca509d 146 } else {
aberk 0:56d5a7ca509d 147 error = -1;
aberk 0:56d5a7ca509d 148 }
aberk 0:56d5a7ca509d 149
aberk 0:56d5a7ca509d 150 spi_->write(0x00);
aberk 0:56d5a7ca509d 151
aberk 0:56d5a7ca509d 152 return error;
aberk 0:56d5a7ca509d 153
aberk 0:56d5a7ca509d 154 }
aberk 0:56d5a7ca509d 155
aberk 0:56d5a7ca509d 156 void AVR910::poll(void) {
aberk 0:56d5a7ca509d 157
aberk 0:56d5a7ca509d 158 int response = 0;
aberk 0:56d5a7ca509d 159
aberk 0:56d5a7ca509d 160 do {
aberk 0:56d5a7ca509d 161 spi_->write(0xF0);
aberk 0:56d5a7ca509d 162 spi_->write(0x00);
aberk 0:56d5a7ca509d 163 spi_->write(0x00);
aberk 0:56d5a7ca509d 164 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 165 } while ((response & 0x01) != 0);
aberk 0:56d5a7ca509d 166
aberk 0:56d5a7ca509d 167 }
aberk 0:56d5a7ca509d 168
aberk 0:56d5a7ca509d 169 int AVR910::readVendorCode(void) {
aberk 0:56d5a7ca509d 170
aberk 0:56d5a7ca509d 171 int response = 0;
aberk 0:56d5a7ca509d 172
aberk 0:56d5a7ca509d 173 //Issue read signature byte command.
aberk 0:56d5a7ca509d 174 //Address 0x00 is vendor code.
aberk 0:56d5a7ca509d 175 spi_->write(0x30);
aberk 0:56d5a7ca509d 176 spi_->write(0x00);
aberk 0:56d5a7ca509d 177 spi_->write(0x00);
aberk 0:56d5a7ca509d 178 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 179
aberk 0:56d5a7ca509d 180 return response;
aberk 0:56d5a7ca509d 181
aberk 0:56d5a7ca509d 182 }
aberk 0:56d5a7ca509d 183
aberk 0:56d5a7ca509d 184 int AVR910::readPartFamilyAndFlashSize(void) {
aberk 0:56d5a7ca509d 185
aberk 0:56d5a7ca509d 186 int response = 0;
aberk 0:56d5a7ca509d 187
aberk 0:56d5a7ca509d 188 //Issue read signature byte command.
aberk 0:56d5a7ca509d 189 //Address 0x01 is part family and flash size code.
aberk 0:56d5a7ca509d 190 spi_->write(0x30);
aberk 0:56d5a7ca509d 191 spi_->write(0x00);
aberk 0:56d5a7ca509d 192 spi_->write(0x01);
aberk 0:56d5a7ca509d 193 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 194
aberk 0:56d5a7ca509d 195 return response;
aberk 0:56d5a7ca509d 196
aberk 0:56d5a7ca509d 197 }
aberk 0:56d5a7ca509d 198
aberk 0:56d5a7ca509d 199 int AVR910::readPartNumber(void) {
aberk 0:56d5a7ca509d 200
aberk 0:56d5a7ca509d 201 int response = 0;
aberk 0:56d5a7ca509d 202
aberk 0:56d5a7ca509d 203 //Issue read signature byte command.
aberk 0:56d5a7ca509d 204 //Address 0x02 is part number code.
aberk 0:56d5a7ca509d 205 spi_->write(0x30);
aberk 0:56d5a7ca509d 206 spi_->write(0x00);
aberk 0:56d5a7ca509d 207 spi_->write(0x02);
aberk 0:56d5a7ca509d 208 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 209
aberk 0:56d5a7ca509d 210 return response;
aberk 0:56d5a7ca509d 211
aberk 0:56d5a7ca509d 212 }
aberk 0:56d5a7ca509d 213
aberk 0:56d5a7ca509d 214 void AVR910::chipErase(void) {
aberk 0:56d5a7ca509d 215
aberk 0:56d5a7ca509d 216 //Issue chip erase command.
aberk 0:56d5a7ca509d 217 spi_->write(0xAC);
aberk 0:56d5a7ca509d 218 spi_->write(0x80);
aberk 0:56d5a7ca509d 219 spi_->write(0x00);
aberk 0:56d5a7ca509d 220 spi_->write(0x00);
aberk 0:56d5a7ca509d 221
aberk 0:56d5a7ca509d 222 poll();
aberk 0:56d5a7ca509d 223
aberk 0:56d5a7ca509d 224 //Temporarily release reset line.
aberk 0:56d5a7ca509d 225 *nReset_ = 1;
aberk 0:56d5a7ca509d 226 *nReset_ = 0;
aberk 0:56d5a7ca509d 227
aberk 0:56d5a7ca509d 228 }
aberk 0:56d5a7ca509d 229
aberk 0:56d5a7ca509d 230 void AVR910::loadMemoryPage(int highLow, char address, char data) {
aberk 0:56d5a7ca509d 231
aberk 0:56d5a7ca509d 232 spi_->write(highLow);
aberk 0:56d5a7ca509d 233 spi_->write(0x00);
aberk 0:56d5a7ca509d 234 spi_->write(address & 0x3F);
aberk 0:56d5a7ca509d 235 spi_->write(data);
aberk 0:56d5a7ca509d 236
aberk 0:56d5a7ca509d 237 poll();
aberk 0:56d5a7ca509d 238
aberk 0:56d5a7ca509d 239 }
aberk 0:56d5a7ca509d 240
aberk 0:56d5a7ca509d 241 void AVR910::writeFlashMemoryPage(char pageNumber) {
aberk 0:56d5a7ca509d 242
aberk 0:56d5a7ca509d 243 spi_->write(0x4C);
aberk 0:56d5a7ca509d 244 spi_->write((pageNumber >> 2) & 0x3F);
aberk 0:56d5a7ca509d 245 spi_->write((pageNumber & 0x03) << 6);
aberk 0:56d5a7ca509d 246 spi_->write(0x00);
aberk 0:56d5a7ca509d 247
aberk 0:56d5a7ca509d 248 poll();
aberk 0:56d5a7ca509d 249
aberk 0:56d5a7ca509d 250 }
aberk 0:56d5a7ca509d 251
aberk 0:56d5a7ca509d 252 char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset) {
aberk 0:56d5a7ca509d 253
aberk 0:56d5a7ca509d 254 int response = 0;
aberk 0:56d5a7ca509d 255
aberk 0:56d5a7ca509d 256 spi_->write(highLow);
aberk 0:56d5a7ca509d 257 spi_->write((pageNumber >> 2) & 0x3F);
aberk 0:56d5a7ca509d 258 spi_->write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
aberk 0:56d5a7ca509d 259 response = spi_->write(0x00);
aberk 0:56d5a7ca509d 260
aberk 0:56d5a7ca509d 261 poll();
aberk 0:56d5a7ca509d 262
aberk 0:56d5a7ca509d 263 return response;
aberk 0:56d5a7ca509d 264
aberk 0:56d5a7ca509d 265 }
aberk 0:56d5a7ca509d 266
aberk 0:56d5a7ca509d 267 int AVR910::checkMemory(int numPages, FILE* binary){
aberk 0:56d5a7ca509d 268
aberk 0:56d5a7ca509d 269 int success = 0;
aberk 0:56d5a7ca509d 270 int response = 0;
aberk 0:56d5a7ca509d 271 char c = 0;
aberk 0:56d5a7ca509d 272
aberk 0:56d5a7ca509d 273 //Go back to the beginning of the binary file.
aberk 0:56d5a7ca509d 274 fseek(binary, 0, SEEK_SET);
aberk 0:56d5a7ca509d 275
aberk 0:56d5a7ca509d 276 for(int i = 0; i < numPages; i++){
aberk 0:56d5a7ca509d 277 for (int j = 0; j < PAGE_SIZE; j++) {
aberk 0:56d5a7ca509d 278 c = getc(binary);
aberk 0:56d5a7ca509d 279 //Read program memory low byte.
aberk 0:56d5a7ca509d 280 response = readProgramMemory(READ_LOW_BYTE, i, j);
aberk 0:56d5a7ca509d 281 //debug.printf("Low byte: 0x%02x\n", response);
aberk 0:56d5a7ca509d 282 if( c != response ){
aberk 0:56d5a7ca509d 283 debug.printf("page %i low byte %i: 0x%02x\n", i, j, response);
aberk 0:56d5a7ca509d 284 debug.printf("correct byte is 0x%02x\n", c);
aberk 0:56d5a7ca509d 285 success = -1;
aberk 0:56d5a7ca509d 286 }
aberk 0:56d5a7ca509d 287
aberk 0:56d5a7ca509d 288 c = getc(binary);
aberk 0:56d5a7ca509d 289 //Read program memory high byte.
aberk 0:56d5a7ca509d 290 response = readProgramMemory(READ_HIGH_BYTE, i, j);
aberk 0:56d5a7ca509d 291 //debug.printf("High byte: 0x%02x\n", response);
aberk 0:56d5a7ca509d 292 if( c != response ){
aberk 0:56d5a7ca509d 293 debug.printf("page %i high byte %i: 0x%02x\n", i, j, response);
aberk 0:56d5a7ca509d 294 debug.printf("correct byte is 0x%02x\n", c);
aberk 0:56d5a7ca509d 295 success = -1;
aberk 0:56d5a7ca509d 296 }
aberk 0:56d5a7ca509d 297 }
aberk 0:56d5a7ca509d 298 }
aberk 0:56d5a7ca509d 299
aberk 0:56d5a7ca509d 300 return success;
aberk 0:56d5a7ca509d 301
aberk 0:56d5a7ca509d 302 }