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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [flash/] [v2_0/] [src/] [flash.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      flash.c
4
//
5
//      Flash programming
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:         2000-07-26
46
// Purpose:      
47
// Description:  
48
//              
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/system.h>
54
#include <pkgconf/io_flash.h>
55
 
56
#include <cyg/hal/hal_arch.h>
57
#include <cyg/hal/hal_intr.h>
58
#include <cyg/hal/hal_cache.h>
59
#include <string.h>
60
 
61
#define  _FLASH_PRIVATE_
62
#include <cyg/io/flash.h>
63
 
64
// When this flag is set, do not actually jump to the relocated code.
65
// This can be used for running the function in place (RAM startup only),
66
// allowing calls to diag_printf() and similar.
67
#undef RAM_FLASH_DEV_DEBUG
68
#if !defined(CYG_HAL_STARTUP_RAM) && defined(RAM_FLASH_DEV_DEBUG)
69
# warning "Can only enable the flash debugging when configured for RAM startup"
70
# undef  CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
71
#endif
72
 
73
struct flash_info flash_info;
74
 
75
int
76
flash_init(void *work_space, int work_space_size, _printf *pf)
77
{
78
    int err;
79
 
80
    if (flash_info.init) return FLASH_ERR_OK;
81
    flash_info.pf = pf; // Do this before calling into the driver
82
    flash_info.work_space = work_space;
83
    flash_info.work_space_size = work_space_size;
84
    if ((err = flash_hwr_init()) != FLASH_ERR_OK) {
85
        return err;
86
    }
87
    flash_info.block_mask = ~(flash_info.block_size-1);
88
    flash_info.init = 1;
89
    return FLASH_ERR_OK;
90
}
91
 
92
#ifndef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
93
// Use this function to make function pointers anonymous - forcing the
94
// compiler to use jumps instead of branches when calling driver
95
// services.
96
static void* __anonymizer(void* p)
97
{
98
  return p;
99
}
100
#endif
101
 
102
// FIXME: Want to change all drivers to use this function. But it may
103
// make sense to wait till device structure pointer arguments get
104
// added as well.
105
void
106
flash_dev_query(void* data)
107
{
108
    typedef void code_fun(void*);
109
    code_fun *_flash_query;
110
    int d_cache, i_cache;
111
 
112
#ifdef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
113
    {
114
        extern char flash_query[], flash_query_end[];
115
        CYG_ADDRESS code_len;
116
 
117
        // Query the device driver - copy 'query' code to RAM for execution
118
        code_len = (CYG_ADDRESS)&flash_query_end - (CYG_ADDRESS)&flash_query;
119
        _flash_query = (code_fun *)flash_info.work_space;
120
        memcpy(_flash_query, &flash_query, code_len);
121
    }
122
#else
123
    {
124
        externC code_fun flash_query;
125
        _flash_query = (code_fun*) __anonymizer(&flash_query);
126
    }
127
#endif
128
 
129
    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
130
    (*_flash_query)(data);
131
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
132
}
133
 
134
int
135
flash_verify_addr(void *target)
136
{
137
    if (!flash_info.init) {
138
        return FLASH_ERR_NOT_INIT;
139
    }
140
    if (((CYG_ADDRESS)target >= (CYG_ADDRESS)flash_info.start) &&
141
        ((CYG_ADDRESS)target <= ( ((CYG_ADDRESS)flash_info.end) - 1) )) {
142
        return FLASH_ERR_OK;
143
    } else {
144
        return FLASH_ERR_INVALID;
145
    }
146
}
147
 
148
int
149
flash_get_limits(void *target, void **start, void **end)
150
{
151
    if (!flash_info.init) {
152
        return FLASH_ERR_NOT_INIT;
153
    }
154
    *start = flash_info.start;
155
    *end = flash_info.end;
156
    return FLASH_ERR_OK;
157
}
158
 
159
int
160
flash_get_block_info(int *block_size, int *blocks)
161
{
162
    if (!flash_info.init) {
163
        return FLASH_ERR_NOT_INIT;
164
    }
165
    *block_size = flash_info.block_size;
166
    *blocks = flash_info.blocks;
167
    return FLASH_ERR_OK;
168
}
169
 
170
int
171
flash_erase(void *addr, int len, void **err_addr)
172
{
173
    unsigned short *block, *end_addr;
174
    int stat = 0;
175
    typedef int code_fun(unsigned short *, unsigned int);
176
    code_fun *_flash_erase_block;
177
    int d_cache, i_cache;
178
 
179
    if (!flash_info.init) {
180
        return FLASH_ERR_NOT_INIT;
181
    }
182
 
183
#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
184
    if (plf_flash_query_soft_wp(addr,len))
185
        return FLASH_ERR_PROTECT;
186
#endif
187
 
188
#ifdef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
189
    {
190
        extern char flash_erase_block[], flash_erase_block_end[];
191
        CYG_ADDRESS code_len;
192
 
193
        // Copy 'erase' code to RAM for execution
194
        code_len = (CYG_ADDRESS)&flash_erase_block_end - (CYG_ADDRESS)&flash_erase_block;
195
        _flash_erase_block = (code_fun *)flash_info.work_space;
196
        memcpy(_flash_erase_block, &flash_erase_block, code_len);
197
    }
198
#else
199
    {
200
        externC code_fun flash_erase_block;
201
        _flash_erase_block = (code_fun*) __anonymizer(&flash_erase_block);
202
    }
203
#endif
204
 
205
    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
206
    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
207
 
208
    /* Check to see if end_addr overflowed */
209
    if( (end_addr < block) && (len > 0) ){
210
        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
211
    }
212
 
213
    (*flash_info.pf)("... Erase from %p-%p: ", (void*)block, (void*)end_addr);
214
 
215
    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
216
    FLASH_Enable(block, end_addr);
217
    while (block < end_addr) {
218
        // Supply the blocksize for a gross check for erase success
219
        int i;
220
        unsigned char *dp;
221
        bool erased = true;
222
        unsigned short *tmp_block;
223
 
224
        dp = (unsigned char *)block;
225
        for (i = 0;  i < flash_info.block_size;  i++) {
226
            if (*dp++ != (unsigned char)0xFF) {
227
                erased = false;
228
                break;
229
            }
230
        }
231
        if (!erased) {
232
            stat = (*_flash_erase_block)(block, flash_info.block_size);
233
            stat = flash_hwr_map_error(stat);
234
        }
235
        if (stat) {
236
            *err_addr = (void *)block;
237
            break;
238
        }
239
 
240
        // Check to see if block will overflow
241
        tmp_block = block + flash_info.block_size / sizeof(*block);
242
        if(tmp_block < block){
243
            // If block address overflows, set block value to end on this loop
244
            block = end_addr;
245
        }
246
        else{
247
            block = tmp_block;
248
        }
249
        (*flash_info.pf)(".");
250
    }
251
    FLASH_Disable(block, end_addr);
252
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
253
    (*flash_info.pf)("\n");
254
    return (stat);
255
}
256
 
257
int
258
flash_program(void *_addr, void *_data, int len, void **err_addr)
259
{
260
    int stat = 0;
261
    int size;
262
    typedef int code_fun(void *, void *, int, unsigned long, int);
263
    code_fun *_flash_program_buf;
264
    unsigned char *addr = (unsigned char *)_addr;
265
    unsigned char *data = (unsigned char *)_data;
266
    CYG_ADDRESS tmp;
267
    int d_cache, i_cache;
268
 
269
    if (!flash_info.init) {
270
        return FLASH_ERR_NOT_INIT;
271
    }
272
 
273
#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
274
    if (plf_flash_query_soft_wp(addr,len))
275
        return FLASH_ERR_PROTECT;
276
#endif
277
 
278
#ifdef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
279
    {
280
        CYG_ADDRESS code_len;
281
        extern char flash_program_buf[], flash_program_buf_end[];
282
        // Copy 'program' code to RAM for execution
283
        code_len = (CYG_ADDRESS)&flash_program_buf_end - (CYG_ADDRESS)&flash_program_buf;
284
        _flash_program_buf = (code_fun *)flash_info.work_space;
285
        memcpy(_flash_program_buf, &flash_program_buf, code_len);
286
    }
287
#else
288
    {
289
        externC code_fun flash_program_buf;
290
        _flash_program_buf = (code_fun*) __anonymizer(&flash_program_buf);
291
    }
292
#endif
293
 
294
    (*flash_info.pf)("... Program from %p-%p at %p: ", (void*)data,
295
                     (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
296
 
297
    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
298
    FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
299
    while (len > 0) {
300
        size = len;
301
        if (size > flash_info.block_size) size = flash_info.block_size;
302
 
303
        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
304
        if (tmp) {
305
                tmp = flash_info.block_size - tmp;
306
                if (size>tmp) size = tmp;
307
 
308
        }
309
 
310
        stat = (*_flash_program_buf)(addr, data, size,
311
                                     flash_info.block_mask, flash_info.buffer_size);
312
        stat = flash_hwr_map_error(stat);
313
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
314
        if (0 == stat) // Claims to be OK
315
            if (memcmp(addr, data, size) != 0) {
316
                stat = 0x0BAD;
317
                (*flash_info.pf)("V");
318
            }
319
#endif
320
        if (stat) {
321
            *err_addr = (void *)addr;
322
            break;
323
        }
324
        (*flash_info.pf)(".");
325
        len -= size;
326
        addr += size/sizeof(*addr);
327
        data += size/sizeof(*data);
328
    }
329
    FLASH_Disable((unsigned short*)addr, (unsigned short *)(addr+len));
330
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
331
    (*flash_info.pf)("\n");
332
    return (stat);
333
}
334
 
335
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
336
 
337
int
338
flash_lock(void *addr, int len, void **err_addr)
339
{
340
    unsigned short *block, *end_addr;
341
    int stat = 0;
342
    typedef int code_fun(unsigned short *);
343
    code_fun *_flash_lock_block;
344
    int d_cache, i_cache;
345
 
346
    if (!flash_info.init) {
347
        return FLASH_ERR_NOT_INIT;
348
    }
349
 
350
#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
351
    if (plf_flash_query_soft_wp(addr,len))
352
        return FLASH_ERR_PROTECT;
353
#endif
354
 
355
#ifdef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
356
    {
357
        extern char flash_lock_block[], flash_lock_block_end[];
358
        CYG_ADDRESS code_len;
359
        // Copy 'lock' code to RAM for execution
360
        code_len = (CYG_ADDRESS)&flash_lock_block_end - (CYG_ADDRESS)&flash_lock_block;
361
        _flash_lock_block = (code_fun *)flash_info.work_space;
362
        memcpy(_flash_lock_block, &flash_lock_block, code_len);
363
    }
364
#else
365
    {
366
        externC code_fun flash_lock_block;
367
        _flash_lock_block = (code_fun*) __anonymizer(&flash_lock_block);
368
    }
369
#endif
370
 
371
    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
372
    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
373
 
374
    /* Check to see if end_addr overflowed */
375
    if( (end_addr < block) && (len > 0) ){
376
        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
377
    }
378
 
379
    (*flash_info.pf)("... Lock from %p-%p: ", block, end_addr);
380
 
381
    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
382
    FLASH_Enable(block, end_addr);
383
    while (block < end_addr) {
384
        unsigned short *tmp_block;
385
        stat = (*_flash_lock_block)(block);
386
        stat = flash_hwr_map_error(stat);
387
        if (stat) {
388
            *err_addr = (void *)block;
389
            break;
390
        }
391
 
392
        // Check to see if block will overflow
393
        tmp_block = block + flash_info.block_size / sizeof(*block);
394
        if(tmp_block < block){
395
            // If block address overflows, set block value to end on this loop
396
            block = end_addr;
397
        }
398
        else{
399
            block = tmp_block;
400
        }
401
        (*flash_info.pf)(".");
402
    }
403
    FLASH_Disable(block, end_addr);
404
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
405
    (*flash_info.pf)("\n");
406
    return (stat);
407
}
408
 
409
int
410
flash_unlock(void *addr, int len, void **err_addr)
411
{
412
    unsigned short *block, *end_addr;
413
    int stat = 0;
414
    typedef int code_fun(unsigned short *, int, int);
415
    code_fun *_flash_unlock_block;
416
    int d_cache, i_cache;
417
 
418
    if (!flash_info.init) {
419
        return FLASH_ERR_NOT_INIT;
420
    }
421
 
422
#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
423
    if (plf_flash_query_soft_wp(addr,len))
424
        return FLASH_ERR_PROTECT;
425
#endif
426
 
427
#ifdef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
428
    {
429
        extern char flash_unlock_block[], flash_unlock_block_end[];
430
        CYG_ADDRESS code_len;
431
        // Copy 'lock' code to RAM for execution
432
        code_len = (CYG_ADDRESS)&flash_unlock_block_end - (CYG_ADDRESS)&flash_unlock_block;
433
        _flash_unlock_block = (code_fun *)flash_info.work_space;
434
        memcpy(_flash_unlock_block, &flash_unlock_block, code_len);
435
    }
436
#else
437
    {
438
        externC code_fun flash_unlock_block;
439
        _flash_unlock_block = (code_fun*) __anonymizer(&flash_unlock_block);
440
    }
441
#endif
442
 
443
    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
444
    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
445
 
446
    /* Check to see if end_addr overflowed */
447
    if( (end_addr < block) && (len > 0) ){
448
        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
449
    }
450
 
451
    (*flash_info.pf)("... Unlock from %p-%p: ", block, end_addr);
452
 
453
    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
454
    FLASH_Enable(block, end_addr);
455
    while (block < end_addr) {
456
        unsigned short *tmp_block;
457
        stat = (*_flash_unlock_block)(block, flash_info.block_size, flash_info.blocks);
458
        stat = flash_hwr_map_error(stat);
459
        if (stat) {
460
            *err_addr = (void *)block;
461
            break;
462
        }
463
 
464
        tmp_block = block + flash_info.block_size / sizeof(*block);
465
        if(tmp_block < block){
466
            // If block address overflows, set block value to end on this loop
467
            block = end_addr;
468
        }
469
        else{
470
            block = tmp_block;
471
        }
472
        (*flash_info.pf)(".");
473
    }
474
    FLASH_Disable(block, end_addr);
475
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
476
    (*flash_info.pf)("\n");
477
    return (stat);
478
}
479
#endif
480
 
481
char *
482
flash_errmsg(int err)
483
{
484
    switch (err) {
485
    case FLASH_ERR_OK:
486
        return "No error - operation complete";
487
    case FLASH_ERR_ERASE_SUSPEND:
488
        return "Device is in erase suspend state";
489
    case FLASH_ERR_PROGRAM_SUSPEND:
490
        return "Device is in program suspend state";
491
    case FLASH_ERR_INVALID:
492
        return "Invalid FLASH address";
493
    case FLASH_ERR_ERASE:
494
        return "Error trying to erase";
495
    case FLASH_ERR_LOCK:
496
        return "Error trying to lock/unlock";
497
    case FLASH_ERR_PROGRAM:
498
        return "Error trying to program";
499
    case FLASH_ERR_PROTOCOL:
500
        return "Generic error";
501
    case FLASH_ERR_PROTECT:
502
        return "Device/region is write-protected";
503
    case FLASH_ERR_NOT_INIT:
504
        return "FLASH sub-system not initialized";
505
    case FLASH_ERR_DRV_VERIFY:
506
        return "Data verify failed after operation";
507
    case FLASH_ERR_DRV_TIMEOUT:
508
        return "Driver timed out waiting for device";
509
    case FLASH_ERR_DRV_WRONG_PART:
510
        return "Driver does not support device";
511
    case FLASH_ERR_LOW_VOLTAGE:
512
        return "Device reports low voltage";
513
    default:
514
        return "Unknown error";
515
    }
516
}
517
 
518
// EOF io/flash/..../flash.c

powered by: WebSVN 2.1.0

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