Date:2012-05-25 18:55:02 (11 years 10 months ago)
Author:Werner Almesberger
Commit:6bdfea64359b0229aa1389c3706d324692ea674a
Message:bacon/prog/: simple PIC 18F{2,4}xJxx programmer (for the Ben Nanonote)

Files: bacon/prog/Makefile (1 diff)
bacon/prog/gpio-xburst.c (1 diff)
bacon/prog/gpio-xburst.h (1 diff)
bacon/prog/picpen.c (1 diff)

Change Details

bacon/prog/Makefile
1#
2# picpen/Makefile - PIC Programmer/Emulator for Nanonote
3#
4# Written 2008, 2010-2011 by Werner Almesberger
5# Copyright 2008, 2010-2011 Werner Almesberger
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12
13
14PREFIX=/usr
15
16ifeq ($(TARGET),)
17TARGET = ben_openwrt
18endif
19
20CC_ben_jlime = mipsel-linux-gcc
21CC_ben_openwrt = mipsel-openwrt-linux-gcc
22
23UPLOAD_ben_jlime = scp f32x jlime:
24UPLOAD_ben_openwrt = scp f32x ben:
25
26NAME = picpen
27CC = $(CC_$(TARGET))
28CFLAGS = -Wall -Wshadow -O9 -g -static
29OBJS = picpen.o gpio-xburst.o
30LDFLAGS = -static
31
32
33.PHONY: all install uninstall clean depend spotless
34
35all: $(NAME)
36
37$(NAME): $(OBJS)
38
39upload:
40        $(UPLOAD_$(TARGET))
41
42install: $(NAME)
43        install -D $(NAME) $(PREFIX)/bin/$(NAME)
44
45uninstall:
46        rm -f $(PREFIX)/bin/$(NAME)
47
48depend:
49        $(CPP) $(CFLAGS) -MM -MG *.c >.depend || \
50          { rm -f .depend; exit 1; }
51
52ifeq (.depend,$(wildcard .depend))
53include .depend
54endif
55
56c2-om.o: c2-bitbang.c
57c2-ben.o: c2-bitbang.c
58
59clean:
60        rm -f $(OBJS) $(OBJS_ben) .depend
61
62spotless: clean
63        rm -f $(NAME)
bacon/prog/gpio-xburst.c
1/*
2 * gpio-xburst.c - Really primitive XBurst GPIO access
3 *
4 * Written 2010-2011 by Werner Almesberger
5 * Copyright 2010-2011 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdlib.h>
15#include <stdio.h>
16#include <fcntl.h>
17#include <sys/mman.h>
18
19#include "gpio-xburst.h"
20
21
22#define BASE 0x10010000
23
24
25volatile void *mem;
26
27
28void gpio_init(void)
29{
30    int fd;
31
32    fd = open("/dev/mem", O_RDWR | O_SYNC);
33        if (fd < 0) {
34        perror("/dev/mem");
35        exit(1);
36    }
37    mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE);
38    if (mem == MAP_FAILED) {
39        perror("mmap");
40        exit(1);
41    }
42}
bacon/prog/gpio-xburst.h
1/*
2 * gpio-xburst.h - Really primitive XBurst GPIO access
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 2010 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13/*
14 * Ports are numbered 0 = A, 1 = B, ...
15 */
16
17
18#ifndef GPIO_XBURST_H
19#define GPIO_XBURST_H
20
21
22#include <stdint.h>
23
24
25volatile void *mem;
26
27
28#define REG(off) (*(volatile uint32_t *) (mem+(off)))
29
30#define port_pin(port) REG(port*0x100)
31#define port_dats(port) REG(port*0x100+0x14)
32#define port_datc(port) REG(port*0x100+0x18)
33#define port_func(port) REG(port*0x100+0x48)
34#define port_dirs(port) REG(port*0x100+0x64)
35#define port_dirc(port) REG(port*0x100+0x68)
36
37
38static inline void gpio_high(unsigned port, unsigned bit)
39{
40    port_dats(port) = 1 << bit;
41}
42
43
44static inline void gpio_low(unsigned port, unsigned bit)
45{
46    port_datc(port) = 1 << bit;
47}
48
49
50static inline void gpio_set(unsigned port, unsigned bit, int value)
51{
52    if (value)
53        gpio_high(port, bit);
54    else
55        gpio_low(port, bit);
56}
57
58
59static inline int gpio_get(unsigned port, unsigned bit)
60{
61    return (port_pin(port) >> bit) & 1;
62}
63
64
65static inline void gpio_output(unsigned port, unsigned bit)
66{
67    port_dirs(port) = 1 << bit;
68}
69
70
71static inline void gpio_input(unsigned port, unsigned bit)
72{
73    port_dirc(port) = 1 << bit;
74}
75
76
77void gpio_init(void);
78
79
80#endif /* !GPIO_XBURST_H */
bacon/prog/picpen.c
1/*
2 * picpen.c - PIC (18F{2,4}xJxx) Programmer/Emulator for Nanonote
3 *
4 * Written 2012 by Werner Almesberger
5 * Copyright 2012 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <assert.h>
20
21#include "gpio-xburst.h"
22
23
24#define POWER_OFF 3, 2 /* PD02 */
25#define nMCLR 3, 13 /* PD13 DAT3 */
26#define PGD 3, 8 /* PD09 CMD */
27#define PGC 3, 9 /* PD08 CLK */
28
29#define ICSP_KEY 0x4d434850
30
31#define P5_US 1 /* Delay Between 4-Bit Command and Command Operand */
32#define P5A_US 1 /* Delay Between 4-Bit Command Operand and Next 4-Bit
33               Command */
34#define P6_US 1 /* Delay Between Last PGC down of Command Byte
35               to First PGC up of Read of Data Word */
36#define P9_US 1200 /* Delay to allow Block Programming to Occur */
37#define P10_US 54000 /* Delay to allow Row Erase to Occur */
38#define P11_US 524000 /* Delay to allow Bulk Erase to Occur */
39#define P12_US 400 /* Input Data Hold Time from nMCLR up */
40#define P13_US 1 /* VDD up Setup Time to nMCLR up */
41#define P16_US 1 /* Delay Between Last PGC down and nMCLR down */
42#define P17_US 3 /* nMCLR down to VDD down */
43#define P19_US 4000 /* Delay from First nMCLR down to First PGC up for
44               Key Sequence on PGD */
45#define P20_US 1 /* Delay from Last PGC down for Key Sequence on
46               PGD to Second nMCLR up */
47
48#define CMD_INSN 0
49#define CMD_TABLAT 0x2
50#define CMD_READ_INC 0x9 /* post-increment by 1 */
51#define CMD_WRITE 0xc
52#define CMD_WRITE_INC 0xd /* post-increment by 2 */
53#define CMD_WRITE_START 0xf
54
55#define INSN_MOVLW 0x0e
56#define INSN_MOVWF 0x6e
57#define INSN_MOVF_W_0 0x50
58#define INSN_MOVFF1 0xcf
59#define INSN_MOVFF2 0xff
60
61#define REG_TABLAT 0xf5
62#define REG_TBLPTRL 0xf6
63#define REG_TBLPTRH 0xf7
64#define REG_TBLPTRU 0xf8
65
66#define REG_ANCON0 0x48 /* banked ! */
67#define REG_ANCON1 0x49 /* banked ! */
68#define REG_PORTA 0x80
69#define REG_PORTC 0x82
70#define REG_LATA 0x89
71#define REG_TRISA 0x92 /* 1 = in */
72#define REG_EECON1 0xa6
73#define REG_CTMUICON 0xb1
74#define REG_CTMUCONL 0xb2
75#define REG_CTMUCONH 0xb3
76#define REG_ADCON1 0xc1
77#define REG_ADCON0 0xc2
78#define REG_ADRESL 0xc3
79#define REG_ADRESH 0xc4
80
81#define BLOCK 64
82
83
84struct rec {
85    uint32_t addr;
86    uint8_t *data;
87    int len;
88    struct rec *next;
89};
90
91static int kb;
92
93
94/* The multiplier (100) is a wild guess. Tested down to 0. */
95
96static inline void delay(int us)
97{
98    uint32_t i;
99
100    if (us < 10)
101        for (i = 0; i != us*100; i++)
102            asm("");
103    else
104        usleep(us);
105}
106
107
108static void icsp_begin(int power)
109{
110    int i;
111
112    gpio_init();
113
114    gpio_high(nMCLR);
115    gpio_high(PGD);
116    gpio_high(PGC);
117
118    if (power) {
119        gpio_output(POWER_OFF);
120        gpio_output(PGD);
121        gpio_output(PGC);
122        gpio_output(nMCLR);
123
124        delay(100*1000); /* precharge */
125    }
126
127    gpio_low(PGD);
128    gpio_low(PGC);
129    gpio_low(nMCLR);
130
131    if (power)
132        gpio_low(POWER_OFF);
133    delay(P13_US);
134
135    gpio_high(nMCLR);
136    delay(1);
137    gpio_low(nMCLR);
138    delay(P19_US);
139
140    for (i = 31; i >= 0; i--) {
141        if ((ICSP_KEY >> i) & 1)
142            gpio_high(PGD);
143        else
144            gpio_low(PGD);
145        gpio_high(PGC);
146        gpio_low(PGC);
147    }
148
149    delay(P20_US);
150    gpio_high(nMCLR);
151    delay(P12_US);
152}
153
154
155static void icsp_end(void)
156{
157    gpio_low(PGD);
158    gpio_low(PGC);
159
160    delay(P16_US);
161    gpio_low(nMCLR);
162    delay(P17_US);
163
164    gpio_high(nMCLR);
165// gpio_high(POWER_OFF);
166
167gpio_input(PGD);
168gpio_input(PGC);
169}
170
171
172static void icsp_send(uint8_t v, int n)
173{
174    int i;
175
176    for (i = 0; i != n; i++) {
177        if ((v >> i) & 1)
178            gpio_high(PGD);
179        else
180            gpio_low(PGD);
181        gpio_high(PGC);
182        gpio_low(PGC);
183    }
184}
185
186
187static uint8_t icsp_recv(int n)
188{
189    uint8_t v = 0;
190    int i;
191
192    for (i = 0; i != n; i++) {
193        gpio_high(PGC);
194        gpio_low(PGC);
195        if (gpio_get(PGD))
196            v |= 1 << i;
197    }
198    return v;
199}
200
201
202static void icsp_write(uint8_t cmd, uint8_t a, uint8_t b)
203{
204    icsp_send(cmd, 4);
205    delay(P5_US);
206    icsp_send(b, 8);
207    icsp_send(a, 8);
208    delay(P5A_US);
209}
210
211
212static void write_reg(uint8_t addr, uint8_t v)
213{
214    icsp_write(CMD_INSN, INSN_MOVLW, v);
215    icsp_write(CMD_INSN, INSN_MOVWF, addr);
216}
217
218
219static uint8_t read_reg(uint8_t addr)
220{
221    uint8_t v;
222
223    icsp_write(CMD_INSN, 0x50, addr);
224    /* for some strange reason we need two writes */
225    icsp_write(CMD_INSN, INSN_MOVWF, REG_TABLAT);
226    icsp_write(CMD_INSN, INSN_MOVWF, REG_TABLAT);
227
228    icsp_send(CMD_TABLAT, 4);
229    delay(P5_US);
230
231    icsp_send(0, 8);
232    delay(P6_US);
233    gpio_input(PGD);
234
235    v = icsp_recv(8);
236    delay(P5A_US);
237    gpio_output(PGD);
238
239    return v;
240}
241
242
243static void set_tblptr(uint32_t addr)
244{
245    write_reg(REG_TBLPTRU, addr >> 16);
246    write_reg(REG_TBLPTRH, addr >> 8);
247    write_reg(REG_TBLPTRL, addr);
248}
249
250
251static void read_mem(uint32_t addr, uint8_t *buf, int len)
252{
253    set_tblptr(addr);
254
255    while (len--) {
256        icsp_send(CMD_READ_INC, 4);
257        delay(P5_US);
258        icsp_send(0, 8);
259        delay(P6_US);
260        gpio_input(PGD);
261
262        *buf++ = icsp_recv(8);
263        delay(P5A_US);
264        gpio_output(PGD);
265    }
266}
267
268
269static void bulk_erase(void)
270{
271    set_tblptr(0x3c0005);
272    icsp_write(CMD_WRITE, 0x01, 0x01);
273    set_tblptr(0x3c0004);
274    icsp_write(CMD_WRITE, 0x80, 0x80);
275    icsp_write(CMD_INSN, 0, 0);
276
277    icsp_send(0, 4);
278    delay(P11_US+P10_US);
279
280    icsp_send(0, 16);
281    delay(P5A_US); /* guess*/
282}
283
284
285static void write_mem(uint32_t addr, const uint8_t *buf, int len)
286{
287    int i;
288    uint8_t first;
289
290    assert(!(addr & (BLOCK-1)));
291    assert(!(len & (BLOCK-1)));
292
293    /* BSF EECON1, WREN */
294    icsp_write(CMD_INSN, 0x84, REG_EECON1);
295
296    while (len) {
297        set_tblptr(addr);
298        for (i = 0; i != BLOCK/2-1; i++) {
299            first = *buf++;
300            icsp_write(CMD_WRITE_INC, *buf++, first);
301        }
302        first = *buf++;
303        icsp_write(CMD_WRITE_START, *buf++, first);
304
305        icsp_send(0, 3);
306        gpio_low(PGD);
307        gpio_high(PGC);
308        delay(P9_US);
309        gpio_low(PGC);
310        delay(P5_US);
311
312        icsp_send(0, 16);
313        delay(P5A_US); /* guess*/
314
315        addr += BLOCK;
316        len -= BLOCK;
317    }
318}
319
320
321/* ----- Flash-level operations -------------------------------------------- */
322
323
324static void flash_record(const struct rec *rec)
325{
326    uint8_t *tmp;
327    int off, padded;
328
329    off = rec->addr & (BLOCK-1);
330    padded = (rec->len+off+BLOCK-1) & ~(BLOCK-1);
331    if (!off && padded == rec->len) {
332        write_mem(rec->addr, rec->data, rec->len);
333        return;
334    }
335    tmp = malloc(padded);
336    if (!tmp) {
337        perror("malloc");
338        exit(1);
339    }
340    memset(tmp, 0xff, off);
341    memcpy(tmp+off, rec->data, rec->len);
342    memset(tmp+off+rec->len, 0xff, padded-rec->len-off);
343    write_mem(rec->addr-off, tmp, padded);
344}
345
346
347static void verify_record(const struct rec *rec)
348{
349    uint8_t *tmp;
350    int i;
351
352    tmp = malloc(rec->len);
353    if (!tmp) {
354        perror("malloc");
355        exit(1);
356    }
357    read_mem(rec->addr, tmp, rec->len);
358    for (i = 0; i != rec->len; i++)
359        if (rec->data[i] != tmp[i]) {
360            fprintf(stderr,
361                "%04x: wrote %02x != read %02x\n",
362                rec->addr+i, rec->data[i], tmp[i]);
363        }
364}
365
366
367static void flash_file(const struct rec *recs)
368{
369    const struct rec *rec;
370
371    for (rec = recs; rec; rec = rec->next)
372        if (rec->addr+rec->len > kb*1024) {
373            fprintf(stderr,
374                "record 0x%x+0x%x ends outside Flash of %d bytes\n",
375                rec->addr, rec->len, kb*1024-8);
376            exit(1);
377        }
378
379    bulk_erase();
380    for (rec = recs; rec; rec = rec->next)
381        flash_record(rec);
382
383    for (rec = recs; rec; rec = rec->next)
384        verify_record(rec);
385}
386
387
388static void dump_flash(void)
389{
390    uint8_t *tmp, c;
391    int i, j;
392
393    tmp = malloc(kb*1024);
394    if (!tmp) {
395        perror("malloc");
396        exit(1);
397    }
398
399    read_mem(0, tmp, kb*1024);
400
401    for (i = 0; i != kb*1024; i += 16) {
402        printf("%04X: ", i);
403        for (j = 0; j != 16; j++)
404            printf("%02X ", tmp[i+j]);
405        for (j = 0; j != 16; j++) {
406            c = tmp[i+j];
407            printf("%c", c >= ' ' && c <= '~' ? c : '.');
408        }
409        printf("\n");
410    }
411}
412
413
414/* ----- Experiments ------------------------------------------------------- */
415
416
417#if 0
418
419static void blink(void)
420{
421    write_reg(REG_TRISA, 0xfc);
422    while (1) {
423        write_reg(REG_LATA, 1);
424gpio_high(PGD);
425        delay(200*1000);
426        write_reg(REG_LATA, 2);
427gpio_high(PGD);
428        delay(200*1000);
429    }
430}
431
432
433static void adc(void)
434{
435int i;
436
437#if 0
438for (i = 0; i != 256; i++) {
439// write_reg(REG_ANCON0, 0xff);
440// write_reg(REG_TABLAT, i);
441// write_reg(REG_TABLAT, i);
442    printf("%02x ", read_reg(REG_PORTC));
443fflush(stdout);
444}
445#endif
446    write_reg(REG_TRISA, 0xfc);
447// write_reg(REG_ANCON0, 0x10); /* AN4 is analog */
448    write_reg(REG_ADCON0, 0x20); /* AN4, Vss to AVdd */
449    write_reg(REG_ADCON1, 0x80); /* Tad = 0, Fosc/2, right just. */
450    write_reg(REG_ADCON0, 0x21); /* Enable ADC module */
451    while (1) {
452        uint8_t hi, lo;
453
454        write_reg(REG_ADCON0, 0x23); /* GO */
455        while (read_reg(REG_ADCON0) & 2)
456            write(2, ".", 1);
457        hi = read_reg(REG_ADRESH);
458        lo = read_reg(REG_ADRESL);
459        printf("\r%02x %02x (%u)\n", hi, lo, hi << 8 | lo);
460    }
461
462#if 0
463    while (1) {
464        write_reg(
465    }
466#endif
467
468}
469
470
471static void cap(void)
472{
473    write_reg(REG_CTMUCONH, 0x00); /* page 405 */
474    write_reg(REG_CTMUCONL, 0x90);
475    write_reg(REG_CTMUICON, 0x01);
476
477    write_reg(REG_TRISA, 0xfc);
478    write_reg(REG_ADCON0, 0x20); /* AN4, Vss to AVdd */
479// write_reg(REG_ADCON1, 0x8e); /* Tad = 2, Fosc/32, right just. */
480    write_reg(REG_ADCON1, 0x88); /* Tad = 2, Fosc/2, right just. */
481    write_reg(REG_ADCON0, 0x21); /* Enable ADC module */
482
483    /* bandgap ?!? */
484
485    while (1) {
486        uint8_t hi, lo;
487
488        write_reg(REG_CTMUCONH, 0x80); /* enable CTMU */
489        write_reg(REG_CTMUCONL, 0x90); /* clear EDGxSTAT */
490        write_reg(REG_CTMUCONH, 0x82); /* ground output */
491        delay(1);
492        write_reg(REG_CTMUCONH, 0x80); /* end drain */
493        write_reg(REG_CTMUCONL, 0x91); /* current on */
494        write_reg(REG_CTMUCONL, 0x90); /* current off */
495
496        write_reg(REG_ADCON0, 0x23); /* GO */
497        while (read_reg(REG_ADCON0) & 2)
498            write(2, ".", 1);
499        hi = read_reg(REG_ADRESH);
500        lo = read_reg(REG_ADRESL);
501        printf("\r%02x %02x (%u)\n", hi, lo, hi << 8 | lo);
502    }
503}
504
505
506static void dump(uint32_t addr)
507{
508    uint8_t buf[BLOCK];
509    int i;
510
511    read_mem(addr, buf, BLOCK);
512    for (i = 0; i != BLOCK; i++) {
513        if (!(i & 15))
514            printf("%04X:", i);
515        printf(" %02X", buf[i]);
516        if ((i & 15) == 15)
517            printf("\n");
518    }
519}
520
521
522static void rerwr(void)
523{
524    uint8_t buf[BLOCK];
525    int i;
526
527    dump(0x3fffc0);
528    dump(0);
529    bulk_erase();
530    dump(0);
531    for (i = 0; i != BLOCK; i++)
532        buf[i] = i;
533    write_mem(0, buf, BLOCK);
534    dump(0x3fffc0);
535    dump(0);
536}
537
538#endif
539
540/* ----- Chip identification ----------------------------------------------0 */
541
542
543struct chip {
544    const char *name;
545    uint8_t id2, id1;
546    int kb;
547} chips[] = {
548    { "PIC18F24J50", 0x4c, 0x00, 16 },
549    { NULL }
550};
551
552
553#define DEVID1 0x3ffffe
554
555
556static void identify(void)
557{
558    uint8_t id[2];
559    const struct chip *chip;
560
561    read_mem(DEVID1, id, 2);
562    for (chip = chips; chip->name; chip++) {
563        if ((chip->id1 ^ id[0]) & 0xe0)
564            continue;
565        if (chip->id2 == id[1])
566            break;
567    }
568    fprintf(stderr, "ID = 0x%02x%02x (%s)\n", id[1], id[0],
569        chip->name ? chip->name : "?");
570    if (!chip->name)
571        exit(1);
572    fprintf(stderr, "%d kB Flash\n", chip->kb);
573    kb = chip->kb;
574}
575
576
577/* ----- Intel HEX file reader --------------------------------------------- */
578
579
580static int hex(char c, int lineno)
581{
582    if (c >= '0' && c <= '9')
583        return c-'0';
584    if (c >= 'A' && c <= 'F')
585        return c-'A'+10;
586    fprintf(stderr, "non-hex character \"%c\" in line %d\n", c, lineno);
587    exit(1);
588}
589
590
591/* http://en.wikipedia.org/wiki/Intel_HEX */
592
593
594static struct rec *load_file(const char *name)
595{
596    struct rec *recs = NULL, *last = NULL, *rec;
597    const struct rec *other;
598    FILE *file;
599    int lineno = 1;
600    char line[1000];
601    const char *s;
602    uint8_t buf[sizeof(line)/2];
603    uint8_t *p, *t, sum;
604    uint32_t xaddr = 0, addr;
605
606    file = fopen(name, "r");
607    if (!file) {
608        perror(name);
609        exit(1);
610    }
611    while (fgets(line, sizeof(line), file)) {
612        if (*line != ':') {
613            fprintf(stderr, "line %d doesn't start with colon\n",
614                lineno);
615            exit(1);
616        }
617        p = buf;
618        for (s = line+1; *s > ' '; s += 2)
619            *p++ = hex(s[0], lineno) << 4 | hex(s[1], lineno);
620        if (p-buf < 5) {
621            fprintf(stderr, "short record in line %d\n", lineno);
622            exit(1);
623        }
624        lineno++;
625        sum = 0;
626        for (t = buf; t != p-1; t++)
627            sum += *t;
628        if (0x100-sum != p[-1]) {
629            fprintf(stderr,
630                "checksum error (0x%02x vs. 0x%02x) in line %d\n",
631                p[-1], 0x100-sum, lineno);
632            exit(1);
633        }
634        switch (buf[3]) {
635        case 0: /* Data record */
636            if (p-buf != buf[0]+5) {
637                fprintf(stderr,
638                    "data record of %d bytes has length %d\n",
639                    p-buf, buf[0]);
640                exit(1);
641            }
642            addr = xaddr << 16 | buf[1] << 8 | buf[2];
643            if (last && last->addr+last->len == addr) {
644                last->data = realloc(last->data,
645                    last->len+buf[0]);
646                if (!last->data) {
647                    perror("realloc");
648                    exit(1);
649                }
650                memcpy(last->data+last->len, buf+4, buf[0]);
651                last->len += buf[0];
652                break;
653            }
654            rec = malloc(sizeof(struct rec));
655            rec->addr = xaddr << 16 | buf[1] << 8 | buf[2];
656            rec->len = buf[0];
657            rec->data = malloc(rec->len);
658            if (!rec->data) {
659                perror("realloc");
660                exit(1);
661            }
662            rec->next = NULL;
663            memcpy(rec->data, buf+4, rec->len);
664            if (last)
665                last->next = rec;
666            else
667                recs = rec;
668            last = rec;
669            break;
670        case 1: /* End Of File record */
671            goto end;
672        case 4: /* Extended Linear Address record */
673            xaddr = buf[4] << 8 | buf[5];
674            break;
675        default:
676            fprintf(stderr,
677                "unrecognized record type 0x%02x in line %d\n",
678                buf[3], lineno);
679            exit(1);
680        }
681    }
682end:
683    for (rec = recs; rec; rec = rec->next)
684        for (other = rec->next; other; other = other->next)
685            if (rec->addr < other->addr+other->len &&
686                rec->addr+rec->len > other->addr) {
687                fprintf(stderr,
688                    "overlapping address ranges 0x%x+0x%x "
689                    "and 0x%x+0x%x\n",
690                    rec->addr, rec->len, other->addr,
691                    other->len);
692            }
693    fclose(file);
694    return recs;
695}
696
697
698/* ----- Command-line parsing ---------------------------------------------- */
699
700
701static void usage(const char *name)
702{
703        fprintf(stderr,
704"usage: %s [-n] [file.bin]\n", name);
705        exit(1);
706}
707
708
709int main(int argc, char **argv)
710{
711    const struct rec *recs = NULL;
712    int power = 1;
713    int c;
714
715    while ((c = getopt(argc, argv, "n")) != EOF)
716        switch (c) {
717        case 'n':
718            power = 0;
719            break;
720        default:
721            usage(*argv);
722        }
723
724    switch (argc-optind) {
725    case 0:
726        break;
727    case 1:
728        recs = load_file(argv[optind]);
729        break;
730    default:
731        usage(*argv);
732    }
733
734    icsp_begin(power);
735    identify();
736
737    if (recs)
738        flash_file(recs);
739    else
740        dump_flash();
741    icsp_end();
742
743    return 0;
744}

Archive Download the corresponding diff file

Branches:
master



interactive