Dependencies:   mbed

Committer:
chris
Date:
Mon Nov 01 22:52:40 2010 +0000
Revision:
1:ce6a12e62219
Parent:
0:20fc0ecfb510
Added a #define to determine if the bin file is deleted

Who changed what in which revision?

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