uint32_t *VirtualPageClass::get(uint32_t magic) { // Give back a page prepared for release and not closed for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t *page = get_page_address(i); if ( // correct magic is set (page[OFFSET_MAGIC] == magic) && // page is in release_prepare mode ((page[OFFSET_STATUS_RELEASE_PREPARE] & BIT_STATUS_RELEASE_PREPARE) == 0) && // page is not released ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0)) { // Return page in release process with priority return &page[OFFSET_DATA]; } } // check if a unreleased page is available for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t *page = get_page_address(i); if ( // correct magic is set (page[OFFSET_MAGIC] == magic) && // page is not released ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0)) { // return page in normal operation return &page[OFFSET_DATA]; } } return (uint32_t *)(~0); }
void VirtualPageClass::clean_up() { // No page found -> try to give back a page prepared for release for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t *page = get_page_address(i); if ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) == 0) { build_page(get_page_address(i), ~0); return; // a maximum of a page is cleaned -> return } } }
void VirtualPageClass::format() { for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t *address = get_page_address(i); build_page(address, (uint32_t)~0); } }
bool quan::stm32::flash::detail::erase (int32_t page_num) { void * page = get_page_address (page_num); if (page != nullptr) { memset (page,0xFF,page_size); return true; } else { return false; } }
uint32_t VirtualPageClass::wear_level() { uint32_t max_erase_cycles = 0; for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t erase_cycles = get_page_erase_cycles(get_page_address(i)); if (erase_cycles > max_erase_cycles) { max_erase_cycles = erase_cycles; } } return (uint32_t)((((uint64_t)max_erase_cycles * 10000)) / Flash.specified_erase_cycles()); }
uint32_t *VirtualPageClass::allocate(uint32_t magic) { uint32_t *return_page = (uint32_t *)(~0); uint32_t max_erase_cycles = (uint32_t)~0; // Avoid duplicate allocation of pages, look for the less used page for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { uint32_t *page = get_page_address(i); // Delete duplicated pages if ( // same magic (page[OFFSET_MAGIC] == magic) && // Not in release_end state ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0) && // Not in release_prepare state (!release_started(page))) { // clear the page build_page(page, (uint32_t)~0); } uint32_t erase_cycles = get_page_erase_cycles(page); // When the page has less erase cycles and is not marked as failed if ((erase_cycles < max_erase_cycles) && (page[OFFSET_MAGIC] > 0) && ( // magic is empty (page[OFFSET_MAGIC] == (uint32_t)~0) || // marked as released ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) == 0))) { max_erase_cycles = erase_cycles; return_page = page; } } // return if no page was found if (return_page == (uint32_t *)~0) { return return_page; } build_page(return_page, magic); return &return_page[OFFSET_DATA]; }