Program an AVR microcontroller using mbed.

Dependencies:   mbed

Committer:
aberk
Date:
Thu Sep 09 11:11:37 2010 +0000
Revision:
2:99c56829a2a8
Parent:
1:276f6df4be7a
Improved support and documentation for non-paged memory devices.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aberk 0:3066745764a5 1 /**
aberk 0:3066745764a5 2 * @author Aaron Berk
aberk 0:3066745764a5 3 *
aberk 0:3066745764a5 4 * @section LICENSE
aberk 0:3066745764a5 5 *
aberk 0:3066745764a5 6 * Copyright (c) 2010 Aaron Berk
aberk 0:3066745764a5 7 *
aberk 0:3066745764a5 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
aberk 0:3066745764a5 9 * of this software and associated documentation files (the "Software"), to deal
aberk 0:3066745764a5 10 * in the Software without restriction, including without limitation the rights
aberk 0:3066745764a5 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
aberk 0:3066745764a5 12 * copies of the Software, and to permit persons to whom the Software is
aberk 0:3066745764a5 13 * furnished to do so, subject to the following conditions:
aberk 0:3066745764a5 14 *
aberk 0:3066745764a5 15 * The above copyright notice and this permission notice shall be included in
aberk 0:3066745764a5 16 * all copies or substantial portions of the Software.
aberk 0:3066745764a5 17 *
aberk 0:3066745764a5 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
aberk 0:3066745764a5 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
aberk 0:3066745764a5 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
aberk 0:3066745764a5 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
aberk 0:3066745764a5 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
aberk 0:3066745764a5 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
aberk 0:3066745764a5 24 * THE SOFTWARE.
aberk 0:3066745764a5 25 *
aberk 0:3066745764a5 26 * @section DESCRIPTION
aberk 0:3066745764a5 27 *
aberk 0:3066745764a5 28 * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
aberk 0:3066745764a5 29 * using an mbed.
aberk 0:3066745764a5 30 *
aberk 0:3066745764a5 31 * AVR910 Application Note:
aberk 0:3066745764a5 32 *
aberk 0:3066745764a5 33 * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
aberk 0:3066745764a5 34 */
aberk 0:3066745764a5 35
aberk 0:3066745764a5 36 /**
aberk 0:3066745764a5 37 * Includes
aberk 0:3066745764a5 38 */
aberk 0:3066745764a5 39 #include "AVR910.h"
aberk 0:3066745764a5 40
aberk 0:3066745764a5 41 Serial debug(USBTX, USBRX);
aberk 0:3066745764a5 42
aberk 0:3066745764a5 43 AVR910::AVR910(PinName mosi,
aberk 0:3066745764a5 44 PinName miso,
aberk 0:3066745764a5 45 PinName sclk,
aberk 0:3066745764a5 46 PinName nReset) : spi_(mosi, miso, sclk), nReset_(nReset) {
aberk 0:3066745764a5 47
aberk 0:3066745764a5 48 //Slow frequency as default to ensure no errors from
aberk 0:3066745764a5 49 //trying to run it too fast. Increase as appropriate.
aberk 0:3066745764a5 50 spi_.frequency(32000);
aberk 0:3066745764a5 51 spi_.format(8, 0);
aberk 0:3066745764a5 52
aberk 0:3066745764a5 53 int response = 0;
aberk 0:3066745764a5 54
aberk 0:3066745764a5 55 //Enter serial programming mode by pulling reset line low.
aberk 0:3066745764a5 56 nReset_ = 0;
aberk 0:3066745764a5 57
aberk 0:3066745764a5 58 //Wait 20ms before issuing first command.
aberk 0:3066745764a5 59 wait_ms(20);
aberk 0:3066745764a5 60
aberk 0:3066745764a5 61 //Issue a programming enable command.
aberk 0:3066745764a5 62 response = enableProgramming();
aberk 1:276f6df4be7a 63
aberk 0:3066745764a5 64 //Simple debugging to see if we get trapped
aberk 0:3066745764a5 65 //in an infinite loop.
aberk 0:3066745764a5 66 DigitalOut working(LED1);
aberk 0:3066745764a5 67 working = 1;
aberk 0:3066745764a5 68
aberk 0:3066745764a5 69 //TODO: introduce a timeout.
aberk 0:3066745764a5 70 while (response < 0) {
aberk 0:3066745764a5 71
aberk 0:3066745764a5 72 //Give nReset a positive pulse.
aberk 0:3066745764a5 73 nReset_ = 1;
aberk 0:3066745764a5 74 wait_ms(20);
aberk 0:3066745764a5 75 nReset_ = 0;
aberk 0:3066745764a5 76 wait_ms(20);
aberk 0:3066745764a5 77
aberk 0:3066745764a5 78 //Issue another programming enable.
aberk 0:3066745764a5 79 response = enableProgramming();
aberk 0:3066745764a5 80
aberk 0:3066745764a5 81 }
aberk 1:276f6df4be7a 82
aberk 0:3066745764a5 83 working = 0;
aberk 0:3066745764a5 84
aberk 0:3066745764a5 85 }
aberk 0:3066745764a5 86
aberk 1:276f6df4be7a 87 int AVR910::program(FILE* binary, int pageSize, int numPages) {
aberk 0:3066745764a5 88
aberk 0:3066745764a5 89 //Clear memory contents.
aberk 0:3066745764a5 90 chipErase();
aberk 0:3066745764a5 91
aberk 0:3066745764a5 92 char pageOffset = 0;
aberk 0:3066745764a5 93 int pageNumber = 0;
aberk 2:99c56829a2a8 94 int address = 0;
aberk 0:3066745764a5 95 int c = 0;
aberk 0:3066745764a5 96 int highLow = 0;
aberk 1:276f6df4be7a 97
aberk 1:276f6df4be7a 98 //We're dealing with paged memory.
aberk 1:276f6df4be7a 99 if (numPages > 1) {
aberk 1:276f6df4be7a 100
aberk 1:276f6df4be7a 101 while ((c = getc(binary)) != EOF) {
aberk 1:276f6df4be7a 102
aberk 1:276f6df4be7a 103 //Page is fully loaded, time to write it to flash.
aberk 1:276f6df4be7a 104 if (pageOffset == (pageSize)) {
aberk 1:276f6df4be7a 105 writeFlashMemoryPage(pageNumber);
aberk 0:3066745764a5 106
aberk 1:276f6df4be7a 107 pageNumber++;
aberk 1:276f6df4be7a 108 if (pageNumber > numPages) {
aberk 1:276f6df4be7a 109 break;
aberk 1:276f6df4be7a 110 }
aberk 1:276f6df4be7a 111 pageOffset = 0;
aberk 1:276f6df4be7a 112 }
aberk 0:3066745764a5 113
aberk 1:276f6df4be7a 114 //Write low byte.
aberk 1:276f6df4be7a 115 if (highLow == 0) {
aberk 1:276f6df4be7a 116 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 117 highLow = 1;
aberk 1:276f6df4be7a 118 }
aberk 1:276f6df4be7a 119 //Write high byte.
aberk 1:276f6df4be7a 120 else {
aberk 1:276f6df4be7a 121 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 122 highLow = 0;
aberk 1:276f6df4be7a 123 pageOffset++;
aberk 1:276f6df4be7a 124 }
aberk 1:276f6df4be7a 125
aberk 0:3066745764a5 126 }
aberk 0:3066745764a5 127
aberk 1:276f6df4be7a 128 }
aberk 1:276f6df4be7a 129 //We're dealing with non-paged memory.
aberk 1:276f6df4be7a 130 else {
aberk 1:276f6df4be7a 131
aberk 1:276f6df4be7a 132 while ((c = getc(binary)) != EOF) {
aberk 1:276f6df4be7a 133
aberk 1:276f6df4be7a 134 //Write low byte.
aberk 1:276f6df4be7a 135 if (highLow == 0) {
aberk 2:99c56829a2a8 136 writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c);
aberk 1:276f6df4be7a 137 highLow = 1;
aberk 1:276f6df4be7a 138 }
aberk 1:276f6df4be7a 139 //Write high byte.
aberk 1:276f6df4be7a 140 else {
aberk 2:99c56829a2a8 141 writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c);
aberk 1:276f6df4be7a 142 highLow = 0;
aberk 2:99c56829a2a8 143 address++;
aberk 1:276f6df4be7a 144
aberk 2:99c56829a2a8 145 //Page size is our memory size in the non-paged memory case.
aberk 2:99c56829a2a8 146 //Therefore if we've gone beyond our size break because we
aberk 2:99c56829a2a8 147 //don't have any more room.
aberk 2:99c56829a2a8 148 if (address > pageSize) {
aberk 1:276f6df4be7a 149 break;
aberk 1:276f6df4be7a 150 }
aberk 1:276f6df4be7a 151
aberk 1:276f6df4be7a 152 }
aberk 1:276f6df4be7a 153
aberk 0:3066745764a5 154 }
aberk 0:3066745764a5 155
aberk 0:3066745764a5 156 }
aberk 0:3066745764a5 157
aberk 0:3066745764a5 158 //We might have partially filled up a page.
aberk 0:3066745764a5 159 writeFlashMemoryPage(pageNumber);
aberk 0:3066745764a5 160
aberk 0:3066745764a5 161 int success = -1;
aberk 0:3066745764a5 162 success = checkMemory(pageNumber, binary);
aberk 0:3066745764a5 163
aberk 0:3066745764a5 164 //Leave serial programming mode by pulling reset line high.
aberk 0:3066745764a5 165 nReset_ = 1;
aberk 0:3066745764a5 166
aberk 0:3066745764a5 167 return success;
aberk 0:3066745764a5 168
aberk 0:3066745764a5 169 }
aberk 0:3066745764a5 170
aberk 0:3066745764a5 171 void AVR910::setFrequency(int frequency) {
aberk 0:3066745764a5 172
aberk 0:3066745764a5 173 spi_.frequency(frequency);
aberk 0:3066745764a5 174
aberk 0:3066745764a5 175 }
aberk 0:3066745764a5 176
aberk 0:3066745764a5 177 int AVR910::enableProgramming(void) {
aberk 0:3066745764a5 178
aberk 0:3066745764a5 179 int response = 0;
aberk 0:3066745764a5 180 int error = 0;
aberk 0:3066745764a5 181
aberk 0:3066745764a5 182 //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
aberk 0:3066745764a5 183 //Byte two echo'd back in byte three.
aberk 0:3066745764a5 184 spi_.write(0xAC);
aberk 0:3066745764a5 185
aberk 0:3066745764a5 186 spi_.write(0x53);
aberk 0:3066745764a5 187
aberk 0:3066745764a5 188 response = spi_.write(0x00);
aberk 0:3066745764a5 189
aberk 0:3066745764a5 190 if (response == 0x53) {
aberk 0:3066745764a5 191 error = 0;
aberk 0:3066745764a5 192 } else {
aberk 0:3066745764a5 193 error = -1;
aberk 0:3066745764a5 194 }
aberk 0:3066745764a5 195
aberk 0:3066745764a5 196 spi_.write(0x00);
aberk 0:3066745764a5 197
aberk 0:3066745764a5 198 return error;
aberk 0:3066745764a5 199
aberk 0:3066745764a5 200 }
aberk 0:3066745764a5 201
aberk 0:3066745764a5 202 void AVR910::poll(void) {
aberk 0:3066745764a5 203
aberk 0:3066745764a5 204 int response = 0;
aberk 0:3066745764a5 205
aberk 0:3066745764a5 206 do {
aberk 0:3066745764a5 207 spi_.write(0xF0);
aberk 0:3066745764a5 208 spi_.write(0x00);
aberk 0:3066745764a5 209 spi_.write(0x00);
aberk 0:3066745764a5 210 response = spi_.write(0x00);
aberk 0:3066745764a5 211 } while ((response & 0x01) != 0);
aberk 0:3066745764a5 212
aberk 0:3066745764a5 213 }
aberk 0:3066745764a5 214
aberk 0:3066745764a5 215 int AVR910::readVendorCode(void) {
aberk 0:3066745764a5 216
aberk 0:3066745764a5 217 int response = 0;
aberk 0:3066745764a5 218
aberk 0:3066745764a5 219 //Issue read signature byte command.
aberk 0:3066745764a5 220 //Address 0x00 is vendor code.
aberk 0:3066745764a5 221 spi_.write(0x30);
aberk 0:3066745764a5 222 spi_.write(0x00);
aberk 0:3066745764a5 223 spi_.write(0x00);
aberk 0:3066745764a5 224 response = spi_.write(0x00);
aberk 0:3066745764a5 225
aberk 0:3066745764a5 226 return response;
aberk 0:3066745764a5 227
aberk 0:3066745764a5 228 }
aberk 0:3066745764a5 229
aberk 0:3066745764a5 230 int AVR910::readPartFamilyAndFlashSize(void) {
aberk 0:3066745764a5 231
aberk 0:3066745764a5 232 int response = 0;
aberk 0:3066745764a5 233
aberk 0:3066745764a5 234 //Issue read signature byte command.
aberk 0:3066745764a5 235 //Address 0x01 is part family and flash size code.
aberk 0:3066745764a5 236 spi_.write(0x30);
aberk 0:3066745764a5 237 spi_.write(0x00);
aberk 0:3066745764a5 238 spi_.write(0x01);
aberk 0:3066745764a5 239 response = spi_.write(0x00);
aberk 0:3066745764a5 240
aberk 0:3066745764a5 241 return response;
aberk 0:3066745764a5 242
aberk 0:3066745764a5 243 }
aberk 0:3066745764a5 244
aberk 0:3066745764a5 245 int AVR910::readPartNumber(void) {
aberk 0:3066745764a5 246
aberk 0:3066745764a5 247 int response = 0;
aberk 0:3066745764a5 248
aberk 0:3066745764a5 249 //Issue read signature byte command.
aberk 0:3066745764a5 250 //Address 0x02 is part number code.
aberk 0:3066745764a5 251 spi_.write(0x30);
aberk 0:3066745764a5 252 spi_.write(0x00);
aberk 0:3066745764a5 253 spi_.write(0x02);
aberk 0:3066745764a5 254 response = spi_.write(0x00);
aberk 0:3066745764a5 255
aberk 0:3066745764a5 256 return response;
aberk 0:3066745764a5 257
aberk 0:3066745764a5 258 }
aberk 0:3066745764a5 259
aberk 0:3066745764a5 260 void AVR910::chipErase(void) {
aberk 0:3066745764a5 261
aberk 0:3066745764a5 262 //Issue chip erase command.
aberk 0:3066745764a5 263 spi_.write(0xAC);
aberk 0:3066745764a5 264 spi_.write(0x80);
aberk 0:3066745764a5 265 spi_.write(0x00);
aberk 0:3066745764a5 266 spi_.write(0x00);
aberk 0:3066745764a5 267
aberk 0:3066745764a5 268 poll();
aberk 0:3066745764a5 269
aberk 0:3066745764a5 270 //Temporarily release reset line.
aberk 0:3066745764a5 271 nReset_ = 1;
aberk 0:3066745764a5 272 nReset_ = 0;
aberk 0:3066745764a5 273
aberk 0:3066745764a5 274 }
aberk 0:3066745764a5 275
aberk 0:3066745764a5 276 void AVR910::loadMemoryPage(int highLow, char address, char data) {
aberk 0:3066745764a5 277
aberk 0:3066745764a5 278 spi_.write(highLow);
aberk 0:3066745764a5 279 spi_.write(0x00);
aberk 0:3066745764a5 280 spi_.write(address & 0x3F);
aberk 0:3066745764a5 281 spi_.write(data);
aberk 0:3066745764a5 282
aberk 0:3066745764a5 283 poll();
aberk 0:3066745764a5 284
aberk 0:3066745764a5 285 }
aberk 0:3066745764a5 286
aberk 2:99c56829a2a8 287 void AVR910::writeFlashMemoryByte(int highLow, int address, char data) {
aberk 2:99c56829a2a8 288
aberk 2:99c56829a2a8 289 spi_.write(highLow);
aberk 2:99c56829a2a8 290 spi_.write(address & 0xFF00 >> 8);
aberk 2:99c56829a2a8 291 spi_.write(address & 0x00FF);
aberk 2:99c56829a2a8 292 spi_.write(data);
aberk 2:99c56829a2a8 293
aberk 2:99c56829a2a8 294 }
aberk 2:99c56829a2a8 295
aberk 0:3066745764a5 296 void AVR910::writeFlashMemoryPage(char pageNumber) {
aberk 0:3066745764a5 297
aberk 0:3066745764a5 298 spi_.write(0x4C);
aberk 0:3066745764a5 299 spi_.write((pageNumber >> 2) & 0x3F);
aberk 0:3066745764a5 300 spi_.write((pageNumber & 0x03) << 6);
aberk 0:3066745764a5 301 spi_.write(0x00);
aberk 0:3066745764a5 302
aberk 0:3066745764a5 303 poll();
aberk 0:3066745764a5 304
aberk 0:3066745764a5 305 }
aberk 0:3066745764a5 306
aberk 0:3066745764a5 307 char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset) {
aberk 0:3066745764a5 308
aberk 0:3066745764a5 309 int response = 0;
aberk 0:3066745764a5 310
aberk 0:3066745764a5 311 spi_.write(highLow);
aberk 0:3066745764a5 312 spi_.write((pageNumber >> 2) & 0x3F);
aberk 0:3066745764a5 313 spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
aberk 0:3066745764a5 314 response = spi_.write(0x00);
aberk 0:3066745764a5 315
aberk 0:3066745764a5 316 poll();
aberk 0:3066745764a5 317
aberk 0:3066745764a5 318 return response;
aberk 0:3066745764a5 319
aberk 0:3066745764a5 320 }
aberk 0:3066745764a5 321
aberk 0:3066745764a5 322 int AVR910::checkMemory(int numPages, FILE* binary) {
aberk 0:3066745764a5 323
aberk 0:3066745764a5 324 int success = 0;
aberk 0:3066745764a5 325 int response = 0;
aberk 0:3066745764a5 326 char c = 0;
aberk 0:3066745764a5 327
aberk 0:3066745764a5 328 //Go back to the beginning of the binary file.
aberk 0:3066745764a5 329 fseek(binary, 0, SEEK_SET);
aberk 0:3066745764a5 330
aberk 0:3066745764a5 331 for (int i = 0; i < numPages; i++) {
aberk 0:3066745764a5 332 for (int j = 0; j < PAGE_SIZE; j++) {
aberk 0:3066745764a5 333 c = getc(binary);
aberk 0:3066745764a5 334 //Read program memory low byte.
aberk 0:3066745764a5 335 response = readProgramMemory(READ_LOW_BYTE, i, j);
aberk 0:3066745764a5 336 //debug.printf("Low byte: 0x%02x\n", response);
aberk 0:3066745764a5 337 if ( c != response ) {
aberk 0:3066745764a5 338 debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response);
aberk 0:3066745764a5 339 debug.printf("Correct byte is 0x%02x\n", c);
aberk 0:3066745764a5 340 success = -1;
aberk 0:3066745764a5 341 }
aberk 0:3066745764a5 342
aberk 0:3066745764a5 343 c = getc(binary);
aberk 0:3066745764a5 344 //Read program memory high byte.
aberk 0:3066745764a5 345 response = readProgramMemory(READ_HIGH_BYTE, i, j);
aberk 0:3066745764a5 346 //debug.printf("High byte: 0x%02x\n", response);
aberk 0:3066745764a5 347 if ( c != response ) {
aberk 0:3066745764a5 348 debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response);
aberk 0:3066745764a5 349 debug.printf("Correct byte is 0x%02x\n", c);
aberk 0:3066745764a5 350 success = -1;
aberk 0:3066745764a5 351 }
aberk 0:3066745764a5 352 }
aberk 0:3066745764a5 353 }
aberk 0:3066745764a5 354
aberk 0:3066745764a5 355 return success;
aberk 0:3066745764a5 356
aberk 0:3066745764a5 357 }