C8051F32x firmware infrastructure

Sign in or create your account | Project List | Help

C8051F32x firmware infrastructure Git Source Tree

Root/f32x/f32x.c

1/*
2 * f32x/f32x.c - Simple C8051F326/7 Flash programmer
3 *
4 * Written 2008-2010 by Werner Almesberger
5 * Copyright 2008-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#include <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <sys/types.h>
20
21#include "c2.h"
22#include "flash.h"
23#include "boundary.h"
24
25
26struct chip {
27    const char *name; /* NULL for end of list */
28    uint8_t dev_id;
29    int max_flash_kb; /* maximum flash size, in kB */
30    
31};
32
33struct mem_layout {
34    int flash_kb; /* real flash size, in kB. 0 for end of list */
35    uint16_t lock_byte; /* location of lock byte */
36};
37
38static struct chip chips[] = {
39    { "C8051F320/1", 0x09, 16 },
40    { "C8051F326/7", 0x0d, 16 },
41    { "C8051F34x", 0x0f, 64 },
42    { NULL, }
43};
44
45static struct mem_layout mem_layouts[] = {
46    { 16, 0x3dff },
47    { 32, 0x7fff },
48    { 64, 0xfbff },
49    { 0, }
50};
51
52static const struct chip *chip = NULL;
53static const struct mem_layout *layout = NULL;
54
55
56static size_t file_size;
57
58
59/* ----- flash ------------------------------------------------------------- */
60
61
62static void dump(const char *title, void *data, size_t size)
63{
64    int i, j;
65
66    fprintf(stderr, "%s:\n", title);
67    for (i = 0; i < size; i += 16) {
68        fprintf(stderr, " %04x", i);
69        for (j = 0; j != 16 && i+j < size; j++)
70            fprintf(stderr, " %02x", ((uint8_t *) data)[i+j]);
71        fprintf(stderr, "\n");
72    }
73}
74
75
76static void flash_device(void *data, size_t size)
77{
78    int i;
79    size_t len;
80    uint8_t buf[256];
81
82    for (i = 0; i < size; i += 256)
83        fputc('-', stderr);
84    fputc('\r', stderr);
85
86    flash_init();
87    flash_device_erase();
88
89    for (i = 0; i < size; i += 256) {
90        fputc('*', stderr);
91        fflush(stderr);
92        len = size-i <= 256 ? size-i : 256;
93        flash_block_write(i, data+i, len);
94    }
95    fputc('\r', stderr);
96
97    for (i = 0; i < size; i += 256) {
98        fputc('#', stderr);
99        fflush(stderr);
100        len = size-i <= 256 ? size-i : 256;
101        flash_block_read(i, buf, len);
102        if (memcmp(buf, data+i, len)) {
103            fprintf(stderr, "compare error at 0x%04x\n", i);
104            dump("Expected", data+i, len);
105            dump("Read", buf, len);
106            exit(1);
107        }
108    }
109    fputc('\n', stderr);
110}
111
112
113static void do_flash(const char *name)
114{
115    FILE *file;
116    uint8_t code[16384];
117
118    file = fopen(name, "r");
119    if (!file) {
120        perror(name);
121        exit(1);
122    }
123    file_size = fread(code, 1, sizeof(code), file);
124    (void) fclose(file);
125    flash_device(code, file_size);
126}
127
128
129/* ----- protect ----------------------------------------------------------- */
130
131
132static void protect(void)
133{
134    uint8_t pages, lock_byte;
135
136    pages = (file_size+511) >> 9;
137    printf("Protecting %d page%s\n", pages, pages == 1 ? "" : "s");
138    lock_byte = ~pages;
139    flash_block_write(layout->lock_byte, &lock_byte, 1);
140}
141
142
143/* ----- erase ------------------------------------------------------------- */
144
145
146static void erase_flash(void)
147{
148    flash_init();
149    flash_device_erase();
150}
151
152
153/* ----- dump -------------------------------------------------------------- */
154
155
156static void dump_flash(size_t size)
157{
158    int i, j;
159    size_t len;
160    uint8_t buf[256], last[256];
161    int skipping = 0;
162
163    flash_init();
164    for (i = 0; i < size; i += 16) {
165        len = size-i <= 16 ? size-i : 16;
166        flash_block_read(i, buf, len);
167        if (i && !memcmp(last, buf, len)) {
168            printf("%04x: *%c", i, skipping ? '\r' : '\n');
169            fflush(stdout);
170            skipping = 1;
171            continue;
172        }
173        skipping = 0;
174        memcpy(last, buf, len);
175        printf("%04x:", i);
176        for (j = 0; j != len; j++)
177            printf(" %02x", buf[j]);
178        printf(" ");
179        for (j = 0; j != len; j++)
180            printf("%c",
181                buf[j] >= ' ' && buf[j] <= '~' ? buf[j] : '.');
182        putchar('\n');
183        fflush(stdout);
184    }
185}
186
187
188/* ----- identify ---------------------------------------------------------- */
189
190
191static void identify_chip(uint8_t dev)
192{
193    const struct chip *p;
194
195    for (p = chips; p->name; p++)
196        if (p->dev_id == dev) {
197            chip = p;
198            return;
199        }
200}
201
202
203static void identify(void)
204{
205    int i, same = 1;
206    uint8_t dev, same_dev;
207
208    c2_addr_write(0);
209    fprintf(stderr, "Dev");
210    for (i = 0; i != 10; i++) {
211        dev = c2_data_read(1);
212        fprintf(stderr, " 0x%02x", dev);
213        if (!i)
214            same_dev = dev;
215        else {
216            if (same_dev != dev)
217                same = 0;
218        }
219    }
220    if (!same) {
221        fprintf(stderr, "\ncommunication error\n");
222        exit(1);
223    }
224    identify_chip(same_dev);
225
226    c2_addr_write(1);
227    fprintf(stderr, "\nRev");
228    for (i = 0; i != 10; i++)
229        fprintf(stderr, " 0x%02x", c2_data_read(1));
230    fprintf(stderr, "\n");
231}
232
233
234static void determine_layout(int kb)
235{
236    if (kb) {
237        if (chip && kb > chip->max_flash_kb) {
238            fprintf(stderr,
239                "chip has only %d kB of flash\n",
240                chip->max_flash_kb);
241            exit(1);
242        }
243    } else {
244        if (chip)
245            kb = chip->max_flash_kb;
246    }
247
248    if (!kb)
249        return;
250    for (layout = mem_layouts; layout->flash_kb; layout++)
251        if (layout->flash_kb == kb)
252            break;
253    if (!layout->flash_kb) {
254        fprintf(stderr, "no memory layout found for %d kB\n", kb);
255        exit(1);
256    }
257}
258
259
260/* ----- main -------------------------------------------------------------- */
261
262
263static void usage(const char *name)
264{
265    fprintf(stderr,
266"usage: %s [-n] [-p] [-k flash_kb] file\n"
267" %s [-n] [-k flash_kb] -d\n"
268" %s [-n] -e\n"
269" %s [-n] -b pin_setup\n"
270" %s [-n]\n\n"
271" -b pin_setup\n"
272" Perform a boundary scan. pin_setup sets all 14 pins in this order:\n"
273" P0_0, P0_1, ..., P0_7, P2_0, ..., P2_5.\n"
274" Pins can be set to 0, 1, or R (pull-up). Dots can be used to structure\n"
275" the bit string. Prints what the pins read back (0 or 1) in the same\n"
276" order, with a dot between P0 and P2.\n"
277" -d dump Flash content\n"
278" -e erase whole Flash\n"
279" -k flash_kb set flash size (16/32/64; default: auto-select)\n"
280" -n do not provide power to the target (default: do provide power)\n"
281" -p protect the data after writing\n"
282"Invocation without argument resets the F32x.\n"
283  , name, name, name, name, name);
284    exit(1);
285}
286
287
288static void need_layout(void)
289{
290    if (layout)
291        return;
292    fprintf(stderr, "please specify flash size with -k flash_kB\n");
293    exit(1);
294}
295
296
297int main(int argc, char **argv)
298{
299    enum {
300        mode_default = 0,
301        mode_flash,
302        mode_dump,
303        mode_erase,
304        mode_scan,
305    } mode = mode_default;
306    int do_protect = 0, power = 1, kb = 0;
307    int c;
308
309    while ((c = getopt(argc, argv, "bdek:np")) != EOF)
310        switch (c) {
311        case 'd':
312            if (mode)
313                usage(*argv);
314            mode = mode_dump;
315            break;
316        case 'e':
317            if (mode)
318                usage(*argv);
319            mode = mode_erase;;
320            break;
321        case 'b':
322            if (mode)
323                usage(*argv);
324            mode = mode_scan;;
325            break;
326        case 'k':
327            kb = atoi(optarg);
328            break;
329        case 'n':
330            power = 0;
331            break;
332        case 'p':
333            do_protect = 1;
334            break;
335        default:
336            usage(*argv);
337        }
338
339    switch (mode) {
340    case mode_default:
341        switch (argc-optind) {
342        case 0:
343            break;
344        case 1:
345            mode = mode_flash;
346            break;
347        default:
348            usage(*argv);
349        }
350        break;
351    case mode_scan:
352        if (argc != optind+1)
353            usage(*argv);
354        break;
355    default:
356        if (argc != optind)
357            usage(*argv);
358        break;
359    }
360    if (do_protect && mode != mode_flash)
361        usage(*argv);
362
363    c2_init(power);
364    identify();
365    determine_layout(kb);
366
367    if (chip)
368        fprintf(stderr, "%s, ", chip->name);
369    else
370        fprintf(stderr, "unknown chip, ");
371    if (layout)
372        fprintf(stderr, "flash size: %d kB\n", layout->flash_kb);
373    else
374        fprintf(stderr, "flash size unknown\n");
375
376    switch (mode) {
377    case mode_default:
378        /* just reset */
379        break;
380    case mode_dump:
381        need_layout();
382        dump_flash(layout->lock_byte+2);
383        break;
384    case mode_erase:
385        erase_flash();
386        break;
387    case mode_flash:
388        if (do_protect)
389            need_layout();
390        do_flash(argv[optind]);
391        if (do_protect)
392            protect();
393        identify();
394        break;
395    case mode_scan:
396        boundary(argv[optind]);
397        break;
398    default:
399        abort();
400    }
401
402    c2_reset();
403
404    return 0;
405}
406

Archive Download this file

Branches:
master



interactive