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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [pid/] [current/] [src/] [flash.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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