/** * @brief Function for handling of system events from SoftDevice. * * @param[in] sys_evt System event received. */ void pstorage_sys_event_handler(uint32_t sys_evt) { uint32_t retval = NRF_SUCCESS; // The event shall only be processed if requested by this module. if (m_cmd_queue.flash_access == true) { cmd_queue_element_t * p_cmd; m_cmd_queue.flash_access = false; switch (sys_evt) { case NRF_EVT_FLASH_OPERATION_SUCCESS: { p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; m_round_val++; bool command_finished = ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size); if (command_finished) { uint8_t queue_rp = m_cmd_queue.rp; m_round_val = 0; m_cmd_queue.count--; m_cmd_queue.rp++; if (m_cmd_queue.rp >= PSTORAGE_CMD_QUEUE_SIZE) { m_cmd_queue.rp -= PSTORAGE_CMD_QUEUE_SIZE; } app_notify(retval, &m_cmd_queue.cmd[queue_rp]); // Initialize/free the element as it is now processed. cmd_queue_element_init(queue_rp); } // Schedule any queued flash access operations. retval = cmd_queue_dequeue(); if (retval != NRF_SUCCESS) { app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]); } } break; case NRF_EVT_FLASH_OPERATION_ERROR: app_notify(NRF_ERROR_TIMEOUT, &m_cmd_queue.cmd[m_cmd_queue.rp]); break; default: // No implementation needed. break; } } }
/** * @brief Function for initializing the command queue. */ static void cmd_queue_init(void) { uint32_t cmd_index; m_round_val = 0; m_cmd_queue.rp = 0; m_cmd_queue.count = 0; m_cmd_queue.flash_access = false; for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++) { cmd_queue_element_init(cmd_index); } }
/** * @brief Handles Flash Access Result Events declared in pstorage_platform.h. * * @param[in] sys_evt System event to be handled. */ void pstorage_sys_event_handler(uint32_t sys_evt) { uint32_t retval = NRF_SUCCESS; // Its possible the flash access was not initiated by bond manager, hence // event is processed only if the event triggered was for an operation requested by the // bond manager. if (m_cmd_queue.flash_access == true) { cmd_queue_element_t * p_cmd; m_cmd_queue.flash_access = false; if (m_swap_state == STATE_SWAP_DIRTY) { if (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) { m_swap_state = STATE_INIT; } else { // If clearing the swap fails, set the application back to un-initialized, to give // the application a chance for a retry. m_module_initialized = false; } // Schedule any queued flash access operations. retval = cmd_queue_dequeue(); if (retval != NRF_SUCCESS) { app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]); } return; } switch (sys_evt) { case NRF_EVT_FLASH_OPERATION_SUCCESS: { p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; m_round_val++; const bool store_finished = ((p_cmd->op_code == PSTORAGE_STORE_OP_CODE) && ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size)); const bool update_finished = ((p_cmd->op_code == PSTORAGE_UPDATE_OP_CODE) && (m_swap_state == STATE_COMPLETE)); const bool clear_block_finished = ((p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) && (m_swap_state == STATE_COMPLETE)); const bool clear_all_finished = ((p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) && ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size) && (m_swap_state == STATE_INIT)); if (update_finished || clear_block_finished || clear_all_finished || store_finished) { uint8_t queue_rp = m_cmd_queue.rp; m_swap_state = STATE_INIT; m_round_val = 0; m_cmd_queue.count--; m_cmd_queue.rp++; if (m_cmd_queue.rp >= PSTORAGE_CMD_QUEUE_SIZE) { m_cmd_queue.rp -= PSTORAGE_CMD_QUEUE_SIZE; } app_notify(retval, &m_cmd_queue.cmd[queue_rp]); // Initialize/free the element as it is now processed. cmd_queue_element_init(queue_rp); } // Schedule any queued flash access operations. retval = cmd_queue_dequeue(); if (retval != NRF_SUCCESS) { app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]); } } break; case NRF_EVT_FLASH_OPERATION_ERROR: // Current command timed out and was not started in SoftDevice. p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; ASSERT(p_cmd->n_tries < SD_CMD_MAX_TRIES); if (++p_cmd->n_tries == SD_CMD_MAX_TRIES) { // If we have already attempted SD_CMD_MAX_TRIES times, give up. app_notify(NRF_ERROR_TIMEOUT, &m_cmd_queue.cmd[m_cmd_queue.rp]); } else { // Retry operation retval = cmd_process(); if (retval != NRF_SUCCESS && retval != NRF_ERROR_BUSY) { app_notify(retval, p_cmd); } } break; default: // No implementation needed. break; } } }