Nordic Semiconductor / nrf51-sdk

Dependents:   nRF51822 nRF51822

Committer:
vcoubard
Date:
Thu Apr 07 17:37:52 2016 +0100
Revision:
27:0fe148f1bca3
Parent:
24:2aea0c1c57ee
Child:
28:041dac1366b2
Synchronized with git rev 25dc1a71
Author: Andres Amaya Garcia
Add ifdef to include correct mbed.h file in mbedOS

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"
Vincent Coubard 0:f2542974c862 43
vcoubard 27:0fe148f1bca3 44 #define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
vcoubard 27:0fe148f1bca3 45 #define SOC_MAX_WRITE_SIZE 1024 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API. */
vcoubard 27:0fe148f1bca3 46 #define RAW_MODE_APP_ID (PSTORAGE_MAX_APPLICATIONS + 1) /**< Application id for raw mode. */
vcoubard 27:0fe148f1bca3 47 #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. */
Vincent Coubard 0:f2542974c862 48
Vincent Coubard 0:f2542974c862 49 /**
Vincent Coubard 0:f2542974c862 50 * @defgroup api_param_check API Parameters check macros.
Vincent Coubard 0:f2542974c862 51 *
Vincent Coubard 0:f2542974c862 52 * @details Macros that verify parameters passed to the module in the APIs. These macros
vcoubard 27:0fe148f1bca3 53 * could be mapped to nothing in final versions of code to save execution and size.
Vincent Coubard 0:f2542974c862 54 *
Vincent Coubard 0:f2542974c862 55 * @{
Vincent Coubard 0:f2542974c862 56 */
Vincent Coubard 0:f2542974c862 57
vcoubard 27:0fe148f1bca3 58 /**
vcoubard 27:0fe148f1bca3 59 * @brief Check if the input pointer is NULL, if it is returns NRF_ERROR_NULL.
Vincent Coubard 0:f2542974c862 60 */
Vincent Coubard 0:f2542974c862 61 #define NULL_PARAM_CHECK(PARAM) \
Vincent Coubard 0:f2542974c862 62 if ((PARAM) == NULL) \
Vincent Coubard 0:f2542974c862 63 { \
Vincent Coubard 0:f2542974c862 64 return NRF_ERROR_NULL; \
Vincent Coubard 0:f2542974c862 65 }
Vincent Coubard 0:f2542974c862 66
vcoubard 27:0fe148f1bca3 67 /**
vcoubard 27:0fe148f1bca3 68 * @brief Verifies the module identifier supplied by the application is within permissible
Vincent Coubard 0:f2542974c862 69 * range.
Vincent Coubard 0:f2542974c862 70 */
Vincent Coubard 0:f2542974c862 71 #define MODULE_ID_RANGE_CHECK(ID) \
vcoubard 27:0fe148f1bca3 72 if ((((ID)->module_id) >= PSTORAGE_MAX_APPLICATIONS) || \
Vincent Coubard 0:f2542974c862 73 (m_app_table[(ID)->module_id].cb == NULL)) \
Vincent Coubard 0:f2542974c862 74 { \
Vincent Coubard 0:f2542974c862 75 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 76 }
Vincent Coubard 0:f2542974c862 77
vcoubard 27:0fe148f1bca3 78 /**
vcoubard 27:0fe148f1bca3 79 * @brief Verifies the block identifier supplied by the application is within the permissible
Vincent Coubard 0:f2542974c862 80 * range.
Vincent Coubard 0:f2542974c862 81 */
Vincent Coubard 0:f2542974c862 82 #define BLOCK_ID_RANGE_CHECK(ID) \
Vincent Coubard 0:f2542974c862 83 if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
Vincent Coubard 0:f2542974c862 84 (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
Vincent Coubard 0:f2542974c862 85 { \
Vincent Coubard 0:f2542974c862 86 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 87 }
Vincent Coubard 0:f2542974c862 88
vcoubard 27:0fe148f1bca3 89 /**
vcoubard 27:0fe148f1bca3 90 * @brief Verifies the block size requested by the application can be supported by the module.
Vincent Coubard 0:f2542974c862 91 */
Vincent Coubard 0:f2542974c862 92 #define BLOCK_SIZE_CHECK(X) \
Vincent Coubard 0:f2542974c862 93 if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
Vincent Coubard 0:f2542974c862 94 { \
Vincent Coubard 0:f2542974c862 95 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 96 }
Vincent Coubard 0:f2542974c862 97
vcoubard 27:0fe148f1bca3 98 /**
vcoubard 27:0fe148f1bca3 99 * @brief Verifies block size requested by 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 27:0fe148f1bca3 103 ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_SWAP_ADDR)) || \
vcoubard 27:0fe148f1bca3 104 ((((COUNT) * (SIZE)) > PSTORAGE_FLASH_PAGE_SIZE) && (PSTORAGE_FLASH_PAGE_SIZE % (SIZE)))) \
Vincent Coubard 0:f2542974c862 105 { \
Vincent Coubard 0:f2542974c862 106 return NRF_ERROR_INVALID_PARAM; \
vcoubard 27:0fe148f1bca3 107 }
Vincent Coubard 0:f2542974c862 108
vcoubard 27:0fe148f1bca3 109 /**
vcoubard 27:0fe148f1bca3 110 * @brief Verifies size parameter provided by application in API.
Vincent Coubard 0:f2542974c862 111 */
Vincent Coubard 0:f2542974c862 112 #define SIZE_CHECK(ID, SIZE) \
Vincent Coubard 0:f2542974c862 113 if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
Vincent Coubard 0:f2542974c862 114 { \
Vincent Coubard 0:f2542974c862 115 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 116 }
Vincent Coubard 0:f2542974c862 117
vcoubard 27:0fe148f1bca3 118 /**
vcoubard 27:0fe148f1bca3 119 * @brief Verifies offset parameter provided by application in API.
Vincent Coubard 0:f2542974c862 120 */
Vincent Coubard 0:f2542974c862 121 #define OFFSET_CHECK(ID, OFFSET, SIZE) \
Vincent Coubard 0:f2542974c862 122 if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
Vincent Coubard 0:f2542974c862 123 { \
Vincent Coubard 0:f2542974c862 124 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 125 }
Vincent Coubard 0:f2542974c862 126
Vincent Coubard 0:f2542974c862 127 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 128
vcoubard 27:0fe148f1bca3 129 /**
vcoubard 27:0fe148f1bca3 130 * @brief Verifies the module identifier supplied by the application is registered for raw mode.
Vincent Coubard 0:f2542974c862 131 */
vcoubard 27:0fe148f1bca3 132 #define MODULE_RAW_ID_RANGE_CHECK(ID) \
vcoubard 27:0fe148f1bca3 133 if ((PSTORAGE_MAX_APPLICATIONS+1 != ((ID)->module_id)) || \
vcoubard 27:0fe148f1bca3 134 (m_raw_app_table.cb == NULL)) \
Vincent Coubard 0:f2542974c862 135 { \
Vincent Coubard 0:f2542974c862 136 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 0:f2542974c862 137 }
Vincent Coubard 0:f2542974c862 138
Vincent Coubard 0:f2542974c862 139 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 140
Vincent Coubard 0:f2542974c862 141 /**@} */
Vincent Coubard 0:f2542974c862 142
Vincent Coubard 0:f2542974c862 143
vcoubard 27:0fe148f1bca3 144 /**@brief Verify module's initialization status.
Vincent Coubard 0:f2542974c862 145 *
vcoubard 27:0fe148f1bca3 146 * @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
vcoubard 27:0fe148f1bca3 147 * module API is called without initializing the module.
Vincent Coubard 0:f2542974c862 148 */
Vincent Coubard 0:f2542974c862 149 #define VERIFY_MODULE_INITIALIZED() \
Vincent Coubard 0:f2542974c862 150 do \
Vincent Coubard 0:f2542974c862 151 { \
vcoubard 27:0fe148f1bca3 152 if (!m_module_initialized) \
Vincent Coubard 0:f2542974c862 153 { \
Vincent Coubard 0:f2542974c862 154 return NRF_ERROR_INVALID_STATE; \
Vincent Coubard 0:f2542974c862 155 } \
Vincent Coubard 0:f2542974c862 156 } while(0)
Vincent Coubard 0:f2542974c862 157
Vincent Coubard 0:f2542974c862 158 /**@brief Macro to fetch the block size registered for the module. */
Vincent Coubard 0:f2542974c862 159 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
Vincent Coubard 0:f2542974c862 160
vcoubard 27:0fe148f1bca3 161
vcoubard 27:0fe148f1bca3 162 /** @brief States for the Update/Clear swap backup state machine. */
Vincent Coubard 0:f2542974c862 163 typedef enum
Vincent Coubard 0:f2542974c862 164 {
vcoubard 27:0fe148f1bca3 165 STATE_INIT, /**< State for indicating that swap can be used when using update/clear API. */
vcoubard 27:0fe148f1bca3 166 STATE_DATA_TO_SWAP_WRITE, /**< State for doing backup of data page into the swap page when using update/clear API. */
vcoubard 27:0fe148f1bca3 167 STATE_DATA_ERASE, /**< State for erasing data page when using update/clear API. */
vcoubard 27:0fe148f1bca3 168 STATE_HEAD_RESTORE, /**< State for restoring head (beginning) of backed up data from swap to data page when using update/clear API. */
vcoubard 27:0fe148f1bca3 169 STATE_TAIL_RESTORE, /**< State for restoring tail (end) of backed up data from swap to data page when using update/clear API. */
vcoubard 27:0fe148f1bca3 170 STATE_NEW_BODY_WRITE, /**< State for writing body (middle) data to the data page when using update/clear API. */
vcoubard 27:0fe148f1bca3 171 STATE_SWAP_ERASE, /**< State for erasing the swap page when using the update/clear API. */
vcoubard 27:0fe148f1bca3 172 STATE_COMPLETE, /**< State for indicating that update/clear sequence is completed internal in the module when using the update/clear API. */
vcoubard 27:0fe148f1bca3 173 STATE_SWAP_DIRTY /**< State for initializing the swap region on module initialization. */
vcoubard 27:0fe148f1bca3 174 } swap_backup_state_t;
Vincent Coubard 0:f2542974c862 175
Vincent Coubard 0:f2542974c862 176
vcoubard 27:0fe148f1bca3 177 /**
vcoubard 27:0fe148f1bca3 178 * @brief Application registration information.
Vincent Coubard 0:f2542974c862 179 *
vcoubard 27:0fe148f1bca3 180 * @details Define application specific information that application needs to maintain to be able
Vincent Coubard 0:f2542974c862 181 * to process requests from each one of them.
Vincent Coubard 0:f2542974c862 182 */
Vincent Coubard 0:f2542974c862 183 typedef struct
Vincent Coubard 0:f2542974c862 184 {
vcoubard 27:0fe148f1bca3 185 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
vcoubard 27:0fe148f1bca3 186 pstorage_block_t base_id; /**< Base block id assigned to the module. */
vcoubard 27:0fe148f1bca3 187 pstorage_size_t block_size; /**< Size of block for the module. */
vcoubard 27:0fe148f1bca3 188 pstorage_size_t block_count; /**< Number of block requested by application. */
vcoubard 27:0fe148f1bca3 189 pstorage_size_t num_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
Vincent Coubard 0:f2542974c862 190 } pstorage_module_table_t;
Vincent Coubard 0:f2542974c862 191
Vincent Coubard 0:f2542974c862 192
Vincent Coubard 0:f2542974c862 193 #ifdef PSTORAGE_RAW_MODE_ENABLE
vcoubard 27:0fe148f1bca3 194 /**
vcoubard 27:0fe148f1bca3 195 * @brief Application registration information.
Vincent Coubard 0:f2542974c862 196 *
vcoubard 27:0fe148f1bca3 197 * @details Define application specific information that application registered for raw mode.
Vincent Coubard 0:f2542974c862 198 */
Vincent Coubard 0:f2542974c862 199 typedef struct
Vincent Coubard 0:f2542974c862 200 {
vcoubard 27:0fe148f1bca3 201 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
vcoubard 27:0fe148f1bca3 202 uint16_t num_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
Vincent Coubard 0:f2542974c862 203 } pstorage_raw_module_table_t;
Vincent Coubard 0:f2542974c862 204 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 205
Vincent Coubard 0:f2542974c862 206
vcoubard 27:0fe148f1bca3 207 /**
vcoubard 27:0fe148f1bca3 208 * @brief Defines command queue element.
Vincent Coubard 0:f2542974c862 209 *
Vincent Coubard 0:f2542974c862 210 * @details Defines command queue element. Each element encapsulates needed information to process
Vincent Coubard 0:f2542974c862 211 * a flash access command.
Vincent Coubard 0:f2542974c862 212 */
Vincent Coubard 0:f2542974c862 213 typedef struct
Vincent Coubard 0:f2542974c862 214 {
vcoubard 27:0fe148f1bca3 215 uint8_t op_code; /**< Identifies flash access operation being queued. Element is free if op-code is INVALID_OPCODE. */
vcoubard 27:0fe148f1bca3 216 uint8_t n_tries; /**< Number of times this command has been retried after failing. */
vcoubard 27:0fe148f1bca3 217 pstorage_size_t size; /**< Identifies size in bytes requested for the operation. */
vcoubard 27:0fe148f1bca3 218 pstorage_size_t offset; /**< Offset requested by the application for access operation. */
vcoubard 27:0fe148f1bca3 219 pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
vcoubard 27:0fe148f1bca3 220 uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
Vincent Coubard 0:f2542974c862 221 } cmd_queue_element_t;
Vincent Coubard 0:f2542974c862 222
Vincent Coubard 0:f2542974c862 223
vcoubard 27:0fe148f1bca3 224 /**
vcoubard 27:0fe148f1bca3 225 * @brief Defines command queue, an element is free if op_code field is not invalid.
Vincent Coubard 0:f2542974c862 226 *
vcoubard 27:0fe148f1bca3 227 * @details Defines commands enqueued for flash access. At any point of time, this queue has one or
vcoubard 27:0fe148f1bca3 228 * more flash access operation pending if the count field is not zero. When the queue is
vcoubard 27:0fe148f1bca3 229 * not empty, the rp (read pointer) field points to the flash access command in progress
vcoubard 27:0fe148f1bca3 230 * or to requested next. The queue implements a simple first in first out algorithm.
vcoubard 27:0fe148f1bca3 231 * Data addresses are assumed to be resident.
Vincent Coubard 0:f2542974c862 232 */
Vincent Coubard 0:f2542974c862 233 typedef struct
Vincent Coubard 0:f2542974c862 234 {
vcoubard 27:0fe148f1bca3 235 uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
vcoubard 27:0fe148f1bca3 236 uint8_t count; /**< Number of elements in the queue. */
vcoubard 27:0fe148f1bca3 237 bool flash_access; /**< Flag to ensure an flash event received is for an request issued by the module. */
vcoubard 27:0fe148f1bca3 238 cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details. */
Vincent Coubard 0:f2542974c862 239 } cmd_queue_t;
Vincent Coubard 0:f2542974c862 240
vcoubard 27:0fe148f1bca3 241
vcoubard 27:0fe148f1bca3 242 static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
vcoubard 27:0fe148f1bca3 243 static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next. */
vcoubard 27:0fe148f1bca3 244 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 can span across flash pages. */
vcoubard 27:0fe148f1bca3 245 static pstorage_size_t m_round_val; /**< Round value for multiple round operations. For erase operations, the round value will contain current round counter which is identical to number of pages erased. For store operations, the round value contains current round of operation * SOC_MAX_WRITE_SIZE to ensure each store to the SoC Flash API is within the SoC limit. */
vcoubard 27:0fe148f1bca3 246 static bool m_module_initialized = false; /**< Flag for checking if module has been initialized. */
vcoubard 27:0fe148f1bca3 247 static swap_backup_state_t m_swap_state; /**< Swap page state. */
vcoubard 27:0fe148f1bca3 248
vcoubard 27:0fe148f1bca3 249
vcoubard 27:0fe148f1bca3 250 static pstorage_module_table_t m_app_table[PSTORAGE_MAX_APPLICATIONS]; /**< Registered application information table. */
Vincent Coubard 0:f2542974c862 251
Vincent Coubard 0:f2542974c862 252 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 253 static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
Vincent Coubard 0:f2542974c862 254 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 255
Vincent Coubard 0:f2542974c862 256
vcoubard 27:0fe148f1bca3 257 /**
vcoubard 27:0fe148f1bca3 258 * @brief Routine called to actually issue the flash access request to the SoftDevice.
Vincent Coubard 0:f2542974c862 259 *
vcoubard 27:0fe148f1bca3 260 * @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
Vincent Coubard 0:f2542974c862 261 */
vcoubard 27:0fe148f1bca3 262 static uint32_t cmd_process(void);
Vincent Coubard 0:f2542974c862 263
Vincent Coubard 0:f2542974c862 264
vcoubard 27:0fe148f1bca3 265 /**
vcoubard 27:0fe148f1bca3 266 * @brief Routine to notify application of any errors.
Vincent Coubard 0:f2542974c862 267 *
vcoubard 27:0fe148f1bca3 268 * @param[in] result Result of event being notified.
Vincent Coubard 0:f2542974c862 269 */
vcoubard 27:0fe148f1bca3 270 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem);
Vincent Coubard 0:f2542974c862 271
Vincent Coubard 0:f2542974c862 272
vcoubard 27:0fe148f1bca3 273 /**
vcoubard 27:0fe148f1bca3 274 * @defgroup utility_functions Utility internal functions.
vcoubard 27:0fe148f1bca3 275 * @{
vcoubard 27:0fe148f1bca3 276 * @details Utility functions needed for interfacing with flash through SoC APIs.
vcoubard 27:0fe148f1bca3 277 * SoC APIs are non blocking and provide the result of flash access through an event.
Vincent Coubard 0:f2542974c862 278 *
vcoubard 27:0fe148f1bca3 279 * @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
vcoubard 27:0fe148f1bca3 280 * maintained by this module.
Vincent Coubard 0:f2542974c862 281 */
Vincent Coubard 0:f2542974c862 282
Vincent Coubard 0:f2542974c862 283
vcoubard 27:0fe148f1bca3 284 /**
vcoubard 27:0fe148f1bca3 285 * @brief Initializes command queue element.
Vincent Coubard 0:f2542974c862 286 *
vcoubard 27:0fe148f1bca3 287 * @param[in] index Element index being initialized.
Vincent Coubard 0:f2542974c862 288 */
Vincent Coubard 0:f2542974c862 289 static void cmd_queue_element_init(uint32_t index)
Vincent Coubard 0:f2542974c862 290 {
Vincent Coubard 0:f2542974c862 291 // Internal function and checks on range of index can be avoided.
Vincent Coubard 0:f2542974c862 292 m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
Vincent Coubard 0:f2542974c862 293 m_cmd_queue.cmd[index].size = 0;
vcoubard 27:0fe148f1bca3 294 m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_MAX_APPLICATIONS;
Vincent Coubard 0:f2542974c862 295 m_cmd_queue.cmd[index].storage_addr.block_id = 0;
Vincent Coubard 0:f2542974c862 296 m_cmd_queue.cmd[index].p_data_addr = NULL;
Vincent Coubard 0:f2542974c862 297 m_cmd_queue.cmd[index].offset = 0;
Vincent Coubard 0:f2542974c862 298 }
Vincent Coubard 0:f2542974c862 299
Vincent Coubard 0:f2542974c862 300
vcoubard 27:0fe148f1bca3 301 /**
vcoubard 27:0fe148f1bca3 302 * @brief Initializes command queue.
Vincent Coubard 0:f2542974c862 303 */
Vincent Coubard 0:f2542974c862 304 static void cmd_queue_init(void)
Vincent Coubard 0:f2542974c862 305 {
vcoubard 27:0fe148f1bca3 306 uint32_t cmd_index;
Vincent Coubard 0:f2542974c862 307
vcoubard 27:0fe148f1bca3 308 m_round_val = 0;
vcoubard 27:0fe148f1bca3 309 m_swap_state = STATE_INIT;
vcoubard 27:0fe148f1bca3 310 m_cmd_queue.rp = 0;
vcoubard 27:0fe148f1bca3 311 m_cmd_queue.count = 0;
vcoubard 27:0fe148f1bca3 312 m_cmd_queue.flash_access = false;
vcoubard 27:0fe148f1bca3 313
vcoubard 27:0fe148f1bca3 314 for (cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
Vincent Coubard 0:f2542974c862 315 {
Vincent Coubard 0:f2542974c862 316 cmd_queue_element_init(cmd_index);
Vincent Coubard 0:f2542974c862 317 }
Vincent Coubard 0:f2542974c862 318 }
Vincent Coubard 0:f2542974c862 319
Vincent Coubard 0:f2542974c862 320
vcoubard 27:0fe148f1bca3 321 /**
vcoubard 27:0fe148f1bca3 322 * @brief Routine to enqueue a flash access operation.
Vincent Coubard 0:f2542974c862 323 *
vcoubard 27:0fe148f1bca3 324 * @param[in] opcode Identifies operation requested to be enqueued.
vcoubard 27:0fe148f1bca3 325 * @param[in] p_storage_addr Identiifes module and flash address on which operation is requested.
vcoubard 27:0fe148f1bca3 326 * @param[in] p_data_addr Identifies data address for flash access.
Vincent Coubard 0:f2542974c862 327 * @param[in] size Size in bytes of data requested for the access operation.
Vincent Coubard 0:f2542974c862 328 * @param[in] offset Offset within the flash memory block at which operation is requested.
Vincent Coubard 0:f2542974c862 329 *
vcoubard 27:0fe148f1bca3 330 * @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
vcoubard 27:0fe148f1bca3 331 *
vcoubard 27:0fe148f1bca3 332 * @note All paramater check should be performed before requesting in an enqueue.
Vincent Coubard 0:f2542974c862 333 */
Vincent Coubard 0:f2542974c862 334 static uint32_t cmd_queue_enqueue(uint8_t opcode,
Vincent Coubard 0:f2542974c862 335 pstorage_handle_t * p_storage_addr,
Vincent Coubard 0:f2542974c862 336 uint8_t * p_data_addr,
Vincent Coubard 0:f2542974c862 337 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 338 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 339 {
vcoubard 27:0fe148f1bca3 340 uint32_t retval;
vcoubard 27:0fe148f1bca3 341 uint8_t write_index = 0;
Vincent Coubard 0:f2542974c862 342
Vincent Coubard 0:f2542974c862 343 if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 0:f2542974c862 344 {
vcoubard 27:0fe148f1bca3 345 // Enqueue the command if it is queue is not full.
vcoubard 27:0fe148f1bca3 346 write_index = m_cmd_queue.rp + m_cmd_queue.count;
Vincent Coubard 0:f2542974c862 347
vcoubard 27:0fe148f1bca3 348 if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 0:f2542974c862 349 {
Vincent Coubard 0:f2542974c862 350 write_index -= PSTORAGE_CMD_QUEUE_SIZE;
Vincent Coubard 0:f2542974c862 351 }
Vincent Coubard 0:f2542974c862 352
Vincent Coubard 0:f2542974c862 353 m_cmd_queue.cmd[write_index].op_code = opcode;
vcoubard 27:0fe148f1bca3 354 m_cmd_queue.cmd[write_index].n_tries = 0;
Vincent Coubard 0:f2542974c862 355 m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
Vincent Coubard 0:f2542974c862 356 m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
Vincent Coubard 0:f2542974c862 357 m_cmd_queue.cmd[write_index].size = size;
Vincent Coubard 0:f2542974c862 358 m_cmd_queue.cmd[write_index].offset = offset;
vcoubard 27:0fe148f1bca3 359 retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 360 if (m_cmd_queue.flash_access == false)
Vincent Coubard 0:f2542974c862 361 {
vcoubard 27:0fe148f1bca3 362 retval = cmd_process();
vcoubard 27:0fe148f1bca3 363 if (retval == NRF_ERROR_BUSY)
vcoubard 27:0fe148f1bca3 364 {
vcoubard 27:0fe148f1bca3 365 // In case of busy error code, it is possible to attempt to access flash.
vcoubard 27:0fe148f1bca3 366 retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 367 }
vcoubard 27:0fe148f1bca3 368 }
vcoubard 27:0fe148f1bca3 369 m_cmd_queue.count++;
Vincent Coubard 0:f2542974c862 370 }
Vincent Coubard 0:f2542974c862 371 else
Vincent Coubard 0:f2542974c862 372 {
vcoubard 27:0fe148f1bca3 373 retval = NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 374 }
Vincent Coubard 0:f2542974c862 375
vcoubard 27:0fe148f1bca3 376 return retval;
Vincent Coubard 0:f2542974c862 377 }
Vincent Coubard 0:f2542974c862 378
Vincent Coubard 0:f2542974c862 379
vcoubard 27:0fe148f1bca3 380 /**
vcoubard 27:0fe148f1bca3 381 * @brief Dequeues a command element.
vcoubard 27:0fe148f1bca3 382 *
vcoubard 27:0fe148f1bca3 383 * @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
Vincent Coubard 0:f2542974c862 384 */
vcoubard 27:0fe148f1bca3 385 static uint32_t cmd_queue_dequeue(void)
Vincent Coubard 0:f2542974c862 386 {
vcoubard 27:0fe148f1bca3 387 uint32_t retval;
vcoubard 27:0fe148f1bca3 388 retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 389
vcoubard 27:0fe148f1bca3 390 // If any flash operation is enqueued, schedule.
vcoubard 27:0fe148f1bca3 391 if ((m_cmd_queue.count > 0) && (m_cmd_queue.flash_access == false))
Vincent Coubard 0:f2542974c862 392 {
vcoubard 27:0fe148f1bca3 393 retval = cmd_process();
vcoubard 27:0fe148f1bca3 394 if (retval != NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 395 {
vcoubard 27:0fe148f1bca3 396 // Flash could be accessed by modules other than Bond Manager, hence a busy error is
vcoubard 27:0fe148f1bca3 397 // acceptable, but any other error needs to be indicated to the bond manager.
vcoubard 27:0fe148f1bca3 398 if (retval == NRF_ERROR_BUSY)
vcoubard 27:0fe148f1bca3 399 {
vcoubard 27:0fe148f1bca3 400 // In case of busy error code, it is possible to attempt to access flash.
vcoubard 27:0fe148f1bca3 401 retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 402 }
vcoubard 27:0fe148f1bca3 403 }
Vincent Coubard 0:f2542974c862 404 }
vcoubard 27:0fe148f1bca3 405 else
vcoubard 27:0fe148f1bca3 406 {
vcoubard 27:0fe148f1bca3 407 // No flash access request pending.
vcoubard 27:0fe148f1bca3 408 }
vcoubard 27:0fe148f1bca3 409
vcoubard 27:0fe148f1bca3 410 return retval;
Vincent Coubard 0:f2542974c862 411 }
Vincent Coubard 0:f2542974c862 412
Vincent Coubard 0:f2542974c862 413
vcoubard 27:0fe148f1bca3 414 /**
vcoubard 27:0fe148f1bca3 415 * @brief Routine to notify application of any errors.
Vincent Coubard 0:f2542974c862 416 *
vcoubard 27:0fe148f1bca3 417 * @param[in] result Result of event being notified.
vcoubard 27:0fe148f1bca3 418 * @param[in] p_elem Pointer to the element for which this result was received.
Vincent Coubard 0:f2542974c862 419 */
vcoubard 1:ebc0e0ef0a11 420 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem)
Vincent Coubard 0:f2542974c862 421 {
Vincent Coubard 0:f2542974c862 422 pstorage_ntf_cb_t ntf_cb;
vcoubard 27:0fe148f1bca3 423 uint8_t op_code = p_elem->op_code;
Vincent Coubard 0:f2542974c862 424
Vincent Coubard 0:f2542974c862 425 #ifdef PSTORAGE_RAW_MODE_ENABLE
vcoubard 1:ebc0e0ef0a11 426 if (p_elem->storage_addr.module_id == RAW_MODE_APP_ID)
Vincent Coubard 0:f2542974c862 427 {
Vincent Coubard 0:f2542974c862 428 ntf_cb = m_raw_app_table.cb;
Vincent Coubard 0:f2542974c862 429 }
Vincent Coubard 0:f2542974c862 430 else
Vincent Coubard 0:f2542974c862 431 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 432 {
vcoubard 1:ebc0e0ef0a11 433 ntf_cb = m_app_table[p_elem->storage_addr.module_id].cb;
Vincent Coubard 0:f2542974c862 434 }
Vincent Coubard 0:f2542974c862 435
vcoubard 27:0fe148f1bca3 436 // Indicate result to client.
vcoubard 27:0fe148f1bca3 437 // For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally
vcoubard 27:0fe148f1bca3 438 // for clients registering multiple pages.
vcoubard 27:0fe148f1bca3 439 ntf_cb(&p_elem->storage_addr,
vcoubard 27:0fe148f1bca3 440 op_code,
vcoubard 27:0fe148f1bca3 441 result,
vcoubard 27:0fe148f1bca3 442 p_elem->p_data_addr,
vcoubard 27:0fe148f1bca3 443 p_elem->size);
vcoubard 24:2aea0c1c57ee 444 }
vcoubard 24:2aea0c1c57ee 445
vcoubard 22:67a8d2c0bbbf 446
vcoubard 27:0fe148f1bca3 447 /**
vcoubard 27:0fe148f1bca3 448 * @brief Handles Flash Access Result Events declared in pstorage_platform.h.
vcoubard 24:2aea0c1c57ee 449 *
vcoubard 27:0fe148f1bca3 450 * @param[in] sys_evt System event to be handled.
vcoubard 24:2aea0c1c57ee 451 */
vcoubard 27:0fe148f1bca3 452 void pstorage_sys_event_handler(uint32_t sys_evt)
vcoubard 24:2aea0c1c57ee 453 {
vcoubard 27:0fe148f1bca3 454 uint32_t retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 455
vcoubard 27:0fe148f1bca3 456 // Its possible the flash access was not initiated by bond manager, hence
vcoubard 27:0fe148f1bca3 457 // event is processed only if the event triggered was for an operation requested by the
vcoubard 27:0fe148f1bca3 458 // bond manager.
vcoubard 27:0fe148f1bca3 459 if (m_cmd_queue.flash_access == true)
Vincent Coubard 0:f2542974c862 460 {
vcoubard 27:0fe148f1bca3 461 cmd_queue_element_t * p_cmd;
vcoubard 24:2aea0c1c57ee 462
vcoubard 27:0fe148f1bca3 463 m_cmd_queue.flash_access = false;
Vincent Coubard 0:f2542974c862 464
vcoubard 27:0fe148f1bca3 465 if (m_swap_state == STATE_SWAP_DIRTY)
Vincent Coubard 0:f2542974c862 466 {
vcoubard 27:0fe148f1bca3 467 if (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS)
Vincent Coubard 0:f2542974c862 468 {
vcoubard 27:0fe148f1bca3 469 m_swap_state = STATE_INIT;
Vincent Coubard 0:f2542974c862 470 }
Vincent Coubard 0:f2542974c862 471 else
Vincent Coubard 0:f2542974c862 472 {
vcoubard 27:0fe148f1bca3 473 // If clearing the swap fails, set the application back to un-initialized, to give
vcoubard 27:0fe148f1bca3 474 // the application a chance for a retry.
vcoubard 27:0fe148f1bca3 475 m_module_initialized = false;
Vincent Coubard 0:f2542974c862 476 }
Vincent Coubard 0:f2542974c862 477
vcoubard 27:0fe148f1bca3 478 // Schedule any queued flash access operations.
vcoubard 27:0fe148f1bca3 479 retval = cmd_queue_dequeue();
vcoubard 27:0fe148f1bca3 480 if (retval != NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 481 {
vcoubard 27:0fe148f1bca3 482 app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]);
vcoubard 27:0fe148f1bca3 483 }
vcoubard 27:0fe148f1bca3 484 return;
Vincent Coubard 0:f2542974c862 485 }
Vincent Coubard 0:f2542974c862 486
vcoubard 27:0fe148f1bca3 487 switch (sys_evt)
vcoubard 27:0fe148f1bca3 488 {
vcoubard 27:0fe148f1bca3 489 case NRF_EVT_FLASH_OPERATION_SUCCESS:
vcoubard 27:0fe148f1bca3 490 {
vcoubard 27:0fe148f1bca3 491 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 27:0fe148f1bca3 492 m_round_val++;
vcoubard 27:0fe148f1bca3 493
vcoubard 27:0fe148f1bca3 494 const bool store_finished =
vcoubard 27:0fe148f1bca3 495 ((p_cmd->op_code == PSTORAGE_STORE_OP_CODE) &&
vcoubard 27:0fe148f1bca3 496 ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size));
vcoubard 27:0fe148f1bca3 497
vcoubard 27:0fe148f1bca3 498 const bool update_finished =
vcoubard 27:0fe148f1bca3 499 ((p_cmd->op_code == PSTORAGE_UPDATE_OP_CODE) &&
vcoubard 27:0fe148f1bca3 500 (m_swap_state == STATE_COMPLETE));
vcoubard 27:0fe148f1bca3 501
vcoubard 27:0fe148f1bca3 502 const bool clear_block_finished =
vcoubard 27:0fe148f1bca3 503 ((p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) &&
vcoubard 27:0fe148f1bca3 504 (m_swap_state == STATE_COMPLETE));
Vincent Coubard 0:f2542974c862 505
vcoubard 27:0fe148f1bca3 506 const bool clear_all_finished =
vcoubard 27:0fe148f1bca3 507 ((p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE) &&
vcoubard 27:0fe148f1bca3 508 ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size) &&
vcoubard 27:0fe148f1bca3 509 (m_swap_state == STATE_INIT));
vcoubard 27:0fe148f1bca3 510
vcoubard 27:0fe148f1bca3 511 if (update_finished ||
vcoubard 27:0fe148f1bca3 512 clear_block_finished ||
vcoubard 27:0fe148f1bca3 513 clear_all_finished ||
vcoubard 27:0fe148f1bca3 514 store_finished)
vcoubard 27:0fe148f1bca3 515 {
vcoubard 27:0fe148f1bca3 516 uint8_t queue_rp = m_cmd_queue.rp;
vcoubard 27:0fe148f1bca3 517
vcoubard 27:0fe148f1bca3 518 m_swap_state = STATE_INIT;
vcoubard 27:0fe148f1bca3 519
vcoubard 27:0fe148f1bca3 520 m_round_val = 0;
vcoubard 27:0fe148f1bca3 521 m_cmd_queue.count--;
vcoubard 27:0fe148f1bca3 522 m_cmd_queue.rp++;
vcoubard 27:0fe148f1bca3 523
vcoubard 27:0fe148f1bca3 524 if (m_cmd_queue.rp >= PSTORAGE_CMD_QUEUE_SIZE)
vcoubard 27:0fe148f1bca3 525 {
vcoubard 27:0fe148f1bca3 526 m_cmd_queue.rp -= PSTORAGE_CMD_QUEUE_SIZE;
vcoubard 27:0fe148f1bca3 527 }
vcoubard 1:ebc0e0ef0a11 528
vcoubard 27:0fe148f1bca3 529 app_notify(retval, &m_cmd_queue.cmd[queue_rp]);
vcoubard 27:0fe148f1bca3 530
vcoubard 27:0fe148f1bca3 531 // Initialize/free the element as it is now processed.
vcoubard 27:0fe148f1bca3 532 cmd_queue_element_init(queue_rp);
vcoubard 27:0fe148f1bca3 533 }
vcoubard 27:0fe148f1bca3 534 // Schedule any queued flash access operations.
vcoubard 27:0fe148f1bca3 535 retval = cmd_queue_dequeue();
vcoubard 27:0fe148f1bca3 536
vcoubard 27:0fe148f1bca3 537 if (retval != NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 538 {
vcoubard 27:0fe148f1bca3 539 app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]);
vcoubard 27:0fe148f1bca3 540 }
vcoubard 27:0fe148f1bca3 541 }
vcoubard 27:0fe148f1bca3 542 break;
vcoubard 27:0fe148f1bca3 543
vcoubard 27:0fe148f1bca3 544 case NRF_EVT_FLASH_OPERATION_ERROR:
vcoubard 27:0fe148f1bca3 545 // Current command timed out and was not started in SoftDevice.
vcoubard 27:0fe148f1bca3 546 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 27:0fe148f1bca3 547
vcoubard 27:0fe148f1bca3 548 ASSERT(p_cmd->n_tries < SD_CMD_MAX_TRIES);
vcoubard 27:0fe148f1bca3 549 if (++p_cmd->n_tries == SD_CMD_MAX_TRIES)
vcoubard 27:0fe148f1bca3 550 {
vcoubard 27:0fe148f1bca3 551 // If we have already attempted SD_CMD_MAX_TRIES times, give up.
vcoubard 27:0fe148f1bca3 552 app_notify(NRF_ERROR_TIMEOUT, &m_cmd_queue.cmd[m_cmd_queue.rp]);
vcoubard 27:0fe148f1bca3 553 }
vcoubard 27:0fe148f1bca3 554 else
vcoubard 27:0fe148f1bca3 555 {
vcoubard 27:0fe148f1bca3 556 // Retry operation
vcoubard 27:0fe148f1bca3 557 retval = cmd_process();
vcoubard 27:0fe148f1bca3 558 if (retval != NRF_SUCCESS && retval != NRF_ERROR_BUSY)
vcoubard 27:0fe148f1bca3 559 {
vcoubard 27:0fe148f1bca3 560 app_notify(retval, p_cmd);
vcoubard 27:0fe148f1bca3 561 }
vcoubard 27:0fe148f1bca3 562 }
vcoubard 27:0fe148f1bca3 563 break;
vcoubard 27:0fe148f1bca3 564
vcoubard 27:0fe148f1bca3 565 default:
vcoubard 27:0fe148f1bca3 566 // No implementation needed.
vcoubard 27:0fe148f1bca3 567 break;
vcoubard 27:0fe148f1bca3 568
vcoubard 27:0fe148f1bca3 569 }
Vincent Coubard 0:f2542974c862 570 }
Vincent Coubard 0:f2542974c862 571 }
Vincent Coubard 0:f2542974c862 572
Vincent Coubard 0:f2542974c862 573
vcoubard 27:0fe148f1bca3 574 /** @brief Function for handling flash accesses when using swap.
vcoubard 27:0fe148f1bca3 575 *
vcoubard 27:0fe148f1bca3 576 * __________________________________________________________
vcoubard 27:0fe148f1bca3 577 * | Page |
vcoubard 27:0fe148f1bca3 578 * |________________________________________________________|
vcoubard 27:0fe148f1bca3 579 * | head | affected body (to be updated or cleared) | tail |
vcoubard 27:0fe148f1bca3 580 * |______|__________________________________________|______|
vcoubard 27:0fe148f1bca3 581 *
vcoubard 27:0fe148f1bca3 582 * @param[in] p_cmd Queue element being processed.
vcoubard 27:0fe148f1bca3 583 * @param[in] page_number The affected page number.
vcoubard 27:0fe148f1bca3 584 * @param[in] head_word_size Size of the head in number of words.
vcoubard 27:0fe148f1bca3 585 * @param[in] tail_word_size Size of the tail in number of words.
vcoubard 27:0fe148f1bca3 586 *
vcoubard 27:0fe148f1bca3 587 * @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
vcoubard 24:2aea0c1c57ee 588 */
vcoubard 27:0fe148f1bca3 589 static uint32_t swap_state_process(cmd_queue_element_t * p_cmd,
vcoubard 27:0fe148f1bca3 590 uint32_t page_number,
vcoubard 27:0fe148f1bca3 591 uint32_t head_word_size,
vcoubard 27:0fe148f1bca3 592 uint32_t tail_word_size)
Vincent Coubard 0:f2542974c862 593 {
vcoubard 27:0fe148f1bca3 594 uint32_t retval = NRF_ERROR_INTERNAL;
vcoubard 27:0fe148f1bca3 595
vcoubard 27:0fe148f1bca3 596 // Adjust entry point to state machine if needed. When we update has no head or tail its
vcoubard 27:0fe148f1bca3 597 // no need for using the swap.
vcoubard 27:0fe148f1bca3 598 if (m_swap_state == STATE_INIT)
vcoubard 24:2aea0c1c57ee 599 {
vcoubard 27:0fe148f1bca3 600 if ((head_word_size == 0) && (tail_word_size == 0))
Vincent Coubard 0:f2542974c862 601 {
vcoubard 27:0fe148f1bca3 602 // Only skip swap usage if the new data fills a whole flash page.
vcoubard 27:0fe148f1bca3 603 m_swap_state = STATE_DATA_ERASE;
Vincent Coubard 0:f2542974c862 604 }
Vincent Coubard 0:f2542974c862 605 else
Vincent Coubard 0:f2542974c862 606 {
vcoubard 27:0fe148f1bca3 607 // Else start backing up application data to swap.
vcoubard 27:0fe148f1bca3 608 m_swap_state = STATE_DATA_TO_SWAP_WRITE;
Vincent Coubard 0:f2542974c862 609 }
Vincent Coubard 0:f2542974c862 610 }
vcoubard 27:0fe148f1bca3 611
vcoubard 27:0fe148f1bca3 612 switch (m_swap_state)
Vincent Coubard 0:f2542974c862 613 {
vcoubard 27:0fe148f1bca3 614 case STATE_DATA_TO_SWAP_WRITE:
vcoubard 27:0fe148f1bca3 615 // Backup previous content into swap page.
vcoubard 27:0fe148f1bca3 616 retval = sd_flash_write((uint32_t *)(PSTORAGE_SWAP_ADDR),
vcoubard 27:0fe148f1bca3 617 (uint32_t *)(page_number * PSTORAGE_FLASH_PAGE_SIZE),
vcoubard 27:0fe148f1bca3 618 PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
vcoubard 27:0fe148f1bca3 619 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 620 {
vcoubard 27:0fe148f1bca3 621 m_swap_state = STATE_DATA_ERASE;
vcoubard 27:0fe148f1bca3 622 }
vcoubard 27:0fe148f1bca3 623 break;
vcoubard 24:2aea0c1c57ee 624
vcoubard 27:0fe148f1bca3 625 case STATE_DATA_ERASE:
vcoubard 27:0fe148f1bca3 626 // Clear the application data page.
vcoubard 27:0fe148f1bca3 627 retval = sd_flash_page_erase(page_number);
vcoubard 27:0fe148f1bca3 628 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 629 {
vcoubard 27:0fe148f1bca3 630 if (head_word_size == 0)
vcoubard 27:0fe148f1bca3 631 {
vcoubard 27:0fe148f1bca3 632 if (tail_word_size == 0)
vcoubard 27:0fe148f1bca3 633 {
vcoubard 27:0fe148f1bca3 634 if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
vcoubard 27:0fe148f1bca3 635 {
vcoubard 27:0fe148f1bca3 636 m_swap_state = STATE_COMPLETE;
vcoubard 27:0fe148f1bca3 637 }
vcoubard 27:0fe148f1bca3 638 else
vcoubard 27:0fe148f1bca3 639 {
vcoubard 27:0fe148f1bca3 640 m_swap_state = STATE_NEW_BODY_WRITE;
vcoubard 27:0fe148f1bca3 641 }
vcoubard 27:0fe148f1bca3 642 }
vcoubard 27:0fe148f1bca3 643 else
vcoubard 27:0fe148f1bca3 644 {
vcoubard 27:0fe148f1bca3 645 m_swap_state = STATE_TAIL_RESTORE;
vcoubard 27:0fe148f1bca3 646 }
vcoubard 27:0fe148f1bca3 647 }
vcoubard 27:0fe148f1bca3 648 else
vcoubard 27:0fe148f1bca3 649 {
vcoubard 27:0fe148f1bca3 650 m_swap_state = STATE_HEAD_RESTORE;
vcoubard 27:0fe148f1bca3 651 }
vcoubard 27:0fe148f1bca3 652 }
vcoubard 22:67a8d2c0bbbf 653 break;
vcoubard 24:2aea0c1c57ee 654
vcoubard 27:0fe148f1bca3 655 case STATE_HEAD_RESTORE:
vcoubard 27:0fe148f1bca3 656 // Restore head from swap to application data page.
vcoubard 27:0fe148f1bca3 657 retval = sd_flash_write((uint32_t *)(page_number * PSTORAGE_FLASH_PAGE_SIZE),
vcoubard 27:0fe148f1bca3 658 (uint32_t *)PSTORAGE_SWAP_ADDR,
vcoubard 27:0fe148f1bca3 659 head_word_size);
vcoubard 27:0fe148f1bca3 660 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 661 {
vcoubard 27:0fe148f1bca3 662 if (tail_word_size == 0)
vcoubard 27:0fe148f1bca3 663 {
vcoubard 27:0fe148f1bca3 664 if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
vcoubard 27:0fe148f1bca3 665 {
vcoubard 27:0fe148f1bca3 666 m_swap_state = STATE_SWAP_ERASE;
vcoubard 27:0fe148f1bca3 667 }
vcoubard 27:0fe148f1bca3 668 else
vcoubard 27:0fe148f1bca3 669 {
vcoubard 27:0fe148f1bca3 670 m_swap_state = STATE_NEW_BODY_WRITE;
vcoubard 27:0fe148f1bca3 671 }
vcoubard 27:0fe148f1bca3 672 }
vcoubard 27:0fe148f1bca3 673 else
vcoubard 27:0fe148f1bca3 674 {
vcoubard 27:0fe148f1bca3 675 m_swap_state = STATE_TAIL_RESTORE;
vcoubard 27:0fe148f1bca3 676 }
vcoubard 27:0fe148f1bca3 677 }
vcoubard 27:0fe148f1bca3 678 break;
vcoubard 19:47192cb9def7 679
vcoubard 27:0fe148f1bca3 680 case STATE_TAIL_RESTORE:
vcoubard 27:0fe148f1bca3 681 // Restore tail from swap to application data page.
vcoubard 27:0fe148f1bca3 682 retval = sd_flash_write((uint32_t *)((page_number * PSTORAGE_FLASH_PAGE_SIZE) +
vcoubard 27:0fe148f1bca3 683 (head_word_size * sizeof(uint32_t)) +
vcoubard 27:0fe148f1bca3 684 p_cmd->size),
vcoubard 27:0fe148f1bca3 685 (uint32_t *)(PSTORAGE_SWAP_ADDR +
vcoubard 27:0fe148f1bca3 686 (head_word_size * sizeof(uint32_t)) +
vcoubard 27:0fe148f1bca3 687 p_cmd->size),
vcoubard 27:0fe148f1bca3 688 tail_word_size);
vcoubard 27:0fe148f1bca3 689 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 690 {
vcoubard 27:0fe148f1bca3 691 if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
vcoubard 27:0fe148f1bca3 692 {
vcoubard 27:0fe148f1bca3 693 m_swap_state = STATE_SWAP_ERASE;
vcoubard 27:0fe148f1bca3 694 }
vcoubard 27:0fe148f1bca3 695 else
vcoubard 27:0fe148f1bca3 696 {
vcoubard 27:0fe148f1bca3 697 m_swap_state = STATE_NEW_BODY_WRITE;
vcoubard 27:0fe148f1bca3 698 }
vcoubard 27:0fe148f1bca3 699 }
vcoubard 27:0fe148f1bca3 700 break;
vcoubard 27:0fe148f1bca3 701
vcoubard 27:0fe148f1bca3 702 case STATE_NEW_BODY_WRITE:
vcoubard 27:0fe148f1bca3 703 // Write new data (body) to application data page.
vcoubard 27:0fe148f1bca3 704 retval = sd_flash_write((uint32_t *)((page_number * PSTORAGE_FLASH_PAGE_SIZE) +
vcoubard 27:0fe148f1bca3 705 (head_word_size * sizeof(uint32_t))),
vcoubard 27:0fe148f1bca3 706 (uint32_t *)p_cmd->p_data_addr,
vcoubard 27:0fe148f1bca3 707 p_cmd->size / sizeof(uint32_t));
vcoubard 27:0fe148f1bca3 708 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 709 {
vcoubard 27:0fe148f1bca3 710 if ((head_word_size == 0) && (tail_word_size == 0))
vcoubard 27:0fe148f1bca3 711 {
vcoubard 27:0fe148f1bca3 712 m_swap_state = STATE_COMPLETE;
vcoubard 27:0fe148f1bca3 713 }
vcoubard 27:0fe148f1bca3 714 else
vcoubard 27:0fe148f1bca3 715 {
vcoubard 27:0fe148f1bca3 716 m_swap_state = STATE_SWAP_ERASE;
vcoubard 27:0fe148f1bca3 717 }
vcoubard 27:0fe148f1bca3 718 }
vcoubard 27:0fe148f1bca3 719 break;
vcoubard 27:0fe148f1bca3 720
vcoubard 27:0fe148f1bca3 721 case STATE_SWAP_ERASE:
vcoubard 27:0fe148f1bca3 722 // Clear the swap page for subsequent use.
vcoubard 27:0fe148f1bca3 723 retval = sd_flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 27:0fe148f1bca3 724 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 725 {
vcoubard 27:0fe148f1bca3 726 m_swap_state = STATE_COMPLETE;
vcoubard 27:0fe148f1bca3 727 }
vcoubard 27:0fe148f1bca3 728 break;
vcoubard 27:0fe148f1bca3 729
vcoubard 27:0fe148f1bca3 730 default:
vcoubard 27:0fe148f1bca3 731 break;
vcoubard 24:2aea0c1c57ee 732 }
vcoubard 27:0fe148f1bca3 733
vcoubard 27:0fe148f1bca3 734 return retval;
vcoubard 24:2aea0c1c57ee 735 }
Vincent Coubard 0:f2542974c862 736
vcoubard 24:2aea0c1c57ee 737
vcoubard 27:0fe148f1bca3 738 /**
vcoubard 27:0fe148f1bca3 739 * @brief Routine called to actually issue the flash access request to the SoftDevice.
vcoubard 24:2aea0c1c57ee 740 *
vcoubard 27:0fe148f1bca3 741 * @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
vcoubard 24:2aea0c1c57ee 742 */
vcoubard 27:0fe148f1bca3 743 static uint32_t cmd_process(void)
vcoubard 27:0fe148f1bca3 744 {
vcoubard 27:0fe148f1bca3 745 uint32_t retval;
vcoubard 27:0fe148f1bca3 746 uint32_t storage_addr;
vcoubard 27:0fe148f1bca3 747 cmd_queue_element_t * p_cmd;
vcoubard 24:2aea0c1c57ee 748
vcoubard 27:0fe148f1bca3 749 retval = NRF_ERROR_FORBIDDEN;
vcoubard 24:2aea0c1c57ee 750
vcoubard 27:0fe148f1bca3 751 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
vcoubard 24:2aea0c1c57ee 752
vcoubard 27:0fe148f1bca3 753 storage_addr = p_cmd->storage_addr.block_id;
Vincent Coubard 0:f2542974c862 754
Vincent Coubard 0:f2542974c862 755 switch (p_cmd->op_code)
Vincent Coubard 0:f2542974c862 756 {
vcoubard 27:0fe148f1bca3 757 case PSTORAGE_STORE_OP_CODE:
vcoubard 27:0fe148f1bca3 758 {
vcoubard 27:0fe148f1bca3 759 uint32_t size;
vcoubard 27:0fe148f1bca3 760 uint32_t offset;
vcoubard 27:0fe148f1bca3 761 uint8_t * p_data_addr = p_cmd->p_data_addr;
vcoubard 27:0fe148f1bca3 762
vcoubard 27:0fe148f1bca3 763 offset = (m_round_val * SOC_MAX_WRITE_SIZE);
vcoubard 27:0fe148f1bca3 764 size = p_cmd->size - offset;
vcoubard 27:0fe148f1bca3 765 p_data_addr += offset;
vcoubard 27:0fe148f1bca3 766 storage_addr += (p_cmd->offset + offset);
vcoubard 27:0fe148f1bca3 767
vcoubard 27:0fe148f1bca3 768 if (size < SOC_MAX_WRITE_SIZE)
vcoubard 27:0fe148f1bca3 769 {
vcoubard 27:0fe148f1bca3 770 retval = sd_flash_write(((uint32_t *)storage_addr),
vcoubard 27:0fe148f1bca3 771 (uint32_t *)p_data_addr,
vcoubard 27:0fe148f1bca3 772 size / sizeof(uint32_t));
vcoubard 27:0fe148f1bca3 773 }
vcoubard 27:0fe148f1bca3 774 else
vcoubard 27:0fe148f1bca3 775 {
vcoubard 27:0fe148f1bca3 776 retval = sd_flash_write(((uint32_t *)storage_addr),
vcoubard 27:0fe148f1bca3 777 (uint32_t *)p_data_addr,
vcoubard 27:0fe148f1bca3 778 SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
vcoubard 27:0fe148f1bca3 779 }
vcoubard 27:0fe148f1bca3 780 }
vcoubard 27:0fe148f1bca3 781 break;
Vincent Coubard 0:f2542974c862 782
Vincent Coubard 0:f2542974c862 783 case PSTORAGE_CLEAR_OP_CODE:
vcoubard 27:0fe148f1bca3 784 {
vcoubard 27:0fe148f1bca3 785 // Calculate page number before clearing.
vcoubard 27:0fe148f1bca3 786 uint32_t page_number;
vcoubard 27:0fe148f1bca3 787
vcoubard 27:0fe148f1bca3 788 pstorage_size_t block_size =
vcoubard 27:0fe148f1bca3 789 m_app_table[p_cmd->storage_addr.module_id].block_size;
vcoubard 27:0fe148f1bca3 790
vcoubard 27:0fe148f1bca3 791 pstorage_size_t block_count =
vcoubard 27:0fe148f1bca3 792 m_app_table[p_cmd->storage_addr.module_id].block_count;
vcoubard 27:0fe148f1bca3 793
vcoubard 27:0fe148f1bca3 794 pstorage_block_t base_address =
vcoubard 27:0fe148f1bca3 795 m_app_table[p_cmd->storage_addr.module_id].base_id;
vcoubard 27:0fe148f1bca3 796
vcoubard 27:0fe148f1bca3 797 // If the whole module should be cleared.
vcoubard 27:0fe148f1bca3 798 if (((base_address == storage_addr) && (block_size * block_count == p_cmd->size)) ||
vcoubard 27:0fe148f1bca3 799 (p_cmd->storage_addr.module_id == RAW_MODE_APP_ID))
vcoubard 27:0fe148f1bca3 800 {
vcoubard 27:0fe148f1bca3 801 page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) + m_round_val);
vcoubard 27:0fe148f1bca3 802
vcoubard 27:0fe148f1bca3 803 retval = sd_flash_page_erase(page_number);
vcoubard 27:0fe148f1bca3 804 }
vcoubard 27:0fe148f1bca3 805 // If one block is to be erased.
vcoubard 27:0fe148f1bca3 806 else
vcoubard 27:0fe148f1bca3 807 {
vcoubard 27:0fe148f1bca3 808 page_number = (storage_addr / PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 27:0fe148f1bca3 809
vcoubard 27:0fe148f1bca3 810 uint32_t head_word_size = (
vcoubard 27:0fe148f1bca3 811 storage_addr -
vcoubard 27:0fe148f1bca3 812 (page_number * PSTORAGE_FLASH_PAGE_SIZE)
vcoubard 27:0fe148f1bca3 813 ) / sizeof(uint32_t);
vcoubard 27:0fe148f1bca3 814
vcoubard 27:0fe148f1bca3 815 uint32_t tail_word_size = (
vcoubard 27:0fe148f1bca3 816 ((page_number + 1) * PSTORAGE_FLASH_PAGE_SIZE) -
vcoubard 27:0fe148f1bca3 817 (storage_addr + p_cmd->size)
vcoubard 27:0fe148f1bca3 818 ) / sizeof(uint32_t);
vcoubard 27:0fe148f1bca3 819
vcoubard 27:0fe148f1bca3 820 retval = swap_state_process(p_cmd,
vcoubard 27:0fe148f1bca3 821 page_number,
vcoubard 27:0fe148f1bca3 822 head_word_size,
vcoubard 27:0fe148f1bca3 823 tail_word_size);
vcoubard 27:0fe148f1bca3 824 }
vcoubard 27:0fe148f1bca3 825 }
vcoubard 27:0fe148f1bca3 826 break;
Vincent Coubard 0:f2542974c862 827
Vincent Coubard 0:f2542974c862 828 case PSTORAGE_UPDATE_OP_CODE:
vcoubard 27:0fe148f1bca3 829 {
vcoubard 27:0fe148f1bca3 830 uint32_t page_number = (storage_addr / PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 27:0fe148f1bca3 831
vcoubard 27:0fe148f1bca3 832 uint32_t head_word_size = (
vcoubard 27:0fe148f1bca3 833 storage_addr + p_cmd->offset -
vcoubard 27:0fe148f1bca3 834 (page_number * PSTORAGE_FLASH_PAGE_SIZE)
vcoubard 27:0fe148f1bca3 835 ) / sizeof(uint32_t);
vcoubard 27:0fe148f1bca3 836
vcoubard 27:0fe148f1bca3 837 uint32_t tail_word_size = (
vcoubard 27:0fe148f1bca3 838 ((page_number + 1) * PSTORAGE_FLASH_PAGE_SIZE) -
vcoubard 27:0fe148f1bca3 839 (storage_addr + p_cmd->offset + p_cmd->size)
vcoubard 27:0fe148f1bca3 840 ) / sizeof(uint32_t);
vcoubard 27:0fe148f1bca3 841
vcoubard 27:0fe148f1bca3 842 retval = swap_state_process(p_cmd, page_number, head_word_size, tail_word_size);
vcoubard 27:0fe148f1bca3 843 }
vcoubard 27:0fe148f1bca3 844 break;
Vincent Coubard 0:f2542974c862 845
Vincent Coubard 0:f2542974c862 846 default:
vcoubard 27:0fe148f1bca3 847 // Should never reach here.
Vincent Coubard 0:f2542974c862 848 break;
Vincent Coubard 0:f2542974c862 849 }
vcoubard 27:0fe148f1bca3 850
vcoubard 27:0fe148f1bca3 851 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 852 {
vcoubard 27:0fe148f1bca3 853 m_cmd_queue.flash_access = true;
vcoubard 27:0fe148f1bca3 854 }
vcoubard 27:0fe148f1bca3 855
vcoubard 27:0fe148f1bca3 856 return retval;
Vincent Coubard 0:f2542974c862 857 }
vcoubard 27:0fe148f1bca3 858 /** @} */
Vincent Coubard 0:f2542974c862 859
Vincent Coubard 0:f2542974c862 860
Vincent Coubard 0:f2542974c862 861 uint32_t pstorage_init(void)
Vincent Coubard 0:f2542974c862 862 {
vcoubard 27:0fe148f1bca3 863 uint32_t retval;
vcoubard 27:0fe148f1bca3 864
Vincent Coubard 0:f2542974c862 865 cmd_queue_init();
Vincent Coubard 0:f2542974c862 866
Vincent Coubard 0:f2542974c862 867 m_next_app_instance = 0;
Vincent Coubard 0:f2542974c862 868 m_next_page_addr = PSTORAGE_DATA_START_ADDR;
vcoubard 27:0fe148f1bca3 869 m_round_val = 0;
vcoubard 27:0fe148f1bca3 870
vcoubard 27:0fe148f1bca3 871 for (uint32_t index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++)
Vincent Coubard 0:f2542974c862 872 {
Vincent Coubard 0:f2542974c862 873 m_app_table[index].cb = NULL;
Vincent Coubard 0:f2542974c862 874 m_app_table[index].block_size = 0;
vcoubard 27:0fe148f1bca3 875 m_app_table[index].num_of_pages = 0;
Vincent Coubard 0:f2542974c862 876 m_app_table[index].block_count = 0;
Vincent Coubard 0:f2542974c862 877 }
Vincent Coubard 0:f2542974c862 878
Vincent Coubard 0:f2542974c862 879 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 880 m_raw_app_table.cb = NULL;
vcoubard 27:0fe148f1bca3 881 m_raw_app_table.num_of_pages = 0;
vcoubard 27:0fe148f1bca3 882 m_module_initialized = true;
vcoubard 27:0fe148f1bca3 883 m_swap_state = STATE_INIT;
vcoubard 27:0fe148f1bca3 884
vcoubard 27:0fe148f1bca3 885 retval = NRF_SUCCESS;
vcoubard 27:0fe148f1bca3 886 #else
vcoubard 27:0fe148f1bca3 887 m_swap_state = STATE_SWAP_DIRTY;
vcoubard 27:0fe148f1bca3 888
vcoubard 27:0fe148f1bca3 889 // Erase swap region in case it is dirty.
vcoubard 27:0fe148f1bca3 890 retval = sd_flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE);
vcoubard 27:0fe148f1bca3 891 if (retval == NRF_SUCCESS)
vcoubard 27:0fe148f1bca3 892 {
vcoubard 27:0fe148f1bca3 893 m_cmd_queue.flash_access = true;
vcoubard 27:0fe148f1bca3 894 m_module_initialized = true;
vcoubard 27:0fe148f1bca3 895 }
Vincent Coubard 0:f2542974c862 896 #endif //PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 897
vcoubard 27:0fe148f1bca3 898 return retval;
Vincent Coubard 0:f2542974c862 899 }
Vincent Coubard 0:f2542974c862 900
Vincent Coubard 0:f2542974c862 901
Vincent Coubard 0:f2542974c862 902 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 0:f2542974c862 903 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 904 {
vcoubard 27:0fe148f1bca3 905 uint16_t page_count;
vcoubard 27:0fe148f1bca3 906 uint32_t total_size;
vcoubard 27:0fe148f1bca3 907
Vincent Coubard 0:f2542974c862 908 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 909 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 0:f2542974c862 910 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 911 NULL_PARAM_CHECK(p_module_param->cb);
vcoubard 1:ebc0e0ef0a11 912 BLOCK_SIZE_CHECK(p_module_param->block_size);
Vincent Coubard 0:f2542974c862 913 BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
Vincent Coubard 0:f2542974c862 914
vcoubard 27:0fe148f1bca3 915 // Block size should be a multiple of word size.
Vincent Coubard 0:f2542974c862 916 if (!((p_module_param->block_size % sizeof(uint32_t)) == 0))
Vincent Coubard 0:f2542974c862 917 {
Vincent Coubard 0:f2542974c862 918 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 0:f2542974c862 919 }
vcoubard 27:0fe148f1bca3 920
vcoubard 27:0fe148f1bca3 921 if (m_next_app_instance == PSTORAGE_MAX_APPLICATIONS)
Vincent Coubard 0:f2542974c862 922 {
Vincent Coubard 0:f2542974c862 923 return NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 924 }
Vincent Coubard 0:f2542974c862 925
Vincent Coubard 0:f2542974c862 926 p_block_id->module_id = m_next_app_instance;
Vincent Coubard 0:f2542974c862 927 p_block_id->block_id = m_next_page_addr;
Vincent Coubard 0:f2542974c862 928
Vincent Coubard 0:f2542974c862 929 m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
Vincent Coubard 0:f2542974c862 930 m_app_table[m_next_app_instance].cb = p_module_param->cb;
Vincent Coubard 0:f2542974c862 931 m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
Vincent Coubard 0:f2542974c862 932 m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
Vincent Coubard 0:f2542974c862 933
vcoubard 27:0fe148f1bca3 934 // Calculate number of flash pages allocated for the device.
vcoubard 27:0fe148f1bca3 935 page_count = 0;
vcoubard 27:0fe148f1bca3 936 total_size = p_module_param->block_size * p_module_param->block_count;
vcoubard 27:0fe148f1bca3 937 do
vcoubard 27:0fe148f1bca3 938 {
vcoubard 27:0fe148f1bca3 939 page_count++;
vcoubard 27:0fe148f1bca3 940 if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
vcoubard 27:0fe148f1bca3 941 {
vcoubard 27:0fe148f1bca3 942 total_size -= PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 27:0fe148f1bca3 943 }
vcoubard 27:0fe148f1bca3 944 else
vcoubard 27:0fe148f1bca3 945 {
vcoubard 27:0fe148f1bca3 946 total_size = 0;
vcoubard 27:0fe148f1bca3 947 }
vcoubard 27:0fe148f1bca3 948 m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
vcoubard 27:0fe148f1bca3 949 }
vcoubard 27:0fe148f1bca3 950 while (total_size > 0);
vcoubard 27:0fe148f1bca3 951
vcoubard 27:0fe148f1bca3 952 m_app_table[m_next_app_instance].num_of_pages = page_count;
vcoubard 27:0fe148f1bca3 953 m_next_app_instance++;
Vincent Coubard 0:f2542974c862 954
Vincent Coubard 0:f2542974c862 955 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 956 }
Vincent Coubard 0:f2542974c862 957
Vincent Coubard 0:f2542974c862 958
Vincent Coubard 0:f2542974c862 959 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
Vincent Coubard 0:f2542974c862 960 pstorage_size_t block_num,
Vincent Coubard 0:f2542974c862 961 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 962 {
Vincent Coubard 0:f2542974c862 963 pstorage_handle_t temp_id;
Vincent Coubard 0:f2542974c862 964
Vincent Coubard 0:f2542974c862 965 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 966 NULL_PARAM_CHECK(p_base_id);
Vincent Coubard 0:f2542974c862 967 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 968 MODULE_ID_RANGE_CHECK(p_base_id);
Vincent Coubard 0:f2542974c862 969
Vincent Coubard 0:f2542974c862 970 temp_id = (*p_base_id);
Vincent Coubard 0:f2542974c862 971 temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
Vincent Coubard 0:f2542974c862 972
Vincent Coubard 0:f2542974c862 973 BLOCK_ID_RANGE_CHECK(&temp_id);
Vincent Coubard 0:f2542974c862 974
Vincent Coubard 0:f2542974c862 975 (*p_block_id) = temp_id;
Vincent Coubard 0:f2542974c862 976
Vincent Coubard 0:f2542974c862 977 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 978 }
Vincent Coubard 0:f2542974c862 979
Vincent Coubard 0:f2542974c862 980
Vincent Coubard 0:f2542974c862 981 uint32_t pstorage_store(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 982 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 983 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 984 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 985 {
Vincent Coubard 0:f2542974c862 986 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 987 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 988 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 989 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 990 BLOCK_ID_RANGE_CHECK(p_dest);
vcoubard 27:0fe148f1bca3 991 SIZE_CHECK(p_dest, size);
vcoubard 27:0fe148f1bca3 992 OFFSET_CHECK(p_dest, offset,size);
vcoubard 27:0fe148f1bca3 993
vcoubard 27:0fe148f1bca3 994 // Verify word alignment.
vcoubard 27:0fe148f1bca3 995 if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset)))
vcoubard 27:0fe148f1bca3 996 {
vcoubard 27:0fe148f1bca3 997 return NRF_ERROR_INVALID_ADDR;
vcoubard 27:0fe148f1bca3 998 }
vcoubard 27:0fe148f1bca3 999
vcoubard 27:0fe148f1bca3 1000 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1001 {
Vincent Coubard 0:f2542974c862 1002 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1003 }
Vincent Coubard 0:f2542974c862 1004
Vincent Coubard 0:f2542974c862 1005 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1006 }
Vincent Coubard 0:f2542974c862 1007
Vincent Coubard 0:f2542974c862 1008
Vincent Coubard 0:f2542974c862 1009 uint32_t pstorage_update(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 1010 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 1011 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1012 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1013 {
Vincent Coubard 0:f2542974c862 1014 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1015 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1016 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1017 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1018 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1019 SIZE_CHECK(p_dest, size);
Vincent Coubard 0:f2542974c862 1020 OFFSET_CHECK(p_dest, offset, size);
Vincent Coubard 0:f2542974c862 1021
vcoubard 27:0fe148f1bca3 1022 // Verify word alignment.
vcoubard 27:0fe148f1bca3 1023 if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset)))
vcoubard 27:0fe148f1bca3 1024 {
vcoubard 27:0fe148f1bca3 1025 return NRF_ERROR_INVALID_ADDR;
vcoubard 27:0fe148f1bca3 1026 }
vcoubard 27:0fe148f1bca3 1027
vcoubard 27:0fe148f1bca3 1028 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1029 {
Vincent Coubard 0:f2542974c862 1030 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1031 }
Vincent Coubard 0:f2542974c862 1032
Vincent Coubard 0:f2542974c862 1033 return cmd_queue_enqueue(PSTORAGE_UPDATE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1034 }
Vincent Coubard 0:f2542974c862 1035
Vincent Coubard 0:f2542974c862 1036
Vincent Coubard 0:f2542974c862 1037 uint32_t pstorage_load(uint8_t * p_dest,
Vincent Coubard 0:f2542974c862 1038 pstorage_handle_t * p_src,
Vincent Coubard 0:f2542974c862 1039 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1040 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1041 {
Vincent Coubard 0:f2542974c862 1042 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1043 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1044 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1045 MODULE_ID_RANGE_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1046 BLOCK_ID_RANGE_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1047 SIZE_CHECK(p_src, size);
Vincent Coubard 0:f2542974c862 1048 OFFSET_CHECK(p_src, offset, size);
Vincent Coubard 0:f2542974c862 1049
vcoubard 27:0fe148f1bca3 1050 // Verify word alignment.
vcoubard 27:0fe148f1bca3 1051 if ((!is_word_aligned(p_dest)) || (!is_word_aligned((void *)(uint32_t)offset)))
vcoubard 27:0fe148f1bca3 1052 {
vcoubard 27:0fe148f1bca3 1053 return NRF_ERROR_INVALID_ADDR;
vcoubard 27:0fe148f1bca3 1054 }
vcoubard 27:0fe148f1bca3 1055
vcoubard 27:0fe148f1bca3 1056 if ((!is_word_aligned((uint32_t *)p_src->block_id)))
Vincent Coubard 0:f2542974c862 1057 {
Vincent Coubard 0:f2542974c862 1058 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1059 }
Vincent Coubard 0:f2542974c862 1060
Vincent Coubard 0:f2542974c862 1061 memcpy(p_dest, (((uint8_t *)p_src->block_id) + offset), size);
Vincent Coubard 0:f2542974c862 1062
Vincent Coubard 0:f2542974c862 1063 m_app_table[p_src->module_id].cb(p_src, PSTORAGE_LOAD_OP_CODE, NRF_SUCCESS, p_dest, size);
Vincent Coubard 0:f2542974c862 1064
Vincent Coubard 0:f2542974c862 1065 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1066 }
Vincent Coubard 0:f2542974c862 1067
Vincent Coubard 0:f2542974c862 1068
Vincent Coubard 0:f2542974c862 1069 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 0:f2542974c862 1070 {
vcoubard 27:0fe148f1bca3 1071 uint32_t retval;
vcoubard 27:0fe148f1bca3 1072
Vincent Coubard 0:f2542974c862 1073 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1074 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1075 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1076 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1077
Vincent Coubard 0:f2542974c862 1078 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 0:f2542974c862 1079 {
Vincent Coubard 0:f2542974c862 1080 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1081 }
Vincent Coubard 0:f2542974c862 1082
Vincent Coubard 0:f2542974c862 1083 if (
Vincent Coubard 0:f2542974c862 1084 !(
Vincent Coubard 0:f2542974c862 1085 ((p_dest->block_id - m_app_table[p_dest->module_id].base_id) %
Vincent Coubard 0:f2542974c862 1086 m_app_table[p_dest->module_id].block_size) == 0
Vincent Coubard 0:f2542974c862 1087 )
Vincent Coubard 0:f2542974c862 1088 )
Vincent Coubard 0:f2542974c862 1089 {
Vincent Coubard 0:f2542974c862 1090 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 0:f2542974c862 1091 }
Vincent Coubard 0:f2542974c862 1092
vcoubard 27:0fe148f1bca3 1093 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
Vincent Coubard 0:f2542974c862 1094
vcoubard 27:0fe148f1bca3 1095 return retval;
Vincent Coubard 0:f2542974c862 1096 }
Vincent Coubard 0:f2542974c862 1097
Vincent Coubard 0:f2542974c862 1098
Vincent Coubard 0:f2542974c862 1099 uint32_t pstorage_access_status_get(uint32_t * p_count)
Vincent Coubard 0:f2542974c862 1100 {
Vincent Coubard 0:f2542974c862 1101 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1102 NULL_PARAM_CHECK(p_count);
Vincent Coubard 0:f2542974c862 1103
Vincent Coubard 0:f2542974c862 1104 (*p_count) = m_cmd_queue.count;
Vincent Coubard 0:f2542974c862 1105
Vincent Coubard 0:f2542974c862 1106 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1107 }
Vincent Coubard 0:f2542974c862 1108
Vincent Coubard 0:f2542974c862 1109 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 0:f2542974c862 1110
vcoubard 27:0fe148f1bca3 1111
Vincent Coubard 0:f2542974c862 1112 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 0:f2542974c862 1113 pstorage_handle_t * p_block_id)
Vincent Coubard 0:f2542974c862 1114 {
Vincent Coubard 0:f2542974c862 1115 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1116 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 0:f2542974c862 1117 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 0:f2542974c862 1118 NULL_PARAM_CHECK(p_module_param->cb);
Vincent Coubard 0:f2542974c862 1119
Vincent Coubard 0:f2542974c862 1120 if (m_raw_app_table.cb != NULL)
Vincent Coubard 0:f2542974c862 1121 {
Vincent Coubard 0:f2542974c862 1122 return NRF_ERROR_NO_MEM;
Vincent Coubard 0:f2542974c862 1123 }
Vincent Coubard 0:f2542974c862 1124
Vincent Coubard 0:f2542974c862 1125 p_block_id->module_id = RAW_MODE_APP_ID;
Vincent Coubard 0:f2542974c862 1126 m_raw_app_table.cb = p_module_param->cb;
Vincent Coubard 0:f2542974c862 1127
Vincent Coubard 0:f2542974c862 1128 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 1129 }
Vincent Coubard 0:f2542974c862 1130
Vincent Coubard 0:f2542974c862 1131
Vincent Coubard 0:f2542974c862 1132 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
Vincent Coubard 0:f2542974c862 1133 uint8_t * p_src,
Vincent Coubard 0:f2542974c862 1134 pstorage_size_t size,
Vincent Coubard 0:f2542974c862 1135 pstorage_size_t offset)
Vincent Coubard 0:f2542974c862 1136 {
Vincent Coubard 0:f2542974c862 1137 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1138 NULL_PARAM_CHECK(p_src);
Vincent Coubard 0:f2542974c862 1139 NULL_PARAM_CHECK(p_dest);
vcoubard 27:0fe148f1bca3 1140 MODULE_RAW_ID_RANGE_CHECK(p_dest);
vcoubard 27:0fe148f1bca3 1141
Vincent Coubard 0:f2542974c862 1142 // Verify word alignment.
vcoubard 27:0fe148f1bca3 1143 if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset)))
Vincent Coubard 0:f2542974c862 1144 {
Vincent Coubard 0:f2542974c862 1145 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 0:f2542974c862 1146 }
vcoubard 27:0fe148f1bca3 1147
Vincent Coubard 0:f2542974c862 1148 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 0:f2542974c862 1149 }
Vincent Coubard 0:f2542974c862 1150
Vincent Coubard 0:f2542974c862 1151
Vincent Coubard 0:f2542974c862 1152 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 0:f2542974c862 1153 {
vcoubard 27:0fe148f1bca3 1154 uint32_t retval;
vcoubard 27:0fe148f1bca3 1155
Vincent Coubard 0:f2542974c862 1156 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 0:f2542974c862 1157 NULL_PARAM_CHECK(p_dest);
vcoubard 27:0fe148f1bca3 1158 MODULE_RAW_ID_RANGE_CHECK(p_dest);
Vincent Coubard 0:f2542974c862 1159
vcoubard 27:0fe148f1bca3 1160 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
vcoubard 27:0fe148f1bca3 1161
vcoubard 27:0fe148f1bca3 1162 return retval;
Vincent Coubard 0:f2542974c862 1163 }
Vincent Coubard 0:f2542974c862 1164
vcoubard 1:ebc0e0ef0a11 1165 #endif // PSTORAGE_RAW_MODE_ENABLE