@@ -54,7 +54,11 @@ static const external_flash_device *flash_device = NULL;
54
54
// cache.
55
55
static uint32_t dirty_mask ;
56
56
57
- // Table of pointers to each cached block
57
+ // Table of pointers to each cached block. Should be zero'd after allocation.
58
+ #define BLOCKS_PER_SECTOR (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE)
59
+ #define PAGES_PER_BLOCK (FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE)
60
+ #define FLASH_CACHE_TABLE_NUM_ENTRIES (BLOCKS_PER_SECTOR * PAGES_PER_BLOCK)
61
+ #define FLASH_CACHE_TABLE_SIZE (FLASH_CACHE_TABLE_NUM_ENTRIES * sizeof (uint8_t *))
58
62
static uint8_t * * flash_cache_table = NULL ;
59
63
60
64
// Wait until both the write enable and write in progress bits have cleared.
@@ -207,7 +211,7 @@ void supervisor_flash_init(void) {
207
211
// Delay to give the SPI Flash time to get going.
208
212
// TODO(tannewt): Only do this when we know power was applied vs a reset.
209
213
uint16_t max_start_up_delay_us = 0 ;
210
- for (uint8_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
214
+ for (size_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
211
215
if (possible_devices [i ].start_up_time_us > max_start_up_delay_us ) {
212
216
max_start_up_delay_us = possible_devices [i ].start_up_time_us ;
213
217
}
@@ -219,7 +223,7 @@ void supervisor_flash_init(void) {
219
223
#ifdef EXTERNAL_FLASH_NO_JEDEC
220
224
// For NVM that don't have JEDEC response
221
225
spi_flash_command (CMD_WAKE );
222
- for (uint8_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
226
+ for (size_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
223
227
const external_flash_device * possible_device = & possible_devices [i ];
224
228
flash_device = possible_device ;
225
229
break ;
@@ -234,7 +238,7 @@ void supervisor_flash_init(void) {
234
238
while ((count -- > 0 ) && (jedec_id_response [0 ] == 0xff || jedec_id_response [2 ] == 0x00 )) {
235
239
spi_flash_read_command (CMD_READ_JEDEC_ID , jedec_id_response , 3 );
236
240
}
237
- for (uint8_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
241
+ for (size_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
238
242
const external_flash_device * possible_device = & possible_devices [i ];
239
243
if (jedec_id_response [0 ] == possible_device -> manufacturer_id &&
240
244
jedec_id_response [1 ] == possible_device -> memory_type &&
@@ -323,7 +327,7 @@ static bool flush_scratch_flash(void) {
323
327
// cached.
324
328
bool copy_to_scratch_ok = true;
325
329
uint32_t scratch_sector = flash_device -> total_size - SPI_FLASH_ERASE_SIZE ;
326
- for (uint8_t i = 0 ; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ; i ++ ) {
330
+ for (size_t i = 0 ; i < BLOCKS_PER_SECTOR ; i ++ ) {
327
331
if ((dirty_mask & (1 << i )) == 0 ) {
328
332
copy_to_scratch_ok = copy_to_scratch_ok &&
329
333
copy_block (current_sector + i * FILESYSTEM_BLOCK_SIZE ,
@@ -338,72 +342,70 @@ static bool flush_scratch_flash(void) {
338
342
// Second, erase the current sector.
339
343
erase_sector (current_sector );
340
344
// Finally, copy the new version into it.
341
- for (uint8_t i = 0 ; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ; i ++ ) {
345
+ for (size_t i = 0 ; i < BLOCKS_PER_SECTOR ; i ++ ) {
342
346
copy_block (scratch_sector + i * FILESYSTEM_BLOCK_SIZE ,
343
347
current_sector + i * FILESYSTEM_BLOCK_SIZE );
344
348
}
345
349
return true;
346
350
}
347
351
352
+ // Free all entries in the partially or completely filled flash_cache_table, and then free the table itself.
353
+ static void release_ram_cache (void ) {
354
+ if (flash_cache_table == NULL ) {
355
+ return ;
356
+ }
357
+
358
+ for (size_t i = 0 ; i < FLASH_CACHE_TABLE_NUM_ENTRIES ; i ++ ) {
359
+ // Table may not be completely full. Stop at first NULL entry.
360
+ if (flash_cache_table [i ] == NULL ) {
361
+ break ;
362
+ }
363
+ port_free (flash_cache_table [i ]);
364
+ }
365
+ port_free (flash_cache_table );
366
+ flash_cache_table = NULL ;
367
+ }
368
+
348
369
// Attempts to allocate a new set of page buffers for caching a full sector in
349
370
// ram. Each page is allocated separately so that the GC doesn't need to provide
350
371
// one huge block. We can free it as we write if we want to also.
351
372
static bool allocate_ram_cache (void ) {
352
- uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ;
353
- uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE ;
354
-
355
- uint32_t table_size = blocks_per_sector * pages_per_block * sizeof (size_t );
356
- // Attempt to allocate outside the heap first.
357
- flash_cache_table = port_malloc (table_size , false);
358
-
359
- // Declare i and j outside the loops in case we fail to allocate everything
360
- // we need. In that case we'll give it back.
361
- uint8_t i = 0 ;
362
- uint8_t j = 0 ;
363
- bool success = flash_cache_table != NULL ;
364
- for (i = 0 ; i < blocks_per_sector && success ; i ++ ) {
365
- for (j = 0 ; j < pages_per_block && success ; j ++ ) {
373
+ flash_cache_table = port_malloc (FLASH_CACHE_TABLE_SIZE , false);
374
+ if (flash_cache_table == NULL ) {
375
+ // Not enough space even for the cache table.
376
+ return false;
377
+ }
378
+
379
+ // Clear all the entries so it's easy to find the last entry.
380
+ memset (flash_cache_table , 0 , FLASH_CACHE_TABLE_SIZE );
381
+
382
+ bool success = true;
383
+ for (size_t i = 0 ; i < BLOCKS_PER_SECTOR && success ; i ++ ) {
384
+ for (size_t j = 0 ; j < PAGES_PER_BLOCK && success ; j ++ ) {
366
385
uint8_t * page_cache = port_malloc (SPI_FLASH_PAGE_SIZE , false);
367
386
if (page_cache == NULL ) {
368
387
success = false;
369
388
break ;
370
389
}
371
- flash_cache_table [i * pages_per_block + j ] = page_cache ;
390
+ flash_cache_table [i * PAGES_PER_BLOCK + j ] = page_cache ;
372
391
}
373
392
}
393
+
374
394
// We couldn't allocate enough so give back what we got.
375
395
if (!success ) {
376
- // We add 1 so that we delete 0 when i is 1. Going to zero (i >= 0)
377
- // would never stop because i is unsigned.
378
- i ++ ;
379
- for (; i > 0 ; i -- ) {
380
- for (; j > 0 ; j -- ) {
381
- port_free (flash_cache_table [(i - 1 ) * pages_per_block + (j - 1 )]);
382
- }
383
- j = pages_per_block ;
384
- }
385
- port_free (flash_cache_table );
386
- flash_cache_table = NULL ;
396
+ release_ram_cache ();
387
397
}
388
398
return success ;
389
399
}
390
400
391
- static void release_ram_cache (void ) {
392
- uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ;
393
- uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE ;
394
- for (uint8_t i = 0 ; i < blocks_per_sector ; i ++ ) {
395
- for (uint8_t j = 0 ; j < pages_per_block ; j ++ ) {
396
- uint32_t offset = i * pages_per_block + j ;
397
- port_free (flash_cache_table [offset ]);
398
- }
399
- }
400
- port_free (flash_cache_table );
401
- flash_cache_table = NULL ;
402
- }
403
-
404
401
// Flush the cached sector from ram onto the flash. We'll free the cache unless
405
402
// keep_cache is true.
406
403
static bool flush_ram_cache (bool keep_cache ) {
404
+ if (flash_cache_table == NULL ) {
405
+ // Nothing to flush because there is no cache.
406
+ return true;
407
+ }
408
+
407
409
if (current_sector == NO_SECTOR_LOADED ) {
408
410
if (!keep_cache ) {
409
411
release_ram_cache ();
@@ -414,13 +416,12 @@ static bool flush_ram_cache(bool keep_cache) {
414
416
// we've cached. If we don't do this we'll erase the data during the sector
415
417
// erase below.
416
418
bool copy_to_ram_ok = true;
417
- uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE ;
418
- for (uint8_t i = 0 ; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ; i ++ ) {
419
+ for (size_t i = 0 ; i < BLOCKS_PER_SECTOR ; i ++ ) {
419
420
if ((dirty_mask & (1 << i )) == 0 ) {
420
- for (uint8_t j = 0 ; j < pages_per_block ; j ++ ) {
421
+ for (size_t j = 0 ; j < PAGES_PER_BLOCK ; j ++ ) {
421
422
copy_to_ram_ok = read_flash (
422
- current_sector + (i * pages_per_block + j ) * SPI_FLASH_PAGE_SIZE ,
423
- flash_cache_table [i * pages_per_block + j ],
423
+ current_sector + (i * PAGES_PER_BLOCK + j ) * SPI_FLASH_PAGE_SIZE ,
424
+ flash_cache_table [i * PAGES_PER_BLOCK + j ],
424
425
SPI_FLASH_PAGE_SIZE );
425
426
if (!copy_to_ram_ok ) {
426
427
break ;
@@ -438,10 +439,10 @@ static bool flush_ram_cache(bool keep_cache) {
438
439
// Second, erase the current sector.
439
440
erase_sector (current_sector );
440
441
// Lastly, write all the data in ram that we've cached.
441
- for (uint8_t i = 0 ; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ; i ++ ) {
442
- for (uint8_t j = 0 ; j < pages_per_block ; j ++ ) {
443
- write_flash (current_sector + (i * pages_per_block + j ) * SPI_FLASH_PAGE_SIZE ,
444
- flash_cache_table [i * pages_per_block + j ],
442
+ for (size_t i = 0 ; i < BLOCKS_PER_SECTOR ; i ++ ) {
443
+ for (size_t j = 0 ; j < PAGES_PER_BLOCK ; j ++ ) {
444
+ write_flash (current_sector + (i * PAGES_PER_BLOCK + j ) * SPI_FLASH_PAGE_SIZE ,
445
+ flash_cache_table [i * PAGES_PER_BLOCK + j ],
445
446
SPI_FLASH_PAGE_SIZE );
446
447
}
447
448
}
@@ -496,15 +497,14 @@ static bool external_flash_read_block(uint8_t *dest, uint32_t block) {
496
497
497
498
// Mask out the lower bits that designate the address within the sector.
498
499
uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1 ));
499
- uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE ) % ( SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ) ;
500
- uint8_t mask = 1 << (block_index );
500
+ size_t block_index = (address / FILESYSTEM_BLOCK_SIZE ) % BLOCKS_PER_SECTOR ;
501
+ uint32_t mask = 1 << (block_index );
501
502
// We're reading from the currently cached sector.
502
503
if (current_sector == this_sector && (mask & dirty_mask ) > 0 ) {
503
504
if (flash_cache_table != NULL ) {
504
- uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE ;
505
- for (int i = 0 ; i < pages_per_block ; i ++ ) {
505
+ for (int i = 0 ; i < PAGES_PER_BLOCK ; i ++ ) {
506
506
memcpy (dest + i * SPI_FLASH_PAGE_SIZE ,
507
- flash_cache_table [block_index * pages_per_block + i ],
507
+ flash_cache_table [block_index * PAGES_PER_BLOCK + i ],
508
508
SPI_FLASH_PAGE_SIZE );
509
509
}
510
510
return true;
@@ -527,8 +527,8 @@ static bool external_flash_write_block(const uint8_t *data, uint32_t block) {
527
527
wait_for_flash_ready ();
528
528
// Mask out the lower bits that designate the address within the sector.
529
529
uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1 ));
530
- uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE ) % ( SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE ) ;
531
- uint8_t mask = 1 << (block_index );
530
+ size_t block_index = (address / FILESYSTEM_BLOCK_SIZE ) % BLOCKS_PER_SECTOR ;
531
+ uint32_t mask = 1 << (block_index );
532
532
// Flush the cache if we're moving onto a sector or we're writing the
533
533
// same block again.
534
534
if (current_sector != this_sector || (mask & dirty_mask ) > 0 ) {
@@ -550,9 +550,8 @@ static bool external_flash_write_block(const uint8_t *data, uint32_t block) {
550
550
dirty_mask |= mask ;
551
551
// Copy the block to the appropriate cache.
552
552
if (flash_cache_table != NULL ) {
553
- uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE ;
554
- for (int i = 0 ; i < pages_per_block ; i ++ ) {
555
- memcpy (flash_cache_table [block_index * pages_per_block + i ],
553
+ for (int i = 0 ; i < PAGES_PER_BLOCK ; i ++ ) {
554
+ memcpy (flash_cache_table [block_index * PAGES_PER_BLOCK + i ],
556
555
data + i * SPI_FLASH_PAGE_SIZE ,
557
556
SPI_FLASH_PAGE_SIZE );
558
557
}
0 commit comments