/*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Copilot (Sonnet 4.6). /**************************************************************************/ /**************************************************************************/ /** */ /** LevelX Component */ /** */ /** NAND Flash */ /** */ /**************************************************************************/ /**************************************************************************/ #define LX_SOURCE_CODE /* Disable ThreadX error checking. */ #ifndef LX_DISABLE_ERROR_CHECKING #define LX_DISABLE_ERROR_CHECKING #endif /* Include necessary system files. */ #include "lx_api.h" /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _lx_nand_flash_block_allocate PORTABLE C */ /* 6.2.1 */ /* AUTHOR */ /* */ /* Xiuwen Cai, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function attempts to get a block in the free block list. */ /* */ /* INPUT */ /* */ /* nand_flash NAND flash instance */ /* block Return block number */ /* */ /* OUTPUT */ /* */ /* return status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Internal LevelX */ /* */ /**************************************************************************/ UINT _lx_nand_flash_block_allocate(LX_NAND_FLASH* nand_flash, ULONG* block) { /* Check if the free block list is empty. */ if (nand_flash -> lx_nand_flash_free_block_list_tail == 0) { #ifdef LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE { ULONG lg; UINT compact_status; /* Emergency compaction: find any pending compaction and execute it to reclaim the old full block. */ for (lg = 0; lg < nand_flash -> lx_nand_flash_total_blocks; lg++) { if (nand_flash -> lx_nand_flash_block_compaction_table[lg] != (USHORT)LX_NAND_BLOCK_UNMAPPED) { compact_status = _lx_nand_flash_logical_group_compact(nand_flash, lg); if (compact_status == LX_SUCCESS) { /* Retry the allocation after compaction freed a block. */ if (nand_flash -> lx_nand_flash_free_block_list_tail > 0) { nand_flash -> lx_nand_flash_free_block_list_tail--; *block = nand_flash -> lx_nand_flash_block_list[nand_flash -> lx_nand_flash_free_block_list_tail]; return(LX_SUCCESS); } } /* Attempt only one compaction per allocate call. */ break; } } } #endif /* LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE */ /* Empty list, return error. */ return(LX_NO_BLOCKS); } /* Remove one block from the list. */ nand_flash -> lx_nand_flash_free_block_list_tail--; /* Return the block number. */ *block = nand_flash -> lx_nand_flash_block_list[nand_flash -> lx_nand_flash_free_block_list_tail]; /* Return successful completion. */ return(LX_SUCCESS); }