modified locally to use with HRM1017

Dependents:   BLE_HTM_HRM1017

Fork of nRF51822 by Nordic Semiconductor

Committer:
nobukuma
Date:
Thu Dec 04 12:50:37 2014 +0000
Revision:
69:b4a3693da52b
Parent:
65:98215c4f3a25
modified locally to use with HRM1017

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