GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_block_reclaim.c Lines: 62 127 48.8 %
Date: 2024-03-11 05:20:25 Branches: 33 74 44.6 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** LevelX Component                                                      */
16
/**                                                                       */
17
/**   NOR Flash                                                           */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define LX_SOURCE_CODE
23
24
25
/* Disable ThreadX error checking.  */
26
27
#ifndef LX_DISABLE_ERROR_CHECKING
28
#define LX_DISABLE_ERROR_CHECKING
29
#endif
30
31
32
/* Include necessary system files.  */
33
34
#include "lx_api.h"
35
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _lx_nor_flash_block_reclaim                         PORTABLE C      */
42
/*                                                           6.3.0        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function reclaims one block from the NOR flash.                */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    nor_flash                             NOR flash instance            */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    return status                                                       */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    _lx_nor_flash_driver_block_erase      Driver erase block            */
62
/*    _lx_nor_flash_driver_write            Driver flash sector write     */
63
/*    _lx_nor_flash_driver_read             Driver flash sector read      */
64
/*    _lx_nor_flash_next_block_to_erase_find                              */
65
/*                                          Find next block to erase      */
66
/*    _lx_nor_flash_physical_sector_allocate                              */
67
/*                                          Allocate new logical sector   */
68
/*    _lx_nor_flash_sector_mapping_cache_invalidate                       */
69
/*                                          Invalidate cache entry        */
70
/*    _lx_nor_flash_system_error            Internal system error handler */
71
/*                                                                        */
72
/*  CALLED BY                                                             */
73
/*                                                                        */
74
/*    Internal LevelX                                                     */
75
/*                                                                        */
76
/*  RELEASE HISTORY                                                       */
77
/*                                                                        */
78
/*    DATE              NAME                      DESCRIPTION             */
79
/*                                                                        */
80
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
81
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
82
/*                                            resulting in version 6.1    */
83
/*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
84
/*                                            resulting in version 6.1.7  */
85
/*  10-31-2023     Xiuwen Cai               Modified comment(s),          */
86
/*                                            added count for minimum     */
87
/*                                            erased blocks, added        */
88
/*                                            obsolete count cache,       */
89
/*                                            resulting in version 6.3.0  */
90
/*                                                                        */
91
/**************************************************************************/
92
1160
UINT  _lx_nor_flash_block_reclaim(LX_NOR_FLASH *nor_flash)
93
{
94
95
ULONG   *block_word_ptr;
96
ULONG   *list_word_ptr;
97
ULONG   list_word;
98
ULONG   i;
99
ULONG   erase_block;
100
ULONG   erase_count;
101
ULONG   temp_erase_count;
102
ULONG   erase_started_value;
103
ULONG   mapped_sectors;
104
ULONG   obsolete_sectors;
105
ULONG   free_sectors;
106
ULONG   logical_sector;
107
ULONG   *new_mapping_address;
108
ULONG   *new_sector_address;
109
ULONG   new_mapping_entry;
110
UINT    status;
111
112
113
    /* Determine the next block to erase.  */
114
1160
    _lx_nor_flash_next_block_to_erase_find(nor_flash, &erase_block, &erase_count, &mapped_sectors, &obsolete_sectors);
115
116
    /* Determine if the search pointer is set for this block.  */
117
1160
    if (nor_flash -> lx_nor_flash_free_block_search == erase_block)
118
    {
119
120
        /* Ensure the search block is not the block we are trying to free.  */
121
196
        nor_flash -> lx_nor_flash_free_block_search =  erase_block + 1;
122
123
        /* Check for wrap condition.  */
124
196
        if (nor_flash -> lx_nor_flash_free_block_search >= nor_flash -> lx_nor_flash_total_blocks)
125
22
            nor_flash -> lx_nor_flash_free_block_search =  0;
126
    }
127
128
    /* Setup the block word pointer to the first word of the search block.  */
129
1160
    block_word_ptr =  nor_flash -> lx_nor_flash_base_address + (nor_flash -> lx_nor_flash_words_per_block * erase_block);
130
131
    /* Determine if this block is completely obsolete.  */
132
1160
    if (obsolete_sectors == nor_flash -> lx_nor_flash_physical_sectors_per_block)
133
    {
134
135
        /* Write the erased started indication.  */
136
        erase_started_value =  LX_BLOCK_ERASE_STARTED;
137
        status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_started_value, 1);
138
139
        /* Check for an error from flash driver. Drivers should never return an error..  */
140
        if (status)
141
        {
142
143
            /* Call system error handler.  */
144
            _lx_nor_flash_system_error(nor_flash, status);
145
146
            /* Return the error.  */
147
            return(status);
148
        }
149
150
        /* Erase the entire block.  */
151
        status =  _lx_nor_flash_driver_block_erase(nor_flash, erase_block, erase_count+1);
152
153
        /* Check for an error from flash driver. Drivers should never return an error..  */
154
        if (status)
155
        {
156
157
            /* Call system error handler.  */
158
            _lx_nor_flash_system_error(nor_flash, status);
159
160
            /* Return the error.  */
161
            return(status);
162
        }
163
164
        /* Determine if the erase count is at the minimum.  */
165
        if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count)
166
        {
167
168
            /* Yes, decrement the minimum erased block count.  */
169
            nor_flash -> lx_nor_flash_minimum_erased_blocks--;
170
        }
171
172
        /* Increment the erase count.  */
173
        erase_count++;
174
175
        /* Determine if the new erase count exceeds the maximum.  */
176
        if (erase_count > ((ULONG) LX_BLOCK_ERASE_COUNT_MAX))
177
        {
178
179
            /* Yes, erase count is in overflow. Stay at the maximum count.  */
180
            erase_count =  ((ULONG) LX_BLOCK_ERASE_COUNT_MAX);
181
        }
182
183
        /* Determine if we need to update the maximum erase count.  */
184
        if (erase_count > nor_flash -> lx_nor_flash_maximum_erase_count)
185
        {
186
187
            /* Yes, a new maximum is present.  */
188
            nor_flash -> lx_nor_flash_maximum_erase_count =  erase_count;
189
        }
190
191
        /* Setup the free bit map that corresponds to the free physical sectors in this
192
           block. Note that we only need to setup the portion of the free bit map that doesn't
193
           have sectors associated with it.  */
194
        status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr+(nor_flash -> lx_nor_flash_block_free_bit_map_offset + (nor_flash -> lx_nor_flash_block_bit_map_words - 1)),
195
                                                                        &(nor_flash -> lx_nor_flash_block_bit_map_mask), 1);
196
197
        /* Check for an error from flash driver. Drivers should never return an error..  */
198
        if (status)
199
        {
200
201
            /* Call system error handler.  */
202
            _lx_nor_flash_system_error(nor_flash, status);
203
204
            /* Return the error.  */
205
            return(status);
206
        }
207
208
        /* Write the initial erase count for the block with upper bit set.  */
209
        temp_erase_count =  (erase_count | LX_BLOCK_ERASED);
210
        status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &temp_erase_count, 1);
211
212
        /* Check for an error from flash driver. Drivers should never return an error..  */
213
        if (status)
214
        {
215
216
            /* Call system error handler.  */
217
            _lx_nor_flash_system_error(nor_flash, status);
218
219
            /* Return the error.  */
220
            return(status);
221
        }
222
223
        /* Write the final initial erase count for the block.  */
224
        status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_count, 1);
225
226
        /* Check for an error from flash driver. Drivers should never return an error..  */
227
        if (status)
228
        {
229
230
            /* Call system error handler.  */
231
            _lx_nor_flash_system_error(nor_flash, status);
232
233
            /* Return the error.  */
234
            return(status);
235
        }
236
237
        /* Update parameters of this flash.  */
238
        nor_flash -> lx_nor_flash_free_physical_sectors =      nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors;
239
        nor_flash -> lx_nor_flash_obsolete_physical_sectors =  nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors;
240
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
241
242
        /* Check if the block is cached by obsolete count cache.  */
243
        if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
244
        {
245
246
            /* Yes, clear the obsolete count for this block.  */
247
            nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] =  0;
248
        }
249
#endif
250
    }
251
    else
252
    {
253
254
        /* Calculate the number of free sectors in this block.  */
255
1160
        free_sectors =  nor_flash -> lx_nor_flash_physical_sectors_per_block - (obsolete_sectors + mapped_sectors);
256
257
        /* Determine if there are enough free sectors outside of this block to reclaim this block.  */
258
1160
        if (mapped_sectors <= (nor_flash -> lx_nor_flash_free_physical_sectors - free_sectors))
259
        {
260
261
            /* Setup a pointer to the mapped list.  */
262
1160
            list_word_ptr =  block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset;
263
264
            /* Now search through the list to find mapped sectors to move.  */
265
17106
            for (i = 0; i < nor_flash -> lx_nor_flash_physical_sectors_per_block; i++)
266
            {
267
268
                /* Pickup the mapped sector list entry.  */
269
#ifdef LX_DIRECT_READ
270
271
                /* Read the word directly.  */
272
                list_word =  *(list_word_ptr);
273
#else
274
17106
                status =  _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1);
275
276
                /* Check for an error from flash driver. Drivers should never return an error..  */
277
17106
                if (status)
278
                {
279
280
                    /* Call system error handler.  */
281
                    _lx_nor_flash_system_error(nor_flash, status);
282
283
                    /* Return the error.  */
284
                    return(status);
285
                }
286
#endif
287
288
                /* Determine if the entry hasn't been used.  */
289
17106
                if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE)
290
                {
291
292
                    /* Since allocations are done sequentially in the block, we know nothing
293
                       else exists after this point.  */
294
                    break;
295
                }
296
297
                /* Is this entry mapped?  */
298
17106
                if (list_word & LX_NOR_PHYSICAL_SECTOR_VALID)
299
                {
300
301
                    /* Pickup the logical sector associated with this mapped physical sector.  */
302
15118
                    logical_sector =  list_word & LX_NOR_LOGICAL_SECTOR_MASK;
303
304
                    /* Invalidate the old sector mapping cache entry.  */
305
15118
                    _lx_nor_flash_sector_mapping_cache_invalidate(nor_flash, logical_sector);
306
307
                    /* Allocate a new physical sector for this write.  */
308
15118
                    _lx_nor_flash_physical_sector_allocate(nor_flash, logical_sector, &new_mapping_address, &new_sector_address);
309
310
                    /* Check to see if the new sector is also in the erase block.  */
311

15118
                    if ((new_sector_address >= block_word_ptr) && (new_sector_address < (block_word_ptr + nor_flash -> lx_nor_flash_words_per_block)))
312
                    {
313
314
                        /* Yes, the new sector was found in the block to be erased. Simply move the search pointer
315
                           to the block after the erase block and search for another sector from there.  */
316
                        nor_flash -> lx_nor_flash_free_block_search =  erase_block + 1;
317
318
                        /* Check for wrap condition.  */
319
                        if (nor_flash -> lx_nor_flash_free_block_search >= nor_flash -> lx_nor_flash_total_blocks)
320
                            nor_flash -> lx_nor_flash_free_block_search =  0;
321
322
                        /* Allocate a new physical sector for this write.  */
323
                        _lx_nor_flash_physical_sector_allocate(nor_flash, logical_sector, &new_mapping_address, &new_sector_address);
324
325
                        /* Check again for the new sector inside of the block to erase. This should be impossible, since
326
                           we check previously if there are enough free sectors outside of this block needed to reclaim
327
                           this block.  */
328
                        if ((new_sector_address >= block_word_ptr) && (new_sector_address < (block_word_ptr + LX_NOR_SECTOR_SIZE)))
329
                        {
330
331
                            /* System error, a new sector is not available outside of the erase block.
332
                               Clear the new sector so we fall through to the error handling. */
333
                            new_mapping_address =  LX_NULL;
334
                        }
335
                    }
336
337
                    /* Determine if the new sector allocation was successful.  */
338
15118
                    if (new_mapping_address)
339
                    {
340
341
                        /* Yes, we were able to allocate a new physical sector.  */
342
343
#ifdef LX_DIRECT_READ
344
                        /* First, write the sector data to the new physical sector.  */
345
                        status =  _lx_nor_flash_driver_write(nor_flash, new_sector_address, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_offset) +
346
                                                                        (i * LX_NOR_SECTOR_SIZE), LX_NOR_SECTOR_SIZE);
347
348
                        /* Check for an error from flash driver. Drivers should never return an error..  */
349
                        if (status)
350
                        {
351
352
                            /* Call system error handler.  */
353
                            _lx_nor_flash_system_error(nor_flash, status);
354
355
                            /* Return the error.  */
356
                            return(status);
357
                        }
358
#else
359
360
                        /* First, read the sector data into the internal memory of the NOR flash instance. This internal memory
361
                           is supplied by the underlying driver during initialization.  */
362
15118
                        status =  _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_offset) +
363
                                                                                       (i * LX_NOR_SECTOR_SIZE), nor_flash -> lx_nor_flash_sector_buffer,
364
                                                                                       LX_NOR_SECTOR_SIZE);
365
366
                        /* Check for an error from flash driver. Drivers should never return an error..  */
367
15118
                        if (status)
368
                        {
369
370
                            /* Call system error handler.  */
371
                            _lx_nor_flash_system_error(nor_flash, status);
372
373
                            /* Return the error.  */
374
                            return(status);
375
                        }
376
377
                        /* Next, write the sector data from the internal buffer to the new physical sector.  */
378
15118
                        status =  _lx_nor_flash_driver_write(nor_flash, new_sector_address, nor_flash -> lx_nor_flash_sector_buffer, LX_NOR_SECTOR_SIZE);
379
380
                        /* Check for an error from flash driver. Drivers should never return an error..  */
381
15118
                        if (status)
382
                        {
383
384
                            /* Call system error handler.  */
385
                            _lx_nor_flash_system_error(nor_flash, status);
386
387
                            /* Return the error.  */
388
                            return(status);
389
                        }
390
#endif
391
392
                        /* Now deprecate the old sector mapping.  */
393
394
                        /* Clear bit 30, which indicates this sector is superceded.  */
395
15118
                        list_word =  list_word & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED);
396
397
                        /* Write the value back to the flash to clear bit 30.  */
398
15118
                        status =  _lx_nor_flash_driver_write(nor_flash, list_word_ptr, &list_word, 1);
399
400
                        /* Check for an error from flash driver. Drivers should never return an error..  */
401
15118
                        if (status)
402
                        {
403
404
                            /* Call system error handler.  */
405
                            _lx_nor_flash_system_error(nor_flash, status);
406
407
                            /* Return the error.  */
408
                            return(status);
409
                        }
410
411
                        /* Now build the new mapping entry - with the not valid bit set initially.  */
412
15118
                        new_mapping_entry =  ((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID) | ((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED) | (ULONG) LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID | logical_sector;
413
414
                        /* Write out the new mapping entry.  */
415
15118
                        status =  _lx_nor_flash_driver_write(nor_flash, new_mapping_address, &new_mapping_entry, 1);
416
417
                        /* Check for an error from flash driver. Drivers should never return an error..  */
418
15118
                        if (status)
419
                        {
420
421
                            /* Call system error handler.  */
422
                            _lx_nor_flash_system_error(nor_flash, status);
423
424
                            /* Return the error.  */
425
                            return(status);
426
                        }
427
428
                        /* Now clear the not valid bit to make this sector mapping valid.  This is done because the writing of the extra bytes itself can
429
                           be interrupted and we need to make sure this can be detected when the flash is opened again.  */
430
15118
                        new_mapping_entry =  new_mapping_entry & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID);
431
432
                        /* Clear the not valid bit.  */
433
15118
                        status =  _lx_nor_flash_driver_write(nor_flash, new_mapping_address, &new_mapping_entry, 1);
434
435
                        /* Check for an error from flash driver. Drivers should never return an error..  */
436
15118
                        if (status)
437
                        {
438
439
                            /* Call system error handler.  */
440
                            _lx_nor_flash_system_error(nor_flash, status);
441
442
                            /* Return the error.  */
443
                            return(status);
444
                        }
445
446
                        /* Now clear bit 31, which indicates this sector is now obsoleted.  */
447
15118
                        list_word =  list_word & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID);
448
449
                        /* Write the value back to the flash to clear bit 31.  */
450
15118
                        status =  _lx_nor_flash_driver_write(nor_flash, list_word_ptr, &list_word, 1);
451
452
                        /* Check for an error from flash driver. Drivers should never return an error..  */
453
15118
                        if (status)
454
                        {
455
456
                            /* Call system error handler.  */
457
                            _lx_nor_flash_system_error(nor_flash, status);
458
459
                            /* Return the error.  */
460
                            return(status);
461
                        }
462
                    }
463
                    else
464
                    {
465
466
                        /* Call system error handler - the allocation should always succeed at this point.  */
467
                        _lx_nor_flash_system_error(nor_flash, LX_SYSTEM_ALLOCATION_FAILED);
468
469
                        /* Return the error.  */
470
                        return(status);
471
                    }
472
473
                    /* Decrement the number of mapped sectors.  */
474
15118
                    mapped_sectors--;
475
476
                    /* Determine if we are done.  */
477
15118
                    if (mapped_sectors == 0)
478
1160
                        break;
479
               }
480
481
               /* Move the list pointer ahead.  */
482
15946
               list_word_ptr++;
483
            }
484
485
            /* Write the erased started indication.  */
486
1160
            erase_started_value =  LX_BLOCK_ERASE_STARTED;
487
1160
            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_started_value, 1);
488
489
            /* Check for an error from flash driver. Drivers should never return an error..  */
490
1160
            if (status)
491
            {
492
493
                /* Call system error handler.  */
494
                _lx_nor_flash_system_error(nor_flash, status);
495
496
                /* Return the error.  */
497
                return(status);
498
            }
499
500
            /* Erase the entire block.  */
501
1160
            status =  _lx_nor_flash_driver_block_erase(nor_flash, erase_block, erase_count+1);
502
503
            /* Check for an error from flash driver. Drivers should never return an error..  */
504
1160
            if (status)
505
            {
506
507
                /* Call system error handler.  */
508
                _lx_nor_flash_system_error(nor_flash, status);
509
510
                /* Return the error.  */
511
                return(status);
512
            }
513
514
            /* Determine if the erase count is at the minimum.  */
515
1160
            if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count)
516
            {
517
518
                /* Yes, decrement the minimum erased block count.  */
519
582
                nor_flash -> lx_nor_flash_minimum_erased_blocks--;
520
            }
521
522
            /* Increment the erase count.  */
523
1160
            erase_count++;
524
525
            /* Determine if the new erase count exceeds the maximum.  */
526
1160
            if (erase_count > ((ULONG) LX_BLOCK_ERASE_COUNT_MAX))
527
            {
528
529
                /* Yes, erase count is in overflow. Stay at the maximum count.  */
530
                erase_count =  ((ULONG) LX_BLOCK_ERASE_COUNT_MAX);
531
            }
532
533
            /* Determine if we need to update the maximum erase count.  */
534
1160
            if (erase_count > nor_flash -> lx_nor_flash_maximum_erase_count)
535
            {
536
537
                /* Yes, a new maximum is present.  */
538
150
                nor_flash -> lx_nor_flash_maximum_erase_count =  erase_count;
539
            }
540
541
            /* Setup the free bit map that corresponds to the free physical sectors in this
542
               block. Note that we only need to setup the portion of the free bit map that doesn't
543
               have sectors associated with it.  */
544
1160
            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr+(nor_flash -> lx_nor_flash_block_free_bit_map_offset + (nor_flash -> lx_nor_flash_block_bit_map_words - 1)) ,
545
                                                                             &(nor_flash -> lx_nor_flash_block_bit_map_mask), 1);
546
547
            /* Check for an error from flash driver. Drivers should never return an error..  */
548
1160
            if (status)
549
            {
550
551
                /* Call system error handler.  */
552
                _lx_nor_flash_system_error(nor_flash, status);
553
554
                /* Return the error.  */
555
                return(status);
556
            }
557
558
            /* Write the initial erase count for the block with the upper bit set.  */
559
1160
            temp_erase_count =  (erase_count | LX_BLOCK_ERASED);
560
1160
            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &temp_erase_count, 1);
561
562
            /* Check for an error from flash driver. Drivers should never return an error..  */
563
1160
            if (status)
564
            {
565
566
                /* Call system error handler.  */
567
                _lx_nor_flash_system_error(nor_flash, status);
568
569
                /* Return the error.  */
570
                return(status);
571
            }
572
573
            /* Write the final initial erase count for the block.  */
574
1160
            status =  _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_count, 1);
575
576
            /* Check for an error from flash driver. Drivers should never return an error..  */
577
1160
            if (status)
578
            {
579
580
                /* Call system error handler.  */
581
                _lx_nor_flash_system_error(nor_flash, status);
582
583
                /* Return the error.  */
584
                return(status);
585
            }
586
587
            /* Update parameters of this flash.  */
588
1160
            nor_flash -> lx_nor_flash_free_physical_sectors =      nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors;
589
1160
            nor_flash -> lx_nor_flash_obsolete_physical_sectors =  nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors;
590
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
591
592
            /* Check if the block is cached by obsolete count cache.  */
593
            if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
594
            {
595
596
                /* Yes, clear the obsolete count for this block.  */
597
                nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] =  0;
598
            }
599
#endif
600
        }
601
    }
602
603
    /* Return status.  */
604
1160
    return(LX_SUCCESS);
605
}
606