Program an AVR microcontroller using mbed.

Dependencies:   mbed

Committer:
aberk
Date:
Wed Sep 01 10:22:51 2010 +0000
Revision:
1:276f6df4be7a
Parent:
0:3066745764a5
Child:
2:99c56829a2a8
Added support for non-paged memory AVRs and changed parameters for the program(...) method to include page size (memory size if non-paged memory) and number of pages (=1 if non-paged memory).

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 0:3066745764a5 94 int c = 0;
aberk 0:3066745764a5 95 int highLow = 0;
aberk 1:276f6df4be7a 96
aberk 1:276f6df4be7a 97 //We're dealing with paged memory.
aberk 1:276f6df4be7a 98 if (numPages > 1) {
aberk 1:276f6df4be7a 99
aberk 1:276f6df4be7a 100 while ((c = getc(binary)) != EOF) {
aberk 1:276f6df4be7a 101
aberk 1:276f6df4be7a 102 //Page is fully loaded, time to write it to flash.
aberk 1:276f6df4be7a 103 if (pageOffset == (pageSize)) {
aberk 1:276f6df4be7a 104 writeFlashMemoryPage(pageNumber);
aberk 0:3066745764a5 105
aberk 1:276f6df4be7a 106 pageNumber++;
aberk 1:276f6df4be7a 107 if (pageNumber > numPages) {
aberk 1:276f6df4be7a 108 break;
aberk 1:276f6df4be7a 109 }
aberk 1:276f6df4be7a 110 pageOffset = 0;
aberk 1:276f6df4be7a 111 }
aberk 0:3066745764a5 112
aberk 1:276f6df4be7a 113 //Write low byte.
aberk 1:276f6df4be7a 114 if (highLow == 0) {
aberk 1:276f6df4be7a 115 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 116 highLow = 1;
aberk 1:276f6df4be7a 117 }
aberk 1:276f6df4be7a 118 //Write high byte.
aberk 1:276f6df4be7a 119 else {
aberk 1:276f6df4be7a 120 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 121 highLow = 0;
aberk 1:276f6df4be7a 122 pageOffset++;
aberk 1:276f6df4be7a 123 }
aberk 1:276f6df4be7a 124
aberk 0:3066745764a5 125 }
aberk 0:3066745764a5 126
aberk 1:276f6df4be7a 127 }
aberk 1:276f6df4be7a 128 //We're dealing with non-paged memory.
aberk 1:276f6df4be7a 129 else {
aberk 1:276f6df4be7a 130
aberk 1:276f6df4be7a 131 while ((c = getc(binary)) != EOF) {
aberk 1:276f6df4be7a 132
aberk 1:276f6df4be7a 133 //Write low byte.
aberk 1:276f6df4be7a 134 if (highLow == 0) {
aberk 1:276f6df4be7a 135 loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 136 highLow = 1;
aberk 1:276f6df4be7a 137 }
aberk 1:276f6df4be7a 138 //Write high byte.
aberk 1:276f6df4be7a 139 else {
aberk 1:276f6df4be7a 140 loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
aberk 1:276f6df4be7a 141 highLow = 0;
aberk 1:276f6df4be7a 142 pageOffset++;
aberk 1:276f6df4be7a 143
aberk 1:276f6df4be7a 144 if (pageOffset > pageSize) {
aberk 1:276f6df4be7a 145 break;
aberk 1:276f6df4be7a 146 }
aberk 1:276f6df4be7a 147
aberk 1:276f6df4be7a 148 }
aberk 1:276f6df4be7a 149
aberk 0:3066745764a5 150 }
aberk 0:3066745764a5 151
aberk 0:3066745764a5 152 }
aberk 0:3066745764a5 153
aberk 0:3066745764a5 154 //We might have partially filled up a page.
aberk 0:3066745764a5 155 writeFlashMemoryPage(pageNumber);
aberk 0:3066745764a5 156
aberk 0:3066745764a5 157 int success = -1;
aberk 0:3066745764a5 158 success = checkMemory(pageNumber, binary);
aberk 0:3066745764a5 159
aberk 0:3066745764a5 160 //Leave serial programming mode by pulling reset line high.
aberk 0:3066745764a5 161 nReset_ = 1;
aberk 0:3066745764a5 162
aberk 0:3066745764a5 163 return success;
aberk 0:3066745764a5 164
aberk 0:3066745764a5 165 }
aberk 0:3066745764a5 166
aberk 0:3066745764a5 167 void AVR910::setFrequency(int frequency) {
aberk 0:3066745764a5 168
aberk 0:3066745764a5 169 spi_.frequency(frequency);
aberk 0:3066745764a5 170
aberk 0:3066745764a5 171 }
aberk 0:3066745764a5 172
aberk 0:3066745764a5 173 int AVR910::enableProgramming(void) {
aberk 0:3066745764a5 174
aberk 0:3066745764a5 175 int response = 0;
aberk 0:3066745764a5 176 int error = 0;
aberk 0:3066745764a5 177
aberk 0:3066745764a5 178 //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
aberk 0:3066745764a5 179 //Byte two echo'd back in byte three.
aberk 0:3066745764a5 180 spi_.write(0xAC);
aberk 0:3066745764a5 181
aberk 0:3066745764a5 182 spi_.write(0x53);
aberk 0:3066745764a5 183
aberk 0:3066745764a5 184 response = spi_.write(0x00);
aberk 0:3066745764a5 185
aberk 0:3066745764a5 186 if (response == 0x53) {
aberk 0:3066745764a5 187 error = 0;
aberk 0:3066745764a5 188 } else {
aberk 0:3066745764a5 189 error = -1;
aberk 0:3066745764a5 190 }
aberk 0:3066745764a5 191
aberk 0:3066745764a5 192 spi_.write(0x00);
aberk 0:3066745764a5 193
aberk 0:3066745764a5 194 return error;
aberk 0:3066745764a5 195
aberk 0:3066745764a5 196 }
aberk 0:3066745764a5 197
aberk 0:3066745764a5 198 void AVR910::poll(void) {
aberk 0:3066745764a5 199
aberk 0:3066745764a5 200 int response = 0;
aberk 0:3066745764a5 201
aberk 0:3066745764a5 202 do {
aberk 0:3066745764a5 203 spi_.write(0xF0);
aberk 0:3066745764a5 204 spi_.write(0x00);
aberk 0:3066745764a5 205 spi_.write(0x00);
aberk 0:3066745764a5 206 response = spi_.write(0x00);
aberk 0:3066745764a5 207 } while ((response & 0x01) != 0);
aberk 0:3066745764a5 208
aberk 0:3066745764a5 209 }
aberk 0:3066745764a5 210
aberk 0:3066745764a5 211 int AVR910::readVendorCode(void) {
aberk 0:3066745764a5 212
aberk 0:3066745764a5 213 int response = 0;
aberk 0:3066745764a5 214
aberk 0:3066745764a5 215 //Issue read signature byte command.
aberk 0:3066745764a5 216 //Address 0x00 is vendor code.
aberk 0:3066745764a5 217 spi_.write(0x30);
aberk 0:3066745764a5 218 spi_.write(0x00);
aberk 0:3066745764a5 219 spi_.write(0x00);
aberk 0:3066745764a5 220 response = spi_.write(0x00);
aberk 0:3066745764a5 221
aberk 0:3066745764a5 222 return response;
aberk 0:3066745764a5 223
aberk 0:3066745764a5 224 }
aberk 0:3066745764a5 225
aberk 0:3066745764a5 226 int AVR910::readPartFamilyAndFlashSize(void) {
aberk 0:3066745764a5 227
aberk 0:3066745764a5 228 int response = 0;
aberk 0:3066745764a5 229
aberk 0:3066745764a5 230 //Issue read signature byte command.
aberk 0:3066745764a5 231 //Address 0x01 is part family and flash size code.
aberk 0:3066745764a5 232 spi_.write(0x30);
aberk 0:3066745764a5 233 spi_.write(0x00);
aberk 0:3066745764a5 234 spi_.write(0x01);
aberk 0:3066745764a5 235 response = spi_.write(0x00);
aberk 0:3066745764a5 236
aberk 0:3066745764a5 237 return response;
aberk 0:3066745764a5 238
aberk 0:3066745764a5 239 }
aberk 0:3066745764a5 240
aberk 0:3066745764a5 241 int AVR910::readPartNumber(void) {
aberk 0:3066745764a5 242
aberk 0:3066745764a5 243 int response = 0;
aberk 0:3066745764a5 244
aberk 0:3066745764a5 245 //Issue read signature byte command.
aberk 0:3066745764a5 246 //Address 0x02 is part number code.
aberk 0:3066745764a5 247 spi_.write(0x30);
aberk 0:3066745764a5 248 spi_.write(0x00);
aberk 0:3066745764a5 249 spi_.write(0x02);
aberk 0:3066745764a5 250 response = spi_.write(0x00);
aberk 0:3066745764a5 251
aberk 0:3066745764a5 252 return response;
aberk 0:3066745764a5 253
aberk 0:3066745764a5 254 }
aberk 0:3066745764a5 255
aberk 0:3066745764a5 256 void AVR910::chipErase(void) {
aberk 0:3066745764a5 257
aberk 0:3066745764a5 258 //Issue chip erase command.
aberk 0:3066745764a5 259 spi_.write(0xAC);
aberk 0:3066745764a5 260 spi_.write(0x80);
aberk 0:3066745764a5 261 spi_.write(0x00);
aberk 0:3066745764a5 262 spi_.write(0x00);
aberk 0:3066745764a5 263
aberk 0:3066745764a5 264 poll();
aberk 0:3066745764a5 265
aberk 0:3066745764a5 266 //Temporarily release reset line.
aberk 0:3066745764a5 267 nReset_ = 1;
aberk 0:3066745764a5 268 nReset_ = 0;
aberk 0:3066745764a5 269
aberk 0:3066745764a5 270 }
aberk 0:3066745764a5 271
aberk 0:3066745764a5 272 void AVR910::loadMemoryPage(int highLow, char address, char data) {
aberk 0:3066745764a5 273
aberk 0:3066745764a5 274 spi_.write(highLow);
aberk 0:3066745764a5 275 spi_.write(0x00);
aberk 0:3066745764a5 276 spi_.write(address & 0x3F);
aberk 0:3066745764a5 277 spi_.write(data);
aberk 0:3066745764a5 278
aberk 0:3066745764a5 279 poll();
aberk 0:3066745764a5 280
aberk 0:3066745764a5 281 }
aberk 0:3066745764a5 282
aberk 0:3066745764a5 283 void AVR910::writeFlashMemoryPage(char pageNumber) {
aberk 0:3066745764a5 284
aberk 0:3066745764a5 285 spi_.write(0x4C);
aberk 0:3066745764a5 286 spi_.write((pageNumber >> 2) & 0x3F);
aberk 0:3066745764a5 287 spi_.write((pageNumber & 0x03) << 6);
aberk 0:3066745764a5 288 spi_.write(0x00);
aberk 0:3066745764a5 289
aberk 0:3066745764a5 290 poll();
aberk 0:3066745764a5 291
aberk 0:3066745764a5 292 }
aberk 0:3066745764a5 293
aberk 0:3066745764a5 294 char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset) {
aberk 0:3066745764a5 295
aberk 0:3066745764a5 296 int response = 0;
aberk 0:3066745764a5 297
aberk 0:3066745764a5 298 spi_.write(highLow);
aberk 0:3066745764a5 299 spi_.write((pageNumber >> 2) & 0x3F);
aberk 0:3066745764a5 300 spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
aberk 0:3066745764a5 301 response = spi_.write(0x00);
aberk 0:3066745764a5 302
aberk 0:3066745764a5 303 poll();
aberk 0:3066745764a5 304
aberk 0:3066745764a5 305 return response;
aberk 0:3066745764a5 306
aberk 0:3066745764a5 307 }
aberk 0:3066745764a5 308
aberk 0:3066745764a5 309 int AVR910::checkMemory(int numPages, FILE* binary) {
aberk 0:3066745764a5 310
aberk 0:3066745764a5 311 int success = 0;
aberk 0:3066745764a5 312 int response = 0;
aberk 0:3066745764a5 313 char c = 0;
aberk 0:3066745764a5 314
aberk 0:3066745764a5 315 //Go back to the beginning of the binary file.
aberk 0:3066745764a5 316 fseek(binary, 0, SEEK_SET);
aberk 0:3066745764a5 317
aberk 0:3066745764a5 318 for (int i = 0; i < numPages; i++) {
aberk 0:3066745764a5 319 for (int j = 0; j < PAGE_SIZE; j++) {
aberk 0:3066745764a5 320 c = getc(binary);
aberk 0:3066745764a5 321 //Read program memory low byte.
aberk 0:3066745764a5 322 response = readProgramMemory(READ_LOW_BYTE, i, j);
aberk 0:3066745764a5 323 //debug.printf("Low byte: 0x%02x\n", response);
aberk 0:3066745764a5 324 if ( c != response ) {
aberk 0:3066745764a5 325 debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response);
aberk 0:3066745764a5 326 debug.printf("Correct byte is 0x%02x\n", c);
aberk 0:3066745764a5 327 success = -1;
aberk 0:3066745764a5 328 }
aberk 0:3066745764a5 329
aberk 0:3066745764a5 330 c = getc(binary);
aberk 0:3066745764a5 331 //Read program memory high byte.
aberk 0:3066745764a5 332 response = readProgramMemory(READ_HIGH_BYTE, i, j);
aberk 0:3066745764a5 333 //debug.printf("High byte: 0x%02x\n", response);
aberk 0:3066745764a5 334 if ( c != response ) {
aberk 0:3066745764a5 335 debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response);
aberk 0:3066745764a5 336 debug.printf("Correct byte is 0x%02x\n", c);
aberk 0:3066745764a5 337 success = -1;
aberk 0:3066745764a5 338 }
aberk 0:3066745764a5 339 }
aberk 0:3066745764a5 340 }
aberk 0:3066745764a5 341
aberk 0:3066745764a5 342 return success;
aberk 0:3066745764a5 343
aberk 0:3066745764a5 344 }