Created
September 14, 2024 13:55
-
-
Save thetrung/4290ab68e016b1eaf65aa265473d50c1 to your computer and use it in GitHub Desktop.
ATMega8_Rescue_ATMega32A
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/io.h> | |
#include <util/delay.h> | |
#define HFUSE 0xDF // Default for ATmega48/88/168, for others see | |
#define LFUSE 0x62 // http://www.engbedded.com/cgi-bin/fc.cgi | |
/* | |
#define DATA PORTD // PORTD = Arduino Digital pins 0-7 | |
#define DATAD DDRD // Data direction register for DATA port | |
#define VCC 8 PB0 | |
#define RDY 12 PB4 // RDY/!BSY signal from target | |
#define OE 11 PB3 | |
#define WR 10 PB2 | |
#define BS1 9 PB1 | |
#define XA0 13 PB5 | |
#define XA1 18 PC4 // Analog inputs 0-5 can be addressed as | |
#define PAGEL 19 PC5 // digital outputs 14-19 | |
#define RST 14 PC0 // Output to level shifter for !RESET | |
#define BS2 16 PC2 | |
#define XTAL1 17 PC3 | |
#define BUTTON 15 PC1 // Run button | |
#define LED 0 | |
*/ | |
// PORTB | |
#define _XA0 (1<<5) // PB5-SCK | |
#define _RDY (1<<4) // PB4-MISO | |
#define _OE (1<<3) // PB3-MOSI | |
#define _WR (1<<2) // PB2-SS | |
#define _BS1 (1<<1) // PB1-OC1A | |
#define _VCC (1<<0) // PB0-PCINT0 | |
// PORTC | |
#define _XA1 (1<<4) // PC4-SDA | |
#define _PAGEL (1<<5) // PC5-SCL | |
#define _RST (1<<0) // PC0-ADC0 | |
#define _BS2 (1<<2) // PC2-ADC2 | |
#define _XTAL1 (1<<3) // PC3-ADC3 | |
#define _BUTTON (1<<1) // PC1-ADC1 | |
void HardwareInit() | |
{ | |
// PB4-MISO | |
DDRB = ~(_RDY); // all outputs except RDY (PB4) | |
PORTB = 0x00; // no pull-up | |
// PC1-ADC1 & PC0-ADC0 | |
DDRC = ~(_BUTTON); // all outputs except BUTTON (PC1) | |
PORTC = (_BUTTON)|(_RST); // pull-up and 12V off (PC0 = 1) | |
DDRD = 0xff; // all outputs | |
PORTD = 0x00; | |
} | |
void sendcmd(unsigned char command) | |
{ | |
// PC4-SDA | |
PORTC |= _XA1; | |
// PB5-SCK & PB1-OC1A | |
PORTB &= ~(_XA0|_BS1); | |
// PCINT [16..23] | |
PORTD = command; | |
// PC3-ADC3 : crystal pulse 1000-Hz | |
PORTC |= _XTAL1; | |
_delay_ms(1); | |
PORTC &= ~(_XTAL1); | |
_delay_ms(1); | |
} | |
void writefuse(unsigned char fuse, char highbyte) | |
{ | |
// PB5-SCK & PC4-SDA | |
PORTC &= ~(_XA1); | |
PORTB |= _XA0; | |
_delay_ms(1); | |
// Send fuse via 8-bit PORT-D [0..7] | |
PORTD = fuse; | |
// pulse 1000-Hz : | |
PORTC |= _XTAL1; | |
_delay_ms(1); | |
PORTC &= ~(_XTAL1); | |
// HFUSE | LFUSE -> PB1-OC1A: | |
if (highbyte) | |
PORTB |= _BS1; | |
else | |
PORTB &= ~(_BS1); | |
// PB2-SS/OC1B : | |
PORTB &= ~(_WR); | |
_delay_ms(1); | |
// PB2-SS/OC1B : | |
PORTB |= _WR; | |
_delay_ms(100); | |
} | |
int main() | |
{ | |
HardwareInit(); | |
for (;;) | |
{ | |
while (PINC & _BUTTON) {} // wait for button | |
// Initialize pins to enter programming mode | |
PORTC &= ~(_PAGEL|_XA1|_BS2); | |
PORTB &= ~(_XA0|_BS1); | |
// Enter programming mode | |
PORTB |= _VCC|_WR|_OE; | |
_delay_ms(1); | |
PORTC &= ~(_RST); | |
_delay_ms(1); | |
// Program HFUSE | |
sendcmd(0b01000000); | |
writefuse(HFUSE, 1); | |
// Program LFUSE | |
sendcmd(0b01000000); | |
writefuse(LFUSE, 0); | |
_delay_ms(1000); // allow button to be released | |
// Exit programming mode | |
PORTC |= _RST; | |
// Turn off outputs | |
PORTD = 0x00; | |
PORTB &= ~(_VCC|_WR|_OE|_XA0|_BS1); | |
PORTC &= ~(_PAGEL|_XA1|_BS2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment