@@ -54,7 +54,11 @@ static const external_flash_device *flash_device = NULL;
5454// cache.
5555static uint32_t dirty_mask ;
5656
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 *))
5862static uint8_t * * flash_cache_table = NULL ;
5963
6064// Wait until both the write enable and write in progress bits have cleared.
@@ -207,7 +211,7 @@ void supervisor_flash_init(void) {
207211 // Delay to give the SPI Flash time to get going.
208212 // TODO(tannewt): Only do this when we know power was applied vs a reset.
209213 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 ++ ) {
211215 if (possible_devices [i ].start_up_time_us > max_start_up_delay_us ) {
212216 max_start_up_delay_us = possible_devices [i ].start_up_time_us ;
213217 }
@@ -219,7 +223,7 @@ void supervisor_flash_init(void) {
219223 #ifdef EXTERNAL_FLASH_NO_JEDEC
220224 // For NVM that don't have JEDEC response
221225 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 ++ ) {
223227 const external_flash_device * possible_device = & possible_devices [i ];
224228 flash_device = possible_device ;
225229 break ;
@@ -234,7 +238,7 @@ void supervisor_flash_init(void) {
234238 while ((count -- > 0 ) && (jedec_id_response [0 ] == 0xff || jedec_id_response [2 ] == 0x00 )) {
235239 spi_flash_read_command (CMD_READ_JEDEC_ID , jedec_id_response , 3 );
236240 }
237- for (uint8_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
241+ for (size_t i = 0 ; i < EXTERNAL_FLASH_DEVICE_COUNT ; i ++ ) {
238242 const external_flash_device * possible_device = & possible_devices [i ];
239243 if (jedec_id_response [0 ] == possible_device -> manufacturer_id &&
240244 jedec_id_response [1 ] == possible_device -> memory_type &&
@@ -323,7 +327,7 @@ static bool flush_scratch_flash(void) {
323327 // cached.
324328 bool copy_to_scratch_ok = true;
325329 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 ++ ) {
327331 if ((dirty_mask & (1 << i )) == 0 ) {
328332 copy_to_scratch_ok = copy_to_scratch_ok &&
329333 copy_block (current_sector + i * FILESYSTEM_BLOCK_SIZE ,
@@ -338,72 +342,70 @@ static bool flush_scratch_flash(void) {
338342 // Second, erase the current sector.
339343 erase_sector (current_sector );
340344 // 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 ++ ) {
342346 copy_block (scratch_sector + i * FILESYSTEM_BLOCK_SIZE ,
343347 current_sector + i * FILESYSTEM_BLOCK_SIZE );
344348 }
345349 return true;
346350}
347351
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+
348369// Attempts to allocate a new set of page buffers for caching a full sector in
349370// ram. Each page is allocated separately so that the GC doesn't need to provide
350371// one huge block. We can free it as we write if we want to also.
351372static 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 ++ ) {
366385 uint8_t * page_cache = port_malloc (SPI_FLASH_PAGE_SIZE , false);
367386 if (page_cache == NULL ) {
368387 success = false;
369388 break ;
370389 }
371- flash_cache_table [i * pages_per_block + j ] = page_cache ;
390+ flash_cache_table [i * PAGES_PER_BLOCK + j ] = page_cache ;
372391 }
373392 }
393+
374394 // We couldn't allocate enough so give back what we got.
375395 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 ();
387397 }
388398 return success ;
389399}
390400
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-
404401// Flush the cached sector from ram onto the flash. We'll free the cache unless
405402// keep_cache is true.
406403static 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+
407409 if (current_sector == NO_SECTOR_LOADED ) {
408410 if (!keep_cache ) {
409411 release_ram_cache ();
@@ -414,13 +416,12 @@ static bool flush_ram_cache(bool keep_cache) {
414416 // we've cached. If we don't do this we'll erase the data during the sector
415417 // erase below.
416418 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 ++ ) {
419420 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 ++ ) {
421422 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 ],
424425 SPI_FLASH_PAGE_SIZE );
425426 if (!copy_to_ram_ok ) {
426427 break ;
@@ -438,10 +439,10 @@ static bool flush_ram_cache(bool keep_cache) {
438439 // Second, erase the current sector.
439440 erase_sector (current_sector );
440441 // 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 ],
445446 SPI_FLASH_PAGE_SIZE );
446447 }
447448 }
@@ -496,15 +497,14 @@ static bool external_flash_read_block(uint8_t *dest, uint32_t block) {
496497
497498 // Mask out the lower bits that designate the address within the sector.
498499 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 );
501502 // We're reading from the currently cached sector.
502503 if (current_sector == this_sector && (mask & dirty_mask ) > 0 ) {
503504 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 ++ ) {
506506 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 ],
508508 SPI_FLASH_PAGE_SIZE );
509509 }
510510 return true;
@@ -527,8 +527,8 @@ static bool external_flash_write_block(const uint8_t *data, uint32_t block) {
527527 wait_for_flash_ready ();
528528 // Mask out the lower bits that designate the address within the sector.
529529 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 );
532532 // Flush the cache if we're moving onto a sector or we're writing the
533533 // same block again.
534534 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) {
550550 dirty_mask |= mask ;
551551 // Copy the block to the appropriate cache.
552552 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 ],
556555 data + i * SPI_FLASH_PAGE_SIZE ,
557556 SPI_FLASH_PAGE_SIZE );
558557 }
0 commit comments