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

Subversion Repositories openrisc

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

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 INTEGRATOR A/P 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:  Philippe Robin
45
// Date:          November 7, 2000
46
// Description:   Tool used to program onboard FLASH image
47
//####DESCRIPTIONEND####
48
 
49
//
50
// This program will program the FLASH on INTEGRATOR A/P 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 PROGRAM_COMMAND    0x00100010
67
#define PROGRAM_VERIFY     0x00D000D0
68
#define READ_STATUS        0x70707070
69
#define SR_MASK            0x00800080
70
#define READ_ARRAY         0x00FF00FF
71
#define BLOCK_ERASE        0x00200020
72
#define BLOCK_WRITE_MODE   0x00E800E8
73
#define BLOCK_LOCK_BITS    0x00600060
74
#define CFI_QUERY_OFFS     0x00000055
75
#define CFI_QUERY_COMMAND  0x00980098
76
#define CFI_DATA_OFFS      0x00000020
77
#define SYS_INFO_SIZE_OFF  0x00000027
78
#define SYS_INFO_WB_OFF    0x0000002A
79
#define SYS_ERASE_SIZE_OFF 0x0000002F
80
#define STATUS_READY_MASK  0x00800080
81
#define BANK_BOUNDARY      0x0001FFFF
82
#define STATUS_ERROR       0x00100010
83
#define MAX_WRITE_BUFF     0xF
84
 
85
// Integrator EBI register definitions
86
 
87
#define INTEGRATOR_EBI_BASE 0x12000000
88
 
89
#define INTEGRATOR_EBI_CSR0_OFFSET      0x00
90
#define INTEGRATOR_EBI_CSR1_OFFSET      0x04
91
#define INTEGRATOR_EBI_CSR2_OFFSET      0x08
92
#define INTEGRATOR_EBI_CSR3_OFFSET      0x0C
93
#define INTEGRATOR_EBI_LOCK_OFFSET      0x20
94
 
95
#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET)
96
#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
97
#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET)
98
#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET)
99
#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
100
 
101
#define INTEGRATOR_EBI_8_BIT            0x00
102
#define INTEGRATOR_EBI_16_BIT           0x01
103
#define INTEGRATOR_EBI_32_BIT           0x02
104
#define INTEGRATOR_EBI_WRITE_ENABLE     0x04
105
#define INTEGRATOR_EBI_SYNC             0x08
106
#define INTEGRATOR_EBI_WS_2             0x00
107
#define INTEGRATOR_EBI_WS_3             0x10
108
#define INTEGRATOR_EBI_WS_4             0x20
109
#define INTEGRATOR_EBI_WS_5             0x30
110
#define INTEGRATOR_EBI_WS_6             0x40
111
#define INTEGRATOR_EBI_WS_7             0x50
112
#define INTEGRATOR_EBI_WS_8             0x60
113
#define INTEGRATOR_EBI_WS_9             0x70
114
#define INTEGRATOR_EBI_WS_10            0x80
115
#define INTEGRATOR_EBI_WS_11            0x90
116
#define INTEGRATOR_EBI_WS_12            0xA0
117
#define INTEGRATOR_EBI_WS_13            0xB0
118
#define INTEGRATOR_EBI_WS_14            0xC0
119
#define INTEGRATOR_EBI_WS_15            0xD0
120
#define INTEGRATOR_EBI_WS_16            0xE0
121
#define INTEGRATOR_EBI_WS_17            0xF0
122
 
123
#define FL_SC_CONTROL                   0x06    // Enable Flash Write and Vpp
124
 
125
 
126
#define INVALID_FTYPE           0x00000000
127
#define UNKNOWN_FTYPE           0xFFFFFFFF
128
#define ATMEL_FTYPE             0x00000001
129
#define INTEL_FTYPE             0x00000002
130
 
131
#define FLASH_TYPE_MASK         (ATMEL_FTYPE | INTEL_FTYPE)
132
 
133
// On Some platforms Boot and program flash may be part of the same device
134
#define INTEGRATED_FTYPE        0x80000000
135
#define BOOT_FTYPE              0x40000000
136
#define APP_FTYPE               0x20000000
137
 
138
#define FLASH_USAGE_MASK        (BOOT_FTYPE | APP_FTYPE)
139
 
140
#define DEFAULT_FLASH_MASK 0xFFFFFFF8
141
#define FLASH_BLOCK_SIZE        0x00020000      // 128Kb
142
#define EPROM_BASE              0x20000000
143
#define EPROM_SIZE              0x00080000      // 512Kb
144
#define FLASH_BASE              0x24000000
145
#define FLASH_SIZE              0x02000000      // 32Mb
146
 
147
typedef int flashWrite(char *address, unsignedint  data, char *flash);
148
typedef int flashWriteBlock(char *address, unsigned int *data, unsigned int size, char *flash);
149
typedef int flashRead(char *address, unsigned int *value);
150
typedef int flashReadBlock(char *address, unsigned int *data, unsigned int size);
151
typedef int flashErase(char *address, unsigned size, char *flash);
152
typedef int flashInit(char *address, char *flash);
153
typedef int flashClose(char *address, char *flash);
154
 
155
typedef struct flashType {
156
    char *base;                 // Base Address of flash
157
    char *physicalBase;         // before mem initialisation
158
    unsigned int size;          // Size of flash, in bytes
159
    unsigned int type;          // Atmel / Intel (CFI) / Unknown
160
    unsigned int writeSize;     // Size of physical block
161
    unsigned int eraseSize;     // Size of block erase
162
    unsigned int logicalSize;   // Size of logical block
163
    flashWrite *write;          // Write one word
164
    flashWriteBlock *writeBlock;// Write a block of writeSize bytes
165
    flashRead *read;            // Read one word
166
    flashReadBlock *readBlock;  // Read a block of writeSize bytes
167
    flashErase *erase;          // Erase a block of eraseSize bytes
168
    flashInit *init;            // Lock a flash device
169
    flashClose *close;          // Unlock a flash device
170
    char *ident;                // identification string
171
    struct flashType *next;     // Pointer to next flash device
172
} tFlash;
173
 
174
tFlash Integrator_Flash[2] = {
175
    {
176
        (char *)EPROM_BASE,     // Base Address of flash
177
        (char *)EPROM_BASE,     // Physical Address of flash
178
        EPROM_SIZE,             // Size of flash, in bytes (512K)
179
        BOOT_FTYPE | ATMEL_FTYPE,// Flash type
180
        FLASH_BLOCK_SIZE,       // Size of physical block
181
        FLASH_BLOCK_SIZE,       // Size of block erase
182
        FLASH_BLOCK_SIZE,       // Size of logical block
183
        ATMEL_Write_Word,       // Write one word
184
        ATMEL_Write_Block,      // Write a block of WriteSize
185
        ATMEL_Read_Word,
186
        ATMEL_Read_Block,
187
        ATMEL_Erase_Block,
188
        0,                       // Lock a flash device
189
        0,                       // Unlock a flash device
190
        "Atmel",                // Null terminated Info string
191
        (tFlash *)&Integrator_Flash[1] // Pointer to next tFlash struct
192
    },
193
    {
194
        (char *)FLASH_BASE,     // Base Address of flash
195
        (char *)FLASH_BASE,     // Physical Address of flash
196
        FLASH_SIZE,             // Size of flash, in bytes
197
        APP_FTYPE | INTEL_FTYPE,// Flash type
198
        FLASH_BLOCK_SIZE,       // Size of physical block
199
        FLASH_BLOCK_SIZE,       // Size of block erase
200
        FLASH_BLOCK_SIZE,       // Size of logical block
201
        CFI_Write_Word,         // Write one word
202
        CFI_Write_Block,        // Write a block of writeSize bytes
203
        CFI_Read_Word,          // Read one word
204
        CFI_Read_Block,         // Read a block of writeSize bytes
205
        CFI_Erase_Block,        // Erase a block of eraseSize bytes
206
        0,                       // Lock a flash device
207
        0,                       // Unlock a flash device
208
        "Intel 28F320S3",       // Null terminated Info string
209
 
210
   }
211
};
212
 
213
#define SYNC_COUNT 63
214
 
215
extern void diag_printf(const char *, ...);
216
int identify_FLASH(void);
217
void write_sector(int, char *);
218
bool load_srecords(char (*readc)(), CYG_ADDRESS *start, int *size);
219
 
220
char dbuf[256];
221
char *raw = (char *)0x10000;
222
char *flash_buffer = (char *)0x30000;
223
int pos, len;
224
 
225
// FUNCTIONS
226
 
227
externC void
228
cyg_package_start( void )
229
{
230
#ifdef CYGPKG_LIBC
231
    cyg_iso_c_start();
232
#else
233
    (void)main(0, NULL);
234
#endif
235
} // cyg_package_start()
236
 
237
char nextch(void)
238
{
239
    return (raw[pos++]);
240
}
241
 
242
int
243
main( int argc, char *argv[] )
244
{
245
    int i, j, size;
246
    CYG_ADDRESS entry;
247
    char c;
248
 
249
    diag_printf("FLASH here!\n");
250
 
251
    CFI_Identify_Flash(Integrator_Flash[1]);
252
 
253
    while (identify_FLASH() == 0) {
254
        diag_printf("... Please change FLASH jumper - hit C/R to continue:");
255
        do {
256
            hal_diag_read_char(&c);
257
        } while ((c != '\r') && (c != '\n'));
258
        diag_printf("\n");
259
    }
260
 restart:
261
    diag_printf("Ready file - hit C/R to continue:");
262
    while (TRUE) {
263
        hal_diag_read_char(&c);
264
        if (c == '>') break;
265
    }
266
    i = 0;  j = 0;
267
    while (1) {
268
        hal_diag_read_char(&c);
269
        if (c == '!') {
270
            diag_printf("... Reset\n");
271
            goto restart;
272
        }
273
        raw[i++] = c;
274
        if (++j == SYNC_COUNT) {
275
            hal_diag_write_char(c);
276
            j = 0;
277
        }
278
        if (c == ':') break;
279
    }
280
    diag_printf("\n");
281
    pos = 0;  len = i;
282
    if (load_srecords(nextch, &entry, &size)) {
283
        diag_printf("Read %x bytes, entry: %x\n", size, entry);
284
        dump_buf(flash_buffer, 128);
285
        diag_printf("\nData loaded - hit '!' to continue:");
286
        while (TRUE) {
287
            hal_diag_read_char(&c);
288
            if (c == '!') break;
289
        }
290
        diag_printf("\n");
291
        diag_printf("...Programming FLASH\n");
292
        pos = 0;  i = 0;
293
        while (pos < size) {
294
            write_sector(i++, flash_buffer+pos);
295
            pos += 256;
296
        }
297
    } else {
298
        // Display buffer around failure        
299
        dump_buf(&raw[pos-32], 64);
300
    }
301
    diag_printf("All done!\n");
302
    while (1) ;
303
}
304
 
305
int
306
CFI_Identify_Flash(tFlash * flash)
307
{
308
     int offset = CFI_DATA_OFFS;
309
 
310
     // CFI query to check for CFI string "QRY"
311
     // Write 0x98 to address flash + 55
312
    *(unsigned int *)(flash->base + CFI_QUERY_OFFS) = CFI_QUERY_COMMAND;
313
 
314
    if ( *(flash->base + offset) == 'Q') {
315
         int temp = 0;
316
         offset += 2;
317
 
318
         if ( *(flash->base+ offset) == 'R') {
319
             temp =  *(flash->base+ SYS_INFO_SIZE_OFF); // read block size
320
             flash->size = 2 ^ temp;
321
             temp = *(flash->base+ SYS_ERASE_SIZE_OFF); // Read Erase Regions
322
             temp += ( *(flash->base+ SYS_ERASE_SIZE_OFF + 1) << 4);
323
 
324
             flash->eraseSize = temp * 256;
325
             // Read Max write Buffer (logical Block size)
326
         } else
327
           return FALSE;
328
    }
329
 
330
    // Reset for Read operation
331
   *(unsigned int *)(flash->base)  = READ_ARRAY;
332
 
333
   return TRUE;
334
}
335
 
336
// Adapted from ARM sample code
337
#define SEQ_ADD1                0x5555
338
#define SEQ_ADD2                0xAAAA
339
#define START_CMD1              0xAA
340
#define START_CMD2              0x55
341
#define ID_CMD                  0x90
342
#define PROG_CMD                0xA0
343
#define STOP_CMD                0xF0
344
 
345
#define MAN_ATMEL               0x1F
346
#define ATMEL_AT29C040_ID       0X5B
347
#define ATMEL_AT29C040A_ID      0XA4
348
#define ATMEL_AT29C1024_ID      0X25
349
#define ATMEL_SECTOR_SIZE       256
350
#define ATMEL_MAX_SECTORS       2048
351
 
352
int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
353
volatile char *FLASH = (volatile char *)0x24000000;
354
 
355
int
356
identify_FLASH(void )
357
{
358
    // enable write to the Flash
359
    flashWriteEnable();
360
 
361
    // Enter Software Product Identification Mode
362
    FLASH[SEQ_ADD1] = START_CMD1;
363
    FLASH[SEQ_ADD2] = START_CMD2;
364
    FLASH[SEQ_ADD1] = ID_CMD;
365
 
366
    // Wait at least 10ms
367
    cyg_thread_delay(2);
368
 
369
    // Read Manufacturer and device code from the device
370
    manuf_code = FLASH[0];
371
    device_code = FLASH[1];
372
 
373
    diag_printf("manuf: %x, device: %x\n", manuf_code, device_code);
374
 
375
    // Exit Software Product Identification Mode
376
    FLASH[SEQ_ADD1] = START_CMD1;
377
    FLASH[SEQ_ADD2] = START_CMD2;
378
    FLASH[SEQ_ADD1] = STOP_CMD;
379
 
380
    // Wait at least 10ms
381
    cyg_thread_delay(5)
382
 
383
    // disble write to the Flash
384
    flashWriteDisable();;
385
 
386
    if (manuf_code != MAN_ATMEL) {
387
        diag_printf ( "Error: Wrong Manufaturer: %02x\n",manuf_code );
388
        return (0);
389
    }
390
 
391
    switch (device_code) {
392
    case  ATMEL_AT29C040A_ID:
393
        diag_printf ("AT29C040A recognised\n");
394
        sector_size = ATMEL_SECTOR_SIZE;
395
        max_no_of_sectors = ATMEL_MAX_SECTORS;
396
        word_mode = FALSE;
397
        break;
398
    case  ATMEL_AT29C1024_ID:
399
        diag_printf ("AT29C1024 recognised\n");
400
        sector_size = ATMEL_SECTOR_SIZE;
401
        max_no_of_sectors = ATMEL_MAX_SECTORS;
402
        word_mode = TRUE;
403
        break;
404
    default :
405
        diag_printf ( "Error: Unsupported device: %02x\n", device_code);
406
        return (0);
407
    }
408
    return (1);
409
}
410
 
411
void
412
write_sector(int num, char *buf)
413
{
414
    int i, cnt;
415
    volatile char *wrt = (volatile int *)&FLASH[num*sector_size];
416
 
417
//    diag_printf("Writing to %08x\n", wrt);
418
    // Enter Program Mode
419
    FLASH[SEQ_ADD1] = START_CMD1;
420
    FLASH[SEQ_ADD2] = START_CMD2;
421
    FLASH[SEQ_ADD1] = PROG_CMD;
422
 
423
    // Note: write bytes as longs regardless of bus width
424
    for (i = 0;  i < sector_size;  i++) {
425
        wrt[i] = buf[i];
426
    }
427
 
428
    // Wait for sector to program
429
    cnt = 0;
430
    i = sector_size - 1;
431
    while (wrt[i] != buf[i]) {
432
        if (cnt++ > 0x01000000) break;
433
    }
434
//    diag_printf("Out - i: %d, wrt[i] = %08X.%08X, buf[i] = %08X, count = %x\n", i, &wrt[i], wrt[i], buf[i], cnt);
435
 
436
    // Verify
437
    for (i = 0;  i < sector_size;  i++) {
438
        for (cnt = 0;  cnt < 10;  cnt++) {
439
            if (*wrt == *buf) break;
440
            cyg_thread_delay(1);
441
        }
442
        if (cnt == 10) {
443
            diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, *buf);
444
        }
445
        wrt++;  buf++;
446
    }
447
}
448
 
449
void
450
flashWriteEnable(void)
451
{
452
     volatile unsigned int *ebi_csr1 = (volatile unsigned int *)INTEGRATOR_EBI_CSR1;
453
 
454
     // allow write access to EBI_CSR1 area (Flash)
455
 
456
     *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE;
457
 
458
     if (!(*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE)) {
459
         *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0xA05F;
460
         *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE;
461
         *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0;
462
     }
463
 
464
     /* Enable Vpp and allow write access to Flash in system controller */
465
 
466
     *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = FL_SC_CONTROL;
467
}
468
 
469
//
470
// flashWriteDisable: disable write access to the Flash memory
471
//
472
 
473
void
474
flashWriteDisable(void)
475
{
476
     volatile unsigned int *ebi_csr1 = (volatile unsigned int *)INTEGRATOR_EBI_CSR1;
477
 
478
     // disable write access to EBI_CSR1 area (Flash)
479
 
480
     *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE;
481
 
482
     if (*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE) {
483
         *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0xA05F;
484
         *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE;
485
         *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 1;
486
     }
487
 
488
     // Disable Vpp and disable write access to Flash in system controller
489
 
490
     *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = 0;
491
}
492
 
493
// S-record download code - viciously 'adapted' from "kernel/src/sload/sload.c"
494
 
495
/*---------------------------------------------------------------------------*/
496
/*
497
//
498
//      An srecord looks like this:
499
//
500
// byte count-+     address
501
// start ---+ |        |       data        +- checksum
502
//          | |        |                   |
503
//        S01000006F6B692D746573742E73726563E4
504
//        S315000448600000000000000000FC00005900000000E9
505
//        S31A0004000023C1400037DE00F023604000377B009020825000348D
506
//        S30B0004485A0000000000004E
507
//        S70500040000F6
508
//
509
//      S<type><length><address><data><checksum>
510
//
511
//      Where
512
//      - length (2 characters)
513
//        is the number of bytes following upto the checksum. Note that
514
//        this is not the number of chars following, since it takes two
515
//        chars to represent a byte.
516
//      - type (2 characters)
517
//        is one of:
518
//        0) header record
519
//        1) two byte address data record
520
//        2) three byte address data record
521
//        3) four byte address data record
522
//        5) record containing the number of S1, S2, or S3 records
523
//        7) four byte address termination record
524
//        8) three byte address termination record
525
//        9) two byte address termination record
526
//
527
//      - address (4, 6, or 8 characters)
528
//        is the start address of the data following, or in the case of
529
//        a termination record, the start address of the image
530
//      - data (0-2n characters)
531
//        is the data.
532
//      - checksum (2 characters)
533
//        is the sum of all the raw byte data in the record, from the length
534
//        upwards, modulo 256 and subtracted from 255.
535
//
536
// Useful S-records for testing purposes:
537
//   Start record:
538
//      S00B0000737461303030447563
539
//   This sets the default address to be 0x02005000:
540
//      S31A020050002700801481C4E0B0A15000000100000091D02000018F
541
//      S31A0200501500000001000000010000002700801881C4E2E4A150C1
542
//      S311020080A42407070A090B0A0781050000E1
543
//   Termination record:
544
//      S70502005000A8
545
//
546
*/
547
 
548
#define S0      0
549
#define S1      1
550
#define S2      2
551
#define S3      3
552
#define S5      5
553
#define S7      7
554
#define S8      8
555
#define S9      9
556
 
557
/*---------------------------------------------------------------------------*/
558
 
559
int hex2digit(char c)
560
{
561
    if( c & 0x40 ) c += 9;;
562
    return c &0x0f;
563
 
564
//    return ( c <= '9' ? c - '0' :
565
//             c <= 'Z' ? c - 'A' + 10 :
566
//             c - 'a' + 10);
567
}
568
 
569
/*---------------------------------------------------------------------------*/
570
 
571
bool load_srecords(char (*readc)(),
572
                   CYG_ADDRESS *start,
573
                   int *size)
574
{
575
    CYG_ADDRESS addr, load_addr;
576
    int addrsize;
577
    int length;
578
    int i;
579
    cyg_uint8 chksum, ochksum;
580
    cyg_uint8 val;
581
    cyg_uint8 *tdata;
582
    char s;
583
    char type;
584
    char len0;
585
    char len1;
586
    bool first = true;
587
 
588
 
589
    do {
590
        // Skip whitespace characters until we find something that
591
        // might be an 'S'.
592
        do {
593
            s = readc();
594
        } while( s == '\r' || s == '\n' || s == ' ');
595
 
596
        // Check that this is an S record
597
        if( s != 'S' ) {
598
            diag_printf("Invalid 'S' record\n");
599
            return false;
600
        }
601
 
602
        // First 4 bytes are standard S + type + len
603
        type = readc();
604
        len0 = readc();
605
        len1 = readc();
606
 
607
        // decode the type
608
        type = hex2digit(type);
609
 
610
        // determine address size
611
        switch (type) {
612
        case S0:                        // start records have no address
613
            addrsize = 0;
614
            break;
615
        case S1:                        // two byte address
616
        case S9:
617
            addrsize = 4;
618
            break;
619
        case S2:                        // 3 byte address
620
        case S8:
621
            addrsize = 6;
622
            break;
623
        case S3:                        // 4 byte address
624
        case S7:
625
            addrsize = 8;
626
            break;
627
        }
628
 
629
        length  = hex2digit (len0) << 4;
630
        length |= hex2digit (len1);
631
        chksum = length;
632
 
633
        // read the address
634
        addr = 0;
635
        for (i = 0; i < addrsize; i++) {
636
            val = hex2digit(readc());
637
            addr = (addr << 4) | val;
638
        }
639
 
640
        // calculate the checksum, which is done by the byte, not the digit
641
        for (i = 0; i < addrsize*4; i += 8) {
642
            chksum += ((addr >>  i) & 0xff);
643
        }
644
 
645
        // decide where to load this data
646
        if (first && (type != S0)) {
647
            load_addr = addr;
648
            first = false;
649
        }
650
 
651
        // read the data and put it directly into memory where it belongs
652
        tdata = (cyg_uint8 *)((addr - load_addr) + flash_buffer);
653
        if (type < S7) {
654
            *size = (addr - load_addr);
655
        }
656
        val = 0;
657
        for (i = 0; i < ((length - 1) * 2) - addrsize; i += 2 ) {
658
            val  = hex2digit (readc()) << 4;
659
            val |= hex2digit (readc());
660
            chksum += val;
661
            if( type != S0 ) *tdata++ = val;
662
            if (type < S7) *size = *size + 1;
663
        }
664
 
665
        // now get the old checksum
666
        ochksum = hex2digit(readc()) << 4;
667
        ochksum |= hex2digit(readc());
668
        chksum = ~chksum;
669
        if (chksum != ochksum) {
670
            diag_printf("Bad checksum - addr: %x\n", addr);
671
            return false;
672
        }
673
 
674
    } while( type < S7 );
675
 
676
    *start = addr;
677
    return true;
678
}

powered by: WebSVN 2.1.0

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