Skip to content

Instantly share code, notes, and snippets.

@thetrung
Created September 14, 2024 13:55
Show Gist options
  • Save thetrung/4290ab68e016b1eaf65aa265473d50c1 to your computer and use it in GitHub Desktop.
Save thetrung/4290ab68e016b1eaf65aa265473d50c1 to your computer and use it in GitHub Desktop.
ATMega8_Rescue_ATMega32A
#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