/**@brief Function to erase a page. * * @param[in] p_cmd The queue element associated with the operation. * * @retval NRF_SUCCESS Success. The request was sent to the SoftDevice. * @retval Any error returned by the SoftDevice flash API. */ static ret_code_t erase_execute(fs_cmd_t * const p_cmd) { ret_code_t ret = sd_flash_page_erase(p_cmd->erase.page++); p_cmd->erase.pages_erased++; return ret; }
uint32_t blocking_flash_page_erase(uint32_t page_number) { uint32_t err_code; do{ err_code = sd_flash_page_erase(page_number); } while(err_code == NRF_ERROR_BUSY); return err_code; }
void erasePageOfFlash(uint8_t page) { if (page > LAST_PAGE || page < FIRST_PAGE) { debug_log("Invalid flash erase address\r\n"); while(1); } else { flashWorking = true; sd_flash_page_erase(page); } }
/// Erase the flash page containing the address. void jshFlashErasePage(uint32_t addr) { uint32_t startAddr; uint32_t pageSize; if (!jshFlashGetPage(addr, &startAddr, &pageSize)) return; uint32_t err; flashIsBusy = true; while ((err = sd_flash_page_erase(startAddr / NRF_FICR->CODEPAGESIZE)) == NRF_ERROR_BUSY); if (err!=NRF_SUCCESS) flashIsBusy = false; WAIT_UNTIL(!flashIsBusy, "jshFlashErasePage"); /*if (err!=NRF_SUCCESS) jsiConsolePrintf("jshFlashErasePage got err %d at 0x%x\n", err, addr);*/ //nrf_nvmc_page_erase(addr); }
otError nrf5FlashPageErase(uint32_t aAddress) { uint32_t retval; nrf_sdh_suspend(); do { sState = FLASH_STATE_PENDING; retval = sd_flash_page_erase(aAddress / FLASH_PAGE_SIZE); if (retval == NRF_SUCCESS) { break; } else if (retval == NRF_ERROR_BUSY) { sState = FLASH_STATE_WAITING_FOR_IDLE; } else { assert(false); } waitInState(FLASH_STATE_WAITING_FOR_IDLE); } while (retval == NRF_ERROR_BUSY); waitInState(FLASH_STATE_PENDING); if (sState != FLASH_STATE_COMPLETE_SUCCESS) { retval = NRF_ERROR_INTERNAL; } sState = FLASH_STATE_IDLE; nrf_sdh_resume(); return nrf5SdErrorToOtError(retval); }
static void __HalFlashShootHead(void) { uint32_t ret; uint32_t info; if (opc[opc_begin].is_write == 1) { ret = sd_flash_write((uint32_t *)((uint32_t)opc[opc_begin].pg_idx * 1024 + (uint32_t)opc[opc_begin].pg_offset), (uint32_t *)(opc[opc_begin].buf), (opc[opc_begin].len / 4)); } else { ret = sd_flash_page_erase((uint32_t)opc[opc_begin].pg_idx); } if (ret == NRF_SUCCESS) { opc_head_status = IN_PROGRESS; } else if (ret == NRF_ERROR_BUSY) { // Not good time opc_head_status = BUSY_WAIT; } else { info = (uint32_t)opc[opc_begin].is_write << 24 | (uint32_t)opc[opc_begin].pg_idx << 16 | (uint32_t)opc[opc_begin].pg_offset; __HalFlashRemoveHead(); persistent_record_error((uint8_t)ret, info); } }
uint32_t pstorage_init(void) { uint32_t retval; cmd_queue_init(); m_next_app_instance = 0; m_next_page_addr = PSTORAGE_DATA_START_ADDR; m_round_val = 0; for (uint32_t index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++) { m_app_table[index].cb = NULL; m_app_table[index].block_size = 0; m_app_table[index].num_of_pages = 0; m_app_table[index].block_count = 0; } #ifdef PSTORAGE_RAW_MODE_ENABLE m_raw_app_table.cb = NULL; m_raw_app_table.num_of_pages = 0; m_module_initialized = true; m_swap_state = STATE_INIT; retval = NRF_SUCCESS; #else m_swap_state = STATE_SWAP_DIRTY; // Erase swap region in case it is dirty. retval = sd_flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE); if (retval == NRF_SUCCESS) { m_cmd_queue.flash_access = true; m_module_initialized = true; } #endif //PSTORAGE_RAW_MODE_ENABLE return retval; }
int32_t flash_erase_sector(flash_t *obj, uint32_t address) { (void)(obj); /* Return value defaults to error. */ uint32_t result = NRF_ERROR_BUSY; if (NRF_HAL_SD_IS_ENABLED()) { /* Convert address to page number. */ uint32_t page_number = address / NRF_FICR->CODEPAGESIZE; /* Setup stop watch for timeout. */ uint32_t start_us = lp_ticker_read(); uint32_t now_us = start_us; /* Retry if flash is busy until timeout is reached. */ while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && (result == NRF_ERROR_BUSY)) { result = sd_flash_page_erase(page_number); /* Read timeout timer. */ now_us = lp_ticker_read(); } } else { /* Raw API doesn't return error code, assume success. */ nrf_nvmc_page_erase(address); result = NRF_SUCCESS; } /* Convert Nordic error code to mbed HAL error code. */ return (result == NRF_SUCCESS) ? 0 : -1; }
/** * @brief Routine called to actually issue the flash access request to the SoftDevice. */ static uint32_t process_cmd(void) { uint32_t retval; uint32_t storage_addr; cmd_queue_element_t * p_cmd; retval = NRF_ERROR_FORBIDDEN; p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; storage_addr = p_cmd->storage_addr.block_id; if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) { // Calculate page number before copy. uint32_t page_number; page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) + m_round_val); retval = sd_flash_page_erase(page_number); if (NRF_SUCCESS == retval) { m_round_val++; } } else if (p_cmd->op_code == PSTORAGE_STORE_OP_CODE) { uint32_t size; uint8_t * p_data_addr = p_cmd->p_data_addr; p_data_addr += m_round_val; storage_addr += (p_cmd->offset + m_round_val); size = p_cmd->size - m_round_val; if (size < SOC_MAX_WRITE_SIZE) { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, size / sizeof(uint32_t)); } else { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, SOC_MAX_WRITE_SIZE / sizeof(uint32_t)); } if (retval == NRF_SUCCESS) { m_round_val += SOC_MAX_WRITE_SIZE; } } else { // Should never reach here. } if (retval == NRF_SUCCESS) { m_cmd_queue.flash_access = true; } return retval; }
/** * @brief Routine called to actually issue the flash access request to the SoftDevice. * * @retval NRF_SUCCESS on success, else an error code indicating reason for failure. */ static uint32_t cmd_process(void) { uint32_t retval; uint32_t storage_addr; cmd_queue_element_t * p_cmd; retval = NRF_ERROR_FORBIDDEN; p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; storage_addr = p_cmd->storage_addr.block_id; switch (p_cmd->op_code) { case PSTORAGE_STORE_OP_CODE: { uint32_t size; uint32_t offset; uint8_t * p_data_addr = p_cmd->p_data_addr; offset = (m_round_val * SOC_MAX_WRITE_SIZE); size = p_cmd->size - offset; p_data_addr += offset; storage_addr += (p_cmd->offset + offset); if (size < SOC_MAX_WRITE_SIZE) { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, size / sizeof(uint32_t)); } else { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, SOC_MAX_WRITE_SIZE / sizeof(uint32_t)); } } break; case PSTORAGE_CLEAR_OP_CODE: { // Calculate page number before clearing. uint32_t page_number; pstorage_size_t block_size = m_app_table[p_cmd->storage_addr.module_id].block_size; pstorage_size_t block_count = m_app_table[p_cmd->storage_addr.module_id].block_count; pstorage_block_t base_address = m_app_table[p_cmd->storage_addr.module_id].base_id; // If the whole module should be cleared. if (((base_address == storage_addr) && (block_size * block_count == p_cmd->size)) || (p_cmd->storage_addr.module_id == RAW_MODE_APP_ID)) { page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) + m_round_val); retval = sd_flash_page_erase(page_number); } // If one block is to be erased. else { page_number = (storage_addr / PSTORAGE_FLASH_PAGE_SIZE); uint32_t head_word_size = ( storage_addr - (page_number * PSTORAGE_FLASH_PAGE_SIZE) ) / sizeof(uint32_t); uint32_t tail_word_size = ( ((page_number + 1) * PSTORAGE_FLASH_PAGE_SIZE) - (storage_addr + p_cmd->size) ) / sizeof(uint32_t); retval = swap_state_process(p_cmd, page_number, head_word_size, tail_word_size); } } break; case PSTORAGE_UPDATE_OP_CODE: { uint32_t page_number = (storage_addr / PSTORAGE_FLASH_PAGE_SIZE); uint32_t head_word_size = ( storage_addr + p_cmd->offset - (page_number * PSTORAGE_FLASH_PAGE_SIZE) ) / sizeof(uint32_t); uint32_t tail_word_size = ( ((page_number + 1) * PSTORAGE_FLASH_PAGE_SIZE) - (storage_addr + p_cmd->offset + p_cmd->size) ) / sizeof(uint32_t); retval = swap_state_process(p_cmd, page_number, head_word_size, tail_word_size); } break; default: // Should never reach here. break; } if (retval == NRF_SUCCESS) { m_cmd_queue.flash_access = true; } return retval; }
/** @brief Function for handling flash accesses when using swap. * * __________________________________________________________ * | Page | * |________________________________________________________| * | head | affected body (to be updated or cleared) | tail | * |______|__________________________________________|______| * * @param[in] p_cmd Queue element being processed. * @param[in] page_number The affected page number. * @param[in] head_word_size Size of the head in number of words. * @param[in] tail_word_size Size of the tail in number of words. * * @retval NRF_SUCCESS on success, else an error code indicating reason for failure. */ static uint32_t swap_state_process(cmd_queue_element_t * p_cmd, uint32_t page_number, uint32_t head_word_size, uint32_t tail_word_size) { uint32_t retval = NRF_ERROR_INTERNAL; // Adjust entry point to state machine if needed. When we update has no head or tail its // no need for using the swap. if (m_swap_state == STATE_INIT) { if ((head_word_size == 0) && (tail_word_size == 0)) { // Only skip swap usage if the new data fills a whole flash page. m_swap_state = STATE_DATA_ERASE; } else { // Else start backing up application data to swap. m_swap_state = STATE_DATA_TO_SWAP_WRITE; } } switch (m_swap_state) { case STATE_DATA_TO_SWAP_WRITE: // Backup previous content into swap page. retval = sd_flash_write((uint32_t *)(PSTORAGE_SWAP_ADDR), (uint32_t *)(page_number * PSTORAGE_FLASH_PAGE_SIZE), PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t)); if (retval == NRF_SUCCESS) { m_swap_state = STATE_DATA_ERASE; } break; case STATE_DATA_ERASE: // Clear the application data page. retval = sd_flash_page_erase(page_number); if (retval == NRF_SUCCESS) { if (head_word_size == 0) { if (tail_word_size == 0) { if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) { m_swap_state = STATE_COMPLETE; } else { m_swap_state = STATE_NEW_BODY_WRITE; } } else { m_swap_state = STATE_TAIL_RESTORE; } } else { m_swap_state = STATE_HEAD_RESTORE; } } break; case STATE_HEAD_RESTORE: // Restore head from swap to application data page. retval = sd_flash_write((uint32_t *)(page_number * PSTORAGE_FLASH_PAGE_SIZE), (uint32_t *)PSTORAGE_SWAP_ADDR, head_word_size); if (retval == NRF_SUCCESS) { if (tail_word_size == 0) { if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) { m_swap_state = STATE_SWAP_ERASE; } else { m_swap_state = STATE_NEW_BODY_WRITE; } } else { m_swap_state = STATE_TAIL_RESTORE; } } break; case STATE_TAIL_RESTORE: // Restore tail from swap to application data page. retval = sd_flash_write((uint32_t *)((page_number * PSTORAGE_FLASH_PAGE_SIZE) + (head_word_size * sizeof(uint32_t)) + p_cmd->size), (uint32_t *)(PSTORAGE_SWAP_ADDR + (head_word_size * sizeof(uint32_t)) + p_cmd->size), tail_word_size); if (retval == NRF_SUCCESS) { if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) { m_swap_state = STATE_SWAP_ERASE; } else { m_swap_state = STATE_NEW_BODY_WRITE; } } break; case STATE_NEW_BODY_WRITE: // Write new data (body) to application data page. retval = sd_flash_write((uint32_t *)((page_number * PSTORAGE_FLASH_PAGE_SIZE) + (head_word_size * sizeof(uint32_t))), (uint32_t *)p_cmd->p_data_addr, p_cmd->size / sizeof(uint32_t)); if (retval == NRF_SUCCESS) { if ((head_word_size == 0) && (tail_word_size == 0)) { m_swap_state = STATE_COMPLETE; } else { m_swap_state = STATE_SWAP_ERASE; } } break; case STATE_SWAP_ERASE: // Clear the swap page for subsequent use. retval = sd_flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE); if (retval == NRF_SUCCESS) { m_swap_state = STATE_COMPLETE; } break; default: break; } return retval; }
/** * @brief Function for processing of commands and issuing flash access request to the SoftDevice. * * @return The return value received from SoftDevice. */ static uint32_t cmd_process(void) { uint32_t retval; uint32_t storage_addr; cmd_queue_element_t * p_cmd; retval = NRF_ERROR_FORBIDDEN; p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; storage_addr = p_cmd->storage_addr.block_id; switch (p_cmd->op_code) { case PSTORAGE_STORE_OP_CODE: { uint32_t size; uint32_t offset; uint8_t * p_data_addr = p_cmd->p_data_addr; offset = (m_round_val * SOC_MAX_WRITE_SIZE); size = p_cmd->size - offset; p_data_addr += offset; storage_addr += (p_cmd->offset + offset); if (size < SOC_MAX_WRITE_SIZE) { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, size / sizeof(uint32_t)); } else { retval = sd_flash_write(((uint32_t *)storage_addr), (uint32_t *)p_data_addr, SOC_MAX_WRITE_SIZE / sizeof(uint32_t)); } } break; case PSTORAGE_CLEAR_OP_CODE: { uint32_t page_number; page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) + m_round_val); retval = sd_flash_page_erase(page_number); } break; default: // Should never reach here. break; } if (retval == NRF_SUCCESS) { m_cmd_queue.flash_access = true; } return retval; }
/**@brief Function to erase a page. * * @param[in] p_cmd The queue element associated with the operation. * * @retval NRF_SUCCESS Success. The request was sent to the SoftDevice. * @retval Any error returned by the SoftDevice flash API. */ static __INLINE uint32_t erase_execute(fs_cmd_t const * const p_cmd) { // Erase the page. return sd_flash_page_erase((uint32_t)(p_cmd->p_addr + p_cmd->offset) / FS_PAGE_SIZE); }
// Executes an erase operation. static uint32_t erase_execute(fs_op_t const * const p_op) { return sd_flash_page_erase(p_op->erase.page); }