Nordic nrf51 sdk sources. Mirrored from https://github.com/ARMmbed/nrf51-sdk.

Dependents:   nRF51822 nRF51822

Committer:
vcoubard
Date:
Thu Apr 07 17:37:49 2016 +0100
Revision:
24:2aea0c1c57ee
Parent:
22:67a8d2c0bbbf
Child:
27:0fe148f1bca3
Synchronized with git rev 709d3cdb
Author: Liyou Zhou
Change version number in README

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 20:a90c48eb1d30 1 /*
vcoubard 20:a90c48eb1d30 2 * Copyright (c) Nordic Semiconductor ASA
vcoubard 20:a90c48eb1d30 3 * All rights reserved.
vcoubard 20:a90c48eb1d30 4 *
vcoubard 20:a90c48eb1d30 5 * Redistribution and use in source and binary forms, with or without modification,
vcoubard 20:a90c48eb1d30 6 * are permitted provided that the following conditions are met:
vcoubard 20:a90c48eb1d30 7 *
vcoubard 20:a90c48eb1d30 8 * 1. Redistributions of source code must retain the above copyright notice, this
vcoubard 20:a90c48eb1d30 9 * list of conditions and the following disclaimer.
vcoubard 20:a90c48eb1d30 10 *
vcoubard 20:a90c48eb1d30 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
vcoubard 20:a90c48eb1d30 12 * list of conditions and the following disclaimer in the documentation and/or
vcoubard 20:a90c48eb1d30 13 * other materials provided with the distribution.
vcoubard 20:a90c48eb1d30 14 *
vcoubard 20:a90c48eb1d30 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
vcoubard 20:a90c48eb1d30 16 * contributors to this software may be used to endorse or promote products
vcoubard 20:a90c48eb1d30 17 * derived from this software without specific prior written permission.
vcoubard 20:a90c48eb1d30 18 *
vcoubard 20:a90c48eb1d30 19 *
vcoubard 20:a90c48eb1d30 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
vcoubard 20:a90c48eb1d30 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
vcoubard 20:a90c48eb1d30 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
vcoubard 20:a90c48eb1d30 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
vcoubard 20:a90c48eb1d30 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
vcoubard 20:a90c48eb1d30 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
vcoubard 20:a90c48eb1d30 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
vcoubard 20:a90c48eb1d30 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
vcoubard 20:a90c48eb1d30 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
vcoubard 20:a90c48eb1d30 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
vcoubard 20:a90c48eb1d30 30 *
Vincent Coubard 0:f2542974c862 31 */
Vincent Coubard 0:f2542974c862 32
Vincent Coubard 0:f2542974c862 33 #include "pstorage.h"
Vincent Coubard 0:f2542974c862 34 #include <stdlib.h>
Vincent Coubard 0:f2542974c862 35 #include <stdint.h>
Vincent Coubard 0:f2542974c862 36 #include <string.h>
Vincent Coubard 0:f2542974c862 37 #include "nordic_common.h"
Vincent Coubard 0:f2542974c862 38 #include "nrf_error.h"
Vincent Coubard 0:f2542974c862 39 #include "nrf_assert.h"
vcoubard 1:ebc0e0ef0a11 40 #include "nrf.h"
Vincent Coubard 0:f2542974c862 41 #include "nrf_soc.h"
Vincent Coubard 0:f2542974c862 42 #include "app_util.h"
vcoubard 24:2aea0c1c57ee 43 #include "app_error.h"
Vincent Coubard 0:f2542974c862 44
vcoubard 24:2aea0c1c57ee 45 #define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
vcoubard 24:2aea0c1c57ee 46 #define SOC_MAX_WRITE_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API. */
vcoubard 24:2aea0c1c57ee 47 #define RAW_MODE_APP_ID (PSTORAGE_NUM_OF_PAGES + 1) /**< Application id for raw mode. */
vcoubard 24:2aea0c1c57ee 48 #define SD_CMD_MAX_TRIES 3 /**< Number of times to try a softdevice flash operation when the @ref NRF_EVT_FLASH_OPERATION_ERROR sys_evt is received. */
vcoubard 24:2aea0c1c57ee 49 #define MASK_TAIL_SWAP_DONE (1 << 0) /**< Flag for checking if the tail restore area has been written to swap page. */
vcoubard 24:2aea0c1c57ee 50 #define MASK_SINGLE_PAGE_OPERATION (1 << 1) /**< Flag for checking if command is a single flash page operation. */
vcoubard 24:2aea0c1c57ee 51 #define MASK_MODULE_INITIALIZED (1 << 2) /**< Flag for checking if the module has been initialized. */
vcoubard 24:2aea0c1c57ee 52 #define MASK_FLASH_API_ERR_BUSY (1 << 3) /**< Flag for checking if flash API returned NRF_ERROR_BUSY. */
Vincent Coubard 0:f2542974c862 53
Vincent Coubard 0:f2542974c862 54 /**
Vincent Coubard 0:f2542974c862 55 * @defgroup api_param_check API Parameters check macros.
Vincent Coubard 0:f2542974c862 56 *
Vincent Coubard 0:f2542974c862 57 * @details Macros that verify parameters passed to the module in the APIs. These macros
vcoubard 24:2aea0c1c57ee 58 * could be mapped to nothing in final code versions to save execution and size.
Vincent Coubard 0:f2542974c862 59 *
Vincent Coubard 0:f2542974c862 60 * @{
Vincent Coubard 0:f2542974c862 61 */
Vincent Coubard 0:f2542974c862 62
vcoubard 24:2aea0c1c57ee 63 /**@brief Check if the input pointer is NULL, if so it returns NRF_ERROR_NULL.
Vincent Coubard 0:f2542974c862 64 */
Vincent Coubard 0:f2542974c862 65 #define NULL_PARAM_CHECK(PARAM) \
Vincent Coubard 0:f2542974c862 66 if ((PARAM) == NULL) \
Vincent Coubard 0:f2542974c862 67 { \
Vincent Coubard 0:f2542974c862 68 return NRF_ERROR_NULL; \
Vincent Coubard 0:f2542974c862 69 }
Vincent Coubard 0:f2542974c862 70
vcoubard 24:2aea0c1c57ee 71 /**@brief Verifies that the module identifier supplied by the application is within permissible
Vincent Coubard 0:f2542974c862 72 * range.
Vincent Coubard 0:f2542974c862 73 */
Vincent Coubard 0:f2542974c862 74 #define MODULE_ID_RANGE_CHECK(ID) \
vcoubard 24:2aea0c1c57ee 75 if ((((ID)->module_id) >= PSTORAGE_NUM_OF_PAGES) || \
Vincent Coubard 0:f2542974c862 76 (m_app_table[(ID)->module_id].cb == NULL)) \
Vincent Coubard 0:f2542974c862 77 { \
Vincent Coubard 0:f2542974c862 78 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 79 }
Vincent Coubard 0:f2542974c862 80
vcoubard 24:2aea0c1c57ee 81 /**@brief Verifies that the block identifier supplied by the application is within the permissible
Vincent Coubard 0:f2542974c862 82 * range.
Vincent Coubard 0:f2542974c862 83 */
Vincent Coubard 0:f2542974c862 84 #define BLOCK_ID_RANGE_CHECK(ID) \
Vincent Coubard 0:f2542974c862 85 if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
Vincent Coubard 0:f2542974c862 86 (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
Vincent Coubard 0:f2542974c862 87 { \
Vincent Coubard 0:f2542974c862 88 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 89 }
Vincent Coubard 0:f2542974c862 90
vcoubard 24:2aea0c1c57ee 91 /**@brief Verifies that the block size requested by the application can be supported by the module.
Vincent Coubard 0:f2542974c862 92 */
Vincent Coubard 0:f2542974c862 93 #define BLOCK_SIZE_CHECK(X) \
Vincent Coubard 0:f2542974c862 94 if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
Vincent Coubard 0:f2542974c862 95 { \
Vincent Coubard 0:f2542974c862 96 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 97 }
Vincent Coubard 0:f2542974c862 98
vcoubard 24:2aea0c1c57ee 99 /**@brief Verifies the block size requested by the application in registration API.
Vincent Coubard 0:f2542974c862 100 */
Vincent Coubard 0:f2542974c862 101 #define BLOCK_COUNT_CHECK(COUNT, SIZE) \
Vincent Coubard 0:f2542974c862 102 if (((COUNT) == 0) || \
vcoubard 24:2aea0c1c57ee 103 ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_SWAP_ADDR))) \
Vincent Coubard 0:f2542974c862 104 { \
Vincent Coubard 0:f2542974c862 105 return NRF_ERROR_INVALID_PARAM; \
vcoubard 24:2aea0c1c57ee 106 }
Vincent Coubard 0:f2542974c862 107
vcoubard 24:2aea0c1c57ee 108 /**@brief Verifies the size parameter provided by the application in API.
Vincent Coubard 0:f2542974c862 109 */
Vincent Coubard 0:f2542974c862 110 #define SIZE_CHECK(ID, SIZE) \
Vincent Coubard 0:f2542974c862 111 if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
Vincent Coubard 0:f2542974c862 112 { \
Vincent Coubard 0:f2542974c862 113 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 114 }
Vincent Coubard 0:f2542974c862 115
vcoubard 24:2aea0c1c57ee 116 /**@brief Verifies the offset parameter provided by the application in API.
Vincent Coubard 0:f2542974c862 117 */
Vincent Coubard 0:f2542974c862 118 #define OFFSET_CHECK(ID, OFFSET, SIZE) \
Vincent Coubard 0:f2542974c862 119 if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
Vincent Coubard 0:f2542974c862 120 { \
Vincent Coubard 0:f2542974c862 121 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 122 }
Vincent Coubard 0:f2542974c862 123
Vincent Coubard 0:f2542974c862 124 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 125
vcoubard 24:2aea0c1c57ee 126 /**@brief Verifies the module identifier supplied by the application.
Vincent Coubard 0:f2542974c862 127 */
vcoubard 24:2aea0c1c57ee 128 #define MODULE_RAW_HANDLE_CHECK(ID) \
vcoubard 24:2aea0c1c57ee 129 if ((((ID)->module_id) != RAW_MODE_APP_ID)) \
Vincent Coubard 0:f2542974c862 130 { \
Vincent Coubard 0:f2542974c862 131 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 132 }
Vincent Coubard 0:f2542974c862 133
Vincent Coubard 0:f2542974c862 134 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 135
Vincent Coubard 0:f2542974c862 136 /**@} */
Vincent Coubard 0:f2542974c862 137
Vincent Coubard 0:f2542974c862 138
vcoubard 24:2aea0c1c57ee 139 /**@brief Verify module's initialization status.
Vincent Coubard 0:f2542974c862 140 *
vcoubard 24:2aea0c1c57ee 141 * @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE when a
vcoubard 24:2aea0c1c57ee 142 * module API is called without initializing the module.
Vincent Coubard 0:f2542974c862 143 */
Vincent Coubard 0:f2542974c862 144 #define VERIFY_MODULE_INITIALIZED() \
Vincent Coubard 0:f2542974c862 145 do \
Vincent Coubard 0:f2542974c862 146 { \
vcoubard 24:2aea0c1c57ee 147 if (!(m_flags & MASK_MODULE_INITIALIZED)) \
Vincent Coubard 0:f2542974c862 148 { \
Vincent Coubard 0:f2542974c862 149 return NRF_ERROR_INVALID_STATE; \
Vincent Coubard 0:f2542974c862 150 } \
Vincent Coubard 0:f2542974c862 151 } while(0)
Vincent Coubard 0:f2542974c862 152
Vincent Coubard 0:f2542974c862 153 /**@brief Macro to fetch the block size registered for the module. */
Vincent Coubard 0:f2542974c862 154 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
Vincent Coubard 0:f2542974c862 155
vcoubard 24:2aea0c1c57ee 156 /**@brief Main state machine of the component. */
Vincent Coubard 0:f2542974c862 157 typedef enum
Vincent Coubard 0:f2542974c862 158 {
vcoubard 24:2aea0c1c57ee 159 STATE_IDLE, /**< State for being idle (no command execution in progress). */
vcoubard 24:2aea0c1c57ee 160 STATE_STORE, /**< State for storing data when using store/update API. */
vcoubard 24:2aea0c1c57ee 161 STATE_DATA_ERASE_WITH_SWAP, /**< State for erasing the data page when using update/clear API when use of swap page is required. */
vcoubard 24:2aea0c1c57ee 162 STATE_DATA_ERASE, /**< State for erasing the data page when using update/clear API without the need to use the swap page. */
vcoubard 24:2aea0c1c57ee 163 STATE_ERROR /**< State entered when command processing is terminated abnormally. */
vcoubard 24:2aea0c1c57ee 164 } pstorage_state_t;
Vincent Coubard 0:f2542974c862 165
vcoubard 24:2aea0c1c57ee 166 /**@brief Sub state machine contained by @ref STATE_DATA_ERASE_WITH_SWAP super state machine. */
vcoubard 24:2aea0c1c57ee 167 typedef enum
vcoubard 24:2aea0c1c57ee 168 {
vcoubard 24:2aea0c1c57ee 169 STATE_ERASE_SWAP, /**< State for erasing the swap page when using the update/clear API. */
vcoubard 24:2aea0c1c57ee 170 STATE_WRITE_DATA_TO_SWAP, /**< State for writing the data page into the swap page when using update/clear API. */
vcoubard 24:2aea0c1c57ee 171 STATE_ERASE_DATA_PAGE, /**< State for erasing data page when using update/clear API. */
vcoubard 24:2aea0c1c57ee 172 STATE_RESTORE_TAIL, /**< State for restoring tail (end) of backed up data from swap to data page when using update/clear API. */
vcoubard 24:2aea0c1c57ee 173 STATE_RESTORE_HEAD, /**< State for restoring head (beginning) of backed up data from swap to data page when using update/clear API. */
vcoubard 24:2aea0c1c57ee 174 SWAP_SUB_STATE_MAX /**< Enumeration upper bound. */
vcoubard 24:2aea0c1c57ee 175 } flash_swap_sub_state_t;
Vincent Coubard 0:f2542974c862 176
vcoubard 24:2aea0c1c57ee 177 /**@brief Application registration information.
Vincent Coubard 0:f2542974c862 178 *
vcoubard 24:2aea0c1c57ee 179 * @details Defines application specific information that the application needs to maintain to be able
Vincent Coubard 0:f2542974c862 180 * to process requests from each one of them.
Vincent Coubard 0:f2542974c862 181 */
Vincent Coubard 0:f2542974c862 182 typedef struct
Vincent Coubard 0:f2542974c862 183 {
vcoubard 24:2aea0c1c57ee 184 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
vcoubard 24:2aea0c1c57ee 185 pstorage_block_t base_id; /**< Base block ID assigned to the module. */
vcoubard 24:2aea0c1c57ee 186 pstorage_size_t block_size; /**< Size of block for the module. */
vcoubard 24:2aea0c1c57ee 187 pstorage_size_t block_count; /**< Number of blocks requested by the application. */
Vincent Coubard 0:f2542974c862 188 } pstorage_module_table_t;
Vincent Coubard 0:f2542974c862 189
Vincent Coubard 0:f2542974c862 190
Vincent Coubard 0:f2542974c862 191 #ifdef PSTORAGE_RAW_MODE_ENABLE
vcoubard 24:2aea0c1c57ee 192 /**@brief Application registration information.
Vincent Coubard 0:f2542974c862 193 *
vcoubard 24:2aea0c1c57ee 194 * @details Defines application specific information that the application registered for raw mode.
Vincent Coubard 0:f2542974c862 195 */
Vincent Coubard 0:f2542974c862 196 typedef struct
Vincent Coubard 0:f2542974c862 197 {
vcoubard 24:2aea0c1c57ee 198 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of the result of flash access. */
Vincent Coubard 0:f2542974c862 199 } pstorage_raw_module_table_t;
Vincent Coubard 0:f2542974c862 200 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 201
Vincent Coubard 0:f2542974c862 202
vcoubard 24:2aea0c1c57ee 203 /**@brief Defines command queue element.
Vincent Coubard 0:f2542974c862 204 *
Vincent Coubard 0:f2542974c862 205 * @details Defines command queue element. Each element encapsulates needed information to process
Vincent Coubard 0:f2542974c862 206 * a flash access command.
Vincent Coubard 0:f2542974c862 207 */
Vincent Coubard 0:f2542974c862 208 typedef struct
Vincent Coubard 0:f2542974c862 209 {
vcoubard 24:2aea0c1c57ee 210 uint8_t op_code; /**< Identifies the flash access operation being queued. Element is free if op-code is INVALID_OPCODE. */
vcoubard 24:2aea0c1c57ee 211 pstorage_size_t size; /**< Identifies the size in bytes requested for the operation. */
vcoubard 24:2aea0c1c57ee 212 pstorage_size_t offset; /**< Offset requested by the application for the access operation. */
vcoubard 24:2aea0c1c57ee 213 pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
vcoubard 24:2aea0c1c57ee 214 uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
Vincent Coubard 0:f2542974c862 215 } cmd_queue_element_t;
Vincent Coubard 0:f2542974c862 216
Vincent Coubard 0:f2542974c862 217
vcoubard 24:2aea0c1c57ee 218 /**@brief Defines command queue, an element is free if the op_code field is not invalid.
Vincent Coubard 0:f2542974c862 219 *
vcoubard 24:2aea0c1c57ee 220 * @details Defines commands enqueued for flash access. At any point in time, this queue has one or
vcoubard 24:2aea0c1c57ee 221 * more flash access operations pending if the count field is not zero. When the queue is
vcoubard 24:2aea0c1c57ee 222 * not empty, the rp (read pointer) field points to the flash access command in progress
vcoubard 24:2aea0c1c57ee 223 * or, if none is in progress, the command to be requested next. The queue implements a
vcoubard 24:2aea0c1c57ee 224 * simple first in first out algorithm. Data addresses are assumed to be resident.
Vincent Coubard 0:f2542974c862 225 */
Vincent Coubard 0:f2542974c862 226 typedef struct
Vincent Coubard 0:f2542974c862 227 {
vcoubard 24:2aea0c1c57ee 228 uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
vcoubard 24:2aea0c1c57ee 229 uint8_t count; /**< Number of elements in the queue. */
vcoubard 24:2aea0c1c57ee 230 cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details. */
Vincent Coubard 0:f2542974c862 231 } cmd_queue_t;
Vincent Coubard 0:f2542974c862 232
vcoubard 24:2aea0c1c57ee 233 static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
vcoubard 24:2aea0c1c57ee 234 static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next. */
vcoubard 24:2aea0c1c57ee 235 static uint32_t m_next_page_addr; /**< Points to the flash address that can be allocated to a module next. This is needed as blocks of a module that can span across flash pages. */
vcoubard 24:2aea0c1c57ee 236 static pstorage_state_t m_state; /**< Main state tracking variable. */
vcoubard 24:2aea0c1c57ee 237 static flash_swap_sub_state_t m_swap_sub_state; /**< Flash swap erase when swap used state tracking variable. */
vcoubard 24:2aea0c1c57ee 238 static uint32_t m_head_word_size; /**< Head restore area size in words. */
vcoubard 24:2aea0c1c57ee 239 static uint32_t m_tail_word_size; /**< Tail restore area size in words. */
vcoubard 24:2aea0c1c57ee 240 static uint32_t m_current_page_id; /**< Variable for tracking the flash page being processed. */
vcoubard 24:2aea0c1c57ee 241 static uint32_t m_num_of_command_retries; /**< Variable for tracking flash operation retries upon flash operation failures. */
vcoubard 24:2aea0c1c57ee 242 static pstorage_module_table_t m_app_table[PSTORAGE_NUM_OF_PAGES]; /**< Registered application information table. */
vcoubard 24:2aea0c1c57ee 243 static uint32_t m_num_of_bytes_written; /**< Variable for tracking the number of bytes written by the store operation. */
vcoubard 24:2aea0c1c57ee 244 static uint32_t m_app_data_size; /**< Variable for storing the application command size parameter internally. */
vcoubard 24:2aea0c1c57ee 245 static uint32_t m_flags = 0; /**< Storage for boolean flags for state tracking. */
Vincent Coubard 0:f2542974c862 246
Vincent Coubard 0:f2542974c862 247 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 248 static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
Vincent Coubard 0:f2542974c862 249 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 250
vcoubard 24:2aea0c1c57ee 251 // Required forward declarations.
vcoubard 24:2aea0c1c57ee 252 static void cmd_process(void);
vcoubard 24:2aea0c1c57ee 253 static void store_operation_execute(void);
vcoubard 24:2aea0c1c57ee 254 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem);
vcoubard 24:2aea0c1c57ee 255 static void cmd_queue_element_init(uint32_t index);
vcoubard 24:2aea0c1c57ee 256 static void cmd_queue_dequeue(void);
vcoubard 24:2aea0c1c57ee 257 static void sm_state_change(pstorage_state_t new_state);
vcoubard 24:2aea0c1c57ee 258 static void swap_sub_state_state_change(flash_swap_sub_state_t new_state);
Vincent Coubard 0:f2542974c862 259
vcoubard 24:2aea0c1c57ee 260 /**@brief Function for consuming a command queue element.
vcoubard 24:2aea0c1c57ee 261 *
vcoubard 24:2aea0c1c57ee 262 * @details Function for consuming a command queue element, which has been fully processed.
vcoubard 24:2aea0c1c57ee 263 */
vcoubard 24:2aea0c1c57ee 264 static void command_queue_element_consume(void)
vcoubard 24:2aea0c1c57ee 265 {
vcoubard 24:2aea0c1c57ee 266 // Initialize/free the element as it is now processed.
vcoubard 24:2aea0c1c57ee 267 cmd_queue_element_init(m_cmd_queue.rp);
vcoubard 24:2aea0c1c57ee 268
vcoubard 24:2aea0c1c57ee 269 // Adjust command queue state tracking variables.
vcoubard 24:2aea0c1c57ee 270 --(m_cmd_queue.count);
vcoubard 24:2aea0c1c57ee 271 if (++(m_cmd_queue.rp) == PSTORAGE_CMD_QUEUE_SIZE)
vcoubard 24:2aea0c1c57ee 272 {
vcoubard 24:2aea0c1c57ee 273 m_cmd_queue.rp = 0;
vcoubard 24:2aea0c1c57ee 274 }
vcoubard 24:2aea0c1c57ee 275 }
vcoubard 24:2aea0c1c57ee 276
vcoubard 24:2aea0c1c57ee 277
vcoubard 24:2aea0c1c57ee 278 /**@brief Function for executing the finalization procedure for the command executed.
vcoubard 24:2aea0c1c57ee 279 *
vcoubard 24:2aea0c1c57ee 280 * @details Function for executing the finalization procedure for command executed, which includes
vcoubard 24:2aea0c1c57ee 281 * notifying the application of command completion, consuming the command queue element,
vcoubard 24:2aea0c1c57ee 282 * and changing the internal state.
vcoubard 24:2aea0c1c57ee 283 */
vcoubard 24:2aea0c1c57ee 284 static void command_end_procedure_run(void)
vcoubard 24:2aea0c1c57ee 285 {
vcoubard 24:2aea0c1c57ee 286 app_notify(NRF_SUCCESS, &m_cmd_queue.cmd[m_cmd_queue.rp]);
vcoubard 24:2aea0c1c57ee 287
vcoubard 24:2aea0c1c57ee 288 command_queue_element_consume();
vcoubard 24:2aea0c1c57ee 289
vcoubard 24:2aea0c1c57ee 290 sm_state_change(STATE_IDLE);
vcoubard 24:2aea0c1c57ee 291 }
vcoubard 24:2aea0c1c57ee 292
vcoubard 24:2aea0c1c57ee 293
vcoubard 24:2aea0c1c57ee 294 /**@brief Function for idle state entry actions.
vcoubard 24:2aea0c1c57ee 295 *
vcoubard 24:2aea0c1c57ee 296 * @details Function for idle state entry actions, which include resetting relevant state data and
vcoubard 24:2aea0c1c57ee 297 * scheduling any possible queued flash access operation.
vcoubard 24:2aea0c1c57ee 298 */
vcoubard 24:2aea0c1c57ee 299 static void state_idle_entry_run(void)
vcoubard 24:2aea0c1c57ee 300 {
vcoubard 24:2aea0c1c57ee 301 m_num_of_command_retries = 0;
vcoubard 24:2aea0c1c57ee 302 m_num_of_bytes_written = 0;
vcoubard 24:2aea0c1c57ee 303
vcoubard 24:2aea0c1c57ee 304 // Schedule any possible queued flash access operation.
vcoubard 24:2aea0c1c57ee 305 cmd_queue_dequeue();
vcoubard 24:2aea0c1c57ee 306 }
vcoubard 24:2aea0c1c57ee 307
vcoubard 24:2aea0c1c57ee 308
vcoubard 24:2aea0c1c57ee 309 /**@brief Function for notifying an application of command completion and transitioning to an error
vcoubard 24:2aea0c1c57ee 310 * state.
vcoubard 24:2aea0c1c57ee 311 *
vcoubard 24:2aea0c1c57ee 312 * @param[in] result Result code of the operation for the application.
vcoubard 24:2aea0c1c57ee 313 */
vcoubard 24:2aea0c1c57ee 314 static void app_notify_error_state_transit(uint32_t result)
vcoubard 24:2aea0c1c57ee 315 {
vcoubard 24:2aea0c1c57ee 316 app_notify(result, &m_cmd_queue.cmd[m_cmd_queue.rp]);
vcoubard 24:2aea0c1c57ee 317 sm_state_change(STATE_ERROR);
vcoubard 24:2aea0c1c57ee 318 }
vcoubard 24:2aea0c1c57ee 319
vcoubard 24:2aea0c1c57ee 320
vcoubard 24:2aea0c1c57ee 321 /**@brief Function for processing flash API error code.
Vincent Coubard 0:f2542974c862 322 *
vcoubard 24:2aea0c1c57ee 323 * @param[in] err_code Error code from the flash API.
vcoubard 24:2aea0c1c57ee 324 */
vcoubard 24:2aea0c1c57ee 325 static void flash_api_err_code_process(uint32_t err_code)
vcoubard 24:2aea0c1c57ee 326 {
vcoubard 24:2aea0c1c57ee 327 switch (err_code)
vcoubard 24:2aea0c1c57ee 328 {
vcoubard 24:2aea0c1c57ee 329 case NRF_SUCCESS:
vcoubard 24:2aea0c1c57ee 330 break;
vcoubard 24:2aea0c1c57ee 331
vcoubard 24:2aea0c1c57ee 332 case NRF_ERROR_BUSY:
vcoubard 24:2aea0c1c57ee 333 // Flash access operation was not accepted and must be reissued upon flash operation
vcoubard 24:2aea0c1c57ee 334 // complete event.
vcoubard 24:2aea0c1c57ee 335 m_flags |= MASK_FLASH_API_ERR_BUSY;
vcoubard 24:2aea0c1c57ee 336 break;
vcoubard 24:2aea0c1c57ee 337
vcoubard 24:2aea0c1c57ee 338 default:
vcoubard 24:2aea0c1c57ee 339 // Complete the operation with appropriate result code and transit to an error state.
vcoubard 24:2aea0c1c57ee 340 app_notify_error_state_transit(err_code);
vcoubard 24:2aea0c1c57ee 341 break;
vcoubard 24:2aea0c1c57ee 342 }
vcoubard 24:2aea0c1c57ee 343 }
vcoubard 24:2aea0c1c57ee 344
vcoubard 24:2aea0c1c57ee 345 /**@brief Function for writing data to flash.
vcoubard 24:2aea0c1c57ee 346 *
vcoubard 24:2aea0c1c57ee 347 * @param[in] p_dst Pointer to start of flash location to be written.
vcoubard 24:2aea0c1c57ee 348 * @param[in] p_src Pointer to buffer with data to be written.
vcoubard 24:2aea0c1c57ee 349 * @param[in] size_in_words Number of 32-bit words to write.
Vincent Coubard 0:f2542974c862 350 */
vcoubard 24:2aea0c1c57ee 351 static void flash_write(uint32_t * const p_dst,
vcoubard 24:2aea0c1c57ee 352 uint32_t const * const p_src,
vcoubard 24:2aea0c1c57ee 353 uint32_t size_in_words)
vcoubard 24:2aea0c1c57ee 354 {
vcoubard 24:2aea0c1c57ee 355 flash_api_err_code_process(sd_flash_write(p_dst, p_src, size_in_words));
vcoubard 24:2aea0c1c57ee 356 }
vcoubard 24:2aea0c1c57ee 357
vcoubard 24:2aea0c1c57ee 358
vcoubard 24:2aea0c1c57ee 359 /**@brief Function for writing data to flash upon store command.
vcoubard 24:2aea0c1c57ee 360 *
vcoubard 24:2aea0c1c57ee 361 * @details Function for writing data to flash upon executing store command. Data is written to
vcoubard 24:2aea0c1c57ee 362 * flash in reverse order, meaning starting at the end. If the data that is to be written
vcoubard 24:2aea0c1c57ee 363 * is greater than the flash page size, it will be fragmented to fit the flash page size.
vcoubard 24:2aea0c1c57ee 364 */
vcoubard 24:2aea0c1c57ee 365 static void store_cmd_flash_write_execute(void)
vcoubard 24:2aea0c1c57ee 366 {
vcoubard 24:2aea0c1c57ee 367 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 368
vcoubard 24:2aea0c1c57ee 369 if (p_cmd->size > SOC_MAX_WRITE_SIZE)
vcoubard 24:2aea0c1c57ee 370 {
vcoubard 24:2aea0c1c57ee 371 const uint32_t offset = p_cmd->size - PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 372 flash_write((uint32_t *)(p_cmd->storage_addr.block_id + p_cmd->offset + offset),
vcoubard 24:2aea0c1c57ee 373 (uint32_t *)(p_cmd->p_data_addr + offset),
vcoubard 24:2aea0c1c57ee 374 PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
vcoubard 24:2aea0c1c57ee 375
vcoubard 24:2aea0c1c57ee 376 m_num_of_bytes_written = PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 377 }
vcoubard 24:2aea0c1c57ee 378 else
vcoubard 24:2aea0c1c57ee 379 {
vcoubard 24:2aea0c1c57ee 380 flash_write((uint32_t *)(p_cmd->storage_addr.block_id + p_cmd->offset),
vcoubard 24:2aea0c1c57ee 381 (uint32_t *)(p_cmd->p_data_addr),
vcoubard 24:2aea0c1c57ee 382 p_cmd->size / sizeof(uint32_t));
vcoubard 24:2aea0c1c57ee 383
vcoubard 24:2aea0c1c57ee 384 m_num_of_bytes_written = p_cmd->size;
vcoubard 24:2aea0c1c57ee 385 }
vcoubard 24:2aea0c1c57ee 386 }
vcoubard 24:2aea0c1c57ee 387
vcoubard 24:2aea0c1c57ee 388
vcoubard 24:2aea0c1c57ee 389 /**@brief Function for store state entry action.
vcoubard 24:2aea0c1c57ee 390 *
vcoubard 24:2aea0c1c57ee 391 * @details Function for store state entry action, which includes writing data to a flash page.
vcoubard 24:2aea0c1c57ee 392 */
vcoubard 24:2aea0c1c57ee 393 static void state_store_entry_run(void)
vcoubard 24:2aea0c1c57ee 394 {
vcoubard 24:2aea0c1c57ee 395 store_cmd_flash_write_execute();
vcoubard 24:2aea0c1c57ee 396 }
Vincent Coubard 0:f2542974c862 397
Vincent Coubard 0:f2542974c862 398
vcoubard 24:2aea0c1c57ee 399 /**@brief Function for data erase with swap state entry actions.
Vincent Coubard 0:f2542974c862 400 *
vcoubard 24:2aea0c1c57ee 401 * @details Function for data erase with swap state entry actions. This includes adjusting relevant
vcoubard 24:2aea0c1c57ee 402 * state and data variables and transitioning to the correct sub state.
Vincent Coubard 0:f2542974c862 403 */
vcoubard 24:2aea0c1c57ee 404 static void state_data_erase_swap_entry_run(void)
vcoubard 24:2aea0c1c57ee 405 {
vcoubard 24:2aea0c1c57ee 406 m_flags &= ~MASK_TAIL_SWAP_DONE;
vcoubard 24:2aea0c1c57ee 407
vcoubard 24:2aea0c1c57ee 408 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 409 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
vcoubard 24:2aea0c1c57ee 410
vcoubard 24:2aea0c1c57ee 411 const uint32_t clear_start_page_id = cmd_block_id / PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 412 m_current_page_id = clear_start_page_id;
vcoubard 24:2aea0c1c57ee 413
vcoubard 24:2aea0c1c57ee 414 // @note: No need to include p_cmd->offset when calculating clear_end_page_id as:
vcoubard 24:2aea0c1c57ee 415 // - clear API does not include offset parameter
vcoubard 24:2aea0c1c57ee 416 // - update and store APIs are limited to operate on single block boundary thus the boolean
vcoubard 24:2aea0c1c57ee 417 // clause ((m_head_word_size == 0) && is_more_than_one_page) below in this function will never
vcoubard 24:2aea0c1c57ee 418 // evaluate as true as if is_more_than_one_page == true m_head_word_size is always != 0
vcoubard 24:2aea0c1c57ee 419 const uint32_t clear_end_page_id = (cmd_block_id + p_cmd->size - 1u) /
vcoubard 24:2aea0c1c57ee 420 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 421
vcoubard 24:2aea0c1c57ee 422 if (clear_start_page_id == clear_end_page_id)
vcoubard 24:2aea0c1c57ee 423 {
vcoubard 24:2aea0c1c57ee 424 m_flags |= MASK_SINGLE_PAGE_OPERATION;
vcoubard 24:2aea0c1c57ee 425 }
vcoubard 24:2aea0c1c57ee 426 else
vcoubard 24:2aea0c1c57ee 427 {
vcoubard 24:2aea0c1c57ee 428 m_flags &= ~MASK_SINGLE_PAGE_OPERATION;
vcoubard 24:2aea0c1c57ee 429 }
vcoubard 24:2aea0c1c57ee 430
vcoubard 24:2aea0c1c57ee 431 if ((m_head_word_size == 0) && !(m_flags & MASK_SINGLE_PAGE_OPERATION))
vcoubard 24:2aea0c1c57ee 432 {
vcoubard 24:2aea0c1c57ee 433 // No head restore required and clear/update area is shared by multiple flash pages, which
vcoubard 24:2aea0c1c57ee 434 // means the current flash page does not have any tail area to restore. You can proceed with
vcoubard 24:2aea0c1c57ee 435 // data page erase directly as no swap is needed for the current flash page.
vcoubard 24:2aea0c1c57ee 436 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
vcoubard 24:2aea0c1c57ee 437 }
vcoubard 24:2aea0c1c57ee 438 else
vcoubard 24:2aea0c1c57ee 439 {
vcoubard 24:2aea0c1c57ee 440 swap_sub_state_state_change(STATE_ERASE_SWAP);
vcoubard 24:2aea0c1c57ee 441 }
vcoubard 24:2aea0c1c57ee 442 }
vcoubard 24:2aea0c1c57ee 443
vcoubard 24:2aea0c1c57ee 444
vcoubard 24:2aea0c1c57ee 445 /**@brief Function for erasing flash page.
vcoubard 24:2aea0c1c57ee 446 *
vcoubard 24:2aea0c1c57ee 447 * @param[in] page_number Page number of the page to be erased.
vcoubard 24:2aea0c1c57ee 448 */
vcoubard 24:2aea0c1c57ee 449 static void flash_page_erase(uint32_t page_number)
vcoubard 24:2aea0c1c57ee 450 {
vcoubard 24:2aea0c1c57ee 451 flash_api_err_code_process(sd_flash_page_erase(page_number));
vcoubard 24:2aea0c1c57ee 452 }
vcoubard 24:2aea0c1c57ee 453
vcoubard 24:2aea0c1c57ee 454
vcoubard 24:2aea0c1c57ee 455 /**@brief Function for data erase state entry action.
vcoubard 24:2aea0c1c57ee 456 *
vcoubard 24:2aea0c1c57ee 457 * @details Function for data erase state entry action, which includes erasing the data flash page.
vcoubard 24:2aea0c1c57ee 458 */
vcoubard 24:2aea0c1c57ee 459 static void state_data_erase_entry_run(void)
vcoubard 24:2aea0c1c57ee 460 {
vcoubard 24:2aea0c1c57ee 461 flash_page_erase(m_current_page_id);
vcoubard 24:2aea0c1c57ee 462 }
vcoubard 24:2aea0c1c57ee 463
vcoubard 24:2aea0c1c57ee 464
vcoubard 24:2aea0c1c57ee 465 /**@brief Function for dispatching the correct application main state entry action.
vcoubard 24:2aea0c1c57ee 466 */
vcoubard 24:2aea0c1c57ee 467 static void state_entry_action_run(void)
vcoubard 24:2aea0c1c57ee 468 {
vcoubard 24:2aea0c1c57ee 469 switch (m_state)
vcoubard 24:2aea0c1c57ee 470 {
vcoubard 24:2aea0c1c57ee 471 case STATE_IDLE:
vcoubard 24:2aea0c1c57ee 472 state_idle_entry_run();
vcoubard 24:2aea0c1c57ee 473 break;
vcoubard 24:2aea0c1c57ee 474
vcoubard 24:2aea0c1c57ee 475 case STATE_STORE:
vcoubard 24:2aea0c1c57ee 476 state_store_entry_run();
vcoubard 24:2aea0c1c57ee 477 break;
vcoubard 24:2aea0c1c57ee 478
vcoubard 24:2aea0c1c57ee 479 case STATE_DATA_ERASE_WITH_SWAP:
vcoubard 24:2aea0c1c57ee 480 state_data_erase_swap_entry_run();
vcoubard 24:2aea0c1c57ee 481 break;
vcoubard 24:2aea0c1c57ee 482
vcoubard 24:2aea0c1c57ee 483 case STATE_DATA_ERASE:
vcoubard 24:2aea0c1c57ee 484 state_data_erase_entry_run();
vcoubard 24:2aea0c1c57ee 485 break;
vcoubard 24:2aea0c1c57ee 486
vcoubard 24:2aea0c1c57ee 487 default:
vcoubard 24:2aea0c1c57ee 488 // No action needed.
vcoubard 24:2aea0c1c57ee 489 break;
vcoubard 24:2aea0c1c57ee 490 }
vcoubard 24:2aea0c1c57ee 491 }
Vincent Coubard 0:f2542974c862 492
Vincent Coubard 0:f2542974c862 493
vcoubard 24:2aea0c1c57ee 494 /**@brief Function for changing application main state and dispatching state entry action.
vcoubard 24:2aea0c1c57ee 495 *
vcoubard 24:2aea0c1c57ee 496 * @param[in] new_state New application main state to transit to.
vcoubard 24:2aea0c1c57ee 497 */
vcoubard 24:2aea0c1c57ee 498 static void sm_state_change(pstorage_state_t new_state)
vcoubard 24:2aea0c1c57ee 499 {
vcoubard 24:2aea0c1c57ee 500 m_state = new_state;
vcoubard 24:2aea0c1c57ee 501 state_entry_action_run();
vcoubard 24:2aea0c1c57ee 502 }
vcoubard 24:2aea0c1c57ee 503
vcoubard 24:2aea0c1c57ee 504
vcoubard 24:2aea0c1c57ee 505 /**@brief Function for swap erase state entry action.
vcoubard 24:2aea0c1c57ee 506 *
vcoubard 24:2aea0c1c57ee 507 * @details Function for swap erase state entry action, which includes erasing swap flash
vcoubard 24:2aea0c1c57ee 508 * page.
vcoubard 24:2aea0c1c57ee 509 */
vcoubard 24:2aea0c1c57ee 510 static void state_swap_erase_entry_run(void)
vcoubard 24:2aea0c1c57ee 511 {
vcoubard 24:2aea0c1c57ee 512 flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 24:2aea0c1c57ee 513 }
vcoubard 24:2aea0c1c57ee 514
vcoubard 24:2aea0c1c57ee 515
vcoubard 24:2aea0c1c57ee 516 /**@brief Function for write data to the swap state entry action.
Vincent Coubard 0:f2542974c862 517 *
vcoubard 24:2aea0c1c57ee 518 * @details Function for write data to the swap state entry action, which includes writing the
vcoubard 24:2aea0c1c57ee 519 * current data page to the swap flash page.
Vincent Coubard 0:f2542974c862 520 */
vcoubard 24:2aea0c1c57ee 521 static void state_write_data_swap_entry_run(void)
vcoubard 24:2aea0c1c57ee 522 {
vcoubard 24:2aea0c1c57ee 523 // @note: There is room for further optimization here as there is only need to write the
vcoubard 24:2aea0c1c57ee 524 // whole flash page to swap area if there is both head and tail area to be restored. In any
vcoubard 24:2aea0c1c57ee 525 // other case we can omit some data from the head or end of the page as that is the clear area.
vcoubard 24:2aea0c1c57ee 526 flash_write((uint32_t *)(PSTORAGE_SWAP_ADDR),
vcoubard 24:2aea0c1c57ee 527 (uint32_t *)(m_current_page_id * PSTORAGE_FLASH_PAGE_SIZE),
vcoubard 24:2aea0c1c57ee 528 PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
vcoubard 24:2aea0c1c57ee 529 }
vcoubard 24:2aea0c1c57ee 530
vcoubard 24:2aea0c1c57ee 531
vcoubard 24:2aea0c1c57ee 532 /**@brief Function for erase data page state entry action.
vcoubard 24:2aea0c1c57ee 533 *
vcoubard 24:2aea0c1c57ee 534 * @details Function for erase data page state entry action, which includes erasing the data flash
vcoubard 24:2aea0c1c57ee 535 * page.
vcoubard 24:2aea0c1c57ee 536 */
vcoubard 24:2aea0c1c57ee 537 static void state_erase_data_page_entry_run(void)
vcoubard 24:2aea0c1c57ee 538 {
vcoubard 24:2aea0c1c57ee 539 flash_page_erase(m_current_page_id);
vcoubard 24:2aea0c1c57ee 540 }
Vincent Coubard 0:f2542974c862 541
Vincent Coubard 0:f2542974c862 542
vcoubard 24:2aea0c1c57ee 543 /**@brief Function for restore tail state entry action.
vcoubard 24:2aea0c1c57ee 544 *
vcoubard 24:2aea0c1c57ee 545 * @details Function for restore tail state entry action, which includes writing the tail section
vcoubard 24:2aea0c1c57ee 546 * back from swap to the data page.
vcoubard 24:2aea0c1c57ee 547 */
vcoubard 24:2aea0c1c57ee 548 static void state_restore_tail_entry_run(void)
vcoubard 24:2aea0c1c57ee 549 {
vcoubard 24:2aea0c1c57ee 550 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 551 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
vcoubard 24:2aea0c1c57ee 552
vcoubard 24:2aea0c1c57ee 553 const uint32_t tail_offset = (cmd_block_id + p_cmd->size + p_cmd->offset) %
vcoubard 24:2aea0c1c57ee 554 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 555
vcoubard 24:2aea0c1c57ee 556 flash_write((uint32_t *)(cmd_block_id + p_cmd->size + p_cmd->offset),
vcoubard 24:2aea0c1c57ee 557 (uint32_t *)(PSTORAGE_SWAP_ADDR + tail_offset),
vcoubard 24:2aea0c1c57ee 558 m_tail_word_size);
vcoubard 24:2aea0c1c57ee 559 }
vcoubard 24:2aea0c1c57ee 560
vcoubard 24:2aea0c1c57ee 561
vcoubard 24:2aea0c1c57ee 562 /**@brief Function for restore head state entry action.
Vincent Coubard 0:f2542974c862 563 *
vcoubard 24:2aea0c1c57ee 564 * @details Function for restore head state entry action, which includes writing the head section
vcoubard 24:2aea0c1c57ee 565 * back from swap to the data page.
vcoubard 24:2aea0c1c57ee 566 */
vcoubard 24:2aea0c1c57ee 567 static void state_restore_head_entry_run(void)
vcoubard 24:2aea0c1c57ee 568 {
vcoubard 24:2aea0c1c57ee 569 flash_write((uint32_t *)((m_current_page_id - 1u) * PSTORAGE_FLASH_PAGE_SIZE),
vcoubard 24:2aea0c1c57ee 570 (uint32_t *)PSTORAGE_SWAP_ADDR,
vcoubard 24:2aea0c1c57ee 571 m_head_word_size);
vcoubard 24:2aea0c1c57ee 572 }
vcoubard 24:2aea0c1c57ee 573
vcoubard 24:2aea0c1c57ee 574
vcoubard 24:2aea0c1c57ee 575 /**@brief Function for dispatching the correct swap sub state entry action.
vcoubard 24:2aea0c1c57ee 576 */
vcoubard 24:2aea0c1c57ee 577 static void swap_sub_state_entry_action_run(void)
vcoubard 24:2aea0c1c57ee 578 {
vcoubard 24:2aea0c1c57ee 579 static void (* const swap_sub_state_sm_lut[SWAP_SUB_STATE_MAX])(void) =
vcoubard 24:2aea0c1c57ee 580 {
vcoubard 24:2aea0c1c57ee 581 state_swap_erase_entry_run,
vcoubard 24:2aea0c1c57ee 582 state_write_data_swap_entry_run,
vcoubard 24:2aea0c1c57ee 583 state_erase_data_page_entry_run,
vcoubard 24:2aea0c1c57ee 584 state_restore_tail_entry_run,
vcoubard 24:2aea0c1c57ee 585 state_restore_head_entry_run
vcoubard 24:2aea0c1c57ee 586 };
vcoubard 24:2aea0c1c57ee 587
vcoubard 24:2aea0c1c57ee 588 swap_sub_state_sm_lut[m_swap_sub_state]();
vcoubard 24:2aea0c1c57ee 589 }
vcoubard 24:2aea0c1c57ee 590
vcoubard 24:2aea0c1c57ee 591
vcoubard 24:2aea0c1c57ee 592 /**@brief Function for changing the swap sub state and dispatching state entry action.
vcoubard 24:2aea0c1c57ee 593 *
vcoubard 24:2aea0c1c57ee 594 * @param[in] new_state New swap sub state to transit to.
vcoubard 24:2aea0c1c57ee 595 */
vcoubard 24:2aea0c1c57ee 596 static void swap_sub_state_state_change(flash_swap_sub_state_t new_state)
vcoubard 24:2aea0c1c57ee 597 {
vcoubard 24:2aea0c1c57ee 598 m_swap_sub_state = new_state;
vcoubard 24:2aea0c1c57ee 599 swap_sub_state_entry_action_run();
vcoubard 24:2aea0c1c57ee 600 }
vcoubard 24:2aea0c1c57ee 601
vcoubard 24:2aea0c1c57ee 602
vcoubard 24:2aea0c1c57ee 603 /**@brief Function for initializing the command queue element.
vcoubard 24:2aea0c1c57ee 604 *
vcoubard 24:2aea0c1c57ee 605 * @param[in] index Index of the element to be initialized.
Vincent Coubard 0:f2542974c862 606 */
Vincent Coubard 0:f2542974c862 607 static void cmd_queue_element_init(uint32_t index)
Vincent Coubard 0:f2542974c862 608 {
Vincent Coubard 0:f2542974c862 609 // Internal function and checks on range of index can be avoided.
Vincent Coubard 0:f2542974c862 610 m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
Vincent Coubard 0:f2542974c862 611 m_cmd_queue.cmd[index].size = 0;
vcoubard 24:2aea0c1c57ee 612 m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_NUM_OF_PAGES;
Vincent Coubard 0:f2542974c862 613 m_cmd_queue.cmd[index].storage_addr.block_id = 0;
Vincent Coubard 0:f2542974c862 614 m_cmd_queue.cmd[index].p_data_addr = NULL;
Vincent Coubard 0:f2542974c862 615 m_cmd_queue.cmd[index].offset = 0;
Vincent Coubard 0:f2542974c862 616 }
Vincent Coubard 0:f2542974c862 617
Vincent Coubard 0:f2542974c862 618
vcoubard 24:2aea0c1c57ee 619 /**@brief Function for initializing the command queue.
Vincent Coubard 0:f2542974c862 620 */
Vincent Coubard 0:f2542974c862 621 static void cmd_queue_init(void)
Vincent Coubard 0:f2542974c862 622 {
vcoubard 24:2aea0c1c57ee 623 m_cmd_queue.rp = 0;
vcoubard 24:2aea0c1c57ee 624 m_cmd_queue.count = 0;
Vincent Coubard 0:f2542974c862 625
vcoubard 24:2aea0c1c57ee 626 for (uint32_t cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; ++cmd_index)
Vincent Coubard 0:f2542974c862 627 {
Vincent Coubard 0:f2542974c862 628 cmd_queue_element_init(cmd_index);
Vincent Coubard 0:f2542974c862 629 }
Vincent Coubard 0:f2542974c862 630 }
Vincent Coubard 0:f2542974c862 631
Vincent Coubard 0:f2542974c862 632
vcoubard 24:2aea0c1c57ee 633 /**@brief Function for enqueuing, and possibly dispatching, a flash access operation.
Vincent Coubard 0:f2542974c862 634 *
vcoubard 24:2aea0c1c57ee 635 * @param[in] opcode Identifies the operation requested to be enqueued.
vcoubard 24:2aea0c1c57ee 636 * @param[in] p_storage_addr Identifies the module and flash address on which the operation is
vcoubard 24:2aea0c1c57ee 637 * requested.
vcoubard 24:2aea0c1c57ee 638 * @param[in] p_data_addr Identifies the data address for flash access.
Vincent Coubard 0:f2542974c862 639 * @param[in] size Size in bytes of data requested for the access operation.
Vincent Coubard 0:f2542974c862 640 * @param[in] offset Offset within the flash memory block at which operation is requested.
Vincent Coubard 0:f2542974c862 641 *
vcoubard 24:2aea0c1c57ee 642 * @retval NRF_SUCCESS Upon success.
vcoubard 24:2aea0c1c57ee 643 * @retval NRF_ERROR_NO_MEM Upon failure, when no space is available in the command queue.
Vincent Coubard 0:f2542974c862 644 */
Vincent Coubard 0:f2542974c862 645 static uint32_t cmd_queue_enqueue(uint8_t opcode,
Vincent Coubard 0:f2542974c862 646 pstorage_handle_t * p_storage_addr,
Vincent Coubard 0:f2542974c862 647 uint8_t * p_data_addr,
Vincent Coubard 0:f2542974c862 648 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 649 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 650 {
vcoubard 24:2aea0c1c57ee 651 uint32_t err_code;
Vincent Coubard 0:f2542974c862 652
Vincent Coubard 0:f2542974c862 653 if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 0:f2542974c862 654 {
vcoubard 24:2aea0c1c57ee 655 // Enqueue the command if it the queue is not full.
vcoubard 24:2aea0c1c57ee 656 uint32_t write_index = m_cmd_queue.rp + m_cmd_queue.count;
Vincent Coubard 0:f2542974c862 657
vcoubard 24:2aea0c1c57ee 658 if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 0:f2542974c862 659 {
Vincent Coubard 0:f2542974c862 660 write_index -= PSTORAGE_CMD_QUEUE_SIZE;
Vincent Coubard 0:f2542974c862 661 }
Vincent Coubard 0:f2542974c862 662
Vincent Coubard 0:f2542974c862 663 m_cmd_queue.cmd[write_index].op_code = opcode;
Vincent Coubard 0:f2542974c862 664 m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
Vincent Coubard 0:f2542974c862 665 m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
Vincent Coubard 0:f2542974c862 666 m_cmd_queue.cmd[write_index].size = size;
Vincent Coubard 0:f2542974c862 667 m_cmd_queue.cmd[write_index].offset = offset;
vcoubard 24:2aea0c1c57ee 668
vcoubard 24:2aea0c1c57ee 669 m_cmd_queue.count++;
vcoubard 24:2aea0c1c57ee 670
vcoubard 24:2aea0c1c57ee 671 if (m_state == STATE_IDLE)
Vincent Coubard 0:f2542974c862 672 {
vcoubard 24:2aea0c1c57ee 673 cmd_process();
vcoubard 24:2aea0c1c57ee 674 }
vcoubard 24:2aea0c1c57ee 675
vcoubard 24:2aea0c1c57ee 676 err_code = NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 677 }
Vincent Coubard 0:f2542974c862 678 else
Vincent Coubard 0:f2542974c862 679 {
vcoubard 24:2aea0c1c57ee 680 err_code = NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 681 }
Vincent Coubard 0:f2542974c862 682
vcoubard 24:2aea0c1c57ee 683 return err_code;
Vincent Coubard 0:f2542974c862 684 }
Vincent Coubard 0:f2542974c862 685
Vincent Coubard 0:f2542974c862 686
vcoubard 24:2aea0c1c57ee 687 /**@brief Function for dequeing a possible pending flash access operation.
Vincent Coubard 0:f2542974c862 688 */
vcoubard 24:2aea0c1c57ee 689 static void cmd_queue_dequeue(void)
Vincent Coubard 0:f2542974c862 690 {
vcoubard 24:2aea0c1c57ee 691 if ((m_cmd_queue.count != 0))
Vincent Coubard 0:f2542974c862 692 {
vcoubard 24:2aea0c1c57ee 693 cmd_process();
Vincent Coubard 0:f2542974c862 694 }
Vincent Coubard 0:f2542974c862 695 }
Vincent Coubard 0:f2542974c862 696
Vincent Coubard 0:f2542974c862 697
vcoubard 24:2aea0c1c57ee 698 /**@brief Function for notifying an application of command completion.
Vincent Coubard 0:f2542974c862 699 *
vcoubard 24:2aea0c1c57ee 700 * @param[in] result Result code of the operation for the application.
vcoubard 24:2aea0c1c57ee 701 * @param[in] p_elem Pointer to the command queue element for which this result was received.
Vincent Coubard 0:f2542974c862 702 */
vcoubard 1:ebc0e0ef0a11 703 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem)
Vincent Coubard 0:f2542974c862 704 {
Vincent Coubard 0:f2542974c862 705 pstorage_ntf_cb_t ntf_cb;
vcoubard 24:2aea0c1c57ee 706 const uint8_t op_code = p_elem->op_code;
Vincent Coubard 0:f2542974c862 707
Vincent Coubard 0:f2542974c862 708 #ifdef PSTORAGE_RAW_MODE_ENABLE
vcoubard 1:ebc0e0ef0a11 709 if (p_elem->storage_addr.module_id == RAW_MODE_APP_ID)
Vincent Coubard 0:f2542974c862 710 {
Vincent Coubard 0:f2542974c862 711 ntf_cb = m_raw_app_table.cb;
Vincent Coubard 0:f2542974c862 712 }
Vincent Coubard 0:f2542974c862 713 else
Vincent Coubard 0:f2542974c862 714 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 715 {
vcoubard 1:ebc0e0ef0a11 716 ntf_cb = m_app_table[p_elem->storage_addr.module_id].cb;
Vincent Coubard 0:f2542974c862 717 }
Vincent Coubard 0:f2542974c862 718
vcoubard 24:2aea0c1c57ee 719 ntf_cb(&p_elem->storage_addr, op_code, result, p_elem->p_data_addr, m_app_data_size);
vcoubard 24:2aea0c1c57ee 720 }
vcoubard 24:2aea0c1c57ee 721
vcoubard 24:2aea0c1c57ee 722
vcoubard 24:2aea0c1c57ee 723 /**@brief Function for evaluating if a data page swap is required for the tail section on the
vcoubard 24:2aea0c1c57ee 724 * current page.
vcoubard 24:2aea0c1c57ee 725 *
vcoubard 24:2aea0c1c57ee 726 * @retval true If data page swap is required.
vcoubard 24:2aea0c1c57ee 727 * @retval false If data page swap is not required.
vcoubard 24:2aea0c1c57ee 728 */
vcoubard 24:2aea0c1c57ee 729 static bool is_tail_data_page_swap_required(void)
vcoubard 24:2aea0c1c57ee 730 {
vcoubard 24:2aea0c1c57ee 731 bool ret_value;
vcoubard 24:2aea0c1c57ee 732
vcoubard 24:2aea0c1c57ee 733 // Extract id of the last page command is executed upon.
vcoubard 24:2aea0c1c57ee 734 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 735 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
vcoubard 24:2aea0c1c57ee 736 const uint32_t last_page_id = (cmd_block_id + p_cmd->size + p_cmd->offset - 1u) /
vcoubard 24:2aea0c1c57ee 737 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 738
vcoubard 24:2aea0c1c57ee 739 // If tail section area exists and the current page is the last page then tail data page swap is
vcoubard 24:2aea0c1c57ee 740 // required.
vcoubard 24:2aea0c1c57ee 741 if ((m_tail_word_size != 0) && (m_current_page_id == last_page_id))
vcoubard 24:2aea0c1c57ee 742 {
vcoubard 24:2aea0c1c57ee 743 ret_value = true;
vcoubard 24:2aea0c1c57ee 744 }
vcoubard 24:2aea0c1c57ee 745 else
vcoubard 24:2aea0c1c57ee 746 {
vcoubard 24:2aea0c1c57ee 747 ret_value = false;
vcoubard 24:2aea0c1c57ee 748 }
vcoubard 24:2aea0c1c57ee 749
vcoubard 24:2aea0c1c57ee 750 return ret_value;
vcoubard 24:2aea0c1c57ee 751 }
vcoubard 24:2aea0c1c57ee 752
vcoubard 24:2aea0c1c57ee 753
vcoubard 24:2aea0c1c57ee 754 /**@brief Function for performing post processing for the update and clear commands.
vcoubard 24:2aea0c1c57ee 755 *
vcoubard 24:2aea0c1c57ee 756 * @details Function for performing post processing for the update and clear commands, which implies
vcoubard 24:2aea0c1c57ee 757 * executing the correct execution path depending on the command.
vcoubard 24:2aea0c1c57ee 758 */
vcoubard 24:2aea0c1c57ee 759 static void clear_post_processing_run(void)
vcoubard 24:2aea0c1c57ee 760 {
vcoubard 24:2aea0c1c57ee 761 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 762
vcoubard 24:2aea0c1c57ee 763 if (p_cmd->op_code != PSTORAGE_UPDATE_OP_CODE)
vcoubard 24:2aea0c1c57ee 764 {
vcoubard 24:2aea0c1c57ee 765 command_end_procedure_run();
vcoubard 24:2aea0c1c57ee 766 }
vcoubard 24:2aea0c1c57ee 767 else
vcoubard 24:2aea0c1c57ee 768 {
vcoubard 24:2aea0c1c57ee 769 store_operation_execute();
vcoubard 24:2aea0c1c57ee 770 }
vcoubard 24:2aea0c1c57ee 771 }
vcoubard 24:2aea0c1c57ee 772
vcoubard 24:2aea0c1c57ee 773
vcoubard 24:2aea0c1c57ee 774 /**@brief Function for doing swap sub state exit action.
vcoubard 24:2aea0c1c57ee 775 */
vcoubard 24:2aea0c1c57ee 776 static void swap_sub_sm_exit_action_run(void)
vcoubard 24:2aea0c1c57ee 777 {
vcoubard 24:2aea0c1c57ee 778 clear_post_processing_run();
vcoubard 24:2aea0c1c57ee 779 }
vcoubard 24:2aea0c1c57ee 780
vcoubard 24:2aea0c1c57ee 781
vcoubard 24:2aea0c1c57ee 782 /**@brief Function for evaluating if the page erase operation is required for the current page.
vcoubard 24:2aea0c1c57ee 783 *
vcoubard 24:2aea0c1c57ee 784 * @retval true If page erase is required.
vcoubard 24:2aea0c1c57ee 785 * @retval false If page erase is not required.
vcoubard 24:2aea0c1c57ee 786 */
vcoubard 24:2aea0c1c57ee 787 static bool is_page_erase_required(void)
vcoubard 24:2aea0c1c57ee 788 {
vcoubard 24:2aea0c1c57ee 789 bool ret;
vcoubard 24:2aea0c1c57ee 790
vcoubard 24:2aea0c1c57ee 791 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 792 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
vcoubard 24:2aea0c1c57ee 793 const uint32_t id_last_page_to_be_cleared = (cmd_block_id + p_cmd->size +
vcoubard 24:2aea0c1c57ee 794 p_cmd->offset - 1u) /
vcoubard 24:2aea0c1c57ee 795 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 796
vcoubard 24:2aea0c1c57ee 797 // True if:
vcoubard 24:2aea0c1c57ee 798 // - current page is not the last page OR
vcoubard 24:2aea0c1c57ee 799 // - current page is the last page AND no tail exists
vcoubard 24:2aea0c1c57ee 800 if ((m_current_page_id < id_last_page_to_be_cleared) ||
vcoubard 24:2aea0c1c57ee 801 ((m_current_page_id == id_last_page_to_be_cleared) && (m_tail_word_size == 0)))
vcoubard 24:2aea0c1c57ee 802 {
vcoubard 24:2aea0c1c57ee 803 ret = true;
vcoubard 24:2aea0c1c57ee 804 }
vcoubard 24:2aea0c1c57ee 805 else
vcoubard 24:2aea0c1c57ee 806 {
vcoubard 24:2aea0c1c57ee 807 ret = false;
vcoubard 24:2aea0c1c57ee 808 }
vcoubard 24:2aea0c1c57ee 809
vcoubard 24:2aea0c1c57ee 810 return ret;
vcoubard 19:47192cb9def7 811 }
vcoubard 19:47192cb9def7 812
Vincent Coubard 0:f2542974c862 813
vcoubard 24:2aea0c1c57ee 814 /**@brief Function for reissuing the last flash operation request, which was rejected by the flash
vcoubard 24:2aea0c1c57ee 815 * API, in swap sub sate.
vcoubard 19:47192cb9def7 816 */
vcoubard 24:2aea0c1c57ee 817 static void swap_sub_state_err_busy_process(void)
vcoubard 19:47192cb9def7 818 {
vcoubard 24:2aea0c1c57ee 819 // Reissue the request by doing a self transition to the current state.
vcoubard 24:2aea0c1c57ee 820 m_flags &= ~MASK_FLASH_API_ERR_BUSY;
vcoubard 24:2aea0c1c57ee 821 swap_sub_state_state_change(m_swap_sub_state);
vcoubard 24:2aea0c1c57ee 822 }
vcoubard 24:2aea0c1c57ee 823
vcoubard 22:67a8d2c0bbbf 824
vcoubard 24:2aea0c1c57ee 825 /**@brief Function for doing restore head state action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 826 *
vcoubard 24:2aea0c1c57ee 827 * @details Function for doing restore head state action upon flash operation success event, which
vcoubard 24:2aea0c1c57ee 828 * includes making a state transition depending on the current state.
vcoubard 24:2aea0c1c57ee 829 */
vcoubard 24:2aea0c1c57ee 830 static void head_restore_state_run(void)
vcoubard 24:2aea0c1c57ee 831 {
vcoubard 24:2aea0c1c57ee 832 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 833 {
vcoubard 24:2aea0c1c57ee 834 if (is_tail_data_page_swap_required())
vcoubard 24:2aea0c1c57ee 835 {
vcoubard 24:2aea0c1c57ee 836 // Additional data page needs to be swapped for tail section as we are clearing a block,
vcoubard 24:2aea0c1c57ee 837 // which is shared between 2 flash pages.
vcoubard 24:2aea0c1c57ee 838
vcoubard 24:2aea0c1c57ee 839 // Adjust variables to ensure correct state transition path is taken after the tail
vcoubard 24:2aea0c1c57ee 840 // section swap has completed.
vcoubard 24:2aea0c1c57ee 841 m_head_word_size = 0;
vcoubard 24:2aea0c1c57ee 842 m_flags |= MASK_TAIL_SWAP_DONE;
vcoubard 24:2aea0c1c57ee 843
vcoubard 24:2aea0c1c57ee 844 swap_sub_state_state_change(STATE_ERASE_SWAP);
vcoubard 24:2aea0c1c57ee 845 }
vcoubard 24:2aea0c1c57ee 846 else if (is_page_erase_required())
vcoubard 24:2aea0c1c57ee 847 {
vcoubard 24:2aea0c1c57ee 848 // Additional page erase operation is required.
vcoubard 24:2aea0c1c57ee 849
vcoubard 24:2aea0c1c57ee 850 // Adjust variable to ensure correct state transition path is taken after the additional
vcoubard 24:2aea0c1c57ee 851 // page erase operation has completed.
vcoubard 24:2aea0c1c57ee 852 m_head_word_size = 0;
vcoubard 24:2aea0c1c57ee 853 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
vcoubard 24:2aea0c1c57ee 854 }
vcoubard 24:2aea0c1c57ee 855 else if (m_tail_word_size != 0)
vcoubard 24:2aea0c1c57ee 856 {
vcoubard 24:2aea0c1c57ee 857 // Proceed with restoring tail from swap to data page.
vcoubard 24:2aea0c1c57ee 858 swap_sub_state_state_change(STATE_RESTORE_TAIL);
vcoubard 24:2aea0c1c57ee 859 }
vcoubard 24:2aea0c1c57ee 860 else
vcoubard 24:2aea0c1c57ee 861 {
vcoubard 24:2aea0c1c57ee 862 // Swap statemachine execution end reached.
vcoubard 24:2aea0c1c57ee 863 swap_sub_sm_exit_action_run();
vcoubard 24:2aea0c1c57ee 864 }
vcoubard 24:2aea0c1c57ee 865 }
vcoubard 24:2aea0c1c57ee 866 else
Vincent Coubard 0:f2542974c862 867 {
vcoubard 24:2aea0c1c57ee 868 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 869 swap_sub_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 870 }
vcoubard 24:2aea0c1c57ee 871 }
vcoubard 19:47192cb9def7 872
vcoubard 24:2aea0c1c57ee 873
vcoubard 24:2aea0c1c57ee 874 /**@brief Function for doing restore tail state action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 875 */
vcoubard 24:2aea0c1c57ee 876 static void tail_restore_state_run(void)
vcoubard 24:2aea0c1c57ee 877 {
vcoubard 24:2aea0c1c57ee 878 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 879 {
vcoubard 24:2aea0c1c57ee 880 swap_sub_sm_exit_action_run();
vcoubard 24:2aea0c1c57ee 881 }
vcoubard 24:2aea0c1c57ee 882 else
vcoubard 24:2aea0c1c57ee 883 {
vcoubard 24:2aea0c1c57ee 884 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 885 swap_sub_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 886 }
vcoubard 24:2aea0c1c57ee 887 }
vcoubard 24:2aea0c1c57ee 888
Vincent Coubard 0:f2542974c862 889
vcoubard 24:2aea0c1c57ee 890 /**@brief Function for doing data page erase state action upon a flash operation success event.
vcoubard 24:2aea0c1c57ee 891 *
vcoubard 24:2aea0c1c57ee 892 * @details Function for doing data page erase state action upon a flash operation success event,
vcoubard 24:2aea0c1c57ee 893 * which includes making a state transit to a new state depending on the current state.
vcoubard 24:2aea0c1c57ee 894 */
vcoubard 24:2aea0c1c57ee 895 static void data_page_erase_state_run(void)
vcoubard 24:2aea0c1c57ee 896 {
vcoubard 24:2aea0c1c57ee 897 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 898 {
vcoubard 24:2aea0c1c57ee 899 ++m_current_page_id;
vcoubard 24:2aea0c1c57ee 900
vcoubard 24:2aea0c1c57ee 901 if (m_head_word_size != 0)
vcoubard 24:2aea0c1c57ee 902 {
vcoubard 24:2aea0c1c57ee 903 swap_sub_state_state_change(STATE_RESTORE_HEAD);
vcoubard 24:2aea0c1c57ee 904 }
vcoubard 24:2aea0c1c57ee 905 else if (is_page_erase_required())
Vincent Coubard 0:f2542974c862 906 {
vcoubard 24:2aea0c1c57ee 907 // Additional page erase operation is required.
vcoubard 24:2aea0c1c57ee 908 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
vcoubard 24:2aea0c1c57ee 909 }
vcoubard 24:2aea0c1c57ee 910 else if (m_tail_word_size != 0)
vcoubard 24:2aea0c1c57ee 911 {
vcoubard 24:2aea0c1c57ee 912 if (!(m_flags & MASK_TAIL_SWAP_DONE))
Vincent Coubard 0:f2542974c862 913 {
vcoubard 24:2aea0c1c57ee 914 // Tail area restore is required and we have not yet written the relevant data page
vcoubard 24:2aea0c1c57ee 915 // to swap area. Start the process of writing the data page to swap.
vcoubard 24:2aea0c1c57ee 916 m_flags |= MASK_TAIL_SWAP_DONE;
vcoubard 24:2aea0c1c57ee 917
vcoubard 24:2aea0c1c57ee 918 swap_sub_state_state_change(STATE_ERASE_SWAP);
Vincent Coubard 0:f2542974c862 919 }
Vincent Coubard 0:f2542974c862 920 else
Vincent Coubard 0:f2542974c862 921 {
vcoubard 24:2aea0c1c57ee 922 // Tail area restore is required and we have already written the relevant data page
vcoubard 24:2aea0c1c57ee 923 // to swap area. Proceed by restoring the tail area.
vcoubard 24:2aea0c1c57ee 924 swap_sub_state_state_change(STATE_RESTORE_TAIL);
Vincent Coubard 0:f2542974c862 925 }
vcoubard 24:2aea0c1c57ee 926 }
vcoubard 24:2aea0c1c57ee 927 else
vcoubard 24:2aea0c1c57ee 928 {
vcoubard 24:2aea0c1c57ee 929 swap_sub_sm_exit_action_run();
vcoubard 24:2aea0c1c57ee 930 }
vcoubard 24:2aea0c1c57ee 931 }
vcoubard 24:2aea0c1c57ee 932 else
vcoubard 24:2aea0c1c57ee 933 {
vcoubard 24:2aea0c1c57ee 934 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 935 swap_sub_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 936 }
vcoubard 24:2aea0c1c57ee 937 }
Vincent Coubard 0:f2542974c862 938
vcoubard 24:2aea0c1c57ee 939
vcoubard 24:2aea0c1c57ee 940 /**@brief Function for doing data to swap write state action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 941 */
vcoubard 24:2aea0c1c57ee 942 static void data_to_swap_write_state_run(void)
vcoubard 24:2aea0c1c57ee 943 {
vcoubard 24:2aea0c1c57ee 944 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 945 {
vcoubard 24:2aea0c1c57ee 946 // If the operation is executed only on 1 single flash page it automatically means that tail
vcoubard 24:2aea0c1c57ee 947 // area is written to the swap, which we store to flags.
vcoubard 24:2aea0c1c57ee 948 if (m_flags & MASK_SINGLE_PAGE_OPERATION)
vcoubard 24:2aea0c1c57ee 949 {
vcoubard 24:2aea0c1c57ee 950 m_flags |= MASK_TAIL_SWAP_DONE;
Vincent Coubard 0:f2542974c862 951 }
Vincent Coubard 0:f2542974c862 952
vcoubard 24:2aea0c1c57ee 953 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
vcoubard 24:2aea0c1c57ee 954 }
vcoubard 24:2aea0c1c57ee 955 else
vcoubard 24:2aea0c1c57ee 956 {
vcoubard 24:2aea0c1c57ee 957 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 958 swap_sub_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 959 }
vcoubard 24:2aea0c1c57ee 960 }
Vincent Coubard 0:f2542974c862 961
vcoubard 1:ebc0e0ef0a11 962
vcoubard 24:2aea0c1c57ee 963 /**@brief Function for doing swap erase state action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 964 */
vcoubard 24:2aea0c1c57ee 965 static void swap_erase_state_run(void)
vcoubard 24:2aea0c1c57ee 966 {
vcoubard 24:2aea0c1c57ee 967 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 968 {
vcoubard 24:2aea0c1c57ee 969 swap_sub_state_state_change(STATE_WRITE_DATA_TO_SWAP);
vcoubard 24:2aea0c1c57ee 970 }
vcoubard 24:2aea0c1c57ee 971 else
vcoubard 24:2aea0c1c57ee 972 {
vcoubard 24:2aea0c1c57ee 973 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 974 swap_sub_state_err_busy_process();
Vincent Coubard 0:f2542974c862 975 }
Vincent Coubard 0:f2542974c862 976 }
Vincent Coubard 0:f2542974c862 977
Vincent Coubard 0:f2542974c862 978
vcoubard 24:2aea0c1c57ee 979 /**@brief Function for dispatching the correct state action for data erase with a swap composite
vcoubard 24:2aea0c1c57ee 980 * state upon a flash operation success event.
vcoubard 24:2aea0c1c57ee 981 */
vcoubard 24:2aea0c1c57ee 982 static void swap_sub_state_sm_run(void)
vcoubard 24:2aea0c1c57ee 983 {
vcoubard 24:2aea0c1c57ee 984 static void (* const swap_sub_state_sm_lut[SWAP_SUB_STATE_MAX])(void) =
vcoubard 24:2aea0c1c57ee 985 {
vcoubard 24:2aea0c1c57ee 986 swap_erase_state_run,
vcoubard 24:2aea0c1c57ee 987 data_to_swap_write_state_run,
vcoubard 24:2aea0c1c57ee 988 data_page_erase_state_run,
vcoubard 24:2aea0c1c57ee 989 tail_restore_state_run,
vcoubard 24:2aea0c1c57ee 990 head_restore_state_run
vcoubard 24:2aea0c1c57ee 991 };
vcoubard 24:2aea0c1c57ee 992
vcoubard 24:2aea0c1c57ee 993 swap_sub_state_sm_lut[m_swap_sub_state]();
vcoubard 24:2aea0c1c57ee 994 }
vcoubard 24:2aea0c1c57ee 995
vcoubard 24:2aea0c1c57ee 996
vcoubard 24:2aea0c1c57ee 997 /**@brief Function for reissuing the last flash operation request, which was rejected by the flash
vcoubard 24:2aea0c1c57ee 998 * API, in main sate.
vcoubard 24:2aea0c1c57ee 999 */
vcoubard 24:2aea0c1c57ee 1000 static void main_state_err_busy_process(void)
vcoubard 24:2aea0c1c57ee 1001 {
vcoubard 24:2aea0c1c57ee 1002 // Reissue the request by doing a self transition to the current state.
vcoubard 24:2aea0c1c57ee 1003 m_flags &= ~MASK_FLASH_API_ERR_BUSY;
vcoubard 24:2aea0c1c57ee 1004 sm_state_change(m_state);
vcoubard 24:2aea0c1c57ee 1005 }
vcoubard 24:2aea0c1c57ee 1006
vcoubard 24:2aea0c1c57ee 1007
vcoubard 24:2aea0c1c57ee 1008 /**@brief Function for doing erase state action upon flash operation success event.
vcoubard 22:67a8d2c0bbbf 1009 *
vcoubard 24:2aea0c1c57ee 1010 * @details Function for doing erase state action upon flash operation success event, which includes
vcoubard 24:2aea0c1c57ee 1011 * making a state transition depending on the current state.
vcoubard 19:47192cb9def7 1012 */
vcoubard 24:2aea0c1c57ee 1013 static void erase_sub_state_sm_run(void)
Vincent Coubard 0:f2542974c862 1014 {
vcoubard 24:2aea0c1c57ee 1015 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 1016 {
vcoubard 24:2aea0c1c57ee 1017 // Clear operation request has succeeded.
vcoubard 24:2aea0c1c57ee 1018 ++m_current_page_id;
vcoubard 24:2aea0c1c57ee 1019
vcoubard 24:2aea0c1c57ee 1020 if (!is_page_erase_required())
vcoubard 24:2aea0c1c57ee 1021 {
vcoubard 24:2aea0c1c57ee 1022 clear_post_processing_run();
vcoubard 24:2aea0c1c57ee 1023 }
vcoubard 24:2aea0c1c57ee 1024 else
vcoubard 24:2aea0c1c57ee 1025 {
vcoubard 24:2aea0c1c57ee 1026 // All required flash pages have not yet been erased, issue erase by doing a self
vcoubard 24:2aea0c1c57ee 1027 // transit.
vcoubard 24:2aea0c1c57ee 1028 sm_state_change(m_state);
vcoubard 24:2aea0c1c57ee 1029 }
vcoubard 24:2aea0c1c57ee 1030 }
vcoubard 24:2aea0c1c57ee 1031 else
vcoubard 24:2aea0c1c57ee 1032 {
vcoubard 24:2aea0c1c57ee 1033 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 1034 main_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 1035 }
vcoubard 24:2aea0c1c57ee 1036 }
vcoubard 22:67a8d2c0bbbf 1037
vcoubard 24:2aea0c1c57ee 1038
vcoubard 24:2aea0c1c57ee 1039 /**@brief Function for doing store state action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 1040 */
vcoubard 24:2aea0c1c57ee 1041 static void store_sub_state_sm_run(void)
vcoubard 24:2aea0c1c57ee 1042 {
vcoubard 24:2aea0c1c57ee 1043 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 24:2aea0c1c57ee 1044 {
vcoubard 24:2aea0c1c57ee 1045 // As write operation request has succeeded, adjust the size tracking state information
vcoubard 24:2aea0c1c57ee 1046 // accordingly.
vcoubard 24:2aea0c1c57ee 1047 cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 1048 p_cmd->size -= m_num_of_bytes_written;
vcoubard 24:2aea0c1c57ee 1049
vcoubard 24:2aea0c1c57ee 1050 if (p_cmd->size == 0)
Vincent Coubard 0:f2542974c862 1051 {
vcoubard 24:2aea0c1c57ee 1052 command_end_procedure_run();
Vincent Coubard 0:f2542974c862 1053 }
Vincent Coubard 0:f2542974c862 1054 else
Vincent Coubard 0:f2542974c862 1055 {
vcoubard 24:2aea0c1c57ee 1056 store_cmd_flash_write_execute();
Vincent Coubard 0:f2542974c862 1057 }
Vincent Coubard 0:f2542974c862 1058 }
vcoubard 24:2aea0c1c57ee 1059 else
Vincent Coubard 0:f2542974c862 1060 {
vcoubard 24:2aea0c1c57ee 1061 // As operation request was rejected by the flash API reissue the request.
vcoubard 24:2aea0c1c57ee 1062 main_state_err_busy_process();
vcoubard 24:2aea0c1c57ee 1063 }
vcoubard 24:2aea0c1c57ee 1064 }
vcoubard 24:2aea0c1c57ee 1065
vcoubard 24:2aea0c1c57ee 1066
vcoubard 24:2aea0c1c57ee 1067 /**@brief Function for doing action upon flash operation success event.
vcoubard 24:2aea0c1c57ee 1068 */
vcoubard 24:2aea0c1c57ee 1069 static void flash_operation_success_run(void)
vcoubard 24:2aea0c1c57ee 1070 {
vcoubard 24:2aea0c1c57ee 1071 switch (m_state)
vcoubard 24:2aea0c1c57ee 1072 {
vcoubard 24:2aea0c1c57ee 1073 case STATE_STORE:
vcoubard 24:2aea0c1c57ee 1074 store_sub_state_sm_run();
vcoubard 22:67a8d2c0bbbf 1075 break;
vcoubard 24:2aea0c1c57ee 1076
vcoubard 22:67a8d2c0bbbf 1077 case STATE_DATA_ERASE:
vcoubard 24:2aea0c1c57ee 1078 erase_sub_state_sm_run();
Vincent Coubard 0:f2542974c862 1079 break;
vcoubard 24:2aea0c1c57ee 1080
vcoubard 24:2aea0c1c57ee 1081 case STATE_DATA_ERASE_WITH_SWAP:
vcoubard 24:2aea0c1c57ee 1082 swap_sub_state_sm_run();
vcoubard 24:2aea0c1c57ee 1083 break;
vcoubard 24:2aea0c1c57ee 1084
vcoubard 24:2aea0c1c57ee 1085 default:
vcoubard 24:2aea0c1c57ee 1086 // No implementation needed.
vcoubard 24:2aea0c1c57ee 1087 break;
vcoubard 24:2aea0c1c57ee 1088 }
vcoubard 24:2aea0c1c57ee 1089 }
vcoubard 24:2aea0c1c57ee 1090
vcoubard 19:47192cb9def7 1091
vcoubard 24:2aea0c1c57ee 1092 /**@brief Function for doing action upon flash operation failure event.
vcoubard 24:2aea0c1c57ee 1093 *
vcoubard 24:2aea0c1c57ee 1094 * @details Function for doing action upon flash operation failure event, which includes retrying
vcoubard 24:2aea0c1c57ee 1095 * the last operation or if retry count has been reached completing the operation with
vcoubard 24:2aea0c1c57ee 1096 * appropriate result code and transitioning to an error state.
vcoubard 24:2aea0c1c57ee 1097 *
vcoubard 24:2aea0c1c57ee 1098 * @note The command is not removed from the command queue, which will result to stalling of the
vcoubard 24:2aea0c1c57ee 1099 * command pipeline and the appropriate application recovery procedure for this is to reset
vcoubard 24:2aea0c1c57ee 1100 * the system by issuing @ref pstorage_init which will also result to flushing of the
vcoubard 24:2aea0c1c57ee 1101 * command queue.
vcoubard 24:2aea0c1c57ee 1102 */
vcoubard 24:2aea0c1c57ee 1103 static void flash_operation_failure_run(void)
vcoubard 24:2aea0c1c57ee 1104 {
vcoubard 24:2aea0c1c57ee 1105 if (++m_num_of_command_retries != SD_CMD_MAX_TRIES)
vcoubard 24:2aea0c1c57ee 1106 {
vcoubard 24:2aea0c1c57ee 1107 // Retry the last operation by doing a self transition to the current state.
vcoubard 24:2aea0c1c57ee 1108
vcoubard 24:2aea0c1c57ee 1109 if (m_state != STATE_DATA_ERASE_WITH_SWAP)
vcoubard 24:2aea0c1c57ee 1110 {
vcoubard 24:2aea0c1c57ee 1111 sm_state_change(m_state);
vcoubard 24:2aea0c1c57ee 1112 }
vcoubard 24:2aea0c1c57ee 1113 else
vcoubard 24:2aea0c1c57ee 1114 {
vcoubard 24:2aea0c1c57ee 1115 swap_sub_state_state_change(m_swap_sub_state);
vcoubard 24:2aea0c1c57ee 1116 }
vcoubard 24:2aea0c1c57ee 1117 }
vcoubard 24:2aea0c1c57ee 1118 else
vcoubard 24:2aea0c1c57ee 1119 {
vcoubard 24:2aea0c1c57ee 1120 // Complete the operation with appropriate result code and transit to an error state.
vcoubard 24:2aea0c1c57ee 1121 app_notify_error_state_transit(NRF_ERROR_TIMEOUT);
vcoubard 24:2aea0c1c57ee 1122 }
vcoubard 24:2aea0c1c57ee 1123 }
Vincent Coubard 0:f2542974c862 1124
vcoubard 24:2aea0c1c57ee 1125
vcoubard 24:2aea0c1c57ee 1126 /**@brief Function for handling flash access result events.
vcoubard 24:2aea0c1c57ee 1127 *
vcoubard 24:2aea0c1c57ee 1128 * @param[in] sys_evt System event to be handled.
vcoubard 24:2aea0c1c57ee 1129 */
vcoubard 24:2aea0c1c57ee 1130 void pstorage_sys_event_handler(uint32_t sys_evt)
vcoubard 24:2aea0c1c57ee 1131 {
vcoubard 24:2aea0c1c57ee 1132 if (m_state != STATE_IDLE && m_state != STATE_ERROR)
vcoubard 24:2aea0c1c57ee 1133 {
vcoubard 24:2aea0c1c57ee 1134 switch (sys_evt)
vcoubard 24:2aea0c1c57ee 1135 {
vcoubard 24:2aea0c1c57ee 1136 case NRF_EVT_FLASH_OPERATION_SUCCESS:
vcoubard 24:2aea0c1c57ee 1137 flash_operation_success_run();
vcoubard 24:2aea0c1c57ee 1138 break;
vcoubard 24:2aea0c1c57ee 1139
vcoubard 24:2aea0c1c57ee 1140 case NRF_EVT_FLASH_OPERATION_ERROR:
vcoubard 24:2aea0c1c57ee 1141 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
vcoubard 22:67a8d2c0bbbf 1142 {
vcoubard 24:2aea0c1c57ee 1143 flash_operation_failure_run();
vcoubard 22:67a8d2c0bbbf 1144 }
vcoubard 22:67a8d2c0bbbf 1145 else
vcoubard 22:67a8d2c0bbbf 1146 {
vcoubard 24:2aea0c1c57ee 1147 // As our last flash operation request was rejected by the flash API reissue the
vcoubard 24:2aea0c1c57ee 1148 // request by doing same code execution path as for flash operation sucess
vcoubard 24:2aea0c1c57ee 1149 // event. This will promote code reuse in the implementation.
vcoubard 24:2aea0c1c57ee 1150 flash_operation_success_run();
vcoubard 24:2aea0c1c57ee 1151 }
vcoubard 24:2aea0c1c57ee 1152 break;
vcoubard 24:2aea0c1c57ee 1153
vcoubard 24:2aea0c1c57ee 1154 default:
vcoubard 24:2aea0c1c57ee 1155 // No implementation needed.
vcoubard 24:2aea0c1c57ee 1156 break;
vcoubard 24:2aea0c1c57ee 1157 }
vcoubard 24:2aea0c1c57ee 1158
vcoubard 24:2aea0c1c57ee 1159 }
vcoubard 24:2aea0c1c57ee 1160 }
vcoubard 24:2aea0c1c57ee 1161
vcoubard 22:67a8d2c0bbbf 1162
vcoubard 24:2aea0c1c57ee 1163 /**@brief Function for calculating the tail area size in number of 32-bit words.
vcoubard 24:2aea0c1c57ee 1164 *
vcoubard 24:2aea0c1c57ee 1165 * @param[in] cmd_end_of_storage_address End of storage area within the scope of the command.
vcoubard 24:2aea0c1c57ee 1166 * @param[in] end_of_storage_address End of allocated storage area for the application.
vcoubard 24:2aea0c1c57ee 1167 */
vcoubard 24:2aea0c1c57ee 1168 static void tail_word_size_calculate(pstorage_size_t cmd_end_of_storage_address,
vcoubard 24:2aea0c1c57ee 1169 pstorage_size_t end_of_storage_address)
vcoubard 24:2aea0c1c57ee 1170 {
vcoubard 24:2aea0c1c57ee 1171 // Two different cases to resolve when calculating correct size for restore tail section:
vcoubard 24:2aea0c1c57ee 1172 // 1) End of storage area and command end area are in the same page.
vcoubard 24:2aea0c1c57ee 1173 // 2) End of storage area and command end area are not in the same page.
vcoubard 24:2aea0c1c57ee 1174
vcoubard 24:2aea0c1c57ee 1175 const uint32_t end_of_storage_area_page = end_of_storage_address /
vcoubard 24:2aea0c1c57ee 1176 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 1177 const uint32_t command_end_of_storage_area_page = cmd_end_of_storage_address /
vcoubard 24:2aea0c1c57ee 1178 PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 22:67a8d2c0bbbf 1179
vcoubard 24:2aea0c1c57ee 1180 if (end_of_storage_area_page == command_end_of_storage_area_page)
vcoubard 24:2aea0c1c57ee 1181 {
vcoubard 24:2aea0c1c57ee 1182 //lint -e{573} suppress "Signed-unsigned mix with divide".
vcoubard 24:2aea0c1c57ee 1183 m_tail_word_size = (end_of_storage_address - cmd_end_of_storage_address) / sizeof(uint32_t);
vcoubard 19:47192cb9def7 1184 }
vcoubard 24:2aea0c1c57ee 1185 else
vcoubard 24:2aea0c1c57ee 1186 {
vcoubard 24:2aea0c1c57ee 1187 //lint -e{573} suppress "Signed-unsigned mix with divide".
vcoubard 24:2aea0c1c57ee 1188 m_tail_word_size = (PSTORAGE_FLASH_PAGE_SIZE -
vcoubard 24:2aea0c1c57ee 1189 (cmd_end_of_storage_address % PSTORAGE_FLASH_PAGE_SIZE)) /
vcoubard 24:2aea0c1c57ee 1190 sizeof(uint32_t);
vcoubard 24:2aea0c1c57ee 1191 }
vcoubard 19:47192cb9def7 1192 }
Vincent Coubard 0:f2542974c862 1193
vcoubard 19:47192cb9def7 1194
vcoubard 24:2aea0c1c57ee 1195 /**@brief Function for executing the clear operation.
vcoubard 19:47192cb9def7 1196 */
vcoubard 24:2aea0c1c57ee 1197 static void clear_operation_execute(void)
vcoubard 24:2aea0c1c57ee 1198 {
vcoubard 24:2aea0c1c57ee 1199 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 1200 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
vcoubard 24:2aea0c1c57ee 1201
vcoubard 24:2aea0c1c57ee 1202 const pstorage_size_t block_size = m_app_table[p_cmd->storage_addr.module_id].block_size;
vcoubard 24:2aea0c1c57ee 1203 const pstorage_size_t block_count = m_app_table[p_cmd->storage_addr.module_id].block_count;
vcoubard 24:2aea0c1c57ee 1204 const pstorage_block_t block_base_id = m_app_table[p_cmd->storage_addr.module_id].base_id;
vcoubard 24:2aea0c1c57ee 1205
vcoubard 24:2aea0c1c57ee 1206 const bool is_start_address_page_aligned = (cmd_block_id % PSTORAGE_FLASH_PAGE_SIZE) == 0;
vcoubard 24:2aea0c1c57ee 1207
vcoubard 24:2aea0c1c57ee 1208 // Calculate the end (1 beyond allocated area) for complete storage area and to the area only
vcoubard 24:2aea0c1c57ee 1209 // within scope of this command.
vcoubard 24:2aea0c1c57ee 1210 const pstorage_block_t end_of_storage_address = block_base_id + (block_size * block_count);
vcoubard 24:2aea0c1c57ee 1211 const pstorage_block_t cmd_end_of_storage_address = cmd_block_id + p_cmd->size + p_cmd->offset;
vcoubard 24:2aea0c1c57ee 1212
vcoubard 24:2aea0c1c57ee 1213 // Zero tail to make sure no extra erase is done erroneously.
vcoubard 24:2aea0c1c57ee 1214 m_tail_word_size = 0;
vcoubard 24:2aea0c1c57ee 1215
vcoubard 24:2aea0c1c57ee 1216 // If the following is true no swap access is needed:
vcoubard 24:2aea0c1c57ee 1217 // - 1st logical test covers the case of: clear/update 1 complete single page.
vcoubard 24:2aea0c1c57ee 1218 // - 2nd logical test covers the case of:
vcoubard 24:2aea0c1c57ee 1219 // 1) Clear/update last allocated page and page is not full (page can't be shared between
vcoubard 24:2aea0c1c57ee 1220 // multiple clients so the end of the page is unused area).
vcoubard 24:2aea0c1c57ee 1221 // 2) Clear/update all allocated storage.
vcoubard 24:2aea0c1c57ee 1222 if ((is_start_address_page_aligned && (p_cmd->size == PSTORAGE_FLASH_PAGE_SIZE)) ||
vcoubard 24:2aea0c1c57ee 1223 (is_start_address_page_aligned && (cmd_end_of_storage_address == end_of_storage_address) &&
vcoubard 24:2aea0c1c57ee 1224 (p_cmd->offset == 0)) || (p_cmd->storage_addr.module_id == RAW_MODE_APP_ID))
vcoubard 24:2aea0c1c57ee 1225 {
vcoubard 24:2aea0c1c57ee 1226 // Nothing to put to the swap and we can just erase the pages(s).
vcoubard 24:2aea0c1c57ee 1227
vcoubard 24:2aea0c1c57ee 1228 m_current_page_id = cmd_block_id / PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 1229
vcoubard 24:2aea0c1c57ee 1230 sm_state_change(STATE_DATA_ERASE);
vcoubard 24:2aea0c1c57ee 1231 }
vcoubard 24:2aea0c1c57ee 1232 else
vcoubard 24:2aea0c1c57ee 1233 {
vcoubard 24:2aea0c1c57ee 1234 // Not all the blocks for the module can be cleared, we need to use swap page for storing
vcoubard 24:2aea0c1c57ee 1235 // data temporarily.
vcoubard 24:2aea0c1c57ee 1236
vcoubard 24:2aea0c1c57ee 1237 m_head_word_size = ((cmd_block_id + p_cmd->offset) % PSTORAGE_FLASH_PAGE_SIZE) /
vcoubard 24:2aea0c1c57ee 1238 sizeof(uint32_t);
vcoubard 24:2aea0c1c57ee 1239
vcoubard 24:2aea0c1c57ee 1240 const bool is_cmd_end_address_page_aligned = ((cmd_end_of_storage_address %
vcoubard 24:2aea0c1c57ee 1241 PSTORAGE_FLASH_PAGE_SIZE) == 0);
vcoubard 24:2aea0c1c57ee 1242 if ((cmd_end_of_storage_address != end_of_storage_address) &&
vcoubard 24:2aea0c1c57ee 1243 !is_cmd_end_address_page_aligned)
vcoubard 24:2aea0c1c57ee 1244 {
vcoubard 24:2aea0c1c57ee 1245 // When command area is not equal to end of the storage allocation area and not ending
vcoubard 24:2aea0c1c57ee 1246 // to page boundary there is a need to restore the tail area.
vcoubard 24:2aea0c1c57ee 1247 tail_word_size_calculate(cmd_end_of_storage_address, end_of_storage_address);
vcoubard 24:2aea0c1c57ee 1248 }
vcoubard 24:2aea0c1c57ee 1249
vcoubard 24:2aea0c1c57ee 1250 sm_state_change(STATE_DATA_ERASE_WITH_SWAP);
vcoubard 24:2aea0c1c57ee 1251 }
vcoubard 24:2aea0c1c57ee 1252 }
vcoubard 24:2aea0c1c57ee 1253
vcoubard 24:2aea0c1c57ee 1254
vcoubard 24:2aea0c1c57ee 1255 /**@brief Function for executing the store operation.
vcoubard 24:2aea0c1c57ee 1256 */
vcoubard 24:2aea0c1c57ee 1257 static void store_operation_execute(void)
vcoubard 24:2aea0c1c57ee 1258 {
vcoubard 24:2aea0c1c57ee 1259 sm_state_change(STATE_STORE);
vcoubard 24:2aea0c1c57ee 1260 }
vcoubard 24:2aea0c1c57ee 1261
vcoubard 24:2aea0c1c57ee 1262
vcoubard 24:2aea0c1c57ee 1263 /**@brief Function for executing the update operation.
vcoubard 24:2aea0c1c57ee 1264 */
vcoubard 24:2aea0c1c57ee 1265 static void update_operation_execute(void)
vcoubard 22:67a8d2c0bbbf 1266 {
vcoubard 24:2aea0c1c57ee 1267 clear_operation_execute();
vcoubard 24:2aea0c1c57ee 1268 }
vcoubard 24:2aea0c1c57ee 1269
vcoubard 19:47192cb9def7 1270
vcoubard 24:2aea0c1c57ee 1271 /**@brief Function for dispatching the flash access operation.
vcoubard 24:2aea0c1c57ee 1272 */
vcoubard 24:2aea0c1c57ee 1273 static void cmd_process(void)
vcoubard 24:2aea0c1c57ee 1274 {
vcoubard 24:2aea0c1c57ee 1275 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 1276 m_app_data_size = p_cmd->size;
Vincent Coubard 0:f2542974c862 1277
Vincent Coubard 0:f2542974c862 1278 switch (p_cmd->op_code)
Vincent Coubard 0:f2542974c862 1279 {
vcoubard 24:2aea0c1c57ee 1280 case PSTORAGE_STORE_OP_CODE:
vcoubard 24:2aea0c1c57ee 1281 store_operation_execute();
vcoubard 24:2aea0c1c57ee 1282 break;
Vincent Coubard 0:f2542974c862 1283
Vincent Coubard 0:f2542974c862 1284 case PSTORAGE_CLEAR_OP_CODE:
vcoubard 24:2aea0c1c57ee 1285 clear_operation_execute();
vcoubard 24:2aea0c1c57ee 1286 break;
Vincent Coubard 0:f2542974c862 1287
Vincent Coubard 0:f2542974c862 1288 case PSTORAGE_UPDATE_OP_CODE:
vcoubard 24:2aea0c1c57ee 1289 update_operation_execute();
vcoubard 24:2aea0c1c57ee 1290 break;
Vincent Coubard 0:f2542974c862 1291
Vincent Coubard 0:f2542974c862 1292 default:
vcoubard 24:2aea0c1c57ee 1293 // No action required.
Vincent Coubard 0:f2542974c862 1294 break;
Vincent Coubard 0:f2542974c862 1295 }
Vincent Coubard 0:f2542974c862 1296 }
Vincent Coubard 0:f2542974c862 1297
Vincent Coubard 0:f2542974c862 1298
Vincent Coubard 0:f2542974c862 1299 uint32_t pstorage_init(void)
Vincent Coubard 0:f2542974c862 1300 {
Vincent Coubard 0:f2542974c862 1301 cmd_queue_init();
Vincent Coubard 0:f2542974c862 1302
Vincent Coubard 0:f2542974c862 1303 m_next_app_instance = 0;
Vincent Coubard 0:f2542974c862 1304 m_next_page_addr = PSTORAGE_DATA_START_ADDR;
vcoubard 24:2aea0c1c57ee 1305 m_current_page_id = 0;
vcoubard 24:2aea0c1c57ee 1306
vcoubard 24:2aea0c1c57ee 1307 for (uint32_t index = 0; index < PSTORAGE_NUM_OF_PAGES; index++)
Vincent Coubard 0:f2542974c862 1308 {
Vincent Coubard 0:f2542974c862 1309 m_app_table[index].cb = NULL;
Vincent Coubard 0:f2542974c862 1310 m_app_table[index].block_size = 0;
Vincent Coubard 0:f2542974c862 1311 m_app_table[index].block_count = 0;
Vincent Coubard 0:f2542974c862 1312 }
Vincent Coubard 0:f2542974c862 1313
Vincent Coubard 0:f2542974c862 1314 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 1315 m_raw_app_table.cb = NULL;
Vincent Coubard 0:f2542974c862 1316 #endif //PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 1317
vcoubard 24:2aea0c1c57ee 1318 m_state = STATE_IDLE;
vcoubard 24:2aea0c1c57ee 1319 m_num_of_command_retries = 0;
vcoubard 24:2aea0c1c57ee 1320 m_flags = 0;
vcoubard 24:2aea0c1c57ee 1321 m_num_of_bytes_written = 0;
vcoubard 24:2aea0c1c57ee 1322 m_flags |= MASK_MODULE_INITIALIZED;
vcoubard 24:2aea0c1c57ee 1323
vcoubard 24:2aea0c1c57ee 1324 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1325 }
Vincent Coubard 0:f2542974c862 1326
Vincent Coubard 0:f2542974c862 1327
Vincent Coubard 0:f2542974c862 1328 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 0:f2542974c862 1329 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 1330 {
Vincent Coubard 0:f2542974c862 1331 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1332 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 0:f2542974c862 1333 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 1334 NULL_PARAM_CHECK(p_module_param->cb);
vcoubard 1:ebc0e0ef0a11 1335 BLOCK_SIZE_CHECK(p_module_param->block_size);
Vincent Coubard 0:f2542974c862 1336 BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
Vincent Coubard 0:f2542974c862 1337
Vincent Coubard 0:f2542974c862 1338 if (!((p_module_param->block_size % sizeof(uint32_t)) == 0))
Vincent Coubard 0:f2542974c862 1339 {
Vincent Coubard 0:f2542974c862 1340 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 0:f2542974c862 1341 }
vcoubard 24:2aea0c1c57ee 1342
vcoubard 24:2aea0c1c57ee 1343 if (m_next_app_instance == PSTORAGE_NUM_OF_PAGES)
Vincent Coubard 0:f2542974c862 1344 {
Vincent Coubard 0:f2542974c862 1345 return NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 1346 }
Vincent Coubard 0:f2542974c862 1347
Vincent Coubard 0:f2542974c862 1348 p_block_id->module_id = m_next_app_instance;
Vincent Coubard 0:f2542974c862 1349 p_block_id->block_id = m_next_page_addr;
Vincent Coubard 0:f2542974c862 1350
Vincent Coubard 0:f2542974c862 1351 m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
Vincent Coubard 0:f2542974c862 1352 m_app_table[m_next_app_instance].cb = p_module_param->cb;
Vincent Coubard 0:f2542974c862 1353 m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
Vincent Coubard 0:f2542974c862 1354 m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
Vincent Coubard 0:f2542974c862 1355
vcoubard 24:2aea0c1c57ee 1356 // Calculate number of flash pages allocated for the device and adjust next free page address.
vcoubard 24:2aea0c1c57ee 1357 const uint32_t page_count = CEIL_DIV((p_module_param->block_size * p_module_param->block_count),
vcoubard 24:2aea0c1c57ee 1358 PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 24:2aea0c1c57ee 1359 m_next_page_addr += page_count * PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 24:2aea0c1c57ee 1360
vcoubard 24:2aea0c1c57ee 1361 ++m_next_app_instance;
Vincent Coubard 0:f2542974c862 1362
Vincent Coubard 0:f2542974c862 1363 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1364 }
Vincent Coubard 0:f2542974c862 1365
Vincent Coubard 0:f2542974c862 1366
Vincent Coubard 0:f2542974c862 1367 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
Vincent Coubard 0:f2542974c862 1368 pstorage_size_t block_num,
Vincent Coubard 0:f2542974c862 1369 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 1370 {
Vincent Coubard 0:f2542974c862 1371 pstorage_handle_t temp_id;
Vincent Coubard 0:f2542974c862 1372
Vincent Coubard 0:f2542974c862 1373 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1374 NULL_PARAM_CHECK(p_base_id);
Vincent Coubard 0:f2542974c862 1375 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 1376 MODULE_ID_RANGE_CHECK(p_base_id);
Vincent Coubard 0:f2542974c862 1377
Vincent Coubard 0:f2542974c862 1378 temp_id = (*p_base_id);
Vincent Coubard 0:f2542974c862 1379 temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
Vincent Coubard 0:f2542974c862 1380
Vincent Coubard 0:f2542974c862 1381 BLOCK_ID_RANGE_CHECK(&temp_id);
Vincent Coubard 0:f2542974c862 1382
Vincent Coubard 0:f2542974c862 1383 (*p_block_id) = temp_id;
Vincent Coubard 0:f2542974c862 1384
Vincent Coubard 0:f2542974c862 1385 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1386 }
Vincent Coubard 0:f2542974c862 1387
Vincent Coubard 0:f2542974c862 1388
Vincent Coubard 0:f2542974c862 1389 uint32_t pstorage_store(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 1390 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 1391 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1392 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1393 {
Vincent Coubard 0:f2542974c862 1394 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1395 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1396 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1397 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1398 BLOCK_ID_RANGE_CHECK(p_dest);
vcoubard 24:2aea0c1c57ee 1399 SIZE_CHECK(p_dest, size);
vcoubard 24:2aea0c1c57ee 1400 OFFSET_CHECK(p_dest, offset, size);
vcoubard 24:2aea0c1c57ee 1401
vcoubard 24:2aea0c1c57ee 1402 if ((!is_word_aligned(p_src)) ||
vcoubard 24:2aea0c1c57ee 1403 (!is_word_aligned((void *)(uint32_t)offset)) ||
vcoubard 24:2aea0c1c57ee 1404 (!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1405 {
Vincent Coubard 0:f2542974c862 1406 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1407 }
Vincent Coubard 0:f2542974c862 1408
Vincent Coubard 0:f2542974c862 1409 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1410 }
Vincent Coubard 0:f2542974c862 1411
Vincent Coubard 0:f2542974c862 1412
Vincent Coubard 0:f2542974c862 1413 uint32_t pstorage_update(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 1414 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 1415 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1416 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1417 {
Vincent Coubard 0:f2542974c862 1418 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1419 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1420 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1421 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1422 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1423 SIZE_CHECK(p_dest, size);
Vincent Coubard 0:f2542974c862 1424 OFFSET_CHECK(p_dest, offset, size);
Vincent Coubard 0:f2542974c862 1425
vcoubard 24:2aea0c1c57ee 1426 if ((!is_word_aligned(p_src)) ||
vcoubard 24:2aea0c1c57ee 1427 (!is_word_aligned((void *)(uint32_t)offset)) ||
vcoubard 24:2aea0c1c57ee 1428 (!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1429 {
Vincent Coubard 0:f2542974c862 1430 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1431 }
Vincent Coubard 0:f2542974c862 1432
Vincent Coubard 0:f2542974c862 1433 return cmd_queue_enqueue(PSTORAGE_UPDATE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1434 }
Vincent Coubard 0:f2542974c862 1435
Vincent Coubard 0:f2542974c862 1436
Vincent Coubard 0:f2542974c862 1437 uint32_t pstorage_load(uint8_t * p_dest,
Vincent Coubard 0:f2542974c862 1438 pstorage_handle_t * p_src,
Vincent Coubard 0:f2542974c862 1439 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1440 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1441 {
Vincent Coubard 0:f2542974c862 1442 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1443 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1444 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1445 MODULE_ID_RANGE_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1446 BLOCK_ID_RANGE_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1447 SIZE_CHECK(p_src, size);
Vincent Coubard 0:f2542974c862 1448 OFFSET_CHECK(p_src, offset, size);
Vincent Coubard 0:f2542974c862 1449
vcoubard 24:2aea0c1c57ee 1450 if ((!is_word_aligned(p_dest)) ||
vcoubard 24:2aea0c1c57ee 1451 (!is_word_aligned((void *)(uint32_t)offset)) ||
vcoubard 24:2aea0c1c57ee 1452 (!is_word_aligned((uint32_t *)p_src->block_id)))
Vincent Coubard 0:f2542974c862 1453 {
Vincent Coubard 0:f2542974c862 1454 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1455 }
Vincent Coubard 0:f2542974c862 1456
Vincent Coubard 0:f2542974c862 1457 memcpy(p_dest, (((uint8_t *)p_src->block_id) + offset), size);
Vincent Coubard 0:f2542974c862 1458
Vincent Coubard 0:f2542974c862 1459 m_app_table[p_src->module_id].cb(p_src, PSTORAGE_LOAD_OP_CODE, NRF_SUCCESS, p_dest, size);
Vincent Coubard 0:f2542974c862 1460
Vincent Coubard 0:f2542974c862 1461 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1462 }
Vincent Coubard 0:f2542974c862 1463
Vincent Coubard 0:f2542974c862 1464
Vincent Coubard 0:f2542974c862 1465 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 0:f2542974c862 1466 {
Vincent Coubard 0:f2542974c862 1467 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1468 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1469 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1470 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1471
Vincent Coubard 0:f2542974c862 1472 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1473 {
Vincent Coubard 0:f2542974c862 1474 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1475 }
Vincent Coubard 0:f2542974c862 1476
vcoubard 24:2aea0c1c57ee 1477 // Check is the area starting from block_id multiple of block_size.
Vincent Coubard 0:f2542974c862 1478 if (
Vincent Coubard 0:f2542974c862 1479 !(
Vincent Coubard 0:f2542974c862 1480 ((p_dest->block_id - m_app_table[p_dest->module_id].base_id) %
Vincent Coubard 0:f2542974c862 1481 m_app_table[p_dest->module_id].block_size) == 0
Vincent Coubard 0:f2542974c862 1482 )
Vincent Coubard 0:f2542974c862 1483 )
Vincent Coubard 0:f2542974c862 1484 {
Vincent Coubard 0:f2542974c862 1485 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 0:f2542974c862 1486 }
Vincent Coubard 0:f2542974c862 1487
vcoubard 24:2aea0c1c57ee 1488 // Check is requested size multiple of registered block size or 0.
vcoubard 24:2aea0c1c57ee 1489 if (((size % m_app_table[p_dest->module_id].block_size) != 0) || (size == 0))
vcoubard 24:2aea0c1c57ee 1490 {
vcoubard 24:2aea0c1c57ee 1491 return NRF_ERROR_INVALID_PARAM;
vcoubard 24:2aea0c1c57ee 1492 }
Vincent Coubard 0:f2542974c862 1493
vcoubard 24:2aea0c1c57ee 1494 const uint32_t registered_allocation_size = m_app_table[p_dest->module_id].block_size *
vcoubard 24:2aea0c1c57ee 1495 m_app_table[p_dest->module_id].block_count;
vcoubard 24:2aea0c1c57ee 1496
vcoubard 24:2aea0c1c57ee 1497 const pstorage_block_t clear_request_end_address = p_dest->block_id + size;
vcoubard 24:2aea0c1c57ee 1498 const pstorage_block_t allocation_end_address = m_app_table[p_dest->module_id].base_id +
vcoubard 24:2aea0c1c57ee 1499 registered_allocation_size;
vcoubard 24:2aea0c1c57ee 1500 // Check if request would lead to a buffer overrun.
vcoubard 24:2aea0c1c57ee 1501 if (clear_request_end_address > allocation_end_address)
vcoubard 24:2aea0c1c57ee 1502 {
vcoubard 24:2aea0c1c57ee 1503 return NRF_ERROR_INVALID_PARAM;
vcoubard 24:2aea0c1c57ee 1504 }
vcoubard 24:2aea0c1c57ee 1505
vcoubard 24:2aea0c1c57ee 1506 return cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
Vincent Coubard 0:f2542974c862 1507 }
Vincent Coubard 0:f2542974c862 1508
Vincent Coubard 0:f2542974c862 1509
Vincent Coubard 0:f2542974c862 1510 uint32_t pstorage_access_status_get(uint32_t * p_count)
Vincent Coubard 0:f2542974c862 1511 {
Vincent Coubard 0:f2542974c862 1512 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1513 NULL_PARAM_CHECK(p_count);
Vincent Coubard 0:f2542974c862 1514
Vincent Coubard 0:f2542974c862 1515 (*p_count) = m_cmd_queue.count;
Vincent Coubard 0:f2542974c862 1516
Vincent Coubard 0:f2542974c862 1517 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1518 }
Vincent Coubard 0:f2542974c862 1519
Vincent Coubard 0:f2542974c862 1520 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 1521
Vincent Coubard 0:f2542974c862 1522 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 0:f2542974c862 1523 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 1524 {
Vincent Coubard 0:f2542974c862 1525 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1526 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 0:f2542974c862 1527 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 1528 NULL_PARAM_CHECK(p_module_param->cb);
Vincent Coubard 0:f2542974c862 1529
Vincent Coubard 0:f2542974c862 1530 if (m_raw_app_table.cb != NULL)
Vincent Coubard 0:f2542974c862 1531 {
Vincent Coubard 0:f2542974c862 1532 return NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 1533 }
Vincent Coubard 0:f2542974c862 1534
Vincent Coubard 0:f2542974c862 1535 p_block_id->module_id = RAW_MODE_APP_ID;
Vincent Coubard 0:f2542974c862 1536 m_raw_app_table.cb = p_module_param->cb;
Vincent Coubard 0:f2542974c862 1537
Vincent Coubard 0:f2542974c862 1538 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1539 }
Vincent Coubard 0:f2542974c862 1540
Vincent Coubard 0:f2542974c862 1541
Vincent Coubard 0:f2542974c862 1542 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 1543 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 1544 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1545 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1546 {
Vincent Coubard 0:f2542974c862 1547 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1548 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1549 NULL_PARAM_CHECK(p_dest);
vcoubard 24:2aea0c1c57ee 1550 MODULE_RAW_HANDLE_CHECK(p_dest);
vcoubard 24:2aea0c1c57ee 1551
vcoubard 24:2aea0c1c57ee 1552 if (size == 0)
vcoubard 24:2aea0c1c57ee 1553 {
vcoubard 24:2aea0c1c57ee 1554 return NRF_ERROR_INVALID_PARAM;
vcoubard 24:2aea0c1c57ee 1555 }
vcoubard 24:2aea0c1c57ee 1556
Vincent Coubard 0:f2542974c862 1557 // Verify word alignment.
vcoubard 24:2aea0c1c57ee 1558 if ((!is_word_aligned(p_src)) ||
vcoubard 24:2aea0c1c57ee 1559 (!is_word_aligned((void *)(uint32_t)size)) ||
vcoubard 24:2aea0c1c57ee 1560 (!is_word_aligned((void *)(uint32_t)offset)) ||
vcoubard 24:2aea0c1c57ee 1561 (!is_word_aligned((void *)(p_dest->block_id))))
Vincent Coubard 0:f2542974c862 1562 {
Vincent Coubard 0:f2542974c862 1563 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1564 }
vcoubard 24:2aea0c1c57ee 1565
Vincent Coubard 0:f2542974c862 1566 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1567 }
Vincent Coubard 0:f2542974c862 1568
Vincent Coubard 0:f2542974c862 1569
Vincent Coubard 0:f2542974c862 1570 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 0:f2542974c862 1571 {
Vincent Coubard 0:f2542974c862 1572 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1573 NULL_PARAM_CHECK(p_dest);
vcoubard 24:2aea0c1c57ee 1574 MODULE_RAW_HANDLE_CHECK(p_dest);
vcoubard 24:2aea0c1c57ee 1575
vcoubard 24:2aea0c1c57ee 1576 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
vcoubard 24:2aea0c1c57ee 1577 {
vcoubard 24:2aea0c1c57ee 1578 return NRF_ERROR_INVALID_ADDR;
vcoubard 24:2aea0c1c57ee 1579 }
Vincent Coubard 0:f2542974c862 1580
vcoubard 24:2aea0c1c57ee 1581 return cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
Vincent Coubard 0:f2542974c862 1582 }
Vincent Coubard 0:f2542974c862 1583
vcoubard 1:ebc0e0ef0a11 1584 #endif // PSTORAGE_RAW_MODE_ENABLE