OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [pid/] [v2_0/] [src/] [flash.c] - Blame information for rev 631

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//        flash.c
4
//
5
//        ARM PID7 eval board FLASH program tool
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):     gthomas
44
// Contributors:  gthomas
45
// Date:          1998-11-18
46
// Description:   Tool used to program onboard FLASH image
47
//####DESCRIPTIONEND####
48
 
49
//
50
// This program will program the FLASH on the PID board
51
//
52
 
53
#include <pkgconf/libc.h>   // Configuration header
54
 
55
#include <cyg/kernel/kapi.h>
56
#include <stdlib.h>
57
#include <ctype.h>
58
#include <cyg/infra/testcase.h>
59
#include <sys/cstartup.h>
60
 
61
#ifndef FALSE
62
#define FALSE 0
63
#define TRUE  1
64
#endif
65
 
66
#define SYNC_COUNT 63
67
 
68
extern void diag_printf(const char *, ...);
69
int identify_FLASH(void);
70
void write_sector(int, char *);
71
bool load_srecords(char (*readc)(), CYG_ADDRESS *start, int *size);
72
 
73
char dbuf[256];
74
char *raw = (char *)0x10000;
75
char *flash_buffer = (char *)0x30000;
76
int pos, len;
77
 
78
// FUNCTIONS
79
 
80
externC void
81
cyg_package_start( void )
82
{
83
#ifdef CYGPKG_LIBC
84
    cyg_iso_c_start();
85
#else
86
    (void)main(0, NULL);
87
#endif
88
} // cyg_package_start()
89
 
90
char nextch(void)
91
{
92
    return (raw[pos++]);
93
}
94
 
95
int
96
main( int argc, char *argv[] )
97
{
98
    int i, j, size;
99
    CYG_ADDRESS entry;
100
    char c;
101
    diag_printf("FLASH here!\n");
102
    while (identify_FLASH() == 0) {
103
        diag_printf("... Please change FLASH jumper - hit C/R to continue:");
104
        do {
105
            hal_diag_read_char(&c);
106
        } while ((c != '\r') && (c != '\n'));
107
        diag_printf("\n");
108
    }
109
 restart:
110
    diag_printf("Ready file - hit C/R to continue:");
111
    while (TRUE) {
112
        hal_diag_read_char(&c);
113
        if (c == '>') break;
114
    }
115
    i = 0;  j = 0;
116
    while (1) {
117
        hal_diag_read_char(&c);
118
        if (c == '!') {
119
            diag_printf("... Reset\n");
120
            goto restart;
121
        }
122
        raw[i++] = c;
123
        if (++j == SYNC_COUNT) {
124
            hal_diag_write_char(c);
125
            j = 0;
126
        }
127
        if (c == ':') break;
128
    }
129
    diag_printf("\n");
130
    pos = 0;  len = i;
131
    if (load_srecords(nextch, &entry, &size)) {
132
        diag_printf("Read %x bytes, entry: %x\n", size, entry);
133
        dump_buf(flash_buffer, 128);
134
        diag_printf("\nData loaded - hit '!' to continue:");
135
        while (TRUE) {
136
            hal_diag_read_char(&c);
137
            if (c == '!') break;
138
        }
139
        diag_printf("\n");
140
        diag_printf("...Programming FLASH\n");
141
        pos = 0;  i = 0;
142
        while (pos < size) {
143
            write_sector(i++, flash_buffer+pos);
144
            pos += 256;
145
        }
146
    } else {
147
        // Display buffer around failure        
148
        dump_buf(&raw[pos-32], 64);
149
    }
150
    diag_printf("All done!\n");
151
    while (1) ;
152
}
153
 
154
// Adapted from ARM sample code
155
#define SEQ_ADD1                0x5555
156
#define SEQ_ADD2                0xAAAA
157
#define START_CMD1              0xAA
158
#define START_CMD2              0x55
159
#define ID_CMD                  0x90
160
#define PROG_CMD                0xA0
161
#define STOP_CMD                0xF0
162
 
163
#define MAN_ATMEL               0x1F
164
#define ATMEL_AT29C040_ID       0X5B
165
#define ATMEL_AT29C040A_ID      0XA4
166
#define ATMEL_AT29C1024_ID      0X25
167
#define ATMEL_SECTOR_SIZE       256
168
#define ATMEL_MAX_SECTORS       2048
169
 
170
int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
171
volatile char *FLASH = (volatile char *)0x04000000;
172
 
173
int
174
identify_FLASH(void )
175
{
176
    // Enter Software Product Identification Mode
177
    FLASH[SEQ_ADD1] = START_CMD1;
178
    FLASH[SEQ_ADD2] = START_CMD2;
179
    FLASH[SEQ_ADD1] = ID_CMD;
180
 
181
    // Wait at least 10ms
182
    cyg_thread_delay(2);
183
 
184
    // Read Manufacturer and device code from the device
185
    manuf_code = FLASH[0];
186
    device_code = FLASH[1];
187
 
188
    diag_printf("manuf: %x, device: %x\n", manuf_code, device_code);
189
 
190
    // Exit Software Product Identification Mode
191
    FLASH[SEQ_ADD1] = START_CMD1;
192
    FLASH[SEQ_ADD2] = START_CMD2;
193
    FLASH[SEQ_ADD1] = STOP_CMD;
194
 
195
    // Wait at least 10ms
196
    cyg_thread_delay(5);
197
 
198
    if (manuf_code != MAN_ATMEL) {
199
        diag_printf ( "Error: Wrong Manufaturer: %02x\n",manuf_code );
200
        return (0);
201
    }
202
 
203
    switch (device_code) {
204
    case  ATMEL_AT29C040A_ID:
205
        diag_printf ("AT29C040A recognised\n");
206
        sector_size = ATMEL_SECTOR_SIZE;
207
        max_no_of_sectors = ATMEL_MAX_SECTORS;
208
        word_mode = FALSE;
209
        break;
210
    case  ATMEL_AT29C1024_ID:
211
        diag_printf ("AT29C1024 recognised\n");
212
        sector_size = ATMEL_SECTOR_SIZE;
213
        max_no_of_sectors = ATMEL_MAX_SECTORS;
214
        word_mode = TRUE;
215
        break;
216
    default :
217
        diag_printf ( "Error: Unsupported device: %02x\n", device_code);
218
        return (0);
219
    }
220
    return (1);
221
}
222
 
223
void
224
write_sector(int num, char *buf)
225
{
226
    int i, cnt;
227
    volatile char *wrt = (volatile int *)&FLASH[num*sector_size];
228
 
229
//    diag_printf("Writing to %08x\n", wrt);
230
    // Enter Program Mode
231
    FLASH[SEQ_ADD1] = START_CMD1;
232
    FLASH[SEQ_ADD2] = START_CMD2;
233
    FLASH[SEQ_ADD1] = PROG_CMD;
234
 
235
    // Note: write bytes as longs regardless of bus width
236
    for (i = 0;  i < sector_size;  i++) {
237
        wrt[i] = buf[i];
238
    }
239
 
240
    // Wait for sector to program
241
    cnt = 0;
242
    i = sector_size - 1;
243
    while (wrt[i] != buf[i]) {
244
        if (cnt++ > 0x01000000) break;
245
    }
246
//    diag_printf("Out - i: %d, wrt[i] = %08X.%08X, buf[i] = %08X, count = %x\n", i, &wrt[i], wrt[i], buf[i], cnt);
247
 
248
    // Verify
249
    for (i = 0;  i < sector_size;  i++) {
250
        for (cnt = 0;  cnt < 10;  cnt++) {
251
            if (*wrt == *buf) break;
252
            cyg_thread_delay(1);
253
        }
254
        if (cnt == 10) {
255
            diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, *buf);
256
        }
257
        wrt++;  buf++;
258
    }
259
}
260
 
261
// S-record download code - viciously 'adapted' from "kernel/src/sload/sload.c"
262
 
263
/*---------------------------------------------------------------------------*/
264
/*
265
//
266
//      An srecord looks like this:
267
//
268
// byte count-+     address
269
// start ---+ |        |       data        +- checksum
270
//          | |        |                   |
271
//        S01000006F6B692D746573742E73726563E4
272
//        S315000448600000000000000000FC00005900000000E9
273
//        S31A0004000023C1400037DE00F023604000377B009020825000348D
274
//        S30B0004485A0000000000004E
275
//        S70500040000F6
276
//
277
//      S<type><length><address><data><checksum>
278
//
279
//      Where
280
//      - length (2 characters)
281
//        is the number of bytes following upto the checksum. Note that
282
//        this is not the number of chars following, since it takes two
283
//        chars to represent a byte.
284
//      - type (2 characters)
285
//        is one of:
286
//        0) header record
287
//        1) two byte address data record
288
//        2) three byte address data record
289
//        3) four byte address data record
290
//        5) record containing the number of S1, S2, or S3 records
291
//        7) four byte address termination record
292
//        8) three byte address termination record
293
//        9) two byte address termination record
294
//
295
//      - address (4, 6, or 8 characters)
296
//        is the start address of the data following, or in the case of
297
//        a termination record, the start address of the image
298
//      - data (0-2n characters)
299
//        is the data.
300
//      - checksum (2 characters)
301
//        is the sum of all the raw byte data in the record, from the length
302
//        upwards, modulo 256 and subtracted from 255.
303
//
304
// Useful S-records for testing purposes:
305
//   Start record:
306
//      S00B0000737461303030447563
307
//   This sets the default address to be 0x02005000:
308
//      S31A020050002700801481C4E0B0A15000000100000091D02000018F
309
//      S31A0200501500000001000000010000002700801881C4E2E4A150C1
310
//      S311020080A42407070A090B0A0781050000E1
311
//   Termination record:
312
//      S70502005000A8
313
//
314
*/
315
 
316
#define S0      0
317
#define S1      1
318
#define S2      2
319
#define S3      3
320
#define S5      5
321
#define S7      7
322
#define S8      8
323
#define S9      9
324
 
325
/*---------------------------------------------------------------------------*/
326
 
327
int hex2digit(char c)
328
{
329
    if( c & 0x40 ) c += 9;;
330
    return c &0x0f;
331
 
332
//    return ( c <= '9' ? c - '0' :
333
//             c <= 'Z' ? c - 'A' + 10 :
334
//             c - 'a' + 10);
335
}
336
 
337
/*---------------------------------------------------------------------------*/
338
 
339
bool load_srecords(char (*readc)(),
340
                   CYG_ADDRESS *start,
341
                   int *size)
342
{
343
    CYG_ADDRESS addr, load_addr;
344
    int addrsize;
345
    int length;
346
    int i;
347
    cyg_uint8 chksum, ochksum;
348
    cyg_uint8 val;
349
    cyg_uint8 *tdata;
350
    char s;
351
    char type;
352
    char len0;
353
    char len1;
354
    bool first = true;
355
 
356
 
357
    do {
358
        // Skip whitespace characters until we find something that
359
        // might be an 'S'.
360
        do {
361
            s = readc();
362
        } while( s == '\r' || s == '\n' || s == ' ');
363
 
364
        // Check that this is an S record
365
        if( s != 'S' ) {
366
            diag_printf("Invalid 'S' record\n");
367
            return false;
368
        }
369
 
370
        // First 4 bytes are standard S + type + len
371
        type = readc();
372
        len0 = readc();
373
        len1 = readc();
374
 
375
        // decode the type
376
        type = hex2digit(type);
377
 
378
        // determine address size
379
        switch (type) {
380
        case S0:                        // start records have no address
381
            addrsize = 0;
382
            break;
383
        case S1:                        // two byte address
384
        case S9:
385
            addrsize = 4;
386
            break;
387
        case S2:                        // 3 byte address
388
        case S8:
389
            addrsize = 6;
390
            break;
391
        case S3:                        // 4 byte address
392
        case S7:
393
            addrsize = 8;
394
            break;
395
        }
396
 
397
        length  = hex2digit (len0) << 4;
398
        length |= hex2digit (len1);
399
        chksum = length;
400
 
401
        // read the address
402
        addr = 0;
403
        for (i = 0; i < addrsize; i++) {
404
            val = hex2digit(readc());
405
            addr = (addr << 4) | val;
406
        }
407
 
408
        // calculate the checksum, which is done by the byte, not the digit
409
        for (i = 0; i < addrsize*4; i += 8) {
410
            chksum += ((addr >>  i) & 0xff);
411
        }
412
 
413
        // decide where to load this data
414
        if (first && (type != S0)) {
415
            load_addr = addr;
416
            first = false;
417
        }
418
 
419
        // read the data and put it directly into memory where it belongs
420
        tdata = (cyg_uint8 *)((addr - load_addr) + flash_buffer);
421
        if (type < S7) {
422
            *size = (addr - load_addr);
423
        }
424
        val = 0;
425
        for (i = 0; i < ((length - 1) * 2) - addrsize; i += 2 ) {
426
            val  = hex2digit (readc()) << 4;
427
            val |= hex2digit (readc());
428
            chksum += val;
429
            if( type != S0 ) *tdata++ = val;
430
            if (type < S7) *size = *size + 1;
431
        }
432
 
433
        // now get the old checksum
434
        ochksum = hex2digit(readc()) << 4;
435
        ochksum |= hex2digit(readc());
436
        chksum = ~chksum;
437
        if (chksum != ochksum) {
438
            diag_printf("Bad checksum - addr: %x\n", addr);
439
            return false;
440
        }
441
 
442
    } while( type < S7 );
443
 
444
    *start = addr;
445
    return true;
446
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.