project for nrf51822 qfab

Dependencies:   eddystone_URL mbed

Fork of eddystone_URL by vo dung

Committer:
jksoft
Date:
Wed Nov 12 02:40:34 2014 +0000
Revision:
0:76dfa9657d9d
????????

Who changed what in which revision?

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