/ ArduinoISP / ArduinoISP / ArduinoISP.ino
ArduinoISP.ino
  1  // SPDX-FileCopyrightText: 2009 David A. Mellis
  2  // SPDX-FileCopyrightText: 2009 Randall Bohn
  3  // SPDX-FileCopyrightText: 2012 William Phelps
  4  // SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
  5  //
  6  // SPDX-License-Identifier: MIT
  7  
  8  // this sketch turns the Arduino into a AVRISP
  9  // using the following pins:
 10  // 10: slave reset
 11  // 11: MOSI
 12  // 12: MISO
 13  // 13: SCK
 14  
 15  // Put an LED (with resistor) on the following pins:
 16  //  8: Error - Lights up if something goes wrong (use red if that makes sense)
 17  // A0: Programming - In communication with the slave
 18  //  6: Heartbeat - shows the programmer is running (removed, see notes below)
 19  // Optional - Piezo speaker on pin A3
 20  // 
 21  // October 2009 by David A. Mellis
 22  // - Added support for the read signature command
 23  //
 24  // February 2009 by Randall Bohn
 25  // - Added support for writing to EEPROM (what took so long?)
 26  // Windows users should consider WinAVR's avrdude instead of the
 27  // avrdude included with Arduino software.
 28  //
 29  // January 2008 by Randall Bohn
 30  // - Thanks to Amplificar for helping me with the STK500 protocol
 31  // - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
 32  // - The SPI functions herein were developed for the AVR910_ARD programmer 
 33  // - More information at http://code.google.com/p/mega-isp
 34  //
 35  // March 2012 - William Phelps
 36  // modify to work with Arduino IDE 1.0 which has a shorter serial port receive buffer
 37  // getEOP() now gets entire request before avrisp() is called to process it
 38  // Serial.print((char) xxx) changed to Serial.write(xxx)
 39  // uint8_t changed to byte
 40  // added support for Piezo speaker
 41  // moved Pmode LED to A0
 42  // removed "heartbeat" on pin 6, added short blip of ERROR LED instead 
 43  // Why is it that PROG_FLASH and PROG_DATA don't actually do anything???
 44  // Tested with Arduino IDE 22 and 1.0
 45  // IDE 22 - 5148 bytes
 46  // IDE 1.0 - 5524 bytes!
 47  
 48  
 49  // SLOW SPEED CHIP ERASE AND FUSE BURNING
 50  //
 51  // Enable LOW_SPEED to allow you to erase chips that would fail otherwise,
 52  // for being running with a clock too slow for the programmer.
 53  //
 54  // This allowed me to recover several ATMega328 that had no boot loader and the
 55  // first instruction was to set the clock to the slowest speed. Usually this
 56  // kind of recovery requires high voltage programming, but this trick will do
 57  // just fine.
 58  //
 59  // How to proceed:
 60  // 1. Enable LOW_SPEED, and load it to the programmer.
 61  // 2. Erase and burn the fuses on the target uC. Example for ATMega328:
 62  //   arduino-1.0.1/hardware/tools/avrdude -Carduino-1.0.1/hardware/tools/avrdude.conf -patmega328p -cstk500v1 -P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900cf1Q-if00-port0 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0x05:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xF7:m
 63  // 3. Comment LOW_SPEED and load it back to the programmer.
 64  // 4. Program the target uC as usual. Example:
 65  //  arduino-1.0.1/hardware/tools/avrdude -Carduino-1.0.1/hardware/tools/avrdude.conf -patmega328p -cstk500v1 -P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900cf1Q-if00-port0 -b19200 -Uflash:w:firmware.hex:i 
 66  //
 67  // Note 1: EXTRA_SPI_DELAY was added to let you slow down SPI even more. You can
 68  // play with the value if it does not work with the default.
 69  // Note 2: LOW_SPEED will alow you only to erase the chip and burn the fuses! It
 70  // will fail if you try to program the target uC this way!
 71  
 72  //#define LOW_SPEED
 73  #ifdef LOW_SPEED
 74  #define EXTRA_SPI_DELAY 125
 75  #else
 76  #define EXTRA_SPI_DELAY 0
 77  #endif
 78  
 79  #include "pins_arduino.h"  // defines SS,MOSI,MISO,SCK
 80  #define RESET SS
 81  
 82  #define LED_ERR 8
 83  #define LED_PMODE A0
 84  //#define LED_HB 6
 85  #define PIEZO A3
 86  
 87  #define HWVER 2
 88  #define SWMAJ 1
 89  #define SWMIN 18
 90  
 91  // STK Definitions
 92  const byte STK_OK = 0x10;
 93  const byte STK_FAILED = 0x11;
 94  const byte STK_UNKNOWN = 0x12;
 95  const byte STK_INSYNC = 0x14;
 96  const byte STK_NOSYNC = 0x15;
 97  const byte CRC_EOP = 0x20; //ok it is a space...
 98  
 99  const byte STK_GET_SYNC     = 0x30;
100  const byte STK_GET_SIGNON   = 0x31;
101  const byte STK_GET_PARM     = 0x41;
102  const byte STK_SET_PARM     = 0x42;
103  const byte STK_SET_PARM_EXT = 0x45;
104  const byte STK_PMODE_START  = 0x50;
105  const byte STK_PMODE_END    = 0x51;
106  const byte STK_SET_ADDR     = 0x55;
107  const byte STK_UNIVERSAL    = 0x56;
108  const byte STK_PROG_FLASH   = 0x60;
109  const byte STK_PROG_DATA    = 0x61;
110  const byte STK_PROG_PAGE    = 0x64;
111  const byte STK_READ_PAGE    = 0x74;
112  const byte STK_READ_SIGN    = 0x75;
113  
114  //// TONES  ==========================================
115  //// Start by defining the relationship between
116  ////       note, period, &  frequency.
117  //#define  c     3830    // 261 Hz
118  //#define  d     3400    // 294 Hz
119  //#define  e     3038    // 329 Hz
120  //#define  f     2864    // 349 Hz
121  //#define  g     2550    // 392 Hz
122  //#define  a     2272    // 440 Hz
123  //#define  b     2028    // 493 Hz
124  //#define  C     1912    // 523 Hz 
125  
126  //void pulse(int pin, int times);
127  
128  int error=0;
129  int pmode=0;
130  // address for reading and writing, set by STK_SET_ADDR command
131  int _addr;
132  byte _buffer[256]; // serial port buffer
133  int pBuffer = 0;  // buffer pointer
134  int iBuffer = 0;  // buffer index
135  byte buff[256];  // temporary buffer
136  boolean EOP_SEEN = false;
137  
138  void setup() {
139  
140    Serial.begin(19200);
141    pinMode(PIEZO, OUTPUT);
142    beep(1700, 40);
143    EOP_SEEN = false;
144    iBuffer = pBuffer = 0;
145  
146    pinMode(LED_PMODE, OUTPUT);
147    pulse(LED_PMODE, 2);
148    pinMode(LED_ERR, OUTPUT);
149    pulse(LED_ERR, 2);
150  //  pinMode(LED_HB, OUTPUT);
151  //  pulse(LED_HB, 2);
152    
153    pinMode(9, OUTPUT);
154    // setup high freq PWM on pin 9 (timer 1)
155    // 50% duty cycle -> 8 MHz
156    OCR1A = 0;
157    ICR1 = 1;
158    // OC1A output, fast PWM
159    TCCR1A = _BV(WGM11) | _BV(COM1A1);
160    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // no clock prescale
161    
162   
163  }
164  
165  #define beget16(addr) (*addr * 256 + *(addr+1) )
166  typedef struct param {
167    byte devicecode;
168    byte revision;
169    byte progtype;
170    byte parmode;
171    byte polling;
172    byte selftimed;
173    byte lockbytes;
174    byte fusebytes;
175    int flashpoll;
176    int eeprompoll;
177    int pagesize;
178    int eepromsize;
179    int flashsize;
180  } 
181  parameter;
182  
183  parameter param;
184  
185  // this provides a heartbeat on pin 6, so you can tell the software is running.
186  //byte hbval=128;
187  //int8_t hbdelta=4;
188  //void heartbeat() {
189  ////  if (hbval > 192) hbdelta = -hbdelta;
190  ////  if (hbval < 32) hbdelta = -hbdelta;
191  //  if (hbval > 250) hbdelta = -hbdelta;
192  //  if (hbval < 10) hbdelta = -hbdelta;
193  //  hbval += hbdelta;
194  //  analogWrite(LED_HB, hbval);
195  //  delay(20);
196  //}
197    
198  void getEOP() {
199    int minL = 0;
200    byte avrch = 0;
201    byte bl = 0;
202    while (!EOP_SEEN) {
203      while (Serial.available()>0) {
204        byte ch = Serial.read();
205        _buffer[iBuffer] = ch;
206        iBuffer = (++iBuffer)%256;  // increment and wrap
207        if (iBuffer == 1)  avrch = ch;  // save command
208        if ((avrch == STK_PROG_PAGE) && (iBuffer==3)) {
209          minL = 256*_buffer[1] + _buffer[2] + 4;
210        }
211        if ((iBuffer>minL) && (ch == CRC_EOP)) {
212          EOP_SEEN = true;
213        }
214      }
215      if (!EOP_SEEN) {
216  //      heartbeat(); // light the heartbeat LED
217        if (bl == 100) {
218          pulse(LED_ERR,1,10);  // blink the red LED
219          bl = 0;
220        }
221        bl++;
222        delay(10);
223      }
224    }
225  }
226  
227  // serialEvent not used so sketch would be compatible with older IDE versions
228  //void serialEvent() {
229  //  int minL = 0;
230  //  byte avrch = 0;
231  //  while (Serial.available()>0)
232  //  {
233  //    byte ch = Serial.read();
234  //    _buffer[iBuffer] = ch;
235  //    iBuffer = (++iBuffer)%256;  // increment and wrap
236  //    if (iBuffer == 1)  avrch = ch;  // save command
237  //    if ((avrch == STK_PROG_PAGE) && (iBuffer==3)) {
238  //      minL = 256*_buffer[1] + _buffer[2] + 4;
239  //    }
240  //    if ((iBuffer>minL) && (ch == CRC_EOP)) {
241  //      EOP_SEEN = true;
242  //    }
243  //  }
244  //}
245  
246  void loop(void) {
247    // is pmode active?
248  //  if (pmode) digitalWrite(LED_PMODE, HIGH); 
249  //  else digitalWrite(LED_PMODE, LOW);
250    digitalWrite(LED_PMODE, LOW);
251    // is there an error?
252    if (error) digitalWrite(LED_ERR, HIGH); 
253    else digitalWrite(LED_ERR, LOW);
254  
255    getEOP();
256    
257    // have we received a complete request?  (ends with CRC_EOP)
258    if (EOP_SEEN) {
259      digitalWrite(LED_PMODE, HIGH);
260      EOP_SEEN = false;
261      avrisp();
262      iBuffer = pBuffer = 0;  // restart buffer
263    }
264    
265  }
266  
267  byte getch() {
268    if (pBuffer == iBuffer) {  // spin until data available ???
269      pulse(LED_ERR, 1);
270      beep(1700, 20);
271      error++;
272      return -1;
273    }
274    byte ch = _buffer[pBuffer];  // get next char
275    pBuffer = (++pBuffer)%256;  // increment and wrap
276    return ch;
277  }
278  
279  void readbytes(int n) {
280    for (int x = 0; x < n; x++) {
281      buff[x] = getch();
282    }
283  }
284  
285  //#define PTIME 20
286  void pulse(int pin, int times, int ptime) {
287    do {
288      digitalWrite(pin, HIGH);
289      delay(ptime);
290      digitalWrite(pin, LOW);
291      delay(ptime);
292      times--;
293    } 
294    while (times > 0);
295  }
296  void pulse(int pin, int times) {
297    pulse(pin, times, 50);
298  }
299  
300  void spi_init() {
301    byte x;
302    SPCR = 0x53;
303  #ifdef LOW_SPEED
304  SPCR=SPCR|B00000011;
305  #endif
306    x=SPSR;
307    x=SPDR;
308  }
309  
310  void spi_wait() {
311    do {
312    } 
313    while (!(SPSR & (1 << SPIF)));
314  }
315  
316  byte spi_send(byte b) {
317    byte reply;
318  #ifdef LOW_SPEED
319      cli();
320      CLKPR=B10000000;
321      CLKPR=B00000011;
322      sei();
323  #endif
324    SPDR=b;
325    spi_wait();
326    reply = SPDR;
327  #ifdef LOW_SPEED
328      cli();
329      CLKPR=B10000000;
330      CLKPR=B00000000;
331     sei();
332  #endif
333      return reply;
334  }
335  
336  byte spi_transaction(byte a, byte b, byte c, byte d) {
337    byte n;
338    spi_send(a); 
339    n=spi_send(b);
340    //if (n != a) error = -1;
341    n=spi_send(c);
342    return spi_send(d);
343  }
344  
345  void replyOK() {
346  //  if (EOP_SEEN == true) {
347    if (CRC_EOP == getch()) {  // EOP should be next char
348      Serial.write(STK_INSYNC);
349      Serial.write(STK_OK);
350    } 
351    else {
352      pulse(LED_ERR, 2);
353      Serial.write(STK_NOSYNC);
354      error++;
355    }
356  }
357  
358  void breply(byte b) {
359    if (CRC_EOP == getch()) {  // EOP should be next char
360      Serial.write(STK_INSYNC);
361      Serial.write(b);
362      Serial.write(STK_OK);
363    } 
364    else {
365      Serial.write(STK_NOSYNC);
366      error++;
367    }
368  }
369  
370  void get_parameter(byte c) {
371    switch(c) {
372    case 0x80:
373      breply(HWVER);
374      break;
375    case 0x81:
376      breply(SWMAJ);
377      break;
378    case 0x82:
379      breply(SWMIN);
380      break;
381    case 0x93:
382      breply('S'); // serial programmer
383      break;
384    default:
385      breply(0);
386    }
387  }
388  
389  void set_parameters() {
390    // call this after reading paramter packet into buff[]
391    param.devicecode = buff[0];
392    param.revision = buff[1];
393    param.progtype = buff[2];
394    param.parmode = buff[3];
395    param.polling = buff[4];
396    param.selftimed = buff[5];
397    param.lockbytes = buff[6];
398    param.fusebytes = buff[7];
399    param.flashpoll = buff[8]; 
400    // ignore buff[9] (= buff[8])
401    //getch(); // discard second value
402    
403    // WARNING: not sure about the byte order of the following
404    // following are 16 bits (big endian)
405    param.eeprompoll = beget16(&buff[10]);
406    param.pagesize = beget16(&buff[12]);
407    param.eepromsize = beget16(&buff[14]);
408  
409    // 32 bits flashsize (big endian)
410    param.flashsize = buff[16] * 0x01000000
411      + buff[17] * 0x00010000
412      + buff[18] * 0x00000100
413      + buff[19];
414  
415  }
416  
417  void start_pmode() {
418    spi_init();
419    // following delays may not work on all targets...
420    pinMode(RESET, OUTPUT);
421    digitalWrite(RESET, HIGH);
422    pinMode(SCK, OUTPUT);
423    digitalWrite(SCK, LOW);
424    delay(50+EXTRA_SPI_DELAY);
425    digitalWrite(RESET, LOW);
426    delay(50+EXTRA_SPI_DELAY);
427    pinMode(MISO, INPUT);
428    pinMode(MOSI, OUTPUT);
429    spi_transaction(0xAC, 0x53, 0x00, 0x00);
430    pmode = 1;
431  }
432  
433  void end_pmode() {
434    pinMode(MISO, INPUT);
435    pinMode(MOSI, INPUT);
436    pinMode(SCK, INPUT);
437    pinMode(RESET, INPUT);
438    pmode = 0;
439  }
440  
441  void universal() {
442  //  int w;
443    byte ch;
444  //  for (w = 0; w < 4; w++) {
445  //    buff[w] = getch();
446  //  }
447    readbytes(4);
448    ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
449    breply(ch);
450  }
451  
452  void flash(byte hilo, int addr, byte data) {
453    spi_transaction(0x40+8*hilo, addr>>8 & 0xFF, addr & 0xFF, data);
454  }
455  void commit(int addr) {
456    spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
457  }
458  
459  //#define _current_page(x) (here & 0xFFFFE0)
460  int current_page(int addr) {
461    if (param.pagesize == 32) return addr & 0xFFFFFFF0;
462    if (param.pagesize == 64) return addr & 0xFFFFFFE0;
463    if (param.pagesize == 128) return addr & 0xFFFFFFC0;
464    if (param.pagesize == 256) return addr & 0xFFFFFF80;
465    return addr;
466  }
467  byte write_flash(int length) {
468    if (param.pagesize < 1) {
469      return STK_FAILED;
470    }
471    //if (param.pagesize != 64) return STK_FAILED;
472    int page = current_page(_addr);
473    int x = 0;
474    while (x < length) {
475      if (page != current_page(_addr)) {
476        commit(page);
477        page = current_page(_addr);
478      }
479      flash(LOW, _addr, buff[x++]);
480      flash(HIGH, _addr, buff[x++]);
481      _addr++;
482    }
483    commit(page);
484    return STK_OK;
485  }
486  
487  byte write_eeprom(int length) {
488    // here is a word address, so we use here*2
489    // this writes byte-by-byte,
490    // page writing may be faster (4 bytes at a time)
491    for (int x = 0; x < length; x++) {
492      spi_transaction(0xC0, 0x00, _addr*2+x, buff[x]);
493      delay(45);
494    } 
495    return STK_OK;
496  }
497  
498  void program_page() {
499    byte result = STK_FAILED;
500    int length = 256 * getch() + getch();
501    if (length > 256) {
502        Serial.write(STK_FAILED);
503        error++;
504        return;
505    }
506    char memtype = (char)getch();
507  //  for (int x = 0; x < length; x++) {
508  //    buff[x] = getch();
509  //  }
510    readbytes(length);
511    if (CRC_EOP == getch()) {
512      Serial.write(STK_INSYNC);
513      switch (memtype) {
514        case 'E':
515          result = (byte)write_eeprom(length);
516          break;
517        case 'F':
518          result = (byte)write_flash(length);
519          break;
520      }
521      Serial.write(result);
522      if (result != STK_OK) {
523        error++;
524      }
525    } 
526    else {
527      Serial.write(STK_NOSYNC);
528      error++;
529    }
530  }
531  
532  byte flash_read(byte hilo, int addr) {
533    return spi_transaction(0x20 + hilo * 8,
534      (addr >> 8) & 0xFF,
535      addr & 0xFF,
536      0);
537  }
538  
539  char flash_read_page(int length) {
540    for (int x = 0; x < length; x+=2) {
541      byte low = flash_read(LOW, _addr);
542      Serial.write( low);
543      byte high = flash_read(HIGH, _addr);
544      Serial.write( high);
545      _addr++;
546    }
547    return STK_OK;
548  }
549  
550  char eeprom_read_page(int length) {
551    // here again we have a word address
552    for (int x = 0; x < length; x++) {
553      byte ee = spi_transaction(0xA0, 0x00, _addr*2+x, 0xFF);
554      Serial.write( ee);
555    }
556    return STK_OK;
557  }
558  
559  void read_page() {
560    byte result = (byte)STK_FAILED;
561    int length = 256 * getch() + getch();
562    char memtype = getch();
563    if (CRC_EOP != getch()) {
564      Serial.write(STK_NOSYNC);
565      return;
566    }
567    Serial.write(STK_INSYNC);
568    if (memtype == 'F') result = flash_read_page(length);
569    if (memtype == 'E') result = eeprom_read_page(length);
570    Serial.write(result);
571    return;
572  }
573  
574  void read_signature() {
575    if (CRC_EOP != getch()) {
576      Serial.write(STK_NOSYNC);
577      error++;
578      return;
579    }
580    Serial.write(STK_INSYNC);
581    byte high = spi_transaction(0x30, 0x00, 0x00, 0x00);
582    Serial.write(high);
583    byte middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
584    Serial.write(middle);
585    byte low = spi_transaction(0x30, 0x00, 0x02, 0x00);
586    Serial.write(low);
587    Serial.write(STK_OK);
588  }
589  //////////////////////////////////////////
590  //////////////////////////////////////////
591  
592  
593  ////////////////////////////////////
594  ////////////////////////////////////
595  
596  int avrisp() { 
597    byte data, low, high;
598    byte avrch = getch();
599    switch (avrch) {
600      case STK_GET_SYNC: // get in sync
601        replyOK();
602        break;
603      case STK_GET_SIGNON:  // get sign on
604        if (getch() == CRC_EOP) {
605          Serial.write(STK_INSYNC);
606          Serial.write("AVR ISP");
607          Serial.write(STK_OK);
608        }
609        break;
610      case STK_GET_PARM:  // 0x41
611        get_parameter(getch());
612        break;
613      case STK_SET_PARM:  // 0x42
614        readbytes(20);
615        set_parameters();
616        replyOK();
617        break;
618      case STK_SET_PARM_EXT: // extended parameters - ignore for now
619        readbytes(5);
620        replyOK();
621        break;
622      case STK_PMODE_START:  // 0x50
623        beep(2272, 20);
624        start_pmode();
625        replyOK();
626        break;
627      case STK_PMODE_END:  //0x51
628        beep(1912, 50);
629        error=0;
630        end_pmode();
631        replyOK();
632        break;
633      case STK_SET_ADDR:  // 0x55
634        _addr = getch() + 256 * getch();
635        replyOK();
636        break;
637      case STK_UNIVERSAL:  //UNIVERSAL 0x56
638        universal();
639        break;
640      case STK_PROG_FLASH: //STK_PROG_FLASH  ???
641        low = getch();
642        high = getch();
643        replyOK();
644        break;
645      case STK_PROG_DATA: //STK_PROG_DATA  ???
646        data = getch();
647        replyOK();
648        break;
649      case STK_PROG_PAGE:  //STK_PROG_PAGE
650  //      beep(1912, 20);
651        program_page();
652        break;
653      case STK_READ_PAGE: //STK_READ_PAGE
654        read_page();    
655        break;
656      case STK_READ_SIGN: //STK_READ_SIGN
657        read_signature();
658        break;
659      // expecting a command, not CRC_EOP
660      // this is how we can get back in sync
661      case CRC_EOP:
662        Serial.write(STK_NOSYNC);
663        break;
664      // anything else we will return STK_UNKNOWN
665      default:
666        if (CRC_EOP == getch()) 
667          Serial.write(STK_UNKNOWN);
668        else
669          Serial.write(STK_NOSYNC);
670    }
671  }
672  
673  // beep without using PWM
674  void beep(int tone, long duration){
675    long elapsed = 0;
676    while (elapsed < (duration * 10000)) {
677      digitalWrite(PIEZO, HIGH);
678      delayMicroseconds(tone / 2);
679      digitalWrite(PIEZO, LOW);
680      delayMicroseconds(tone / 2);
681      // Keep track of how long we pulsed
682      elapsed += tone;
683    } 
684  }