Statistics
| Revision:

root / Ports / examples / isp_flash / isp_flash.pde

History | View | Annotate | Download (9.1 KB)

1
//>>> The latest version of this code can be found at https://github.com/jcw/ !!
2
3
// Derived from http://arduino.cc/en/Tutorial/ArduinoISP - 2010-04-17, jcw
4
// $Id: isp_flash.pde 7763 2011-12-11 01:28:16Z jcw $
5
6
// see http://news.jeelabs.org/2010/04/24/isp-plug/
7
// and http://jeelabs.org/2011/05/29/summary-of-isp-options/
8
9
// pin definitions
10
#define PIN_SCK     14
11
#define PIN_MISO    4
12
#define PIN_MOSI    17
13
#define PIN_RESET   7
14
#define LED_PMODE   15  // on while programming (LED to VCC via resistor)
15
16
// original comments:
17
//
18
// October 2009 by David A. Mellis
19
// - Added support for the read signature command
20
// 
21
// February 2009 by Randall Bohn
22
// - Added support for writing to EEPROM (what took so long?)
23
// Windows users should consider WinAVR's avrdude instead of the
24
// avrdude included with Arduino software.
25
//
26
// January 2008 by Randall Bohn
27
// - Thanks to Amplificar for helping me with the STK500 protocol
28
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
29
// - The SPI functions herein were developed for the AVR910_ARD programmer 
30
// - More information at http://code.google.com/p/mega-isp
31
32
#define HWVER 2
33
#define SWMAJ 1
34
#define SWMIN 18
35
36
// STK Definitions
37
#define STK_OK      '\x10'
38
#define STK_FAILED  '\x11'
39
#define STK_UNKNOWN '\x12'
40
#define STK_INSYNC  '\x14'
41
#define STK_NOSYNC  '\x15'
42
#define CRC_EOP     '\x20' //ok it is a space...
43
44
int here;           // address for reading and writing, set by 'U' command
45
byte data[256];     // global block storage
46
47
struct {
48
    byte devicecode;
49
    byte revision;
50
    byte progtype;
51
    byte parmode;
52
    byte polling;
53
    byte selftimed;
54
    byte lockbytes;
55
    byte fusebytes;
56
    int flashpoll;
57
    int eeprompoll;
58
    int pagesize;
59
    // not used in this code:
60
    // int eepromsize;
61
    // long flashsize;
62
} param;
63
64
static byte getch() {
65
    while (!Serial.available())
66
        ;
67
    return Serial.read();
68
}
69
70
static void putch(char c) {
71
    Serial.print(c);
72
}
73
74
static void readbytes(int n) {
75
    for (byte x = 0; x < n; x++)
76
        data[x] = getch();
77
}
78
79
static void spi_init() {
80
    digitalWrite(PIN_SCK, 1);
81
    digitalWrite(PIN_MISO, 1);
82
    digitalWrite(PIN_MOSI, 1);
83
    digitalWrite(PIN_RESET, 1);
84
85
    pinMode(PIN_SCK, OUTPUT);
86
    pinMode(PIN_MISO, INPUT);
87
    pinMode(PIN_MOSI, OUTPUT);
88
    pinMode(PIN_RESET, OUTPUT);
89
}
90
91
static byte spi_send(byte b) {
92
    byte reply = 0;
93
    for (byte i = 0; i < 8; ++i) {
94
        digitalWrite(PIN_MOSI, b & 0x80);
95
        digitalWrite(PIN_SCK, 0); // slow pulse, max 60KHz
96
        digitalWrite(PIN_SCK, 1);
97
        b <<= 1;
98
        reply = (reply << 1) | digitalRead(PIN_MISO);
99
    }
100
    return reply;
101
}
102
103
static byte spi_transaction(byte a, byte b, byte c, byte d) {
104
    spi_send(a); 
105
    spi_send(b);
106
    spi_send(c);
107
    return spi_send(d);
108
}
109
110
static byte spi_transaction_wait(byte a, byte b, byte c, byte d) {
111
    byte reply = spi_transaction(a, b, c, d);
112
    while (spi_transaction(0xF0, 0, 0, 0) & 1)
113
        ;
114
    return reply;
115
}
116
117
static void empty_reply() {
118
    if (getch() == CRC_EOP) {
119
        putch(STK_INSYNC);
120
        putch(STK_OK);
121
    } else
122
        putch(STK_NOSYNC);
123
}
124
125
static void breply(byte b) {
126
    if (getch() == CRC_EOP) {
127
        putch(STK_INSYNC);
128
        putch(b);
129
        putch(STK_OK);
130
    } else
131
        putch(STK_NOSYNC);
132
}
133
134
static void get_version(byte c) {
135
    switch(c) {
136
        case 0x80:  breply(HWVER); break;
137
        case 0x81:  breply(SWMAJ); break;
138
        case 0x82:  breply(SWMIN); break;
139
        case 0x93:  breply('S'); break;
140
        default:    breply(0);
141
    }
142
}
143
144
static void set_parameters() {
145
    // call this after reading paramter packet into data[]
146
    memcpy(&param, data, 9);
147
    // following fields are big endian
148
    param.eeprompoll = data[10] * 0x0100 + data[11];
149
    param.pagesize = data[12] * 0x0100 + data[13];
150
    // not used in this code:
151
    // param.eepromsize = data[14] * 0x0100 + data[15];
152
    // param.flashsize = data[16] * 0x01000000L + data[17] * 0x00010000L +
153
    //                     data[18] * 0x00000100 + data[19];
154
}
155
156
static void start_pmode() {
157
    spi_init();
158
    // following delays may not work on all targets...
159
    pinMode(PIN_RESET, OUTPUT);
160
    digitalWrite(PIN_RESET, HIGH);
161
    pinMode(PIN_SCK, OUTPUT);
162
    digitalWrite(PIN_SCK, LOW);
163
    delay(50);
164
    digitalWrite(PIN_RESET, LOW);
165
    delay(50);
166
    pinMode(PIN_MISO, INPUT);
167
    pinMode(PIN_MOSI, OUTPUT);
168
    spi_transaction_wait(0xAC, 0x53, 0x00, 0x00);
169
    digitalWrite(LED_PMODE, 0); 
170
}
171
172
static void end_pmode() {
173
    pinMode(PIN_MISO, INPUT);
174
    pinMode(PIN_MOSI, INPUT);
175
    pinMode(PIN_SCK, INPUT);
176
    pinMode(PIN_RESET, INPUT);
177
    digitalWrite(LED_PMODE, 1); 
178
}
179
180
static void universal() {
181
    readbytes(4);
182
    breply(spi_transaction_wait(data[0], data[1], data[2], data[3]));
183
}
184
185
static void flash(byte hilo, int addr, byte value) {
186
    spi_transaction_wait(0x40+8*hilo, addr >> 8, addr, value);
187
}
188
189
static void commit(int addr) {
190
    spi_transaction_wait(0x4C, addr >> 8, addr, 0);
191
}
192
193
static int current_page(int addr) {
194
    return here & ~(param.pagesize/2-1);
195
}
196
197
static byte write_flash(int length) {
198
    if (param.pagesize < 1) return STK_FAILED;
199
    int page = current_page(here);
200
    int x = 0;
201
    while (x < length) {
202
        if (page != current_page(here)) {
203
            commit(page);
204
            page = current_page(here);
205
        }
206
        flash(LOW, here, data[x++]);
207
        flash(HIGH, here, data[x++]);
208
        here++;
209
    }
210
    commit(page);
211
    return STK_OK;
212
}
213
214
static byte write_eeprom(int length) {
215
    // this writes byte-by-byte, page writing may be faster (4 bytes at a time)
216
    for (int x = 0; x < length; x++)
217
        spi_transaction_wait(0xC0, 0x00, here*2+x, data[x]);
218
    return STK_OK;
219
}
220
221
static void program_page() {
222
    char result = STK_FAILED;
223
    int length = 256 * getch();
224
    length += getch();
225
    if (length > 256) {
226
        putch(STK_FAILED);
227
        return;
228
    }
229
    char memtype = getch();
230
    readbytes(length);
231
    if (getch() == CRC_EOP) {
232
        putch(STK_INSYNC);
233
        if (memtype == 'F') result = write_flash(length);
234
        if (memtype == 'E') result = write_eeprom(length);
235
        putch(result);
236
    } else
237
        putch(STK_NOSYNC);
238
}
239
240
static byte flash_read(byte hilo, int addr) {
241
    return spi_transaction(0x20 + hilo * 8, addr >> 8, addr, 0);
242
}
243
244
static char flash_read_page(int length) {
245
    for (int x = 0; x < length; x+=2) {
246
        putch(flash_read(LOW, here));
247
        putch(flash_read(HIGH, here));
248
        here++;
249
    }
250
    return STK_OK;
251
}
252
253
static char eeprom_read_page(int length) {
254
    for (int x = 0; x < length; x++)
255
        putch(spi_transaction(0xA0, 0x00, here*2+x, 0xFF));
256
    return STK_OK;
257
}
258
259
static void read_page() {
260
    int length = 256 * getch();
261
    length += getch();
262
    char memtype = getch();
263
    if (getch() == CRC_EOP) {
264
        putch(STK_INSYNC);
265
        char result = STK_FAILED;
266
        if (memtype == 'F') result = flash_read_page(length);
267
        if (memtype == 'E') result = eeprom_read_page(length);
268
        putch(result);
269
    } else
270
        putch(STK_NOSYNC);
271
}
272
273
static void read_signature() {
274
    if (getch() == CRC_EOP) {
275
        putch(STK_INSYNC);
276
        putch(spi_transaction(0x30, 0x00, 0x00, 0x00));
277
        putch(spi_transaction(0x30, 0x00, 0x01, 0x00));
278
        putch(spi_transaction(0x30, 0x00, 0x02, 0x00));
279
        putch(STK_OK);
280
    } else
281
        putch(STK_NOSYNC);
282
}
283
284
static int avrisp() { 
285
    switch (getch()) {
286
        case '0': // signon
287
            empty_reply();
288
            break;
289
        case '1':
290
            if (getch() == CRC_EOP) {
291
                putch(STK_INSYNC);
292
                for (const char* p = "AVR ISP"; *p != 0; ++p)
293
                    putch(*p);
294
                putch(STK_OK);
295
            }
296
            break;
297
        case 'A':
298
            get_version(getch());
299
            break;
300
        case 'B':
301
            readbytes(20);
302
            set_parameters();
303
            empty_reply();
304
            break;
305
        case 'E': // extended parameters - ignore for now
306
            readbytes(5);
307
            empty_reply();
308
            break;
309
        case 'P':
310
            start_pmode();
311
            empty_reply();
312
            break;
313
        case 'U':
314
            here = getch();
315
            here += 256 * getch();
316
            empty_reply();
317
            break;
318
        case '`': //STK_PROG_FLASH
319
            getch();
320
            getch();
321
            empty_reply();
322
            break;
323
        case 'a': //STK_PROG_DATA
324
            getch();
325
            empty_reply();
326
            break;
327
        case 'd': //STK_PROG_PAGE
328
            program_page();
329
            break;
330
        case 't': //STK_READ_PAGE
331
            read_page();    
332
            break;
333
        case 'V':
334
            universal();
335
            break;
336
        case 'Q':
337
            end_pmode();
338
            empty_reply();
339
            break;
340
        case 'u': //STK_READ_SIGN
341
            read_signature();
342
            break;
343
            // expecting a command, not CRC_EOP
344
            // this is how we can get back in sync
345
        case CRC_EOP:
346
            putch(STK_NOSYNC);
347
            break;
348
            // anything else we will return STK_UNKNOWN
349
        default:
350
            putch(getch() == CRC_EOP ? STK_UNKNOWN : STK_NOSYNC);
351
    }
352
}
353
354
void setup() {
355
    Serial.begin(19200);
356
    pinMode(LED_PMODE, OUTPUT);
357
    digitalWrite(LED_PMODE, 1);
358
}
359
360
void loop(void) {
361
    avrisp();
362
}