Program an AVR microcontroller using mbed.

Dependencies:   mbed

Committer:
aberk
Date:
Tue Aug 31 14:09:53 2010 +0000
Revision:
0:3066745764a5
Child:
1:276f6df4be7a
Version 1.0

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