Added project
This commit is contained in:
parent
fe9aa14dfd
commit
2d73cc8845
186 changed files with 21174 additions and 0 deletions
248
lib/isp-repair/MegaIspRepair.cpp
Normal file
248
lib/isp-repair/MegaIspRepair.cpp
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Reflash a boot loader and a sketch an a second ATmega.
|
||||
* MegaIspRepair
|
||||
* 2014, Jan 21 <w.cazander@gmail.com> Rewrote to class and converted to boot pair with lcd.
|
||||
* IspRepair
|
||||
* 2010-05-29 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
|
||||
* BootCloner
|
||||
* adapted from http://www.arduino.cc/playground/BootCloner/BootCloner
|
||||
* original copyright notice: 2007 by Amplificar <mailto:amplificar@gmail.com>
|
||||
*/
|
||||
|
||||
#include <MegaIspRepair.h>
|
||||
#include <MegaIspRepairConfig.h>
|
||||
|
||||
bool fastSPI = false; // don't start in fast mode right away
|
||||
|
||||
// transfer a byte using software SPI, using a faster mode when possible
|
||||
byte MegaIspRepair::XferByte(byte v) {
|
||||
byte result = 0;
|
||||
if (fastSPI)
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
bitWrite(PORTC, 3, v & 0x80);
|
||||
v <<= 1;
|
||||
bitClear(PORTC, 0);
|
||||
result <<= 1;
|
||||
bitSet(PORTC, 0);
|
||||
result |= bitRead(PIND, 4);
|
||||
}
|
||||
else
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
digitalWrite(PIN_MOSI, v & 0x80);
|
||||
digitalWrite(PIN_SCK, 0); // slow pulse, max 60KHz
|
||||
digitalWrite(PIN_SCK, 1);
|
||||
v <<= 1;
|
||||
result = (result << 1) | digitalRead(PIN_MISO);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// send 4 bytes to target microcontroller, returns the fourth MISO byte
|
||||
byte MegaIspRepair::Send_ISP(word v01, byte v2, byte v3) {
|
||||
XferByte(v01 >> 8);
|
||||
XferByte(v01);
|
||||
XferByte(v2);
|
||||
return XferByte(v3);
|
||||
}
|
||||
|
||||
// send 4 bytes to target microcontroller and wait for completion
|
||||
void MegaIspRepair::Send_ISP_wait(word v01, byte v2, byte v3) {
|
||||
Send_ISP(v01, v2, v3);
|
||||
while (Send_ISP(CMD_Poll) & 1)
|
||||
;
|
||||
}
|
||||
|
||||
// reset the target microcontroller
|
||||
void MegaIspRepair::Reset_Target() {
|
||||
digitalWrite(RESET, 1);
|
||||
digitalWrite(PIN_SCK, 0); // has to be set LOW at startup, or PE fails
|
||||
delay(30);
|
||||
digitalWrite(RESET, 0);
|
||||
delay(30); // minimum delay here is 20ms for the ATmega8
|
||||
}
|
||||
|
||||
// print the 16 signature bytes (device codes)
|
||||
void MegaIspRepair::Read_Signature() {
|
||||
Serial.print("Signatures:");
|
||||
for (byte x = 0; x < 8; ++x) {
|
||||
Serial.print(" ");
|
||||
Serial.print(Send_ISP(CMD_Read_Signature, x), HEX);
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
// prints the lock and fuse bits (no leading zeros)
|
||||
byte MegaIspRepair::Read_Fuses(byte flo, byte fhi) {
|
||||
Serial.print("Lock Bits: ");
|
||||
Serial.println(Send_ISP(CMD_Read_Lock), HEX);
|
||||
Serial.print("Fuses: low ");
|
||||
Serial.print(Send_ISP(CMD_Read_Fuse_Low), HEX);
|
||||
Serial.print(", high ");
|
||||
Serial.print(Send_ISP(CMD_Read_Fuse_High), HEX);
|
||||
Serial.print(", extended ");
|
||||
Serial.println(Send_ISP(CMD_Read_Fuse_Extended), HEX);
|
||||
return Send_ISP(CMD_Read_Lock) == LOCK_BITS && Send_ISP(CMD_Read_Fuse_Low) == flo && Send_ISP(CMD_Read_Fuse_High) == fhi && Send_ISP(CMD_Read_Fuse_Extended) == FUSE_EXTENDED;
|
||||
}
|
||||
|
||||
word MegaIspRepair::addr2page(word addr) {
|
||||
return (word)(addr & ~(PAGE_BYTES - 1)) >> 1;
|
||||
}
|
||||
|
||||
void MegaIspRepair::LoadPage(word addr, const byte* ptr) {
|
||||
word cmd = addr & 1 ? CMD_Load_Page_High : CMD_Load_Page_Low;
|
||||
Send_ISP(cmd | (addr >> 9), addr >> 1, pgm_read_byte(ptr));
|
||||
}
|
||||
|
||||
void MegaIspRepair::WritePage(word page) {
|
||||
Send_ISP_wait(CMD_Write_Page | (page >> 8), page);
|
||||
}
|
||||
|
||||
void MegaIspRepair::WriteData(word start, const byte* data, word count) {
|
||||
word page = addr2page(start);
|
||||
for (word i = 0; i < count; i += 2) {
|
||||
if (page != addr2page(start)) {
|
||||
WritePage(page);
|
||||
Serial.print('.');
|
||||
page = addr2page(start);
|
||||
}
|
||||
LoadPage(start++, data + i);
|
||||
LoadPage(start++, data + i + 1);
|
||||
}
|
||||
WritePage(page);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
byte MegaIspRepair::EnableProgramming() {
|
||||
Reset_Target();
|
||||
if (Send_ISP(CMD_Program_Enable, 0x22, 0x22) != 0x22) {
|
||||
Serial.println("Program Enable FAILED");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MegaIspRepair::blink() {
|
||||
pinMode(DONE_LED, OUTPUT);
|
||||
digitalWrite(DONE_LED, 0); // inverted logic
|
||||
delay(100); // blink briefly
|
||||
pinMode(DONE_LED, INPUT);
|
||||
}
|
||||
|
||||
byte MegaIspRepair::readConfig() {
|
||||
static byte pins[] = { CONFIG1, CONFIG2, CONFIG3, CONFIG4 };
|
||||
byte switches = 0;
|
||||
for (byte i = 0; i < 4; ++i) {
|
||||
pinMode(pins[i], INPUT);
|
||||
digitalWrite(pins[i], 1); // enable pull-up
|
||||
bitWrite(switches, i, digitalRead(pins[i]));
|
||||
digitalWrite(pins[i], 0); // disable pull-up
|
||||
}
|
||||
return switches; // a 4-bit value, i.e. 0..15
|
||||
}
|
||||
|
||||
byte MegaIspRepair::programSection(byte index, mega_flash_data_struct sections[]) {
|
||||
Serial.print(index, DEC);
|
||||
byte f = EnableProgramming();
|
||||
if (f) {
|
||||
fastSPI = FAST_SPI && PIN_SCK == 14 && PIN_MISO == 4 && PIN_MOSI == 17;
|
||||
WriteData(sections[index].start, sections[index].progdata + sections[index].off, sections[index].count);
|
||||
fastSPI = false;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void MegaIspRepair::run(const char* typeTitle, mega_flash_data_struct sections[]) {
|
||||
Serial.begin(57600);
|
||||
Serial.println();
|
||||
Serial.println("# Booting mega_isp_repair");
|
||||
Serial.println("# Version=3.0");
|
||||
Serial.print("# Type=");
|
||||
Serial.print(typeTitle);
|
||||
Serial.println();
|
||||
blink();
|
||||
|
||||
digitalWrite(PIN_SCK, 1);
|
||||
digitalWrite(PIN_MOSI, 1);
|
||||
digitalWrite(RESET, 1);
|
||||
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(RESET, OUTPUT);
|
||||
|
||||
byte config = readConfig();
|
||||
byte xspeed = 0;
|
||||
|
||||
// Always burn a boot pair
|
||||
byte bootld = (config * 2) + 0;
|
||||
byte sketch = (config * 2) + 1;
|
||||
|
||||
Serial.print("Configuration: ");
|
||||
Serial.print(config, HEX);
|
||||
Serial.println(xspeed ? " (resonator)" : " (crystal)");
|
||||
Serial.println();
|
||||
Serial.println(sections[sketch].title);
|
||||
Serial.println(sections[bootld].title);
|
||||
Serial.println();
|
||||
|
||||
if (EnableProgramming()) {
|
||||
Serial.println("Erasing Flash");
|
||||
Send_ISP_wait(CMD_Erase_Flash, 0x22, 0x22);
|
||||
|
||||
if (EnableProgramming()) {
|
||||
byte fuseLo = xspeed ? FUSE_LOW_FAST : FUSE_LOW_XTAL;
|
||||
// derive the boot size from its starting address
|
||||
byte fuseHi = FUSE_HIGH_2048;
|
||||
switch (sections[bootld].start & 0x0FFF) {
|
||||
case 0x0E00:
|
||||
fuseHi = FUSE_HIGH_512;
|
||||
break;
|
||||
case 0x0C00:
|
||||
fuseHi = FUSE_HIGH_1024;
|
||||
break;
|
||||
case 0x0800:
|
||||
fuseHi = FUSE_HIGH_2048;
|
||||
break;
|
||||
case 0x0000:
|
||||
fuseHi = FUSE_HIGH_4096;
|
||||
break;
|
||||
}
|
||||
|
||||
// set the fuses and lock bits
|
||||
Serial.println("Setting Fuses");
|
||||
Send_ISP_wait(CMD_Write_Fuse_Low, 0, fuseLo);
|
||||
Send_ISP_wait(CMD_Write_Fuse_High, 0, fuseHi);
|
||||
Send_ISP_wait(CMD_Write_Fuse_Extended, 0, FUSE_EXTENDED);
|
||||
Send_ISP_wait(CMD_Write_Lock, 0, LOCK_BITS);
|
||||
|
||||
// burn the sketch and bootstrap code
|
||||
if (programSection(sketch, sections) && programSection(bootld, sections)) {
|
||||
Read_Signature();
|
||||
if (Read_Fuses(fuseLo, fuseHi)) {
|
||||
Serial.println("\nDone.");
|
||||
blink();
|
||||
} else
|
||||
Serial.println("Fuses NOT OK!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pinMode(PIN_SCK, INPUT);
|
||||
pinMode(PIN_MOSI, INPUT);
|
||||
pinMode(RESET, INPUT);
|
||||
|
||||
digitalWrite(PIN_SCK, 0);
|
||||
digitalWrite(PIN_MOSI, 0);
|
||||
digitalWrite(RESET, 0);
|
||||
|
||||
#if ARDUINO >= 100
|
||||
Serial.flush();
|
||||
#endif
|
||||
delay(10); // let the serial port finish
|
||||
cli(); // stop responding to interrupts
|
||||
ADCSRA &= ~bit(ADEN); // disable the ADC
|
||||
//PRR = 0xFF; // disable all subsystems
|
||||
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
|
||||
sleep_mode();
|
||||
// total power down, can only wake up with a hardware reset
|
||||
}
|
||||
|
||||
39
lib/isp-repair/MegaIspRepair.h
Normal file
39
lib/isp-repair/MegaIspRepair.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef IspRepair_h
|
||||
#define IspRepair_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
const char* title;
|
||||
const char* mdate;
|
||||
const unsigned char* progdata;
|
||||
unsigned start;
|
||||
unsigned off;
|
||||
unsigned count;
|
||||
} mega_flash_data_struct;
|
||||
|
||||
class MegaIspRepair {
|
||||
private:
|
||||
static byte XferByte(byte v);
|
||||
static byte Send_ISP(word v01, byte v2 = 0, byte v3 = 0);
|
||||
static void Send_ISP_wait(word v01, byte v2 = 0, byte v3 = 0);
|
||||
static void Reset_Target();
|
||||
static void Read_Signature();
|
||||
static byte Read_Fuses(byte flo, byte fhi);
|
||||
static word addr2page(word addr);
|
||||
static void LoadPage(word addr, const byte* ptr);
|
||||
static void WritePage(word page);
|
||||
static void WriteData(word start, const byte* data, word count);
|
||||
static byte EnableProgramming();
|
||||
static void blink();
|
||||
static byte readConfig();
|
||||
static byte programSection(byte index, mega_flash_data_struct sections[]);
|
||||
public:
|
||||
void run(const char* typeTitle, mega_flash_data_struct sections[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
49
lib/isp-repair/MegaIspRepairConfig.h
Normal file
49
lib/isp-repair/MegaIspRepairConfig.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#define FAST_SPI 1 // comment out to revert to digitalWrite() calls
|
||||
|
||||
// pin definitions
|
||||
#define PIN_SCK 14 // PC0 - AIO1 - serial clock to target avr
|
||||
#define PIN_MISO 4 // PD4 - DIO1 - input from target avr
|
||||
#define PIN_MOSI 17 // PC3 - AIO4 - output to target avr
|
||||
#define RESET 7 // PD7 - DIO4 - reset pin of the target avr
|
||||
#define DONE_LED 9 // B1 - blue LED on JN USB, blinks on start and when ok
|
||||
|
||||
// pins used for the optional config switches
|
||||
#define CONFIG1 5 // DIO2
|
||||
#define CONFIG2 15 // AIO2
|
||||
#define CONFIG3 16 // AIO3
|
||||
#define CONFIG4 6 // DIO3
|
||||
|
||||
// MPU-specific values
|
||||
#define PAGE_BYTES 128 // ATmega168 and ATmega328
|
||||
#define LOCK_BITS 0xCF
|
||||
#define FUSE_LOW_XTAL 0xFF
|
||||
#define FUSE_LOW_FAST 0xDE
|
||||
#define FUSE_HIGH_512 0xDE
|
||||
#define FUSE_HIGH_1024 0xDC
|
||||
#define FUSE_HIGH_2048 0xDA
|
||||
#define FUSE_HIGH_4096 0xD8 // not in ATmega168
|
||||
#define FUSE_EXTENDED 0xFD
|
||||
|
||||
// ISP Command Words
|
||||
#define CMD_Program_Enable 0xAC53
|
||||
#define CMD_Erase_Flash 0xAC80
|
||||
#define CMD_Poll 0xF000
|
||||
#define CMD_Read_Flash_Low 0x2000
|
||||
#define CMD_Read_Flash_High 0x2800
|
||||
#define CMD_Load_Page_Low 0x4000
|
||||
#define CMD_Load_Page_High 0x4800
|
||||
#define CMD_Write_Page 0x4C00
|
||||
#define CMD_Read_EEPROM 0xA000
|
||||
#define CMD_Write_EEPROM 0xC000
|
||||
#define CMD_Read_Lock 0x5800
|
||||
#define CMD_Write_Lock 0xACE0
|
||||
#define CMD_Read_Signature 0x3000
|
||||
#define CMD_Write_Fuse_Low 0xACA0
|
||||
#define CMD_Write_Fuse_High 0xACA8
|
||||
#define CMD_Write_Fuse_Extended 0xACA4
|
||||
#define CMD_Read_Fuse_Low 0x5000
|
||||
#define CMD_Read_Fuse_High 0x5808
|
||||
#define CMD_Read_Fuse_Extended 0x5008
|
||||
#define CMD_Read_Fuse_High 0x5808
|
||||
#define CMD_Read_Calibration 0x3800
|
||||
|
||||
44
lib/isp-repair/readme.txt
Normal file
44
lib/isp-repair/readme.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
// This code is adapted from isp_prepare. It omits the button and run LED,
|
||||
// and starts right away. To use, open a serial console and wait until done.
|
||||
//
|
||||
// The 6 ISP pins of the target board need to be connected to the board running
|
||||
// this sketch as follows (using Arduino pin naming):
|
||||
//
|
||||
// ISP pin 1 <-> digital 4 (MISO) ISP CONNECTOR
|
||||
// ISP pin 2 <-> VCC +---+---+
|
||||
// ISP pin 3 <-> analog 0 (SCK) | 1 | 2 |
|
||||
// ISP pin 4 <-> analog 3 (MOSI) | 3 | 4 |
|
||||
// ISP pin 5 <-> digital 7 (RESET) | 5 | 6 |
|
||||
// ISP pin 6 <-> ground +---+---+
|
||||
//
|
||||
// The same hookup, using JeeNode port/pin names:
|
||||
//
|
||||
// ISP pin 1 <-> DIO1
|
||||
// ISP pin 2 <-> +3V
|
||||
// ISP pin 3 <-> AIO1
|
||||
// ISP pin 4 <-> AIO4
|
||||
// ISP pin 5 <-> DIO4
|
||||
// ISP pin 6 <-> GND
|
||||
//
|
||||
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
/* Include code using a file generated in isp_prepare/ dir with this cmd:
|
||||
|
||||
./hex2c.tcl Blink.cpp.hex \
|
||||
RF12demo.cpp.hex \
|
||||
optiboot_atmega328.hex \
|
||||
ATmegaBOOT_168_atmega328.hex \
|
||||
optiboot_atmega328_1s.hex \
|
||||
optiboot_atmega328.hex >../isp_repair2/data.h
|
||||
|
||||
Code choices are fixed: section 0 is RF12demo, section 1 is blink
|
||||
Boot choices are entries 2..5 in the sections[] array in data.h
|
||||
*/
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue