Resetting Fuses

Hello, My name is Bob and I am new To the Forum, relatively new to Arduino and I could use some help.

I ordered 50 SMD Atttinys 85 (20pu) from China (Aliexpress) but I was unable to program them.

To verify it was not due to my homemade program card I bought a couple from a Dutch website. These worked fine. After some searching on the internet I found that sometimes the fuse settings are set wrong in batch ordered Attinys from China because the were preprogramed. So I build a High Voltage Programer card controlled by my Arduino Uno. The programer did read the fuses (witch are wrong) but was unable to rewrite them.

Again I thought it was due to my program card or due to the program I was using so I bricked one of the Dutch bought Tinys by setting an external clock. On this chip the HVP worked like a charm. I will check tonight but I think the Chinese bought chips read something like 52 - 5F - FF .

Does anyone of know if there can be another setting preventing the HVP to reset the fuses? I will include the program I found on the internet and used in the next post.

Thanx for your help.

Bob

// AVR High-voltage Serial Programmer
// Originally created by Paul Willoughby 03/20/2010
// http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
// Inspired by Jeff Keyzer http://mightyohm.com
// Serial Programming routines from ATtiny25/45/85 datasheet

// Desired fuse configuration
#define HFUSE 0xDF // Defaults for ATtiny25/45/85
#define LFUSE 0x62
// For Attiny13 use
// #define HFUSE 0xFF
// #define LFUSE 0x6A

#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("lfuses 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("hfuses 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("efuses as ");
Serial.println(inData, HEX);
Serial.println();
}

I fyou can read the fuses you should be able to change them I think. Were you able to change fuses of Dutch chips via HVP? How you found the fuse of Chinese chip was not changed?

Can you read a correct device signature? I think that some fuses and memory protection bytes can only be reset with a "chip erase" command.

Thanx for your Reply,

The program first Reads and shows the fuses values in the serial monitor. Than it writes and reads again. finally it shows the new values in the serial monitor. So I could see the Dutch chips changed back to factory default. The Chinese ones did not change at all.

Hello WestFW, thanx for helping.

I am a Novice to all this. But when I tried to program the chips via ISP it responded with invalid device signature. Can you tell me how to use the Chip Erase command? Is this also done by HVP ?

what was the device signature it read out?

Yes, erasing the device can be done using HVP. Datasheet says:

The Chip Erase will erase the Flash and EEPROM(1) memories plus Lock bits. The Lock bits are not reset until the Program memory has been completely erased. The Fuse bits are not changed. A Chip Erase must be performed before the Flash and/or EEPROM are re- programmed.

Note: 1. The EEPROM memory is preserved during Chip Erase if the EESAVE Fuse is programmed. 1. Load command “Chip Erase” (see Table 20-16). 2. Wait after Instr. 3 until SDO goes high for the “Chip Erase” cycle to finish. 3. Load Command “No Operation”.

$&#-+$* lock bits, I forgot about them. They protect Flash AND Fuses to be written. Chip Erase clears Flash and the lock bits so AFTER it you should be able to change the Fuses.

I had the same problem some time ago but completly forgot about the lock bits part...

OK this really helps.

@ Westfa, This is way above my level of knowledge. Do you know of a way to incorporate this in the program i have for resetting the fuses?

@Jiggy Ninja 52 - 5F - FE .

Thanx again.

Bobvanderhoest: OK this really helps.

@ Westfa, This is way above my level of knowledge. Do you know of a way to incorporate this in the program i have for resetting the fuses?

@Jiggy Ninja 52 - 5F - FE .

Thanx again.

I can't even find that signature in avrdude.conf. I even hand-checked some of the current official Arduino chips (mega328P, mega2560, mega1280, mega32u4) and nothing even comes close.

What chip are you trying to program?

Sorry Jiggy Ninja, these are the fuse settings. I will check te signature tonight.

You can try adding the following code just before the readFuses() call... I don't have a HVSP handy, so I'm not sure that this works; it's consistent with the datasheet and the existing code that you're using, I think...

   // Erase chip, including reset of lock bits
    Serial.println("Chip Erase");
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x80, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
    delay_microseconds(5000);  /* Supposed to be 2.5ms "typical" */
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x4C); /* Noop */

You might have to consider that the chips you got could be duds or outright fakes. Aliexpress is about as reliable as eBay (some vendors are fine, some are "sketchy.")

Wel first of: Westfw You are Awesome!!!

I did give it a thought that the would be dead at first but when the fuses gave a normal reading… I was hoping the would be ok.

I added the code you gave me. the only thing i changed was delay_microseconds(5000); into delayMicroseconds(5000); and it worked.

If you don’t mind I will post this solution in some tutorials on HVP cause I think there will be more with the same issue, the vendor is still selling these chips. I will post the complete code in the next post so the can be just copied and pasted.

Here is a link to the HVP I build and used http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/

Thanx again

Bob

Result.png

// AVR High-voltage Serial Programmer
// Originally created by Paul Willoughby 03/20/2010
// http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
// Inspired by Jeff Keyzer http://mightyohm.com
// Serial Programming routines from ATtiny25/45/85 datasheet

// Desired fuse configuration
#define HFUSE 0xDF // Defaults for ATtiny25/45/85
#define LFUSE 0x62
// For Attiny13 use
// #define HFUSE 0xFF
// #define LFUSE 0x6A

#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
// Erase chip, including reset of lock bits
Serial.println(“Chip Erase”);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x80, 0x4C);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
delayMicroseconds(5000); /* Supposed to be 2.5ms “typical” /
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x4C); /
Noop */

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("lfuses 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("hfuses 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("efuses as ");
Serial.println(inData, HEX);
Serial.println();
}

Glad to hear that it worked! Thanks for the update.