forked from adafruit/Standalone-Arduino-AVR-ISP-programmer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
adaLoader.pde
216 lines (174 loc) · 5.17 KB
/
adaLoader.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Standalone AVR ISP programmer
// August 2011 by Limor Fried / Ladyada / Adafruit
// Jan 2011 by Bill Westfield ("WestfW")
//
// this sketch allows an Arduino to program a flash program
// into any AVR if you can fit the HEX file into program memory
// No computer is necessary. Two LEDs for status notification
// Press button to program a new chip. Piezo beeper for error/success
// This is ideal for very fast mass-programming of chips!
//
// It is based on AVRISP
//
// using the following pins:
// 10: slave reset
// 11: MOSI
// 12: MISO
// 13: SCK
// 9: 8 MHz clock output - connect this to the XTAL1 pin of the AVR
// if you want to program a chip that requires a crystal without
// soldering a crystal in
// ----------------------------------------------------------------------
#include "optiLoader.h"
#include "SPI.h"
// Global Variables
int pmode=0;
byte pageBuffer[128]; /* One page of flash */
/*
* Pins to target
*/
#define SCK 13
#define MISO 12
#define MOSI 11
#define RESET 10
#define CLOCK 9 // self-generate 8mhz clock - handy!
#define BUTTON A1
#define PIEZOPIN A3
void setup () {
Serial.begin(57600); /* Initialize serial for status msgs */
Serial.println("\nAdaBootLoader Bootstrap programmer (originally OptiLoader Bill Westfield (WestfW))");
pinMode(PIEZOPIN, OUTPUT);
pinMode(LED_PROGMODE, OUTPUT);
pulse(LED_PROGMODE,2);
pinMode(LED_ERR, OUTPUT);
pulse(LED_ERR, 2);
pinMode(BUTTON, INPUT); // button for next programming
digitalWrite(BUTTON, HIGH); // pullup
pinMode(CLOCK, OUTPUT);
// setup high freq PWM on pin 9 (timer 1)
// 50% duty cycle -> 8 MHz
OCR1A = 0;
ICR1 = 1;
// OC1A output, fast PWM
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // no clock prescale
}
void loop (void) {
Serial.println("\nType 'G' or hit BUTTON for next chip");
while (1) {
if ((! digitalRead(BUTTON)) || (Serial.read() == 'G'))
break;
}
target_poweron(); /* Turn on target power */
uint16_t signature;
image_t *targetimage;
if (! (signature = readSignature())) // Figure out what kind of CPU
error("Signature fail");
if (! (targetimage = findImage(signature))) // look for an image
error("Image fail");
eraseChip();
if (! programFuses(targetimage->image_progfuses)) // get fuses ready to program
error("Programming Fuses fail");
if (! verifyFuses(targetimage->image_progfuses, targetimage->fusemask) ) {
error("Failed to verify fuses");
}
end_pmode();
start_pmode();
byte *hextext = targetimage->image_hexcode;
uint16_t pageaddr = 0;
uint8_t pagesize = pgm_read_byte(&targetimage->image_pagesize);
uint16_t chipsize = pgm_read_word(&targetimage->chipsize);
//Serial.println(chipsize, DEC);
while (pageaddr < chipsize) {
byte *hextextpos = readImagePage (hextext, pageaddr, pagesize, pageBuffer);
boolean blankpage = true;
for (uint8_t i=0; i<pagesize; i++) {
if (pageBuffer[i] != 0xFF) blankpage = false;
}
if (! blankpage) {
if (! flashPage(pageBuffer, pageaddr, pagesize))
error("Flash programming failed");
}
hextext = hextextpos;
pageaddr += pagesize;
}
// Set fuses to 'final' state
if (! programFuses(targetimage->image_normfuses))
error("Programming Fuses fail");
end_pmode();
start_pmode();
Serial.println("\nVerifing flash...");
if (! verifyImage(targetimage->image_hexcode) ) {
error("Failed to verify chip");
} else {
Serial.println("\tFlash verified correctly!");
}
if (! verifyFuses(targetimage->image_normfuses, targetimage->fusemask) ) {
error("Failed to verify fuses");
} else {
Serial.println("Fuses verified correctly!");
}
target_poweroff(); /* turn power off */
tone(PIEZOPIN, 4000, 200);
}
void error(char *string) {
Serial.println(string);
digitalWrite(LED_ERR, HIGH);
while(1) {
tone(PIEZOPIN, 4000, 500);
}
}
void start_pmode () {
pinMode(13, INPUT); // restore to default
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV128);
debug("...spi_init done");
// following delays may not work on all targets...
pinMode(RESET, OUTPUT);
digitalWrite(RESET, HIGH);
pinMode(SCK, OUTPUT);
digitalWrite(SCK, LOW);
delay(50);
digitalWrite(RESET, LOW);
delay(50);
pinMode(MISO, INPUT);
pinMode(MOSI, OUTPUT);
debug("...spi_transaction");
spi_transaction(0xAC, 0x53, 0x00, 0x00);
debug("...Done");
pmode = 1;
}
void end_pmode () {
SPCR = 0; /* reset SPI */
digitalWrite(MISO, 0); /* Make sure pullups are off too */
pinMode(MISO, INPUT);
digitalWrite(MOSI, 0);
pinMode(MOSI, INPUT);
digitalWrite(SCK, 0);
pinMode(SCK, INPUT);
digitalWrite(RESET, 0);
pinMode(RESET, INPUT);
pmode = 0;
}
/*
* target_poweron
* begin programming
*/
boolean target_poweron ()
{
pinMode(LED_PROGMODE, OUTPUT);
digitalWrite(LED_PROGMODE, HIGH);
digitalWrite(RESET, LOW); // reset it right away.
pinMode(RESET, OUTPUT);
delay(100);
Serial.print("Starting Program Mode");
start_pmode();
Serial.println(" [OK]");
return true;
}
boolean target_poweroff ()
{
end_pmode();
digitalWrite(LED_PROGMODE, LOW);
return true;
}