Digispark ATtiny85 boards come with the Micronucleus bootloader and with the reset pin disabled. When reset is disabled you get an additional digital pin, and you must upload sketches using the bootloader. You may not use ISP programming.
There are projects where I want to use Digispark and need to enable the reset pin for various reasons:
This Instructable documents how I unlock the reset pin and program the Digispark with ISP programming to convert it to a Trinket. I have a clone Digispark, which works the same as the Kickstarter Digispark from Digistump.
In this Instructable, I use an Uno as the high voltage programmer, and later I use it as an ISP. You can also use a Nano or Pro Mini, which are simply small Unos.
Using this method you can continue to use the board as a Digispark, or use it as a plain ATtiny85 breakout board and program it via ISP, or use it as a Trinket. If you continue to use the board as a Digispark, the P5 pin has been converted from a regular I/O pin to a reset pin.
Since the Digispark is simply a small break out board for the ATtiny85 MCU, you can also use this Instructable to rescue fuses on a stand alone ATtiny85 MCU.
A sketch for Uno is available here for unlocking ATtiny85:
http://www.rickety.us/wp-content/uploads/2010/03/hv_serial_prog.pde
Code is by Paul Willoughby and original article for unlocking bare ATtiny85 ICs here:
http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
Sketch:
// AVR High-voltage Serial Programmer
// Originally created by Paul Willoughby 03/20/2010 // www.rickety.us slash 2010/03/arduino-avr-high-voltage-serial-programmer/ // Inspired by Jeff Keyzer mightyohm.com // Serial Programming routines from ATtiny25/45/85 datasheet// Desired fuse configuration #define HFUSE 0xDF // Defaults for ATtiny25/45/85 #define LFUSE 0x62
#define RST 13 // Output to level shifter for !RESET from transistor to Pin 1 #define CLKOUT 12 // Connect to Serial Clock Input (SCI) Pin 2 #define DATAIN 11 // Connect to Serial Data Output (SDO) Pin 7 #define INSTOUT 10 // Connect to Serial Instruction Input (SII) Pin 6 #define DATAOUT 9 // Connect to Serial Data Input (SDI) Pin 5 #define VCC 8 // Connect to VCC Pin 8
int inByte = 0; // incoming serial byte Computer int inData = 0; // incoming serial byte AVR
void setup() { // Set up control lines for HV parallel programming pinMode(VCC, OUTPUT); pinMode(RST, OUTPUT); pinMode(DATAOUT, OUTPUT); pinMode(INSTOUT, OUTPUT); pinMode(CLKOUT, OUTPUT); pinMode(DATAIN, OUTPUT); // configured as input when in programming mode // Initialize output pins as needed digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V // start serial port at 9600 bps: Serial.begin(9600); establishContact(); // send a byte to establish contact until receiver responds }
void loop() { // if we get a valid byte, run: if (Serial.available() > 0) { // get incoming byte: inByte = Serial.read(); Serial.println(byte(inByte)); Serial.println("Entering programming Mode\n");
// Initialize pins to enter programming mode pinMode(DATAIN, OUTPUT); //Temporary digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(DATAIN, LOW); digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V // Enter High-voltage Serial programming mode digitalWrite(VCC, HIGH); // Apply VCC to start programming process delayMicroseconds(20); digitalWrite(RST, LOW); //Turn on 12v delayMicroseconds(10); pinMode(DATAIN, INPUT); //Release DATAIN delayMicroseconds(300); //Programming mode readFuses(); //Write hfuse Serial.println("Writing hfuse"); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, HFUSE, 0x2C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x74); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7C); //Write lfuse Serial.println("Writing lfuse\n"); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, LFUSE, 0x2C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
readFuses(); Serial.println("Exiting programming Mode\n"); digitalWrite(CLKOUT, LOW); digitalWrite(VCC, LOW); digitalWrite(RST, HIGH); //Turn off 12v } }
void establishContact() { while (Serial.available() <= 0) { Serial.println("Enter a character to continue"); // send an initial string delay(1000); } }
int shiftOut2(uint8_t dataPin, uint8_t dataPin1, uint8_t clockPin, uint8_t bitOrder, byte val, byte val1) { int i; int inBits = 0; //Wait until DATAIN goes high while (!digitalRead(DATAIN)); //Start bit digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) { digitalWrite(dataPin, !!(val & (1 << i))); digitalWrite(dataPin1, !!(val1 & (1 << i))); } else { digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(dataPin1, !!(val1 & (1 << (7 - i)))); } inBits <<=1; inBits |= digitalRead(DATAIN); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); }
//End bits digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); return inBits; }
void readFuses(){ //Read lfuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x68); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C); Serial.print("lfuse reads as "); Serial.println(inData, HEX); //Read hfuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7A); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7E); Serial.print("hfuse reads as "); Serial.println(inData, HEX); //Read efuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6A); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6E); Serial.print("efuse reads as "); Serial.println(inData, HEX); Serial.println(); }