ATmega328/168/8/48/88 Programming Shield
ATmega328/168/48/8/88 programming and bootloader shield.
Components and supplies
Arduino UNO
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
Tools and machines
Solder Flux, Soldering
Soldering Station, 110 V
Solder Wire, Lead Free
Desoldering Braid, Solder Wick
Apps and platforms
Arduino IDE
Arduino IDE 2.0 (beta)
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