diff --git a/common/inc/lx_api.h b/common/inc/lx_api.h index 314831a..e556902 100644 --- a/common/inc/lx_api.h +++ b/common/inc/lx_api.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* lx_api.h PORTABLE C */ -/* 6.2.1 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -79,7 +79,13 @@ /* modified NAND logic, */ /* added new driver interface */ /* and user extension, */ -/* resulting in version 6.2.1 */ +/* resulting in version 6.2.1 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* made LX_NOR_SECTOR_SIZE */ +/* configurable, added mapping */ +/* bitmap and obsolete count */ +/* cache for NOR flash, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ @@ -191,8 +197,8 @@ typedef unsigned long long ULONG64; /* Define basic constants for the LevelX Stack. */ #define AZURE_RTOS_LEVELX #define LEVELX_MAJOR_VERSION 6 -#define LEVELX_MINOR_VERSION 2 -#define LEVELX_PATCH_VERSION 1 +#define LEVELX_MINOR_VERSION 3 +#define LEVELX_PATCH_VERSION 0 /* Define general LevelX Constants. */ @@ -233,7 +239,9 @@ typedef unsigned long long ULONG64; #define LX_NOR_FLASH_OPENED ((ULONG) 0x4E4F524F) #define LX_NOR_FLASH_CLOSED ((ULONG) 0x4E4F5244) +#ifndef LX_NOR_SECTOR_SIZE #define LX_NOR_SECTOR_SIZE (512/sizeof(ULONG)) +#endif #define LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET 1 #define LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET 2 #ifndef LX_NOR_FLASH_MAX_ERASE_COUNT_DELTA @@ -246,6 +254,11 @@ typedef unsigned long long ULONG64; #ifndef LX_NOR_EXTENDED_CACHE_SIZE #define LX_NOR_EXTENDED_CACHE_SIZE 8 /* Maximum number of extended cache sectors. */ #endif +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +#ifndef LX_NOR_OBSOLETE_COUNT_CACHE_TYPE +#define LX_NOR_OBSOLETE_COUNT_CACHE_TYPE UCHAR +#endif +#endif /* Define the mask for the hash index into the sector mapping cache table. The sector mapping cache is divided @@ -566,6 +579,7 @@ typedef struct LX_NOR_FLASH_STRUCT ULONG lx_nor_flash_mapped_physical_sectors; ULONG lx_nor_flash_obsolete_physical_sectors; ULONG lx_nor_flash_minimum_erase_count; + ULONG lx_nor_flash_minimum_erased_blocks; ULONG lx_nor_flash_maximum_erase_count; ULONG lx_nor_flash_free_block_search; @@ -616,6 +630,15 @@ typedef struct LX_NOR_FLASH_STRUCT lx_nor_flash_extended_cache[LX_NOR_EXTENDED_CACHE_SIZE]; ULONG lx_nor_flash_extended_cache_hits; ULONG lx_nor_flash_extended_cache_misses; +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP + ULONG *lx_nor_flash_extended_cache_mapping_bitmap; + ULONG lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector; +#endif +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + LX_NOR_OBSOLETE_COUNT_CACHE_TYPE + *lx_nor_flash_extended_cache_obsolete_count; + ULONG lx_nor_flash_extended_cache_obsolete_count_max_block; +#endif #endif #ifdef LX_THREAD_SAFE_ENABLE diff --git a/common/inc/lx_user_sample.h b/common/inc/lx_user_sample.h index 98777f3..9301a8c 100644 --- a/common/inc/lx_user_sample.h +++ b/common/inc/lx_user_sample.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* lx_user.h PORTABLE C */ -/* 6.2.1 */ +/* 6.3.0 */ /* */ /* AUTHOR */ /* */ @@ -50,7 +50,12 @@ /* resulting in version 6.1.7 */ /* 03-08-2023 Xiuwen Cai Modified comment(s), and */ /* added new NAND options, */ -/* resulting in version 6.2.1 */ +/* resulting in version 6.2.1 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added options for mapping , */ +/* bitmap cache and obsolete */ +/* count cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ @@ -113,15 +118,39 @@ /* #define LX_STANDALONE_ENABLE */ -/* Define user extension for NOR flash control block. */ +/* Define user extension for NOR flash control block. User extension is placed at the end of flash control block and it is not cleared on opening flash. */ /* #define LX_NOR_FLASH_USER_EXTENSION ???? */ -/* Define user extension for NAND flash control block. */ +/* Define user extension for NAND flash control block. User extension is placed at the end of flash control block and it is not cleared on opening flash. */ /* #define LX_NAND_FLASH_USER_EXTENSION ???? */ +/* Determine if logical sector mapping bitmap should be enabled in extended cache. + Cache memory will be allocated to sector mapping bitmap first. One bit can be allocated for each physical sector. */ +/* +#define LX_NOR_ENABLE_MAPPING_BITMAP +*/ + +/* Determine if obsolete count cache should be enabled in extended cache. + Cache memory will be allocated to obsolete count cache after the mapping bitmap if enabled, + and the rest of the cache memory is allocated to sector cache. */ +/* +#define LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +*/ + +/* Defines obsolete count cache element size. If number of sectors per block is greater than 256, use USHORT instead of UCHAR. */ +/* +#define LX_NOR_OBSOLETE_COUNT_CACHE_TYPE UCHAR +*/ + +/* Define the logical sector size for NOR flash. The sector size is in units of 32-bit words. + This sector size should match the sector size used in file system. */ +/* +#define LX_NOR_SECTOR_SIZE (512/sizeof(ULONG)) +*/ + #endif diff --git a/common/src/fx_nor_flash_simulator_driver.c b/common/src/fx_nor_flash_simulator_driver.c index 304e80b..b575485 100644 --- a/common/src/fx_nor_flash_simulator_driver.c +++ b/common/src/fx_nor_flash_simulator_driver.c @@ -36,19 +36,19 @@ LX_NOR_FLASH nor_flash; the fx_media_open call. fx_media_format(&ram_disk, - _fx_nor_sim_driver, // Driver entry - FX_NULL, // Unused - media_memory, // Media buffer pointer - sizeof(media_memory), // Media buffer size - "MY_NOR_DISK", // Volume Name - 1, // Number of FATs - 32, // Directory Entries - 0, // Hidden sectors - 120, // Total sectors - 512, // Sector size - 1, // Sectors per cluster - 1, // Heads - 1); // Sectors per track + _fx_nor_sim_driver, // Driver entry + FX_NULL, // Unused + media_memory, // Media buffer pointer + sizeof(media_memory), // Media buffer size + "MY_NOR_DISK", // Volume Name + 1, // Number of FATs + 32, // Directory Entries + 0, // Hidden sectors + 120, // Total sectors + LX_NOR_SECTOR_SIZE * sizeof(ULONG), // Sector size + 1, // Sectors per cluster + 1, // Heads + 1); // Sectors per track */ @@ -231,7 +231,7 @@ UINT status; /* Move to the next entries. */ logical_sector++; - destination_buffer = destination_buffer + 512; + destination_buffer = destination_buffer + media_ptr -> fx_media_bytes_per_sector; } /* Successful driver request. */ @@ -265,7 +265,7 @@ UINT status; /* Move to the next entries. */ logical_sector++; - source_buffer = source_buffer + 512; + source_buffer = source_buffer + media_ptr -> fx_media_bytes_per_sector; } /* Successful driver request. */ @@ -428,6 +428,15 @@ UINT status; case FX_DRIVER_BOOT_WRITE: { + /* Make sure the media bytes per sector equals to the LevelX logical sector size. */ + if (media_ptr -> fx_media_bytes_per_sector != (LX_NOR_SECTOR_SIZE) * sizeof(ULONG)) + { + + /* Sector size mismatch, return error. */ + media_ptr -> fx_media_driver_status = FX_IO_ERROR; + break; + } + /* Write the boot record and return to the caller. */ /* Setup the source buffer. */ diff --git a/common/src/lx_nand_flash_format.c b/common/src/lx_nand_flash_format.c index 83d2432..1d3ee62 100644 --- a/common/src/lx_nand_flash_format.c +++ b/common/src/lx_nand_flash_format.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nand_flash_format PORTABLE C */ -/* 6.2.1 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* Xiuwen Cai, Microsoft Corporation */ @@ -87,7 +87,12 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */ +/* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* avoided clearing user */ +/* extension in flash control */ +/* block, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nand_flash_format(LX_NAND_FLASH* nand_flash, CHAR* name, @@ -102,8 +107,8 @@ UCHAR *page_buffer_ptr; LX_PARAMETER_NOT_USED(name); - /* Clear the NAND flash control block. */ - LX_MEMSET(nand_flash, 0, sizeof(LX_NAND_FLASH)); + /* Clear the NAND flash control block. User extension is not cleared. */ + LX_MEMSET(nand_flash, 0, (ULONG)((UCHAR*)&(nand_flash -> lx_nand_flash_open_previous) - (UCHAR*)nand_flash) + sizeof(nand_flash -> lx_nand_flash_open_previous)); /* Call the flash driver's initialization function. */ (nand_driver_initialize)(nand_flash); diff --git a/common/src/lx_nand_flash_open.c b/common/src/lx_nand_flash_open.c index b6a5b27..adbb322 100644 --- a/common/src/lx_nand_flash_open.c +++ b/common/src/lx_nand_flash_open.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nand_flash_open PORTABLE C */ -/* 6.2.1 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* Xiuwen Cai, Microsoft Corporation */ @@ -85,7 +85,12 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */ +/* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* avoided clearing user */ +/* extension in flash control */ +/* block, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nand_flash_open(LX_NAND_FLASH *nand_flash, CHAR *name, UINT (*nand_driver_initialize)(LX_NAND_FLASH *), @@ -107,9 +112,9 @@ LX_INTERRUPT_SAVE_AREA LX_PARAMETER_NOT_USED(name); - /* Clear the NAND flash control block. */ - LX_MEMSET(nand_flash, 0, sizeof(LX_NAND_FLASH)); - + /* Clear the NAND flash control block. User extension is not cleared. */ + LX_MEMSET(nand_flash, 0, (ULONG)((UCHAR*)&(nand_flash -> lx_nand_flash_open_previous) - (UCHAR*)nand_flash) + sizeof(nand_flash -> lx_nand_flash_open_previous)); + /* Call the flash driver's initialization function. */ (nand_driver_initialize)(nand_flash); diff --git a/common/src/lx_nor_flash_block_reclaim.c b/common/src/lx_nor_flash_block_reclaim.c index eea676d..16f516c 100644 --- a/common/src/lx_nor_flash_block_reclaim.c +++ b/common/src/lx_nor_flash_block_reclaim.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_block_reclaim PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -83,6 +83,11 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added count for minimum */ +/* erased blocks, added */ +/* obsolete count cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_block_reclaim(LX_NOR_FLASH *nor_flash) @@ -156,7 +161,15 @@ UINT status; /* Return the error. */ return(status); } - + + /* Determine if the erase count is at the minimum. */ + if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count) + { + + /* Yes, decrement the minimum erased block count. */ + nor_flash -> lx_nor_flash_minimum_erased_blocks--; + } + /* Increment the erase count. */ erase_count++; @@ -225,6 +238,16 @@ UINT status; /* Update parameters of this flash. */ nor_flash -> lx_nor_flash_free_physical_sectors = nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors; nor_flash -> lx_nor_flash_obsolete_physical_sectors = nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Check if the block is cached by obsolete count cache. */ + if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Yes, clear the obsolete count for this block. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] = 0; + } +#endif } else { @@ -489,6 +512,14 @@ UINT status; return(status); } + /* Determine if the erase count is at the minimum. */ + if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count) + { + + /* Yes, decrement the minimum erased block count. */ + nor_flash -> lx_nor_flash_minimum_erased_blocks--; + } + /* Increment the erase count. */ erase_count++; @@ -557,6 +588,16 @@ UINT status; /* Update parameters of this flash. */ nor_flash -> lx_nor_flash_free_physical_sectors = nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors; nor_flash -> lx_nor_flash_obsolete_physical_sectors = nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Check if the block is cached by obsolete count cache. */ + if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Yes, clear the obsolete count for this block. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] = 0; + } +#endif } } diff --git a/common/src/lx_nor_flash_extended_cache_enable.c b/common/src/lx_nor_flash_extended_cache_enable.c index c7c1269..27c8049 100644 --- a/common/src/lx_nor_flash_extended_cache_enable.c +++ b/common/src/lx_nor_flash_extended_cache_enable.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_extended_cache_enable PORTABLE C */ -/* 6.1.9 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -84,6 +84,10 @@ /* added check for out of */ /* bound memory access, */ /* resulting in version 6.1.9 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* added obsolete count cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, ULONG size) @@ -93,6 +97,22 @@ UINT _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, UINT i; ULONG cache_size; ULONG *cache_memory; +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP +ULONG mapping_bitmap_words; +ULONG mapping_bitmap_word; +ULONG logical_sector; +ULONG *mapping_bitmap_ptr; +#endif +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +ULONG obsolete_count_words; +ULONG obsolete_sectors; +#endif +#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) +ULONG *block_word_ptr; +UINT j; +UINT status; +ULONG block_word; +#endif /* Determine if memory was specified but with an invalid size (less than one NOR sector). */ @@ -118,6 +138,157 @@ ULONG *cache_memory; /* Setup cache memory pointer. */ cache_memory = (ULONG *) memory; +#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) + + /* Check if the NOR flash is opened. */ + if (nor_flash -> lx_nor_flash_state == LX_NOR_FLASH_OPENED) + { +#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) + + /* Get the mapping bitmap cache size. */ + mapping_bitmap_words = (nor_flash -> lx_nor_flash_total_physical_sectors + 31) / 32; + + /* Check if the mapping bitmap cache fits in the suppiled cache memory. */ + if (cache_size < mapping_bitmap_words) + { + + /* Update the cache size. */ + mapping_bitmap_words = cache_size; + } + + /* Setup the mapping bitmap cache. */ + nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap = cache_memory; + + /* Setup the mapping bitmap cache size. */ + nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector = mapping_bitmap_words * 32; + + /* Clear the mapping bitmap cache. */ + for (i = 0; i < mapping_bitmap_words; i++) + { + cache_memory[i] = 0; + } + + /* Update the cache memory pointer. */ + mapping_bitmap_ptr = cache_memory; + + /* Update the cache size. */ + cache_size = cache_size - mapping_bitmap_words; + + /* Update the cache memory pointer. */ + cache_memory = cache_memory + mapping_bitmap_words; +#endif + +#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) + + /* Get the obsolete count cache size. */ + obsolete_count_words = nor_flash -> lx_nor_flash_total_blocks * sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE) / 4; + + /* Check if the obsolete count cache fits in the suppiled cache memory. */ + if (cache_size < obsolete_count_words) + { + + /* Update the cache size. */ + obsolete_count_words = cache_size; + } + + /* Setup the obsolete count cache. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE*)cache_memory; + + /* Setup the obsolete count cache size. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block = obsolete_count_words * 4 / sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE); + + /* Update the cache size. */ + cache_size = cache_size - obsolete_count_words; + + /* Update the cache memory pointer. */ + cache_memory = cache_memory + obsolete_count_words; +#endif + + /* Loop through the blocks. */ + for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++) + { + /* Setup the block word pointer to the first word of the block. */ + block_word_ptr = (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block)); + +#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) + + /* Initialize the obsolete count cache. */ + obsolete_sectors = 0; +#endif + + /* Now walk the list of logical-physical sector mapping. */ + for (j = 0; j < nor_flash ->lx_nor_flash_physical_sectors_per_block; j++) + { + + /* Read this word of the sector mapping list. */ +#ifdef LX_DIRECT_READ + + /* Read the word directly. */ + block_word = *(block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j); +#else + status = _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j), &block_word, 1); + + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) + { + + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); + + /* Return an error. */ + return(LX_ERROR); + } +#endif + /* Determine if the entry hasn't been used. */ + if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE) + { + break; + } + + /* Is this entry valid? */ + if ((block_word & (LX_NOR_PHYSICAL_SECTOR_VALID | LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID)) == LX_NOR_PHYSICAL_SECTOR_VALID) + { +#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) + + /* Yes, get the logical sector. */ + logical_sector = block_word & LX_NOR_LOGICAL_SECTOR_MASK; + + /* Get the mapping bitmap word. */ + mapping_bitmap_word = logical_sector >> 5; + + /* Check if the mapping bitmap word is within the cache. */ + if (mapping_bitmap_word < mapping_bitmap_words) + { + + /* Set the bit in the mapping bitmap. */ + mapping_bitmap_ptr[mapping_bitmap_word] |= (ULONG)(1 << (logical_sector & 31)); + } +#endif + + } + else + { +#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) + + /* Increment the obsolete sector count. */ + obsolete_sectors++; +#endif + } + } +#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) + + /* Check if the block is cached by obsolete count cache. */ + if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Yes, cache the obsolete sector count. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE)obsolete_sectors; + } +#endif + } + } +#endif + /* Loop through the memory supplied and assign to cache entries. */ i = 0; while (cache_size >= LX_NOR_SECTOR_SIZE) diff --git a/common/src/lx_nor_flash_logical_sector_find.c b/common/src/lx_nor_flash_logical_sector_find.c index f467724..f873258 100644 --- a/common/src/lx_nor_flash_logical_sector_find.c +++ b/common/src/lx_nor_flash_logical_sector_find.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_logical_sector_find PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -70,6 +70,7 @@ /* CALLS */ /* */ /* _lx_nor_flash_driver_read Driver flash sector read */ +/* _lx_nor_flash_driver_write Driver flash sector write */ /* _lx_nor_flash_system_error Internal system error handler */ /* */ /* CALLED BY */ @@ -85,6 +86,12 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* added obsolete count cache, */ +/* optimized full obsoleted */ +/* block searching logic, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_logical_sector_find(LX_NOR_FLASH *nor_flash, ULONG logical_sector, ULONG superceded_check, ULONG **physical_sector_map_entry, ULONG **physical_sector_address) @@ -102,7 +109,10 @@ ULONG i, j; ULONG search_start; LX_NOR_SECTOR_MAPPING_CACHE_ENTRY *sector_mapping_cache_entry_ptr = LX_NULL; LX_NOR_SECTOR_MAPPING_CACHE_ENTRY temp_sector_mapping_cache_entry; -#ifndef LX_DIRECT_READ +#ifndef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +ULONG valid_sector_found; +#endif +#if !defined(LX_DIRECT_READ) || !defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE) UINT status; #endif @@ -118,6 +128,24 @@ UINT status; /* No mapped sector so nothing can be found!. */ return(LX_SECTOR_NOT_FOUND); } + +#ifndef LX_NOR_DISABLE_EXTENDED_CACHE +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP + + /* Determine if the logical sector is in the range of mapping bitmap cache. */ + if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector) + { + + /* Determine if the logical sector is mapped. */ + if ((nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] & (ULONG)(1 << (logical_sector & 31))) == 0) + { + + /* Not mapped, return not found. */ + return(LX_SECTOR_NOT_FOUND); + } + } +#endif +#endif /* Determine if the sector mapping cache is enabled. */ if (nor_flash -> lx_nor_flash_sector_mapping_cache_enabled) @@ -223,6 +251,36 @@ UINT status; /* Loop through the blocks to attempt to find the mapped logical sector. */ while (total_blocks--) { + +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + /* Determine if the obsolete sector count is available in the cache. */ + if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Check if the block contains obsolete sectors only. */ + if ((ULONG)nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] == nor_flash -> lx_nor_flash_physical_sectors_per_block) + { + + /* Move to the next block. */ + i++; + + /* Determine if we have wrapped. */ + if (i >= nor_flash -> lx_nor_flash_total_blocks) + { + + /* Yes, we have wrapped, set to block 0. */ + i = 0; + } + + /* Start at the first sector in the next block. */ + j = 0; + + /* No point in looking further into this block, just continue the loop. */ + continue; + + } + } +#endif /* Setup the block word pointer to the first word of the search block. */ block_word_ptr = (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block)); @@ -249,52 +307,68 @@ UINT status; return(status); } #endif + + /* Is the value valid? */ + if (min_logical_sector != LX_ALL_ONES) + { #ifdef LX_DIRECT_READ - /* Read the word directly. */ - max_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET); + /* Read the word directly. */ + max_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET); #else - status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1); + status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1); - /* Check for an error from flash driver. Drivers should never return an error.. */ - if (status) - { - - /* Call system error handler. */ - _lx_nor_flash_system_error(nor_flash, status); + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) + { + + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); - /* Return the error. */ - return(status); - } + /* Return the error. */ + return(status); + } #endif - /* Are the values valid? */ - if ((min_logical_sector != LX_ALL_ONES) && (max_logical_sector != LX_ALL_ONES)) - { - - /* Now let's check to see if the search sector is within this range. */ - if ((logical_sector < min_logical_sector) || (logical_sector > max_logical_sector)) + /* Is the value valid? */ + if (max_logical_sector != LX_ALL_ONES) { - /* Move to the next block. */ - i++; - - /* Determine if we have wrapped. */ - if (i >= nor_flash -> lx_nor_flash_total_blocks) + /* Now let's check to see if the search sector is within this range. */ + if ((logical_sector < min_logical_sector) || (logical_sector > max_logical_sector)) { - - /* Yes, we have wrapped, set to block 0. */ - i = 0; - } - /* Start at the first sector in the next block. */ - j = 0; - - /* No point in looking further into this block, just continue the loop. */ - continue; + /* Move to the next block. */ + i++; + + /* Determine if we have wrapped. */ + if (i >= nor_flash -> lx_nor_flash_total_blocks) + { + + /* Yes, we have wrapped, set to block 0. */ + i = 0; + } + + /* Start at the first sector in the next block. */ + j = 0; + + /* No point in looking further into this block, just continue the loop. */ + continue; + } } } - + else + { + + /* Set the max logical sector to all ones. */ + max_logical_sector = LX_ALL_ONES; + } +#ifndef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Clear the valid sector found flag. */ + valid_sector_found = LX_FALSE; +#endif + /* Setup the total number of sectors. */ total_sectors = nor_flash -> lx_nor_flash_physical_sectors_per_block; @@ -440,6 +514,11 @@ UINT status; return(LX_SUCCESS); } } +#ifndef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Set the valid sector found flag. */ + valid_sector_found = LX_TRUE; +#endif } /* Move to the next list entry. */ @@ -453,6 +532,29 @@ UINT status; j = 0; } } +#ifndef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + /* Check if the block contains no valid sectors. */ + if ((valid_sector_found == LX_FALSE) && (max_logical_sector != LX_ALL_ONES)) + { + + /* Clear max logical sector to indicate sectors are all obsoleted. */ + max_logical_sector = 0; + + /* Write the max logical sector to the block header. */ + status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1); + + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) + { + + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); + + /* Return the error. */ + return(status); + } + } +#endif /* Determine if there are any more mapped sectors. */ if (mapped_sectors == 0) diff --git a/common/src/lx_nor_flash_next_block_to_erase_find.c b/common/src/lx_nor_flash_next_block_to_erase_find.c index 51d5b4a..d50aadd 100644 --- a/common/src/lx_nor_flash_next_block_to_erase_find.c +++ b/common/src/lx_nor_flash_next_block_to_erase_find.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_next_block_to_erase_find PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -81,6 +81,12 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* added obsolete count cache, */ +/* optimized full obsoleted */ +/* block searching logic, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_next_block_to_erase_find(LX_NOR_FLASH *nor_flash, ULONG *return_erase_block, ULONG *return_erase_count, ULONG *return_mapped_sectors, ULONG *return_obsolete_sectors) @@ -97,16 +103,23 @@ ULONG min_block_erase = 0; ULONG min_block_erase_count; ULONG min_block_obsolete_count = 0; ULONG min_block_mapped_count = 0; +ULONG min_block_mapped_count_available = LX_FALSE; ULONG max_obsolete_sectors; ULONG max_obsolete_block = 0; ULONG max_obsolete_erase_count = 0; ULONG max_obsolete_mapped_count = 0; +ULONG max_obsolete_mapped_count_available = LX_FALSE; ULONG min_system_block_erase_count; +ULONG system_min_erased_blocks; ULONG max_system_block_erase_count; ULONG erase_count_threshold; +ULONG min_logical_sector; +ULONG max_logical_sector; #ifndef LX_DIRECT_READ UINT status; #endif +UINT obsolete_sectors_available; +UINT mapped_sectors_available; /* Setup the block word pointer to the first word of the search block. */ @@ -117,6 +130,7 @@ UINT status; /* Initialize the system minimum and maximum erase counts. */ min_system_block_erase_count = LX_ALL_ONES; + system_min_erased_blocks = 0; max_system_block_erase_count = 0; /* Initialize the maximum obsolete sector count. */ @@ -161,34 +175,71 @@ UINT status; #endif /* Update the system minimum and maximum erase counts. */ + if (erase_count == min_system_block_erase_count) + { + system_min_erased_blocks ++; + } if (erase_count < min_system_block_erase_count) + { min_system_block_erase_count = erase_count; + system_min_erased_blocks = 1; + } if (erase_count > max_system_block_erase_count) max_system_block_erase_count = erase_count; - /* Compute the number of obsolete and mapped sectors for this block. */ - obsolete_sectors = 0; - mapped_sectors = 0; + /* Initialize the obsolete and mapped sector count available flags. */ + obsolete_sectors_available = LX_FALSE; + mapped_sectors_available = LX_FALSE; - /* Setup a pointer to the mapped list. */ - list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE - /* Loop through the mapped list for this block. */ - for (j = 0; j < nor_flash -> lx_nor_flash_physical_sectors_per_block; j++) + /* Determine if the obsolete sector count is available in the cache. */ + if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Yes, the obsolete sector count is available. */ + obsolete_sectors_available = LX_TRUE; + + /* Pickup the obsolete sector count from the cache. */ + obsolete_sectors = (ULONG)nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i]; + } + else + { +#endif + /* Read the minimum and maximum logical sector values in this block. */ +#ifdef LX_DIRECT_READ + + /* Read the word directly. */ + min_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET); +#else + status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET, &min_logical_sector, 1); + + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) { - /* Read the current mapping entry. */ + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); + + /* Return the error. */ + return(status); + } +#endif + + /* Determine if the minimum logical sector is valid. */ + if (min_logical_sector != LX_ALL_ONES) + { #ifdef LX_DIRECT_READ /* Read the word directly. */ - list_word = *(list_word_ptr); + max_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET); #else - status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1); + status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1); /* Check for an error from flash driver. Drivers should never return an error.. */ if (status) { - + /* Call system error handler. */ _lx_nor_flash_system_error(nor_flash, status); @@ -196,33 +247,104 @@ UINT status; return(status); } #endif - - /* Determine if the entry hasn't been used. */ - if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE) - { - - /* Since allocations are done sequentially in the block, we know nothing - else exists after this point. */ - break; - } - - /* Is this entry obsolete? */ - if ((list_word & LX_NOR_PHYSICAL_SECTOR_VALID) == 0) - { - - /* Increment the number of obsolete sectors. */ - obsolete_sectors++; - } - else - { - - /* Increment the number of mapped sectors. */ - mapped_sectors++; - } - /* Move the list pointer ahead. */ - list_word_ptr++; + /* Are the values valid? */ + /* Now let's check to see if all the sector are obsoleted. */ + if ((max_logical_sector != LX_ALL_ONES) && (max_logical_sector < min_logical_sector)) + { + + obsolete_sectors_available = LX_TRUE; + obsolete_sectors = nor_flash -> lx_nor_flash_physical_sectors_per_block; + } } +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + } +#endif + + /* Determine if the mapped sector count is available. */ + if (obsolete_sectors_available == LX_FALSE) + { + + /* Compute the number of obsolete and mapped sectors for this block. */ + + /* Initialize the obsolete and mapped sector counts. */ + obsolete_sectors = 0; + mapped_sectors = 0; + + /* Set the mapped sector count and obsolete sector count available flags. */ + mapped_sectors_available = LX_TRUE; + obsolete_sectors_available = LX_TRUE; + + /* Setup a pointer to the mapped list. */ + list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset; + + /* Loop through the mapped list for this block. */ + for (j = 0; j < nor_flash -> lx_nor_flash_physical_sectors_per_block; j++) + { + + /* Read the current mapping entry. */ +#ifdef LX_DIRECT_READ + + /* Read the word directly. */ + list_word = *(list_word_ptr); +#else + status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1); + + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) + { + + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); + + /* Return the error. */ + return(status); + } +#endif + + /* Determine if the entry hasn't been used. */ + if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE) + { + + /* Since allocations are done sequentially in the block, we know nothing + else exists after this point. */ + break; + } + + /* Is this entry obsolete? */ + if ((list_word & LX_NOR_PHYSICAL_SECTOR_VALID) == 0) + { + + /* Increment the number of obsolete sectors. */ + obsolete_sectors++; + } + else + { + + /* Increment the number of mapped sectors. */ + mapped_sectors++; + } + + /* Move the list pointer ahead. */ + list_word_ptr++; + } + } + + /* Determine if this block contains full obsoleted sectors and the erase count is minimum. */ + if ((obsolete_sectors == nor_flash -> lx_nor_flash_physical_sectors_per_block) && + (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count) && + (nor_flash -> lx_nor_flash_minimum_erased_blocks > 0)) + { + + /* Yes, we have a full obsoleted block with minimum erase count. */ + *return_erase_block = i; + *return_erase_count = erase_count; + *return_obsolete_sectors = obsolete_sectors; + *return_mapped_sectors = mapped_sectors; + + break; + } + /* Determine if we have a block with a new maximum number of obsolete sectors. */ if ((obsolete_sectors > max_obsolete_sectors) && (erase_count <= erase_count_threshold)) @@ -233,6 +355,8 @@ UINT status; max_obsolete_block = i; max_obsolete_erase_count = erase_count; max_obsolete_mapped_count = mapped_sectors; + max_obsolete_mapped_count_available = mapped_sectors_available; + } else if ((max_obsolete_sectors) && (obsolete_sectors == max_obsolete_sectors) && (erase_count <= erase_count_threshold)) { @@ -247,6 +371,7 @@ UINT status; max_obsolete_block = i; max_obsolete_erase_count = erase_count; max_obsolete_mapped_count = mapped_sectors; + max_obsolete_mapped_count_available = mapped_sectors_available; } } @@ -259,36 +384,105 @@ UINT status; min_block_erase = i; min_block_obsolete_count = obsolete_sectors; min_block_mapped_count = mapped_sectors; + min_block_mapped_count_available = mapped_sectors_available; } /* Move to the next block. */ block_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_words_per_block; } - /* Determine if we can erase the block with the most obsolete sectors. */ - if (max_obsolete_sectors) + /* Determine if we found a block with full obsoleted sector and the erase count is minimum. */ + if (i == nor_flash -> lx_nor_flash_total_blocks) { - - /* Erase the block with the most obsolete sectors. */ - *return_erase_block = max_obsolete_block; - *return_erase_count = max_obsolete_erase_count; - *return_obsolete_sectors = max_obsolete_sectors; - *return_mapped_sectors = max_obsolete_mapped_count; - } - else - { - - /* Otherwise, choose the block with the smallest erase count. */ - *return_erase_block = min_block_erase; - *return_erase_count = min_block_erase_count; - *return_obsolete_sectors = min_block_obsolete_count; - *return_mapped_sectors = min_block_mapped_count; + + /* Determine if we can erase the block with the most obsolete sectors. */ + if (max_obsolete_sectors) + { + + /* Erase the block with the most obsolete sectors. */ + *return_erase_block = max_obsolete_block; + *return_erase_count = max_obsolete_erase_count; + *return_obsolete_sectors = max_obsolete_sectors; + *return_mapped_sectors = max_obsolete_mapped_count; + mapped_sectors_available = max_obsolete_mapped_count_available; + } + else + { + + /* Otherwise, choose the block with the smallest erase count. */ + *return_erase_block = min_block_erase; + *return_erase_count = min_block_erase_count; + *return_obsolete_sectors = min_block_obsolete_count; + *return_mapped_sectors = min_block_mapped_count; + mapped_sectors_available = min_block_mapped_count_available; + } + + /* Update the overall minimum and maximum erase count. */ + nor_flash -> lx_nor_flash_minimum_erase_count = min_system_block_erase_count; + nor_flash -> lx_nor_flash_minimum_erased_blocks = system_min_erased_blocks; + nor_flash -> lx_nor_flash_maximum_erase_count = max_system_block_erase_count; } - /* Update the overall minimum and maximum erase count. */ - nor_flash -> lx_nor_flash_minimum_erase_count = min_system_block_erase_count; - nor_flash -> lx_nor_flash_maximum_erase_count = max_system_block_erase_count; - + /* Determine if the mapped sector count is available. */ + if (mapped_sectors_available == LX_FALSE) + { + + /* Compute the number of obsolete and mapped sectors for this block. */ + mapped_sectors = 0; + + /* Setup a pointer to the mapped list. */ + block_word_ptr = nor_flash -> lx_nor_flash_base_address + *return_erase_block * nor_flash -> lx_nor_flash_words_per_block; + list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset; + + /* Loop through the mapped list for this block. */ + for (j = 0; j < nor_flash -> lx_nor_flash_physical_sectors_per_block; j++) + { + + /* Read the current mapping entry. */ +#ifdef LX_DIRECT_READ + + /* Read the word directly. */ + list_word = *(list_word_ptr); +#else + status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1); + + /* Check for an error from flash driver. Drivers should never return an error.. */ + if (status) + { + + /* Call system error handler. */ + _lx_nor_flash_system_error(nor_flash, status); + + /* Return the error. */ + return(status); + } +#endif + + /* Determine if the entry hasn't been used. */ + if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE) + { + + /* Since allocations are done sequentially in the block, we know nothing + else exists after this point. */ + break; + } + + /* Is this entry mapped? */ + if ((list_word & LX_NOR_PHYSICAL_SECTOR_VALID) != 0) + { + + /* Increment the number of mapped sectors. */ + mapped_sectors++; + } + + /* Move the list pointer ahead. */ + list_word_ptr++; + } + + /* Return the mapped sector count. */ + *return_mapped_sectors = mapped_sectors; + + } /* Return success. */ return(LX_SUCCESS); } diff --git a/common/src/lx_nor_flash_open.c b/common/src/lx_nor_flash_open.c index 9fecd0d..632ed31 100644 --- a/common/src/lx_nor_flash_open.c +++ b/common/src/lx_nor_flash_open.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_open PORTABLE C */ -/* 6.2.1 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -94,7 +94,15 @@ /* resulting in version 6.1.7 */ /* 03-08-2023 Xiuwen Cai Modified comment(s), */ /* added new driver interface, */ -/* resulting in version 6.2.1 */ +/* resulting in version 6.2.1 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added count for minimum */ +/* erased blocks, added */ +/* obsolete count cache, */ +/* avoided clearing user */ +/* extension in flash control */ +/* block, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_open(LX_NOR_FLASH *nor_flash, CHAR *name, UINT (*nor_driver_initialize)(LX_NOR_FLASH *)) @@ -112,7 +120,7 @@ ULONG free_sectors; ULONG used_sectors; ULONG *new_map_entry; ULONG *new_sector_address; -ULONG erased_count, min_erased_count, max_erased_count, temp_erased_count; +ULONG erased_count, min_erased_count, max_erased_count, temp_erased_count, min_erased_blocks; ULONG j, k, l; UINT status; #ifdef LX_FREE_SECTOR_DATA_VERIFY @@ -124,8 +132,8 @@ LX_INTERRUPT_SAVE_AREA LX_PARAMETER_NOT_USED(name); - /* Clear the NOR flash control block. */ - LX_MEMSET(nor_flash, 0, sizeof(LX_NOR_FLASH)); + /* Clear the NOR flash control block. User extension is not cleared. */ + LX_MEMSET(nor_flash, 0, (ULONG)((UCHAR*)&(nor_flash -> lx_nor_flash_open_previous) - (UCHAR*)nor_flash) + sizeof(nor_flash -> lx_nor_flash_open_previous)); /* Call the flash driver's initialization function. */ (nor_driver_initialize)(nor_flash); @@ -213,6 +221,7 @@ LX_INTERRUPT_SAVE_AREA /* Setup default values for the max/min erased counts. */ min_erased_count = LX_ALL_ONES; + min_erased_blocks = 0; max_erased_count = 0; /* Setup the block word pointer to the first word of the first block, which is effectively the @@ -254,13 +263,24 @@ LX_INTERRUPT_SAVE_AREA /* No, valid block. Isolate the erased count. */ erased_count = (block_word & LX_BLOCK_ERASE_COUNT_MASK); - + + /* Is the erased count the minimum? */ + if (erased_count == min_erased_count) + { + + /* Yes, increment the minimum erased block count. */ + min_erased_blocks++; + } + /* Is this the new minimum? */ if (erased_count < min_erased_count) { /* Yes, remember the new minimum. */ min_erased_count = erased_count; + + /* Reset the minimum erased block count. */ + min_erased_blocks = 1; } /* Is this the new maximum? */ @@ -327,6 +347,7 @@ LX_INTERRUPT_SAVE_AREA /* Update the overall minimum and maximum erase count. */ nor_flash -> lx_nor_flash_minimum_erase_count = 1; + nor_flash -> lx_nor_flash_minimum_erased_blocks = nor_flash -> lx_nor_flash_total_blocks; nor_flash -> lx_nor_flash_maximum_erase_count = 1; /* Update the number of free physical sectors. */ @@ -806,6 +827,7 @@ LX_INTERRUPT_SAVE_AREA /* Update the overall minimum and maximum erase count. */ nor_flash -> lx_nor_flash_minimum_erase_count = min_erased_count; + nor_flash -> lx_nor_flash_minimum_erased_blocks = min_erased_blocks; nor_flash -> lx_nor_flash_maximum_erase_count = max_erased_count; /* Determine if we need to update the free sector search pointer. */ diff --git a/common/src/lx_nor_flash_sector_read.c b/common/src/lx_nor_flash_sector_read.c index fb85068..b81f128 100644 --- a/common/src/lx_nor_flash_sector_read.c +++ b/common/src/lx_nor_flash_sector_read.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_sector_read PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -84,6 +84,9 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_sector_read(LX_NOR_FLASH *nor_flash, ULONG logical_sector, VOID *buffer) @@ -179,6 +182,18 @@ ULONG *sector_address; /* Return status. */ return(LX_ERROR); } +#ifndef LX_NOR_DISABLE_EXTENDED_CACHE +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP + + /* Determine if the logical sector is within the mapping bitmap. */ + if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector) + { + + /* Set the bit in the mapping bitmap. */ + nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] |= (ULONG)(1 << (logical_sector & 31)); + } +#endif +#endif /* Increment the number of mapped physical sectors. */ nor_flash -> lx_nor_flash_mapped_physical_sectors++; diff --git a/common/src/lx_nor_flash_sector_release.c b/common/src/lx_nor_flash_sector_release.c index 0f3e326..5afd771 100644 --- a/common/src/lx_nor_flash_sector_release.c +++ b/common/src/lx_nor_flash_sector_release.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_sector_release PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -84,6 +84,10 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* added obsolete count cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_sector_release(LX_NOR_FLASH *nor_flash, ULONG logical_sector) @@ -94,6 +98,9 @@ ULONG *mapping_address; ULONG mapping_entry; ULONG *sector_address; ULONG i; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +ULONG block; +#endif #ifdef LX_THREAD_SAFE_ENABLE @@ -164,9 +171,36 @@ ULONG i; return(LX_ERROR); } +#ifndef LX_NOR_DISABLE_EXTENDED_CACHE +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP + + /* Determine if the logical sector is within the mapping bitmap. */ + if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector) + { + + /* Set the bit in the mapping bitmap. */ + nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] &= (ULONG)~(1 << (logical_sector & 31)); + } +#endif +#endif + /* Increment the number of obsolete physical sectors. */ nor_flash -> lx_nor_flash_obsolete_physical_sectors++; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Get the block number from mapping address. */ + block = (ULONG)(mapping_address - nor_flash -> lx_nor_flash_base_address) / nor_flash -> lx_nor_flash_words_per_block; + + /* Determine if this block is within the range of the obsolete count cache. */ + if (block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Increment the obsolete count for this block. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count[block] ++; + } +#endif + /* Decrement the number of mapped physical sectors. */ nor_flash -> lx_nor_flash_mapped_physical_sectors--; diff --git a/common/src/lx_nor_flash_sector_write.c b/common/src/lx_nor_flash_sector_write.c index 0889bb8..d88e406 100644 --- a/common/src/lx_nor_flash_sector_write.c +++ b/common/src/lx_nor_flash_sector_write.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _lx_nor_flash_sector_write PORTABLE C */ -/* 6.1.7 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -87,6 +87,10 @@ /* resulting in version 6.1 */ /* 06-02-2021 Bhupendra Naphade Modified comment(s), */ /* resulting in version 6.1.7 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added mapping bitmap cache, */ +/* added obsolete count cache, */ +/* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _lx_nor_flash_sector_write(LX_NOR_FLASH *nor_flash, ULONG logical_sector, VOID *buffer) @@ -101,7 +105,9 @@ ULONG new_mapping_entry; ULONG i; LX_NOR_SECTOR_MAPPING_CACHE_ENTRY *sector_mapping_cache_entry_ptr; UINT status; - +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE +ULONG block; +#endif #ifdef LX_THREAD_SAFE_ENABLE @@ -269,6 +275,18 @@ UINT status; /* Return status. */ return(LX_ERROR); } +#ifndef LX_NOR_DISABLE_EXTENDED_CACHE +#ifdef LX_NOR_ENABLE_MAPPING_BITMAP + + /* Determine if the logical sector is within the mapping bitmap. */ + if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector) + { + + /* Set the bit in the mapping bitmap. */ + nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] |= (ULONG)(1 << (logical_sector & 31)); + } +#endif +#endif /* Increment the number of mapped physical sectors. */ nor_flash -> lx_nor_flash_mapped_physical_sectors++; @@ -303,6 +321,20 @@ UINT status; /* Increment the number of obsolete physical sectors. */ nor_flash -> lx_nor_flash_obsolete_physical_sectors++; +#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE + + /* Get the block number from mapping address. */ + block = (ULONG)(old_mapping_address - nor_flash -> lx_nor_flash_base_address) / nor_flash -> lx_nor_flash_words_per_block; + + /* Determine if this block is within the range of the obsolete count cache. */ + if (block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) + { + + /* Increment the obsolete count for this block. */ + nor_flash -> lx_nor_flash_extended_cache_obsolete_count[block] ++; + } +#endif + /* Decrement the number of mapped physical sectors. */ nor_flash -> lx_nor_flash_mapped_physical_sectors--;