テスト用です。

Dependencies:   mbed

Committer:
jksoft
Date:
Tue Oct 11 11:09:42 2016 +0000
Revision:
0:8468a4403fea
SB??ver;

Who changed what in which revision?

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