ATmega328/168/8/48/88 Programming Shield
ATmega328/168/48/8/88 programming and bootloader shield.
Devices & Components
Arduino Uno Rev3
EFTDI PROGRAMMER
Resistor 1k ohm
Tactile Switch, Top Actuated
Capacitor 1 µF
5 mm LED: Green
Terminal Block Interface, Terminal Block
5 mm LED: Yellow
5 mm LED: Red
16 MHz Crystal
Capacitor 100 nF
Capacitor 100 µF
Capacitor 22 pF
IC & Component Socket, 28 Contacts
Male-Header 36 Position 1 Row- Long (0.1")
ATmega328PB microcontroller
Resistor 10k ohm
Hardware & Tools
Solder Flux, Soldering
Soldering Station, 110 V
Solder Wire, Lead Free
Desoldering Braid, Solder Wick
Software & Tools
Arduino IDE
Project description
Code
Arduino ISP Programmer Sketch
arduino
Code to convert an arduino into an ISP Programmer
1// ArduinoISP 2// Copyright (c) 2008-2011 Randall Bohn 3// If you require a license, see 4// https://opensource.org/licenses/bsd-license.php 5// 6// This sketch turns the Arduino into a AVRISP using the following Arduino pins: 7// 8// Pin 10 is used to reset the target microcontroller. 9// 10// By default, the hardware SPI pins MISO, MOSI and SCK are used to communicate 11// with the target. On all Arduinos, these pins can be found 12// on the ICSP/SPI header: 13// 14// MISO °. . 5V (!) Avoid this pin on Due, Zero... 15// SCK . . MOSI 16// . . GND 17// 18// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same pins as 19// digital pin 11, 12 and 13, respectively. That is why many tutorials instruct 20// you to hook up the target to these pins. If you find this wiring more 21// practical, have a define USE_OLD_STYLE_WIRING. This will work even when not 22// using an Uno. (On an Uno this is not needed). 23// 24// Alternatively you can use any other digital pin by configuring 25// software ('BitBanged') SPI and having appropriate defines for PIN_MOSI, 26// PIN_MISO and PIN_SCK. 27// 28// IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...) as 29// the programmer, make sure to not expose any of the programmer's pins to 5V. 30// A simple way to accomplish this is to power the complete system (programmer 31// and target) at 3V3. 32// 33// Put an LED (with resistor) on the following pins: 34// 9: Heartbeat - shows the programmer is running 35// 8: Error - Lights up if something goes wrong (use red if that makes sense) 36// 7: Programming - In communication with the slave 37// 38 39#include "Arduino.h" 40#undef SERIAL 41 42 43#define PROG_FLICKER true 44 45// Configure SPI clock (in Hz). 46// E.g. for an ATtiny @ 128 kHz: the datasheet states that both the high and low 47// SPI clock pulse must be > 2 CPU cycles, so take 3 cycles i.e. divide target 48// f_cpu by 6: 49// #define SPI_CLOCK (128000/6) 50// 51// A clock slow enough for an ATtiny85 @ 1 MHz, is a reasonable default: 52 53#define SPI_CLOCK (1000000/6) 54 55 56// Select hardware or software SPI, depending on SPI clock. 57// Currently only for AVR, for other architectures (Due, Zero,...), hardware SPI 58// is probably too fast anyway. 59 60#if defined(ARDUINO_ARCH_AVR) 61 62 #if SPI_CLOCK > (F_CPU / 128) 63 #define USE_HARDWARE_SPI 64 #endif 65 66#endif 67 68// Configure which pins to use: 69 70// The standard pin configuration. 71#ifndef ARDUINO_HOODLOADER2 72 73 #define RESET 10 // Use pin 10 to reset the target rather than SS 74 #define LED_HB 9 75 #define LED_ERR 8 76 #define LED_PMODE 7 77 78 // Uncomment following line to use the old Uno style wiring 79 // (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due... 80 81 // #define USE_OLD_STYLE_WIRING 82 83 #ifdef USE_OLD_STYLE_WIRING 84 85 #define PIN_MOSI 11 86 #define PIN_MISO 12 87 #define PIN_SCK 13 88 89 #endif 90 91 // HOODLOADER2 means running sketches on the ATmega16U2 serial converter chips 92 // on Uno or Mega boards. We must use pins that are broken out: 93#else 94 95 #define RESET 4 96 #define LED_HB 7 97 #define LED_ERR 6 98 #define LED_PMODE 5 99 100#endif 101 102// By default, use hardware SPI pins: 103#ifndef PIN_MOSI 104 #define PIN_MOSI MOSI 105#endif 106 107#ifndef PIN_MISO 108 #define PIN_MISO MISO 109#endif 110 111#ifndef PIN_SCK 112 #define PIN_SCK SCK 113#endif 114 115// Force bitbanged SPI if not using the hardware SPI pins: 116#if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK) 117 #undef USE_HARDWARE_SPI 118#endif 119 120 121// Configure the serial port to use. 122// 123// Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one: 124// - it does not autoreset (except for the magic baud rate of 1200). 125// - it is more reliable because of USB handshaking. 126// 127// Leonardo and similar have an USB virtual serial port: 'Serial'. 128// Due and Zero have an USB virtual serial port: 'SerialUSB'. 129// 130// On the Due and Zero, 'Serial' can be used too, provided you disable autoreset. 131// To use 'Serial': #define SERIAL Serial 132 133#ifdef SERIAL_PORT_USBVIRTUAL 134 #define SERIAL SERIAL_PORT_USBVIRTUAL 135#else 136 #define SERIAL Serial 137#endif 138 139 140// Configure the baud rate: 141 142#define BAUDRATE 19200 143// #define BAUDRATE 115200 144// #define BAUDRATE 1000000 145 146 147#define HWVER 2 148#define SWMAJ 1 149#define SWMIN 18 150 151// STK Definitions 152#define STK_OK 0x10 153#define STK_FAILED 0x11 154#define STK_UNKNOWN 0x12 155#define STK_INSYNC 0x14 156#define STK_NOSYNC 0x15 157#define CRC_EOP 0x20 //ok it is a space... 158 159void pulse(int pin, int times); 160 161#ifdef USE_HARDWARE_SPI 162#include "SPI.h" 163#else 164 165#define SPI_MODE0 0x00 166 167#if !defined(ARDUINO_API_VERSION) || ARDUINO_API_VERSION != 10001 // A SPISettings class is declared by ArduinoCore-API 1.0.1 168class SPISettings { 169 public: 170 // clock is in Hz 171 SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clockFreq(clock) { 172 (void) bitOrder; 173 (void) dataMode; 174 }; 175 176 uint32_t getClockFreq() const { 177 return clockFreq; 178 } 179 180 private: 181 uint32_t clockFreq; 182}; 183#endif // !defined(ARDUINO_API_VERSION) 184 185class BitBangedSPI { 186 public: 187 void begin() { 188 digitalWrite(PIN_SCK, LOW); 189 digitalWrite(PIN_MOSI, LOW); 190 pinMode(PIN_SCK, OUTPUT); 191 pinMode(PIN_MOSI, OUTPUT); 192 pinMode(PIN_MISO, INPUT); 193 } 194 195 void beginTransaction(SPISettings settings) { 196 pulseWidth = (500000 + settings.getClockFreq() - 1) / settings.getClockFreq(); 197 if (pulseWidth == 0) { 198 pulseWidth = 1; 199 } 200 } 201 202 void end() {} 203 204 uint8_t transfer(uint8_t b) { 205 for (unsigned int i = 0; i < 8; ++i) { 206 digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW); 207 digitalWrite(PIN_SCK, HIGH); 208 delayMicroseconds(pulseWidth); 209 b = (b << 1) | digitalRead(PIN_MISO); 210 digitalWrite(PIN_SCK, LOW); // slow pulse 211 delayMicroseconds(pulseWidth); 212 } 213 return b; 214 } 215 216 private: 217 unsigned long pulseWidth; // in microseconds 218}; 219 220static BitBangedSPI SPI; 221 222#endif 223 224void setup() { 225 SERIAL.begin(BAUDRATE); 226 227 pinMode(LED_PMODE, OUTPUT); 228 pulse(LED_PMODE, 2); 229 pinMode(LED_ERR, OUTPUT); 230 pulse(LED_ERR, 2); 231 pinMode(LED_HB, OUTPUT); 232 pulse(LED_HB, 2); 233 234} 235 236int ISPError = 0; 237int pmode = 0; 238// address for reading and writing, set by 'U' command 239unsigned int here; 240uint8_t buff[256]; // global block storage 241 242#define beget16(addr) (*addr * 256 + *(addr+1) ) 243typedef struct param { 244 uint8_t devicecode; 245 uint8_t revision; 246 uint8_t progtype; 247 uint8_t parmode; 248 uint8_t polling; 249 uint8_t selftimed; 250 uint8_t lockbytes; 251 uint8_t fusebytes; 252 uint8_t flashpoll; 253 uint16_t eeprompoll; 254 uint16_t pagesize; 255 uint16_t eepromsize; 256 uint32_t flashsize; 257} 258parameter; 259 260parameter param; 261 262// this provides a heartbeat on pin 9, so you can tell the software is running. 263uint8_t hbval = 128; 264int8_t hbdelta = 8; 265void heartbeat() { 266 static unsigned long last_time = 0; 267 unsigned long now = millis(); 268 if ((now - last_time) < 40) { 269 return; 270 } 271 last_time = now; 272 if (hbval > 192) { 273 hbdelta = -hbdelta; 274 } 275 if (hbval < 32) { 276 hbdelta = -hbdelta; 277 } 278 hbval += hbdelta; 279 analogWrite(LED_HB, hbval); 280} 281 282static bool rst_active_high; 283 284void reset_target(bool reset) { 285 digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW); 286} 287 288void loop(void) { 289 // is pmode active? 290 if (pmode) { 291 digitalWrite(LED_PMODE, HIGH); 292 } else { 293 digitalWrite(LED_PMODE, LOW); 294 } 295 // is there an error? 296 if (ISPError) { 297 digitalWrite(LED_ERR, HIGH); 298 } else { 299 digitalWrite(LED_ERR, LOW); 300 } 301 302 // light the heartbeat LED 303 heartbeat(); 304 if (SERIAL.available()) { 305 avrisp(); 306 } 307} 308 309uint8_t getch() { 310 while (!SERIAL.available()); 311 return SERIAL.read(); 312} 313void fill(int n) { 314 for (int x = 0; x < n; x++) { 315 buff[x] = getch(); 316 } 317} 318 319#define PTIME 30 320void pulse(int pin, int times) { 321 do { 322 digitalWrite(pin, HIGH); 323 delay(PTIME); 324 digitalWrite(pin, LOW); 325 delay(PTIME); 326 } while (times--); 327} 328 329void prog_lamp(int state) { 330 if (PROG_FLICKER) { 331 digitalWrite(LED_PMODE, state); 332 } 333} 334 335uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { 336 SPI.transfer(a); 337 SPI.transfer(b); 338 SPI.transfer(c); 339 return SPI.transfer(d); 340} 341 342void empty_reply() { 343 if (CRC_EOP == getch()) { 344 SERIAL.print((char)STK_INSYNC); 345 SERIAL.print((char)STK_OK); 346 } else { 347 ISPError++; 348 SERIAL.print((char)STK_NOSYNC); 349 } 350} 351 352void breply(uint8_t b) { 353 if (CRC_EOP == getch()) { 354 SERIAL.print((char)STK_INSYNC); 355 SERIAL.print((char)b); 356 SERIAL.print((char)STK_OK); 357 } else { 358 ISPError++; 359 SERIAL.print((char)STK_NOSYNC); 360 } 361} 362 363void get_version(uint8_t c) { 364 switch (c) { 365 case 0x80: 366 breply(HWVER); 367 break; 368 case 0x81: 369 breply(SWMAJ); 370 break; 371 case 0x82: 372 breply(SWMIN); 373 break; 374 case 0x93: 375 breply('S'); // serial programmer 376 break; 377 default: 378 breply(0); 379 } 380} 381 382void set_parameters() { 383 // call this after reading parameter packet into buff[] 384 param.devicecode = buff[0]; 385 param.revision = buff[1]; 386 param.progtype = buff[2]; 387 param.parmode = buff[3]; 388 param.polling = buff[4]; 389 param.selftimed = buff[5]; 390 param.lockbytes = buff[6]; 391 param.fusebytes = buff[7]; 392 param.flashpoll = buff[8]; 393 // ignore buff[9] (= buff[8]) 394 // following are 16 bits (big endian) 395 param.eeprompoll = beget16(&buff[10]); 396 param.pagesize = beget16(&buff[12]); 397 param.eepromsize = beget16(&buff[14]); 398 399 // 32 bits flashsize (big endian) 400 param.flashsize = buff[16] * 0x01000000 401 + buff[17] * 0x00010000 402 + buff[18] * 0x00000100 403 + buff[19]; 404 405 // AVR devices have active low reset, AT89Sx are active high 406 rst_active_high = (param.devicecode >= 0xe0); 407} 408 409void start_pmode() { 410 411 // Reset target before driving PIN_SCK or PIN_MOSI 412 413 // SPI.begin() will configure SS as output, so SPI master mode is selected. 414 // We have defined RESET as pin 10, which for many Arduinos is not the SS pin. 415 // So we have to configure RESET as output here, 416 // (reset_target() first sets the correct level) 417 reset_target(true); 418 pinMode(RESET, OUTPUT); 419 SPI.begin(); 420 SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); 421 422 // See AVR datasheets, chapter "SERIAL_PRG Programming Algorithm": 423 424 // Pulse RESET after PIN_SCK is low: 425 digitalWrite(PIN_SCK, LOW); 426 delay(20); // discharge PIN_SCK, value arbitrarily chosen 427 reset_target(false); 428 // Pulse must be minimum 2 target CPU clock cycles so 100 usec is ok for CPU 429 // speeds above 20 KHz 430 delayMicroseconds(100); 431 reset_target(true); 432 433 // Send the enable programming command: 434 delay(50); // datasheet: must be > 20 msec 435 spi_transaction(0xAC, 0x53, 0x00, 0x00); 436 pmode = 1; 437} 438 439void end_pmode() { 440 SPI.end(); 441 // We're about to take the target out of reset so configure SPI pins as input 442 pinMode(PIN_MOSI, INPUT); 443 pinMode(PIN_SCK, INPUT); 444 reset_target(false); 445 pinMode(RESET, INPUT); 446 pmode = 0; 447} 448 449void universal() { 450 uint8_t ch; 451 452 fill(4); 453 ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); 454 breply(ch); 455} 456 457void flash(uint8_t hilo, unsigned int addr, uint8_t data) { 458 spi_transaction(0x40 + 8 * hilo, 459 addr >> 8 & 0xFF, 460 addr & 0xFF, 461 data); 462} 463void commit(unsigned int addr) { 464 if (PROG_FLICKER) { 465 prog_lamp(LOW); 466 } 467 spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); 468 if (PROG_FLICKER) { 469 delay(PTIME); 470 prog_lamp(HIGH); 471 } 472} 473 474unsigned int current_page() { 475 if (param.pagesize == 32) { 476 return here & 0xFFFFFFF0; 477 } 478 if (param.pagesize == 64) { 479 return here & 0xFFFFFFE0; 480 } 481 if (param.pagesize == 128) { 482 return here & 0xFFFFFFC0; 483 } 484 if (param.pagesize == 256) { 485 return here & 0xFFFFFF80; 486 } 487 return here; 488} 489 490 491void write_flash(int length) { 492 fill(length); 493 if (CRC_EOP == getch()) { 494 SERIAL.print((char) STK_INSYNC); 495 SERIAL.print((char) write_flash_pages(length)); 496 } else { 497 ISPError++; 498 SERIAL.print((char) STK_NOSYNC); 499 } 500} 501 502uint8_t write_flash_pages(int length) { 503 int x = 0; 504 unsigned int page = current_page(); 505 while (x < length) { 506 if (page != current_page()) { 507 commit(page); 508 page = current_page(); 509 } 510 flash(LOW, here, buff[x++]); 511 flash(HIGH, here, buff[x++]); 512 here++; 513 } 514 515 commit(page); 516 517 return STK_OK; 518} 519 520#define EECHUNK (32) 521uint8_t write_eeprom(unsigned int length) { 522 // here is a word address, get the byte address 523 unsigned int start = here * 2; 524 unsigned int remaining = length; 525 if (length > param.eepromsize) { 526 ISPError++; 527 return STK_FAILED; 528 } 529 while (remaining > EECHUNK) { 530 write_eeprom_chunk(start, EECHUNK); 531 start += EECHUNK; 532 remaining -= EECHUNK; 533 } 534 write_eeprom_chunk(start, remaining); 535 return STK_OK; 536} 537// write (length) bytes, (start) is a byte address 538uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) { 539 // this writes byte-by-byte, page writing may be faster (4 bytes at a time) 540 fill(length); 541 prog_lamp(LOW); 542 for (unsigned int x = 0; x < length; x++) { 543 unsigned int addr = start + x; 544 spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); 545 delay(45); 546 } 547 prog_lamp(HIGH); 548 return STK_OK; 549} 550 551void program_page() { 552 char result = (char) STK_FAILED; 553 unsigned int length = 256 * getch(); 554 length += getch(); 555 char memtype = getch(); 556 // flash memory @here, (length) bytes 557 if (memtype == 'F') { 558 write_flash(length); 559 return; 560 } 561 if (memtype == 'E') { 562 result = (char)write_eeprom(length); 563 if (CRC_EOP == getch()) { 564 SERIAL.print((char) STK_INSYNC); 565 SERIAL.print(result); 566 } else { 567 ISPError++; 568 SERIAL.print((char) STK_NOSYNC); 569 } 570 return; 571 } 572 SERIAL.print((char)STK_FAILED); 573 return; 574} 575 576uint8_t flash_read(uint8_t hilo, unsigned int addr) { 577 return spi_transaction(0x20 + hilo * 8, 578 (addr >> 8) & 0xFF, 579 addr & 0xFF, 580 0); 581} 582 583char flash_read_page(int length) { 584 for (int x = 0; x < length; x += 2) { 585 uint8_t low = flash_read(LOW, here); 586 SERIAL.print((char) low); 587 uint8_t high = flash_read(HIGH, here); 588 SERIAL.print((char) high); 589 here++; 590 } 591 return STK_OK; 592} 593 594char eeprom_read_page(int length) { 595 // here again we have a word address 596 int start = here * 2; 597 for (int x = 0; x < length; x++) { 598 int addr = start + x; 599 uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); 600 SERIAL.print((char) ee); 601 } 602 return STK_OK; 603} 604 605void read_page() { 606 char result = (char)STK_FAILED; 607 int length = 256 * getch(); 608 length += getch(); 609 char memtype = getch(); 610 if (CRC_EOP != getch()) { 611 ISPError++; 612 SERIAL.print((char) STK_NOSYNC); 613 return; 614 } 615 SERIAL.print((char) STK_INSYNC); 616 if (memtype == 'F') { 617 result = flash_read_page(length); 618 } 619 if (memtype == 'E') { 620 result = eeprom_read_page(length); 621 } 622 SERIAL.print(result); 623} 624 625void read_signature() { 626 if (CRC_EOP != getch()) { 627 ISPError++; 628 SERIAL.print((char) STK_NOSYNC); 629 return; 630 } 631 SERIAL.print((char) STK_INSYNC); 632 uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); 633 SERIAL.print((char) high); 634 uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); 635 SERIAL.print((char) middle); 636 uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); 637 SERIAL.print((char) low); 638 SERIAL.print((char) STK_OK); 639} 640////////////////////////////////////////// 641////////////////////////////////////////// 642 643 644//////////////////////////////////// 645//////////////////////////////////// 646void avrisp() { 647 uint8_t ch = getch(); 648 switch (ch) { 649 case '0': // signon 650 ISPError = 0; 651 empty_reply(); 652 break; 653 case '1': 654 if (getch() == CRC_EOP) { 655 SERIAL.print((char) STK_INSYNC); 656 SERIAL.print("AVR ISP"); 657 SERIAL.print((char) STK_OK); 658 } else { 659 ISPError++; 660 SERIAL.print((char) STK_NOSYNC); 661 } 662 break; 663 case 'A': 664 get_version(getch()); 665 break; 666 case 'B': 667 fill(20); 668 set_parameters(); 669 empty_reply(); 670 break; 671 case 'E': // extended parameters - ignore for now 672 fill(5); 673 empty_reply(); 674 break; 675 case 'P': 676 if (!pmode) { 677 start_pmode(); 678 } 679 empty_reply(); 680 break; 681 case 'U': // set address (word) 682 here = getch(); 683 here += 256 * getch(); 684 empty_reply(); 685 break; 686 687 case 0x60: //STK_PROG_FLASH 688 getch(); // low addr 689 getch(); // high addr 690 empty_reply(); 691 break; 692 case 0x61: //STK_PROG_DATA 693 getch(); // data 694 empty_reply(); 695 break; 696 697 case 0x64: //STK_PROG_PAGE 698 program_page(); 699 break; 700 701 case 0x74: //STK_READ_PAGE 't' 702 read_page(); 703 break; 704 705 case 'V': //0x56 706 universal(); 707 break; 708 case 'Q': //0x51 709 ISPError = 0; 710 end_pmode(); 711 empty_reply(); 712 break; 713 714 case 0x75: //STK_READ_SIGN 'u' 715 read_signature(); 716 break; 717 718 // expecting a command, not CRC_EOP 719 // this is how we can get back in sync 720 case CRC_EOP: 721 ISPError++; 722 SERIAL.print((char) STK_NOSYNC); 723 break; 724 725 // anything else we will return STK_UNKNOWN 726 default: 727 ISPError++; 728 if (CRC_EOP == getch()) { 729 SERIAL.print((char)STK_UNKNOWN); 730 } else { 731 SERIAL.print((char)STK_NOSYNC); 732 } 733 } 734}
Downloadable files
ATmega328/168/8/48/88 Programming Shield
Download PDF File
ATmega328/168/8/48/88 Programming Shield
ATmega328/168/8/48/88 Programming Shield
Download PDF File
ATmega328/168/8/48/88 Programming Shield
Comments
Only logged in users can leave comments