Як відновити неправильно виставлені фьюзы в ATtiny

image

Привіт всім хаброюзерам. Думаю багато хто, хто займається мікроконтролерами, мають невеликий досвід «блокування» мікроконтролера неправильно виставленими фьюз-бітами, будь то перепризначення порту Reset на порт введення-виводу або ж неправильні налаштування тактирования мікроконтролера, зокрема — дуже маленька частота, наприклад 16 КГц.



У цьому відео я розповім і покажу, як можна розблокувати мікроконтролери серії ATtiny у яких не правильно выставленые фьюз-біти, даний метод годиться не для всіх ATtiny але підходить для більшості популярних, а саме:

  • ATtiny13;
  • ATtiny24;
  • ATtiny25;
  • ATtiny44;
  • ATtiny45;
  • ATtiny84;
  • ATtiny85.
На відео я показав як це можна відновити заводські фьюз-біти за допомогою Arduino, по суті інформація представлена нижче дублюється у відеоформаті.

Даний метод повинен підійти для випадків коли були неправильно виставлені фью-збиты RSTDISBL, а конкретніше, порт RESET використовується як порт вводу/виводу або недбале ставлення до фьюз-біту SPIEN(дозвіл на послідовне програмування) це все виключає прошивку класичним способом за протоколом SPI(In-System Programming).


Скажу відразу, за основу взято проект товариша Wayne Holder, за що йому велике спасибі, ось посилання на його статті.
Отже, приступимо, ось схема підключення на прикладі ATtiny13:

image

А ось так ця схема виглядає в моєму виконанні:

image

Про підключення до ATtiny25/45/85/24/44/84 буде нижче.

Як Ви можете бачити, схема складається з 6 резисторів номіналом в 1 КОм, 1 NPN транзистора 2n3904, ось його призначення:

image

Можна взяти радянський КТ315 або його аналоги, ну власне джерела напруги 11.5-12.5, як рекомендують інженери з ATmel в документаціях до тих мікроконтролерах що згадані вище. Не думаю, що варто завищувати або занижувати напруга, так що перед відновленням раджу перевірити напругу на джерелі живлення вольтметром або мультиметром. На момент зйомки відео, напруга на моєму акумуляторі було 12.4 Ст.

Пару слів де можна взяти 12 В — це різного роду блоки живлення для роутерів або модемів, ось наприклад, мій DSL модем ASUS DSL-N10E як раз має 12 блок живлення, як правило на кожному блоці живлення зазначено напруга.
Так само 12 В можна взяти з роз'єм MOLEX комп'ютера:

image

А якщо точніше — жовтий і чорний.

Варто згадати, що потрібно дотримуватися підвищеної обережності при підключенні 12 В частині, тому, що це напруга запросто палить як мікроконтролери так і іншу периферію Arduino, наприклад перетворювач USB-TTL, посилаюся на особистий досвід. Тому дотримуємося алгоритмом:

  • Збираємо схему;
  • Подаємо харчування на Arduino підключивши до юсб;
  • Подаємо +12В на транзистор;
  • Відновлюємо мікроконтролер;
  • Відключаємо +12В.
Саме таким чином я скидав фьюз-біти ATtiny13(використовував порт Reset як порт введення/виводу), вже раз 10-15 при налагодженні одного мого проекту, ось короткий його відео прев'ю:

LCD(HD44780) вольтамперметр на ATtiny13
Підключаємо до інших мікроконтролерів наш «відновник фьюз-битовов» наступним чином:

image

  • Порт RST ATtiny підключається між резистором на 1 КОм, той що підключається до +12В, і колектором транзистора VT1;
  • 13-й пін Arduino, він же PB5, підключається через резистор на 1 КОм до бази транзистора VT1;
  • 12-ї пін Arduino, він же PB4, підключається через резистор на 1 КОм до SCI(Target Clock Input) ATtiny;
  • 11-й пін Arduino, він же PB3, підключається через резистор на 1 КОм до SDO(Target Data Output) ATtiny;
  • 10-ї пін Arduino, він же PB2, підключається через резистор на 1 КОм до SII(Target Instruction Input) ATtiny;
  • 9-ї пін Arduino, він же PB1, підключається через резистор на 1 КОм до SDI (Target Data Input) ATtiny;
  • 8-ї пін Arduino, він же PB0, бажано підключити через резистор на 100-330 Ом до VCC ATtiny, на всяк випадок.
  • GND — загальний провід, так звана «земля».
  • Не забуваємо подати +5В на VCC на AVCC.


Все це набуватиме в коді, ніяких проблем.

Ось код з сторінки автора
// AVR High-voltage Serial Fuse Reprogrammer
// Adapted from code and design by Paul Willoughby 03/20/2010
// http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
//
// Fuse Calc:
// http://www.engbedded.com/fusecalc/

#define RST 13 // Output to level shifter for !RESET from transistor
#define SCI 12 // Target Clock Input
#define SDO 11 // Target Data Output
#define SII 10 // Target Instruction Input
#define SDI 9 // Target Data Input
#define VCC 8 // Target VCC

#define HFUSE 0x747C
#define LFUSE 0x646C
#define EFUSE 0x666E

// Define ATTiny series signatures
#define ATTINY13 0x9007 // L: 0x6A, H: 0xFF 8 pin
#define ATTINY24 0x910B // L: 0x62, H: 0xDF, E: 0xFF 14 pin
#define ATTINY25 0x9108 // L: 0x62, H: 0xDF, E: 0xFF 8 pin
#define ATTINY44 0x9207 // L: 0x62, H: 0xDF, E: 0xFFF 14 pin
#define ATTINY45 0x9206 // L: 0x62, H: 0xDF, E: 0xFF 8 pin
#define ATTINY84 0x930C // L: 0x62, H: 0xDF, E: 0xFFF 14 pin
#define ATTINY85 0x930B // L: 0x62, H: 0xDF, E: 0xFF 8 pin

void setup() {
pinMode(VCC, OUTPUT);
pinMode(RST, OUTPUT);
pinMode(SDI, OUTPUT);
pinMode(SII, OUTPUT);
pinMode(SCI, OUTPUT);
pinMode(SDO, OUTPUT); // Configured as input when in programming mode
digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V
Serial.begin(19200);
}

void loop() {
if (Serial.available() > 0) {
Serial.read();
pinMode(SDO, OUTPUT); // Set SDO to output
digitalWrite(SDI, LOW);
digitalWrite(SII, LOW);
digitalWrite(SDO, LOW);
digitalWrite(RST, HIGH); // 12v Off
digitalWrite(VCC, HIGH); // Vcc On
delayMicroseconds(20);
digitalWrite(RST, LOW); // 12v On
delayMicroseconds(10);
pinMode(SDO, INPUT); // Set SDO to input
delayMicroseconds(300);
unsigned int sig = readSignature();
Serial.print("Signature is: ");
Serial.println(sig, HEX);
readFuses();
if (sig == ATTINY13) {
writeFuse(LFUSE, 0x6A);
writeFuse(HFUSE, 0xFF);
} else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) {
writeFuse(LFUSE, 0x62);
writeFuse(HFUSE, 0xDF);
writeFuse(EFUSE, 0xFF);
}
readFuses();
digitalWrite(SCI, LOW);
digitalWrite(VCC, LOW); // Vcc Off
digitalWrite(RST, HIGH); // 12v Off
}
}

byte shiftOut (byte val1, byte val2) {
int inBits = 0;
//Wait until SDO goes high
while (!digitalRead(SDO))
;
unsigned int dout = (unsigned int) val1 << 2;
unsigned int iout = (unsigned int) val2 << 2;
for (int ii = 10; ii >= 0; ii--) {
digitalWrite(SDI, !!(dout & (1 << ii));
digitalWrite(SII, !!(iout & (1 << ii));
inBits <<= 1;
inBits |= digitalRead(SDO);
digitalWrite(SCI, HIGH);
digitalWrite(SCI, LOW);
}
return inBits >> 2;
}

void writeFuse (unsigned int fuse, byte val) {
shiftOut(0x40, 0x4C);
shiftOut( val, 0x2C);
shiftOut(0x00, (byte) (fuse >> 8));
shiftOut(0x00, (byte) fuse);
}

void readFuses () {
byte val;
shiftOut(0x04, 0x4C); // LFuse
shiftOut(0x00, 0x68);
val = shiftOut(0x00, 0x6C);
Serial.print("LFuse: ");
Serial.print(val, HEX);
shiftOut(0x04, 0x4C); // HFuse
shiftOut(0x00, 0x7A);
val = shiftOut(0x00, 0x7E);
Serial.print(", HFuse: ");
Serial.print(val, HEX);
shiftOut(0x04, 0x4C); // EFuse
shiftOut(0x00, 0x6A);
val = shiftOut(0x00, 0x6E);
Serial.print(", EFuse: ");
Serial.println(val, HEX);
}

unsigned int readSignature () {
unsigned int sig = 0;
byte val;
for (int ii = 1; ii < 3; ii++) {
shiftOut(0x08, 0x4C);
shiftOut( ii, 0x0C);
shiftOut(0x00, 0x68);
val = shiftOut(0x00, 0x6C);
sig = (sig << 8) + val;
}
return sig;
}


Як бачите, нічого надприродного, відправили будь-який символ в Arduino через UART і вуаля, фьюз-біти відновлені до заводських, при цьому ми бачимо так само які були перед розблокуванням і які стали.

Так само рекомендую відвідати трохи інший проект товариша Wayne Holder:

ATTiny Fuse Reset with 12 Volt Charge Pump

Суть та ж, тільки не треба шукати джерело 12 Ст.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.