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

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

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

[embedded content]

В этом видео я расскажу, и покажу, как можно разблокировать микроконтроллеры из серии ATtiny у которых не правильно выставленные фьюз-биты.

Данный метод годиться не для всех ATtiny, но подходит для большинства популярных, вот их список:

ATtiny13; ATtiny24; ATtiny25; ATtiny44; ATtiny45; ATtiny84; ATtiny85. На видео я показал как можно восстановить заводские фьюз-биты при помощи Arduino, по сути информация представлена ниже дублируется в видеоформате.Скажу сразу, за основу взят проект товарища 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 [embedded content]

Подключаем к другим микроконтроллерам наш «восстановитель фьюз-битовов» следующим образом: 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 — разумеется общий провод или другими словами «земля». Всё это переназначается в коде, никаких проблем.

Вот код из странички автора // 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 0×747C #define LFUSE 0×646C #define EFUSE 0×666E

// Define ATTiny series signatures #define ATTINY13 0×9007 // L: 0×6A, H: 0xFF 8 pin #define ATTINY24 0×910B // L: 0×62, H: 0xDF, E: 0xFF 14 pin #define ATTINY25 0×9108 // L: 0×62, H: 0xDF, E: 0xFF 8 pin #define ATTINY44 0×9207 // L: 0×62, H: 0xDF, E: 0xFFF 14 pin #define ATTINY45 0×9206 // L: 0×62, H: 0xDF, E: 0xFF 8 pin #define ATTINY84 0×930C // L: 0×62, H: 0xDF, E: 0xFFF 14 pin #define ATTINY85 0×930B // L: 0×62, 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, 0×6A); writeFuse (HFUSE, 0xFF); } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 || sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) { writeFuse (LFUSE, 0×62); 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 (0×40, 0×4C); shiftOut (val, 0×2C); shiftOut (0×00, (byte) (fuse >> 8)); shiftOut (0×00, (byte) fuse); }

void readFuses () { byte val; shiftOut (0×04, 0×4C); // LFuse shiftOut (0×00, 0×68); val = shiftOut (0×00, 0×6C); Serial.print («LFuse:»); Serial.print (val, HEX); shiftOut (0×04, 0×4C); // HFuse shiftOut (0×00, 0×7A); val = shiftOut (0×00, 0×7E); Serial.print (», HFuse:»); Serial.print (val, HEX); shiftOut (0×04, 0×4C); // EFuse shiftOut (0×00, 0×6A); val = shiftOut (0×00, 0×6E); 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 В.

P.S. Serial.begin (19200);

© Habrahabr.ru