Old version

Dependents:   VNG_BLE_Basic

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Wed Jan 21 10:01:17 2015 +0000
Revision:
93:0e7a9efee6d7
Parent:
65:98215c4f3a25
Synchronized with git rev e4fab54b
Author: Rohit Grover
include the pstorage module in the nRF port.

Who changed what in which revision?

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