1. Залоченный ATMega8 RSTDISBL: решение старой проблемы

  2. ATMega8

Иногда случается по невнимательности во время программирования Mega8 случайно записать фюзы с выставленным в 1 битом RSTDISBL. В результате такой оплошности ножка RESET переключается в режим обычного порта ввода-вывода и микроконтроллер больше не хочет программироваться "последовательными" программаторами.

Решение проблемы очень простое: надо просто вернуть бит RSTDISBL в исходное состояние. Но, к сожалению, сделать это можно только с помощью "параллельного" программатора.

Если под рукой есть еще один рабочий микроконтроллер (в моём случае это был Mega32), макетная плата и немного проводков, то за 20 минут процессор можно вернуть к жизни.

Ниже приведена принципиальная схема, на которой показано соединение рабочей Mega32 и впавшей в кому Mega8.

Схема соединений ATMega32 и ATMega8 с залоченным RSTDISBL

Схема соединений ATMega32 и ATMega8 с залоченным RSTDISBL

Принципиальная схема в формате Splan7

Привожу исходный код лечащей программы. Как можно заметить, программа написана на простом С. Я компилировал это в IAR Embedded Workbench for Atmel. Поскольку код очень простой, не составит поправить заголовки под любую другую среду разработки. Так-же несложно переписать код для работы с другим процессором, например Mega8.

Следует иметь ввиду, что перед тем, как записать "правильные" фюзы в микроконтроллер происходит предварительное выполнение команды "Chip erase". В результате этого всё содержимое памяти программ микроконтроллера стирается. Делается это затем, что микросхема может оказаться не только со сброшенным битом RSTDISBL, но и с выставленной защитой от записи-считывания. Поэтому лучше сначала подстраховаться при помощи команды "Chip erase", сбросив биты защиты.

В схеме стоит кварцевый резонатор на 11,0592 MHz. Вместо него можно использовать любой другой, имеющийся под рукой или использовать тактование от внутреннего генератора. Надо только не забыть соответственно поправить заголовочный файл main.h так, чтоб задержкт рассчитывались с учётом изменившейся тактовой частоты.

Для этого надо в строке
#define     F_CPU     11059200UL
переопределить F_CPU, подставив своё значение частоты в герцах.



#include "pin_macros.h"

#include <iom32.h>
#include <pgmspace.h>
#include <stdlib.h>
#include <pgmspace.h>
#include <inavr.h>

#include "main.h"

#define   nOE    0 // B0
#define   nWR    1 // B1
#define   BS1    2 // B2
#define   XA0    3 // B3
#define   XA1    4 // B4

#define   RDY    0 // C0
#define   XTAL1  1 // C1
#define   BS2    2 // C2
#define   PAGEL  3 // C3
#define   nPROG  4 // C4

#define   nLED   5 // C5

void XtalPulse(void);

//---------------------------------------------------------------------------
int main() {

	DDRA = 0xFF; // Data port is Output
	DDRB = (1<<XA1) | (1<<XA0) | (1<<BS1) | (1<<nWR) | (1<<nOE);
	DDRC = (1<<nLED) | (1<<nPROG) | (1<<PAGEL) | (1<<BS2) | (1<<XTAL1);

	
	PORTA = 0x00;
	PORTB = (1<<nWR);
	PORTC = 0x01;


    SetBit(PORTC, nLED);

    _delay_us(100);

		
		
    //=====  Stage 1  - Chip Erase  =====

    ClearBit(PORTB, XA0);						// Set XA1, XA0 to “10”. This enables command loading
    SetBit(PORTB, XA1);
		
    ClearBit(PORTB, BS1);						// Set BS1 to “0”
    ClearBit(PORTC, BS2);

    PORTA = 0x80;								// Load "Chip Erase" command

    XtalPulse();								// Give XTAL1 a positive pulse. This loads the command

    _delay_us(10);
		
    ClearBit(PORTB, nWR);						// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low
    _delay_us(10);
    SetBit(PORTB, nWR);

    do {
      _delay_us(10);
    } while( !(PINC & (1<<RDY)) );	// Wait until RDY/BSY goes high

		
		
		
    //======  Stage 2  - Write FUSE Low Byte   ======

	ClearBit(PORTB, XA0);						// Set XA1, XA0 to “10”. This enables command loading
    SetBit(PORTB, XA1);
		
    ClearBit(PORTB, BS1);						// Set BS1 to “0”
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    PORTA = 0x40;								// Load "Write FUSE" command

    XtalPulse();								// Give XTAL1 a positive pulse. This loads the command

    SetBit(PORTB, XA0);							// Set XA1, XA0 to “01”. This enables data loading
    ClearBit(PORTB, XA1);						// (High or Low data byte for Flash determined by BS1)

    ClearBit(PORTB, BS1);						// Set BS1 to “0” - Low byte
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    PORTA = 0xE1;								// 0b11100001 BODLEVEL BODEN SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0

    XtalPulse();

    ClearBit(PORTB, BS1);						// Set BS1 to “0” - Low byte
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    ClearBit(PORTB, nWR);						// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low
    _delay_us(10);
    SetBit(PORTB, nWR);

    do {
      _delay_us(10);
    } while( !(PINC & (1<<RDY)) );	// Wait until RDY/BSY goes high

		
		
	//=====  Stage 3  - Write FUSE High Byte   ======
		
    ClearBit(PORTB, XA0);						// Set XA1, XA0 to “10”. This enables command loading
    SetBit(PORTB, XA1);

    ClearBit(PORTB, BS1);						// Set BS1 to “0” - Low byte
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    PORTA = 0x40;								// Load "Write FUSE" command

    XtalPulse();								// Give XTAL1 a positive pulse. This loads the command

    SetBit(PORTB, XA0);							// Set XA1, XA0 to “01”. This enables data loading
    ClearBit(PORTB, XA1);						// (High or Low data byte for Flash determined by BS1)

    ClearBit(PORTB, BS1);						// Set BS1 to “0” - Low byte
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    PORTA = 0xD9;								// 0b11011001 ;(RSTDISBL WDTON SPIEN CKOPT EESAVE BOOTSZ1 BOOTSZ0 BOOTRST)

    XtalPulse();

    SetBit(PORTB, BS1);							// Set BS1 to “1” - High byte
    ClearBit(PORTC, BS2);						// Set BS2 to “0”

    ClearBit(PORTB, nWR);						// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low
    _delay_us(10);
    SetBit(PORTB, nWR);

    do {
      _delay_us(10);
    } while( !(PINC & (1<<RDY)) );	// Wait until RDY/BSY goes high

    ClearBit(PORTC, nLED);
		
	for(;;);

}

void XtalPulse(void) {
    _delay_us(10);
    SetBit(PORTC, XTAL1);
    _delay_us(10);
    ClearBit(PORTC, XTAL1);
    _delay_us(10);
}

	

#ifndef MAIN_H
#define MAIN_H

#define   F_CPU 11059200UL

#define   _delay_us(temp)(__delay_cycles((temp * F_CPU)/1000000UL));

#define ClearBit(reg, bit) reg &= ~(1<<(bit))
#define SetBit(reg, bit) reg |= (1<<(bit))
#define FlipBit(reg, bit) reg ^= (1<<(bit))

#endif
	

Прошивка

Версия 1.0.0 (26.09.2021)

Прошивка для процессора Mega32 с внешним кварцем на 4MHz. Версия 1.0: (доступно зарегистрированным пользователям)

ОБСУЖДЕНИЯ

Аватар пользователя MAGAЭ

как посмотреть принципиальные схемы

Мага

Аватар пользователя Leog - Linker.Ru

Принципиальная схема приведена в статье. Ничего другого нет.

Аватар пользователя MAGAЭ

здравствуйте вы не можете прислать прошивку?в статье я не нашол спасибо зарание.

Мага

Аватар пользователя Leog - Linker.Ru

К сожалению, файла с прошивкой не осталось. Есть только исходный код, котороый в статье. Я попробую сделать прошивку, но не обещаю. Если получится - выложу в на выходных.

Аватар пользователя MAGAЭ

спасибо буду очень рад.

Мага

Аватар пользователя Leog - Linker.Ru

Возьмите прошивку в конце статьи

Аватар пользователя MAGAЭ

Спасибо большое вам эта прошивка на мега 8 не подойтет?

Мага

Аватар пользователя Leog - Linker.Ru

Не пойдет, там нет порта A, который используется

Аватар пользователя MAGAЭ

спасибо буду искать мегу 32 или же схему на атмега 8.

Мага