From a2a06f56cce4f378ffa9e21c442ca1b1a57f8b76 Mon Sep 17 00:00:00 2001 From: "Randall Bohn (Huckle)" Date: Tue, 31 Jan 2012 05:51:18 -0700 Subject: [PATCH 01/25] Be more specific about datatypes in the parameter struct. --- .../examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index d5bf7b81a..622d7cd35 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -91,12 +91,12 @@ typedef struct param { uint8_t selftimed; uint8_t lockbytes; uint8_t fusebytes; - int flashpoll; - int eeprompoll; - int pagesize; - int eepromsize; - int flashsize; -} + uint8_t flashpoll; + uint16_t eeprompoll; + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; +} parameter; parameter param; From d968c7a8eee7f334ce7c3f9fcaba58c81f207630 Mon Sep 17 00:00:00 2001 From: "Randall Bohn (Huckle)" Date: Sat, 18 Feb 2012 07:18:29 -0700 Subject: [PATCH 02/25] Don't start_pmode if we're already in pmode. --- .../examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 622d7cd35..060ad77ac 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -66,7 +66,7 @@ void pulse(int pin, int times); void setup() { - Serial.begin(19200); + Serial.begin(9600); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); @@ -510,9 +510,13 @@ int avrisp() { fill(5); empty_reply(); break; - case 'P': - start_pmode(); + if (pmode) { + pulse(LED_ERR, 3); + } + else { + start_pmode(); + } empty_reply(); break; case 'U': // set address (word) From 8dfe833e499c05205caf369b22dfcda7f727f2de Mon Sep 17 00:00:00 2001 From: "Randall Bohn (Huckle)" Date: Sat, 18 Feb 2012 09:11:58 -0700 Subject: [PATCH 03/25] Set error if GET_SIGN_ON not followed by CRC_EOP --- .../shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 060ad77ac..6578aa4bf 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -497,6 +497,10 @@ int avrisp() { Serial.print("AVR ISP"); Serial.print((char) STK_OK); } + else { + error++; + Serial.print((char) STK_NOSYNC); + } break; case 'A': get_version(getch()); @@ -574,5 +578,3 @@ int avrisp() { } } - - From aeaed27e1342141da72959e8602b813ee2d5273d Mon Sep 17 00:00:00 2001 From: "Randall Bohn (Huckle)" Date: Sat, 18 Feb 2012 10:11:05 -0700 Subject: [PATCH 04/25] Use SPI library. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 52 ++++++------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 6578aa4bf..7b67f6e54 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -43,6 +43,7 @@ // - The SPI functions herein were developed for the AVR910_ARD programmer // - More information at http://code.google.com/p/mega-isp +#include "SPI.h" #include "pins_arduino.h" #define RESET SS @@ -67,12 +68,17 @@ void pulse(int pin, int times); void setup() { Serial.begin(9600); + SPI.setDataMode(0); + SPI.setBitOrder(MSBFIRST); + // Clock Div can be 2,4,8,16,32,64, or 128 + SPI.setClockDivider(SPI_CLOCK_DIV128); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); pulse(LED_ERR, 2); pinMode(LED_HB, OUTPUT); pulse(LED_HB, 2); + } int error = 0; @@ -96,7 +102,7 @@ typedef struct param { uint16_t pagesize; uint16_t eepromsize; uint32_t flashsize; -} +} parameter; parameter param; @@ -164,33 +170,13 @@ void prog_lamp(int state) { } } -void spi_init() { - uint8_t x; - SPCR = 0x53; - x = SPSR; - x = SPDR; -} - -void spi_wait() { - do { - } while (!(SPSR & (1 << SPIF))); -} - -uint8_t spi_send(uint8_t b) { - uint8_t reply; - SPDR = b; - spi_wait(); - reply = SPDR; - return reply; -} - uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { uint8_t n; - spi_send(a); - n = spi_send(b); + SPI.transfer(a); + n = SPI.transfer(b); //if (n != a) error = -1; - n = spi_send(c); - return spi_send(d); + n = SPI.transfer(c); + return SPI.transfer(d); } void empty_reply() { @@ -259,25 +245,19 @@ void set_parameters() { } void start_pmode() { - spi_init(); - // following delays may not work on all targets... - pinMode(RESET, OUTPUT); + SPI.begin(); digitalWrite(RESET, HIGH); - pinMode(SCK, OUTPUT); + pinMode(RESET, OUTPUT); digitalWrite(SCK, LOW); - delay(50); + delay(20); digitalWrite(RESET, LOW); - delay(50); - pinMode(MISO, INPUT); - pinMode(MOSI, OUTPUT); spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; } void end_pmode() { - pinMode(MISO, INPUT); - pinMode(MOSI, INPUT); - pinMode(SCK, INPUT); + SPI.end(); + digitalWrite(RESET, HIGH); pinMode(RESET, INPUT); pmode = 0; } From ad2a32fd24edbe4e6052995594badacfa4cd2bab Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Fri, 13 Feb 2015 20:48:40 +0100 Subject: [PATCH 05/25] Avoid delay in heartbeat. That way we can also set the baudrate back to the value used in the IDE. In fact, with this fix, baud rates of up to 115200 work also. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 7b67f6e54..9ad5a1b33 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -67,7 +67,7 @@ void pulse(int pin, int times); void setup() { - Serial.begin(9600); + Serial.begin(19200); SPI.setDataMode(0); SPI.setBitOrder(MSBFIRST); // Clock Div can be 2,4,8,16,32,64, or 128 @@ -111,18 +111,17 @@ parameter param; uint8_t hbval = 128; int8_t hbdelta = 8; void heartbeat() { - if (hbval > 192) { - hbdelta = -hbdelta; - } - if (hbval < 32) { - hbdelta = -hbdelta; - } + static unsigned long last_time = 0; + unsigned long now = millis(); + if ((now - last_time) < 40) + return; + last_time = now; + if (hbval > 192) hbdelta = -hbdelta; + if (hbval < 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); - delay(20); } - void loop(void) { // is pmode active? if (pmode) { From 93b31b6cfa721372260a810f1048b6fb75b15ee1 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 25 Feb 2015 21:17:22 +0100 Subject: [PATCH 06/25] Simply use pin 10 to reset the target. It works for all Arduino's and allows the same "ArduinoISP shield" to be used on all of them. Such a shield has an ISP connector that: - wires MISO,MOSI, SCK, GND and 5V to the ISP connector of the programming Arduino - wires RESET to pin 10 of the programming Arduino. --- .../shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 9ad5a1b33..bff56fd54 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -7,7 +7,7 @@ // using the following arduino pins: // // pin name: not-mega: mega(1280 and 2560) -// slave reset: 10: 53 +// slave reset: 10: 10 // MOSI: 11: 51 // MISO: 12: 50 // SCK: 13: 52 @@ -45,7 +45,8 @@ #include "SPI.h" #include "pins_arduino.h" -#define RESET SS +// Use pin 10 to reset the target +#define RESET 10 #define LED_HB 9 #define LED_ERR 8 From 56e09109dfd051c4af8bee8e21972a87ac05faa4 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 25 Feb 2015 21:30:34 +0100 Subject: [PATCH 07/25] The delay between reset and the enter progmode command got lost when introducing the SPI library. Put it back in. --- build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index bff56fd54..2f31d6269 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -251,6 +251,7 @@ void start_pmode() { digitalWrite(SCK, LOW); delay(20); digitalWrite(RESET, LOW); + delay(50); spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; } From 15da182399658719fbf2906295cc413aedac706e Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 25 Feb 2015 21:52:30 +0100 Subject: [PATCH 08/25] Support at89sx mcu's by adding the possibility to specify the polarity of the target reset signal. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 2f31d6269..0569a3464 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -123,6 +123,13 @@ void heartbeat() { analogWrite(LED_HB, hbval); } +static bool rst_active_high; + +void reset_target(bool reset) +{ + digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW); +} + void loop(void) { // is pmode active? if (pmode) { @@ -242,15 +249,24 @@ void set_parameters() { + buff[18] * 0x00000100 + buff[19]; + // avr devices have active low reset, at89sx are active high + rst_active_high = (param.devicecode >= 0xe0); } void start_pmode() { SPI.begin(); - digitalWrite(RESET, HIGH); + // SPI.begin() has configured SS as output, + // so SPI master mode is selected. + // We have defined RESET as pin 10, + // which for many arduino's is not the SS pin. + // So we have to configure RESET as output here, + // (reset_target() first sets the level correct) + reset_target(false); pinMode(RESET, OUTPUT); + digitalWrite(SCK, LOW); delay(20); - digitalWrite(RESET, LOW); + reset_target(true); delay(50); spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; @@ -258,7 +274,7 @@ void start_pmode() { void end_pmode() { SPI.end(); - digitalWrite(RESET, HIGH); + reset_target(false); pinMode(RESET, INPUT); pmode = 0; } From a17a7577224d33cb36be590fde994d7327707ae5 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 25 Feb 2015 21:55:14 +0100 Subject: [PATCH 09/25] Configure SPI pins as input when target is not in reset. --- build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 0569a3464..8a63e8e8b 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -274,6 +274,10 @@ void start_pmode() { void end_pmode() { SPI.end(); + // We're about to take the target out of reset + // so configure SPI pins as input + pinMode(MOSI, INPUT); + pinMode(SCK, INPUT); reset_target(false); pinMode(RESET, INPUT); pmode = 0; From 64e52d8016662a3c741e64697377ab7dc37408d0 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 16 Jun 2015 22:10:25 +0200 Subject: [PATCH 10/25] Implement bitbang SPI for slow clock devices. (Sylvan Butler). --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 8a63e8e8b..09e33b66c 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -43,7 +43,6 @@ // - The SPI functions herein were developed for the AVR910_ARD programmer // - More information at http://code.google.com/p/mega-isp -#include "SPI.h" #include "pins_arduino.h" // Use pin 10 to reset the target #define RESET 10 @@ -53,6 +52,17 @@ #define LED_PMODE 7 #define PROG_FLICKER true +#if defined(ARDUINO_ARCH_SAM) or defined(ARDUINO_ARCH_SAMD) + +#define SPI_CLOCK_DIV_MAX 255 + +#else + +#define USE_HARDWARE_SPI +#define SPI_CLOCK_DIV_MAX SPI_CLOCK_DIV_128 + +#endif + #define HWVER 2 #define SWMAJ 1 #define SWMIN 18 @@ -67,12 +77,52 @@ void pulse(int pin, int times); +#ifdef USE_HARDWARE_SPI +#include "SPI.h" +#else + +class BitBangedSPI { + public: + void setDataMode(uint8_t dataMode) { + (void) dataMode; + } + void setBitOrder(uint8_t bitOrder) { + (void) bitOrder; + } + void setClockDivider(uint8_t clockDiv) { + (void) clockDiv; + } + + void begin() { + pinMode(MISO, INPUT); + pinMode(RESET, OUTPUT); + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); + } + + void end() {} + + uint8_t transfer (uint8_t b) { + for (unsigned int i = 0; i < 8; ++i) { + digitalWrite(MOSI, b & 0x80); + digitalWrite(SCK, HIGH); + b = (b << 1) | digitalRead(MISO); + digitalWrite(SCK, LOW); // slow pulse + } + return b; + } +}; + +static BitBangedSPI SPI; + +#endif + void setup() { Serial.begin(19200); SPI.setDataMode(0); SPI.setBitOrder(MSBFIRST); - // Clock Div can be 2,4,8,16,32,64, or 128 - SPI.setClockDivider(SPI_CLOCK_DIV128); + // Select the slowest possible clock + SPI.setClockDivider(SPI_CLOCK_DIV_MAX); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); From c8b5e99267d4eb0979b8f7586dbb2dbb54276251 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 7 Jul 2015 21:42:21 +0200 Subject: [PATCH 11/25] Configure the serial port to use. Prefer native USB port if the Arduino has one. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 112 ++++++++++-------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 09e33b66c..7e7a33c4f 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -43,7 +43,9 @@ // - The SPI functions herein were developed for the AVR910_ARD programmer // - More information at http://code.google.com/p/mega-isp -#include "pins_arduino.h" +#include "Arduino.h" +#undef SERIAL + // Use pin 10 to reset the target #define RESET 10 @@ -63,6 +65,26 @@ #endif + +// Configure the serial port to use. +// +// Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one: +// - it does not autoreset (except for the magic baud rate of 1200). +// - it is more reliable because of USB handshaking. +// +// Leonardo and similar have an USB virtual serial port: 'Serial'. +// Due and Zero have an USB virtual serial port: 'SerialUSB'. +// +// On the Due and Zero, 'Serial' can be used too, provided you disable autoreset. +// To use 'Serial': #define SERIAL Serial + +#ifdef SERIAL_PORT_USBVIRTUAL +#define SERIAL SERIAL_PORT_USBVIRTUAL +#else +#define SERIAL Serial +#endif + + #define HWVER 2 #define SWMAJ 1 #define SWMIN 18 @@ -118,7 +140,7 @@ static BitBangedSPI SPI; #endif void setup() { - Serial.begin(19200); + SERIAL.begin(19200); SPI.setDataMode(0); SPI.setBitOrder(MSBFIRST); // Select the slowest possible clock @@ -196,14 +218,14 @@ void loop(void) { // light the heartbeat LED heartbeat(); - if (Serial.available()) { + if (SERIAL.available()) { avrisp(); } } uint8_t getch() { - while (!Serial.available()); - return Serial.read(); + while (!SERIAL.available()); + return SERIAL.read(); } void fill(int n) { for (int x = 0; x < n; x++) { @@ -238,22 +260,22 @@ uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { void empty_reply() { if (CRC_EOP == getch()) { - Serial.print((char)STK_INSYNC); - Serial.print((char)STK_OK); + SERIAL.print((char)STK_INSYNC); + SERIAL.print((char)STK_OK); } else { error++; - Serial.print((char)STK_NOSYNC); + SERIAL.print((char)STK_NOSYNC); } } void breply(uint8_t b) { if (CRC_EOP == getch()) { - Serial.print((char)STK_INSYNC); - Serial.print((char)b); - Serial.print((char)STK_OK); + SERIAL.print((char)STK_INSYNC); + SERIAL.print((char)b); + SERIAL.print((char)STK_OK); } else { error++; - Serial.print((char)STK_NOSYNC); + SERIAL.print((char)STK_NOSYNC); } } @@ -380,11 +402,11 @@ int current_page(int addr) { void write_flash(int length) { fill(length); if (CRC_EOP == getch()) { - Serial.print((char) STK_INSYNC); - Serial.print((char) write_flash_pages(length)); + SERIAL.print((char) STK_INSYNC); + SERIAL.print((char) write_flash_pages(length)); } else { error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); } } @@ -451,15 +473,15 @@ void program_page() { if (memtype == 'E') { result = (char)write_eeprom(length); if (CRC_EOP == getch()) { - Serial.print((char) STK_INSYNC); - Serial.print(result); + SERIAL.print((char) STK_INSYNC); + SERIAL.print(result); } else { error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); } return; } - Serial.print((char)STK_FAILED); + SERIAL.print((char)STK_FAILED); return; } @@ -473,9 +495,9 @@ uint8_t flash_read(uint8_t hilo, int addr) { char flash_read_page(int length) { for (int x = 0; x < length; x += 2) { uint8_t low = flash_read(LOW, here); - Serial.print((char) low); + SERIAL.print((char) low); uint8_t high = flash_read(HIGH, here); - Serial.print((char) high); + SERIAL.print((char) high); here++; } return STK_OK; @@ -487,7 +509,7 @@ char eeprom_read_page(int length) { for (int x = 0; x < length; x++) { int addr = start + x; uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); - Serial.print((char) ee); + SERIAL.print((char) ee); } return STK_OK; } @@ -499,34 +521,29 @@ void read_page() { char memtype = getch(); if (CRC_EOP != getch()) { error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); return; } - Serial.print((char) STK_INSYNC); - if (memtype == 'F') { - result = flash_read_page(length); - } - if (memtype == 'E') { - result = eeprom_read_page(length); - } - Serial.print(result); - return; + SERIAL.print((char) STK_INSYNC); + if (memtype == 'F') result = flash_read_page(length); + if (memtype == 'E') result = eeprom_read_page(length); + SERIAL.print(result); } void read_signature() { if (CRC_EOP != getch()) { error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); return; } - Serial.print((char) STK_INSYNC); + SERIAL.print((char) STK_INSYNC); uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); - Serial.print((char) high); + SERIAL.print((char) high); uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); - Serial.print((char) middle); + SERIAL.print((char) middle); uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); - Serial.print((char) low); - Serial.print((char) STK_OK); + SERIAL.print((char) low); + SERIAL.print((char) STK_OK); } ////////////////////////////////////////// ////////////////////////////////////////// @@ -544,13 +561,13 @@ int avrisp() { break; case '1': if (getch() == CRC_EOP) { - Serial.print((char) STK_INSYNC); - Serial.print("AVR ISP"); - Serial.print((char) STK_OK); + SERIAL.print((char) STK_INSYNC); + SERIAL.print("AVR ISP"); + SERIAL.print((char) STK_OK); } else { error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); } break; case 'A': @@ -615,17 +632,16 @@ int avrisp() { // this is how we can get back in sync case CRC_EOP: error++; - Serial.print((char) STK_NOSYNC); + SERIAL.print((char) STK_NOSYNC); break; // anything else we will return STK_UNKNOWN default: error++; - if (CRC_EOP == getch()) { - Serial.print((char)STK_UNKNOWN); - } else { - Serial.print((char)STK_NOSYNC); - } + if (CRC_EOP == getch()) + SERIAL.print((char)STK_UNKNOWN); + else + SERIAL.print((char)STK_NOSYNC); } } From eca360bf4204d95093a7c9e54e8babdf180df9ae Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Fri, 10 Jul 2015 14:02:47 +0200 Subject: [PATCH 12/25] Fix typo: SPI_CLOCK_DIV128 --- .../examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 7e7a33c4f..215a16bf7 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -54,14 +54,9 @@ #define LED_PMODE 7 #define PROG_FLICKER true -#if defined(ARDUINO_ARCH_SAM) or defined(ARDUINO_ARCH_SAMD) - -#define SPI_CLOCK_DIV_MAX 255 - -#else +#if !defined(ARDUINO_ARCH_SAM) and !defined(ARDUINO_ARCH_SAMD) #define USE_HARDWARE_SPI -#define SPI_CLOCK_DIV_MAX SPI_CLOCK_DIV_128 #endif @@ -101,8 +96,11 @@ void pulse(int pin, int times); #ifdef USE_HARDWARE_SPI #include "SPI.h" +#define SPI_CLOCK_DIV_MAX SPI_CLOCK_DIV128 #else +#define SPI_CLOCK_DIV_MAX 255 + class BitBangedSPI { public: void setDataMode(uint8_t dataMode) { From 5a04ab2a322ac18029232ff75c2ba4417f3f535a Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Mon, 13 Jul 2015 21:49:42 +0200 Subject: [PATCH 13/25] Don't pulse error led if avrdude enters programming mode twice --- .../shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 215a16bf7..eddeb11cb 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -581,12 +581,8 @@ int avrisp() { empty_reply(); break; case 'P': - if (pmode) { - pulse(LED_ERR, 3); - } - else { + if (!pmode) start_pmode(); - } empty_reply(); break; case 'U': // set address (word) From 50f9e539d8b424842f4dab9d1357b30c6db3e0d8 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 14 Jul 2015 21:20:39 +0200 Subject: [PATCH 14/25] Ensure minimum spi pulse width. --- .../examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index eddeb11cb..5c3144ba5 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -114,6 +114,10 @@ class BitBangedSPI { } void begin() { + // slow enough for an attiny85 @ 1MHz + // (pulseWidth should be > 2 cpu cycles, so take 3 cycles:) + pulseWidth = 3; + pinMode(MISO, INPUT); pinMode(RESET, OUTPUT); pinMode(SCK, OUTPUT); @@ -126,11 +130,16 @@ class BitBangedSPI { for (unsigned int i = 0; i < 8; ++i) { digitalWrite(MOSI, b & 0x80); digitalWrite(SCK, HIGH); + delayMicroseconds(pulseWidth); b = (b << 1) | digitalRead(MISO); digitalWrite(SCK, LOW); // slow pulse + delayMicroseconds(pulseWidth); } return b; } + + private: + unsigned long pulseWidth; // in microseconds }; static BitBangedSPI SPI; From 89184a36682abed7377ab508c7abb42389751f21 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 14 Jul 2015 23:06:54 +0200 Subject: [PATCH 15/25] Use new style SPI::beginTransaction() api, make SPI_CLOCK configurable, select hardware or software SPI based on SPI_CLOCK. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 5c3144ba5..57e78f4e3 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -54,12 +54,32 @@ #define LED_PMODE 7 #define PROG_FLICKER true -#if !defined(ARDUINO_ARCH_SAM) and !defined(ARDUINO_ARCH_SAMD) +// Configure SPI clock. +// E.g. for an attiny @128 kHz: +// (pulseWidth should be > 2 cpu cycles, so take 3 cycles:) +// #define SPI_CLOCK (128000/3) +// +// A clock slow enough for an attiny85 @ 1MHz, is a reasonable default: +#define SPI_CLOCK (1000000/3) + +// Select hardware or software SPI, depending on SPI clock. +// Currently only for AVR, for other archs (Due, Zero,...), +// hardware SPI is probably too fast anyway. + +#if defined(ARDUINO_ARCH_AVR) + +#if SPI_CLOCK > (F_CPU / 128) #define USE_HARDWARE_SPI +#endif #endif +#ifdef USE_HARDWARE_SPI +#warning hw spi !!! +#else +#warning NOT usung hw spi +#endif // Configure the serial port to use. // @@ -96,27 +116,34 @@ void pulse(int pin, int times); #ifdef USE_HARDWARE_SPI #include "SPI.h" -#define SPI_CLOCK_DIV_MAX SPI_CLOCK_DIV128 #else -#define SPI_CLOCK_DIV_MAX 255 +#define SPI_MODE0 0x00 + +class SPISettings { +public: + // clock is in Hz + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clock(clock){ + (void) bitOrder; + (void) dataMode; + }; + +private: + uint32_t clock; + +friend class BitBangedSPI; +}; class BitBangedSPI { public: - void setDataMode(uint8_t dataMode) { - (void) dataMode; - } - void setBitOrder(uint8_t bitOrder) { - (void) bitOrder; - } - void setClockDivider(uint8_t clockDiv) { - (void) clockDiv; + + void beginTransaction(SPISettings settings) { + pulseWidth = 1000 / (settings.clock / 1000); + if (pulseWidth == 0) + pulseWidth = 1; } void begin() { - // slow enough for an attiny85 @ 1MHz - // (pulseWidth should be > 2 cpu cycles, so take 3 cycles:) - pulseWidth = 3; pinMode(MISO, INPUT); pinMode(RESET, OUTPUT); @@ -148,10 +175,9 @@ static BitBangedSPI SPI; void setup() { SERIAL.begin(19200); - SPI.setDataMode(0); - SPI.setBitOrder(MSBFIRST); - // Select the slowest possible clock - SPI.setClockDivider(SPI_CLOCK_DIV_MAX); + + SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); + pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); From 8d95899450dcd2bbc6544b202d561f192d77b5b0 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 28 Jul 2015 22:26:58 +0200 Subject: [PATCH 16/25] Call SPI.beginTransaction() after SPI.begin() --- build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 57e78f4e3..6d1b74633 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -176,7 +176,6 @@ static BitBangedSPI SPI; void setup() { SERIAL.begin(19200); - SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); @@ -360,6 +359,7 @@ void set_parameters() { void start_pmode() { SPI.begin(); + SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); // SPI.begin() has configured SS as output, // so SPI master mode is selected. // We have defined RESET as pin 10, From d271c1c8a2fe06fd86dcf826c1ce044a69e80741 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Tue, 28 Jul 2015 22:31:34 +0200 Subject: [PATCH 17/25] BitBangedSPI::begin(): initialize levels of SCK and MOSI. Correct indentation. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 6d1b74633..a4d3d4dfb 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -135,38 +135,37 @@ friend class BitBangedSPI; }; class BitBangedSPI { - public: +public: + void begin() { + digitalWrite(SCK, LOW); + digitalWrite(MOSI, LOW); + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(MISO, INPUT); + } - void beginTransaction(SPISettings settings) { - pulseWidth = 1000 / (settings.clock / 1000); - if (pulseWidth == 0) - pulseWidth = 1; + void beginTransaction(SPISettings settings) { + pulseWidth = 1000 / (settings.clock / 1000); + if (pulseWidth == 0) + pulseWidth = 1; + } + + void end() {} + + uint8_t transfer (uint8_t b) { + for (unsigned int i = 0; i < 8; ++i) { + digitalWrite(MOSI, b & 0x80); + digitalWrite(SCK, HIGH); + delayMicroseconds(pulseWidth); + b = (b << 1) | digitalRead(MISO); + digitalWrite(SCK, LOW); // slow pulse + delayMicroseconds(pulseWidth); } + return b; + } - void begin() { - - pinMode(MISO, INPUT); - pinMode(RESET, OUTPUT); - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); - } - - void end() {} - - uint8_t transfer (uint8_t b) { - for (unsigned int i = 0; i < 8; ++i) { - digitalWrite(MOSI, b & 0x80); - digitalWrite(SCK, HIGH); - delayMicroseconds(pulseWidth); - b = (b << 1) | digitalRead(MISO); - digitalWrite(SCK, LOW); // slow pulse - delayMicroseconds(pulseWidth); - } - return b; - } - - private: - unsigned long pulseWidth; // in microseconds +private: + unsigned long pulseWidth; // in microseconds }; static BitBangedSPI SPI; From 044a7b78c764ce8493cd6fa09082427a10b4b6fb Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 29 Jul 2015 21:37:04 +0200 Subject: [PATCH 18/25] Fix warnings. Use unsigned int to represent a (word) address: the compiler will use the most efficient type on each platform: 32 bit on arm, 16 bit on avr which is is big enough. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 56 ++++++++----------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index a4d3d4dfb..ed467e8f6 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -75,12 +75,6 @@ #endif -#ifdef USE_HARDWARE_SPI -#warning hw spi !!! -#else -#warning NOT usung hw spi -#endif - // Configure the serial port to use. // // Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one: @@ -188,7 +182,7 @@ void setup() { int error = 0; int pmode = 0; // address for reading and writing, set by 'U' command -int here; +unsigned int here; uint8_t buff[256]; // global block storage #define beget16(addr) (*addr * 256 + *(addr+1) ) @@ -228,8 +222,7 @@ void heartbeat() { static bool rst_active_high; -void reset_target(bool reset) -{ +void reset_target(bool reset) { digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW); } @@ -281,11 +274,9 @@ void prog_lamp(int state) { } uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - uint8_t n; SPI.transfer(a); - n = SPI.transfer(b); - //if (n != a) error = -1; - n = SPI.transfer(c); + SPI.transfer(b); + SPI.transfer(c); return SPI.transfer(d); } @@ -388,7 +379,6 @@ void end_pmode() { } void universal() { - int w; uint8_t ch; fill(4); @@ -396,13 +386,13 @@ void universal() { breply(ch); } -void flash(uint8_t hilo, int addr, uint8_t data) { +void flash(uint8_t hilo, unsigned int addr, uint8_t data) { spi_transaction(0x40 + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data); } -void commit(int addr) { +void commit(unsigned int addr) { if (PROG_FLICKER) { prog_lamp(LOW); } @@ -413,8 +403,7 @@ void commit(int addr) { } } -//#define _current_page(x) (here & 0xFFFFE0) -int current_page(int addr) { +unsigned int current_page() { if (param.pagesize == 32) { return here & 0xFFFFFFF0; } @@ -444,11 +433,11 @@ void write_flash(int length) { uint8_t write_flash_pages(int length) { int x = 0; - int page = current_page(here); + unsigned int page = current_page(); while (x < length) { - if (page != current_page(here)) { + if (page != current_page()) { commit(page); - page = current_page(here); + page = current_page(); } flash(LOW, here, buff[x++]); flash(HIGH, here, buff[x++]); @@ -461,10 +450,10 @@ uint8_t write_flash_pages(int length) { } #define EECHUNK (32) -uint8_t write_eeprom(int length) { +uint8_t write_eeprom(unsigned int length) { // here is a word address, get the byte address - int start = here * 2; - int remaining = length; + unsigned int start = here * 2; + unsigned int remaining = length; if (length > param.eepromsize) { error++; return STK_FAILED; @@ -478,13 +467,13 @@ uint8_t write_eeprom(int length) { return STK_OK; } // write (length) bytes, (start) is a byte address -uint8_t write_eeprom_chunk(int start, int length) { +uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) { // this writes byte-by-byte, // page writing may be faster (4 bytes at a time) fill(length); prog_lamp(LOW); - for (int x = 0; x < length; x++) { - int addr = start + x; + for (unsigned int x = 0; x < length; x++) { + unsigned int addr = start + x; spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); delay(45); } @@ -494,7 +483,7 @@ uint8_t write_eeprom_chunk(int start, int length) { void program_page() { char result = (char) STK_FAILED; - int length = 256 * getch(); + unsigned int length = 256 * getch(); length += getch(); char memtype = getch(); // flash memory @here, (length) bytes @@ -517,7 +506,7 @@ void program_page() { return; } -uint8_t flash_read(uint8_t hilo, int addr) { +uint8_t flash_read(uint8_t hilo, unsigned int addr) { return spi_transaction(0x20 + hilo * 8, (addr >> 8) & 0xFF, addr & 0xFF, @@ -583,8 +572,7 @@ void read_signature() { //////////////////////////////////// //////////////////////////////////// -int avrisp() { - uint8_t data, low, high; +void avrisp() { uint8_t ch = getch(); switch (ch) { case '0': // signon @@ -626,12 +614,12 @@ int avrisp() { break; case 0x60: //STK_PROG_FLASH - low = getch(); - high = getch(); + getch(); // low addr + getch(); // high addr empty_reply(); break; case 0x61: //STK_PROG_DATA - data = getch(); + getch(); // data empty_reply(); break; From 13cc57ed7e01fb468a521c759343b05ae26a7700 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Wed, 26 Aug 2015 22:43:00 +0200 Subject: [PATCH 19/25] Reset target before driving SCK or MOSI, reset sequence as in AVR datasheets under "Serial Programming Algorithm" --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index ed467e8f6..7247b2644 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -169,7 +169,6 @@ static BitBangedSPI SPI; void setup() { SERIAL.begin(19200); - pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); @@ -348,21 +347,33 @@ void set_parameters() { } void start_pmode() { - SPI.begin(); - SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); - // SPI.begin() has configured SS as output, + + // Reset target before driving SCK or MOSI + + // SPI.begin() will configure SS as output, // so SPI master mode is selected. // We have defined RESET as pin 10, // which for many arduino's is not the SS pin. // So we have to configure RESET as output here, - // (reset_target() first sets the level correct) - reset_target(false); - pinMode(RESET, OUTPUT); - - digitalWrite(SCK, LOW); - delay(20); + // (reset_target() first sets the correct level) reset_target(true); - delay(50); + pinMode(RESET, OUTPUT); + SPI.begin(); + SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); + + // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": + + // Pulse RESET after SCK is low: + digitalWrite(SCK, LOW); + delay(20); // discharge SCK, value arbitrally chosen + reset_target(false); + // Pulse must be minimum 2 target CPU clock cycles + // so 100 usec is ok for CPU speeds above 20KHz + delayMicroseconds(100); + reset_target(true); + + // Send the enable programming command: + delay(50); // datasheet: must be > 20 msec spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; } From e3866e0ef5ead4420b30abbcb477f87437994880 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Sun, 30 Aug 2015 20:27:38 +0200 Subject: [PATCH 20/25] Elaborate configuration of which pins to use: support HOODLOADER2 and old Uno style wiring. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 7247b2644..73c2fcc7e 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -46,12 +46,7 @@ #include "Arduino.h" #undef SERIAL -// Use pin 10 to reset the target -#define RESET 10 -#define LED_HB 9 -#define LED_ERR 8 -#define LED_PMODE 7 #define PROG_FLICKER true // Configure SPI clock. @@ -75,6 +70,44 @@ #endif +// Configure which pins to use + +// The standard pin configuration. +#ifndef ARDUINO_HOODLOADER2 + +#define RESET 10 // Use pin 10 to reset the target rather than SS +#define LED_HB 9 +#define LED_ERR 8 +#define LED_PMODE 7 + +// Uncomment following line to use the old uno style wiring +// (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due... + +// #define USE_OLD_STYLE_WIRING + +#ifdef USE_OLD_STYLE_WIRING +#undef USE_HARDWARE_SPI +#undef MOSI +#undef MISO +#undef SCK +#define MOSI 11 +#define MISO 12 +#define SCK 13 +#endif + +// HOODLOADER2 means running sketches on the atmega16u2 +// serial converter chips on Uno or Mega boards. +// We must use pins that are broken out: +#else + +#define RESET 4 +#define LED_HB 7 +#define LED_ERR 6 +#define LED_PMODE 5 + +#endif + + // Configure the serial port to use. // // Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one: From 2c1728f086051c602a16f943aea99f55ae8fa3b8 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Sun, 30 Aug 2015 20:36:39 +0200 Subject: [PATCH 21/25] Use digitalWrite() only with values HIGH and LOW. --- build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 73c2fcc7e..a791f210b 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -181,7 +181,7 @@ public: uint8_t transfer (uint8_t b) { for (unsigned int i = 0; i < 8; ++i) { - digitalWrite(MOSI, b & 0x80); + digitalWrite(MOSI, (b & 0x80) ? HIGH : LOW); digitalWrite(SCK, HIGH); delayMicroseconds(pulseWidth); b = (b << 1) | digitalRead(MISO); From 82e5d4a88daf4697e9c562d6756b95519848b94a Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Mon, 31 Aug 2015 22:17:12 +0200 Subject: [PATCH 22/25] Remove change history to make room for documentation. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 51 ++++++++----------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index a791f210b..d290695a6 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -1,4 +1,4 @@ -// ArduinoISP version 04m3 +// ArduinoISP // Copyright (c) 2008-2011 Randall Bohn // If you require a license, see // http://www.opensource.org/licenses/bsd-license.php @@ -6,42 +6,31 @@ // This sketch turns the Arduino into a AVRISP // using the following arduino pins: // -// pin name: not-mega: mega(1280 and 2560) -// slave reset: 10: 10 -// MOSI: 11: 51 -// MISO: 12: 50 -// SCK: 13: 52 +// Pin 10 is used to reset the target microcontroller. +// +// The MISO, MOSI and SCK pins are used to communicate with the target, +// on all Arduinos, these pins can be found on the ICSP header: +// +// MISO °. . 5V (!) Avoid this pin on Due, Zero... +// SCK . . MOSI +// . . GND +// +// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same pins +// as digital pin 11, 12 and 13, respectively. That is why many tutorials +// instruct you to hook up the target to these pins. If you find this wiring +// more practical, have a define USE_OLD_STYLE_WIRING. This will work even +// even when not using an Uno. (On an Uno this is not needed). +// +// IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...) +// as the programmer, make sure to not expose any of the programmer's pins to 5V. +// A simple way to accomplish this is to power the complete system (programmer +// and target) at 3V3. // // Put an LED (with resistor) on the following pins: // 9: Heartbeat - shows the programmer is running // 8: Error - Lights up if something goes wrong (use red if that makes sense) // 7: Programming - In communication with the slave // -// 23 July 2011 Randall Bohn -// -Address Arduino issue 509 :: Portability of ArduinoISP -// http://code.google.com/p/arduino/issues/detail?id=509 -// -// October 2010 by Randall Bohn -// - Write to EEPROM > 256 bytes -// - Better use of LEDs: -// -- Flash LED_PMODE on each flash commit -// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress) -// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync. -// - Use pins_arduino.h (should also work on Arduino Mega) -// -// October 2009 by David A. Mellis -// - Added support for the read signature command -// -// February 2009 by Randall Bohn -// - Added support for writing to EEPROM (what took so long?) -// Windows users should consider WinAVR's avrdude instead of the -// avrdude included with Arduino software. -// -// January 2008 by Randall Bohn -// - Thanks to Amplificar for helping me with the STK500 protocol -// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader -// - The SPI functions herein were developed for the AVR910_ARD programmer -// - More information at http://code.google.com/p/mega-isp #include "Arduino.h" #undef SERIAL From bfffb17e40e1a4d849505785df1084d8f2702fdc Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Sat, 5 Sep 2015 20:41:03 +0200 Subject: [PATCH 23/25] Improve SPI clock configuration. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index d290695a6..6b75ce549 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -38,14 +38,16 @@ #define PROG_FLICKER true -// Configure SPI clock. -// E.g. for an attiny @128 kHz: -// (pulseWidth should be > 2 cpu cycles, so take 3 cycles:) -// #define SPI_CLOCK (128000/3) +// Configure SPI clock (in Hz). +// E.g. for an attiny @128 kHz: the datasheet states that both the high +// and low spi clock pulse must be > 2 cpu cycles, so take 3 cycles i.e. +// divide target f_cpu by 6: +// #define SPI_CLOCK (128000/6) // -// A clock slow enough for an attiny85 @ 1MHz, is a reasonable default: +// A clock slow enough for an attiny85 @ 1MHz, is a reasonable default: + +#define SPI_CLOCK (1000000/6) -#define SPI_CLOCK (1000000/3) // Select hardware or software SPI, depending on SPI clock. // Currently only for AVR, for other archs (Due, Zero,...), @@ -161,7 +163,7 @@ public: } void beginTransaction(SPISettings settings) { - pulseWidth = 1000 / (settings.clock / 1000); + pulseWidth = (500000 + settings.clock - 1) / settings.clock; if (pulseWidth == 0) pulseWidth = 1; } From d2a38f23a831c993877c2cb723a1034b0d60c52c Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Sat, 5 Sep 2015 20:43:44 +0200 Subject: [PATCH 24/25] Rework pin configuration. --- .../11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 80 ++++++++++++------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 6b75ce549..24c795203 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -8,8 +8,9 @@ // // Pin 10 is used to reset the target microcontroller. // -// The MISO, MOSI and SCK pins are used to communicate with the target, -// on all Arduinos, these pins can be found on the ICSP header: +// By default, the hardware SPI pins MISO, MOSI and SCK pins are used +// to communicate with the target. On all Arduinos, these pins can be found +// on the ICSP/SPI header: // // MISO °. . 5V (!) Avoid this pin on Due, Zero... // SCK . . MOSI @@ -20,6 +21,9 @@ // instruct you to hook up the target to these pins. If you find this wiring // more practical, have a define USE_OLD_STYLE_WIRING. This will work even // even when not using an Uno. (On an Uno this is not needed). +// +// Alternatively you can use any other digital pin by configuring software ('BitBanged') +// SPI and having appropriate defines for PIN_MOSI, PIN_MISO and PIN_SCK. // // IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...) // as the programmer, make sure to not expose any of the programmer's pins to 5V. @@ -61,7 +65,7 @@ #endif -// Configure which pins to use +// Configure which pins to use: // The standard pin configuration. #ifndef ARDUINO_HOODLOADER2 @@ -71,19 +75,17 @@ #define LED_ERR 8 #define LED_PMODE 7 -// Uncomment following line to use the old uno style wiring +// Uncomment following line to use the old Uno style wiring // (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due... // #define USE_OLD_STYLE_WIRING #ifdef USE_OLD_STYLE_WIRING -#undef USE_HARDWARE_SPI -#undef MOSI -#undef MISO -#undef SCK -#define MOSI 11 -#define MISO 12 -#define SCK 13 + +#define PIN_MOSI 11 +#define PIN_MISO 12 +#define PIN_SCK 13 + #endif // HOODLOADER2 means running sketches on the atmega16u2 @@ -91,13 +93,31 @@ // We must use pins that are broken out: #else -#define RESET 4 -#define LED_HB 7 -#define LED_ERR 6 -#define LED_PMODE 5 +#define RESET 4 +#define LED_HB 7 +#define LED_ERR 6 +#define LED_PMODE 5 #endif +// By default, use hardware SPI pins: +#ifndef PIN_MOSI +#define PIN_MOSI MOSI +#endif + +#ifndef PIN_MISO +#define PIN_MISO MISO +#endif + +#ifndef PIN_SCK +#define PIN_SCK SCK +#endif + +// Force bitbanged SPI if not using the hardware SPI pins: +#if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK) +#undef USE_HARDWARE_SPI +#endif + // Configure the serial port to use. // @@ -155,11 +175,11 @@ friend class BitBangedSPI; class BitBangedSPI { public: void begin() { - digitalWrite(SCK, LOW); - digitalWrite(MOSI, LOW); - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); - pinMode(MISO, INPUT); + digitalWrite(PIN_SCK, LOW); + digitalWrite(PIN_MOSI, LOW); + pinMode(PIN_SCK, OUTPUT); + pinMode(PIN_MOSI, OUTPUT); + pinMode(PIN_MISO, INPUT); } void beginTransaction(SPISettings settings) { @@ -172,11 +192,11 @@ public: uint8_t transfer (uint8_t b) { for (unsigned int i = 0; i < 8; ++i) { - digitalWrite(MOSI, (b & 0x80) ? HIGH : LOW); - digitalWrite(SCK, HIGH); + digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW); + digitalWrite(PIN_SCK, HIGH); delayMicroseconds(pulseWidth); - b = (b << 1) | digitalRead(MISO); - digitalWrite(SCK, LOW); // slow pulse + b = (b << 1) | digitalRead(PIN_MISO); + digitalWrite(PIN_SCK, LOW); // slow pulse delayMicroseconds(pulseWidth); } return b; @@ -372,7 +392,7 @@ void set_parameters() { void start_pmode() { - // Reset target before driving SCK or MOSI + // Reset target before driving PIN_SCK or PIN_MOSI // SPI.begin() will configure SS as output, // so SPI master mode is selected. @@ -387,9 +407,9 @@ void start_pmode() { // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": - // Pulse RESET after SCK is low: - digitalWrite(SCK, LOW); - delay(20); // discharge SCK, value arbitrally chosen + // Pulse RESET after PIN_SCK is low: + digitalWrite(PIN_SCK, LOW); + delay(20); // discharge PIN_SCK, value arbitrally chosen reset_target(false); // Pulse must be minimum 2 target CPU clock cycles // so 100 usec is ok for CPU speeds above 20KHz @@ -406,8 +426,8 @@ void end_pmode() { SPI.end(); // We're about to take the target out of reset // so configure SPI pins as input - pinMode(MOSI, INPUT); - pinMode(SCK, INPUT); + pinMode(PIN_MOSI, INPUT); + pinMode(PIN_SCK, INPUT); reset_target(false); pinMode(RESET, INPUT); pmode = 0; From ff1158a1b97f46de159e097523266666a0ac0d26 Mon Sep 17 00:00:00 2001 From: Peter Van Hoyweghen Date: Sat, 5 Sep 2015 20:45:15 +0200 Subject: [PATCH 25/25] Add a define for baudrate configuration. --- .../examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino index 24c795203..d4fd37ea5 100644 --- a/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino +++ b/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino @@ -138,6 +138,13 @@ #endif +// Configure the baud rate: + +#define BAUDRATE 19200 +// #define BAUDRATE 115200 +// #define BAUDRATE 1000000 + + #define HWVER 2 #define SWMAJ 1 #define SWMIN 18 @@ -211,7 +218,7 @@ static BitBangedSPI SPI; #endif void setup() { - SERIAL.begin(19200); + SERIAL.begin(BAUDRATE); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2);