Nordic stack and drivers for the mbed BLE API

Fork of nRF51822 by Nordic Semiconductor

Committer:
bogdanm
Date:
Wed Mar 26 14:38:17 2014 +0000
Revision:
0:eff01767de02
Child:
33:8efbbf54b66f
Initial import of the nRF51822 code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:eff01767de02 1 /* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
bogdanm 0:eff01767de02 2 *
bogdanm 0:eff01767de02 3 * The information contained herein is property of Nordic Semiconductor ASA.
bogdanm 0:eff01767de02 4 * Terms and conditions of usage are described in detail in NORDIC
bogdanm 0:eff01767de02 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
bogdanm 0:eff01767de02 6 *
bogdanm 0:eff01767de02 7 * Licensees are granted free, non-transferable use of the information. NO
bogdanm 0:eff01767de02 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
bogdanm 0:eff01767de02 9 * the file.
bogdanm 0:eff01767de02 10 *
bogdanm 0:eff01767de02 11 */
bogdanm 0:eff01767de02 12
bogdanm 0:eff01767de02 13 #include <stdlib.h>
bogdanm 0:eff01767de02 14 #include <stdint.h>
bogdanm 0:eff01767de02 15 #include <string.h>
bogdanm 0:eff01767de02 16 #include "nordic_common.h"
bogdanm 0:eff01767de02 17 #include "nrf_error.h"
bogdanm 0:eff01767de02 18 #include "nrf_assert.h"
bogdanm 0:eff01767de02 19 //#include "nrf.h"
bogdanm 0:eff01767de02 20 #include "nrf_soc.h"
bogdanm 0:eff01767de02 21 #include "app_util.h"
bogdanm 0:eff01767de02 22 #include "pstorage.h"
bogdanm 0:eff01767de02 23
bogdanm 0:eff01767de02 24
bogdanm 0:eff01767de02 25 #define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
bogdanm 0:eff01767de02 26 #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. */
bogdanm 0:eff01767de02 27
bogdanm 0:eff01767de02 28 /**
bogdanm 0:eff01767de02 29 * @defgroup api_param_check API Parameters check macros.
bogdanm 0:eff01767de02 30 *
bogdanm 0:eff01767de02 31 * @details Macros that verify parameters passed to the module in the APIs. These macros
bogdanm 0:eff01767de02 32 * could be mapped to nothing in final versions of code to save execution and size.
bogdanm 0:eff01767de02 33 *
bogdanm 0:eff01767de02 34 * @{
bogdanm 0:eff01767de02 35 */
bogdanm 0:eff01767de02 36 /**
bogdanm 0:eff01767de02 37 * @brief Check if the input pointer is NULL, if it is returns NRF_ERROR_NULL.
bogdanm 0:eff01767de02 38 */
bogdanm 0:eff01767de02 39 #define NULL_PARAM_CHECK(PARAM) \
bogdanm 0:eff01767de02 40 if ((PARAM) == NULL) \
bogdanm 0:eff01767de02 41 { \
bogdanm 0:eff01767de02 42 return NRF_ERROR_NULL; \
bogdanm 0:eff01767de02 43 }
bogdanm 0:eff01767de02 44
bogdanm 0:eff01767de02 45 /**
bogdanm 0:eff01767de02 46 * @brief Verifies the module identifier supplied by the application is within permissible
bogdanm 0:eff01767de02 47 * range.
bogdanm 0:eff01767de02 48 */
bogdanm 0:eff01767de02 49 #define MODULE_ID_RANGE_CHECK(ID) \
bogdanm 0:eff01767de02 50 if ((((ID)->module_id) >= PSTORAGE_MAX_APPLICATIONS) || \
bogdanm 0:eff01767de02 51 (m_app_table[(ID)->module_id].cb == NULL)) \
bogdanm 0:eff01767de02 52 { \
bogdanm 0:eff01767de02 53 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 54 }
bogdanm 0:eff01767de02 55
bogdanm 0:eff01767de02 56 /**
bogdanm 0:eff01767de02 57 * @brief Verifies the block identifier supplied by the application is within the permissible
bogdanm 0:eff01767de02 58 * range.
bogdanm 0:eff01767de02 59 */
bogdanm 0:eff01767de02 60 #define BLOCK_ID_RANGE_CHECK(ID) \
bogdanm 0:eff01767de02 61 if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
bogdanm 0:eff01767de02 62 (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
bogdanm 0:eff01767de02 63 { \
bogdanm 0:eff01767de02 64 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 65 }
bogdanm 0:eff01767de02 66
bogdanm 0:eff01767de02 67
bogdanm 0:eff01767de02 68 /**
bogdanm 0:eff01767de02 69 * @brief Verifies the block size requested by the application can be supported by the module.
bogdanm 0:eff01767de02 70 */
bogdanm 0:eff01767de02 71 #define BLOCK_SIZE_CHECK(X) \
bogdanm 0:eff01767de02 72 if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
bogdanm 0:eff01767de02 73 { \
bogdanm 0:eff01767de02 74 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 75 }
bogdanm 0:eff01767de02 76
bogdanm 0:eff01767de02 77 /**
bogdanm 0:eff01767de02 78 * @brief Verifies block size requested by Application in registration API.
bogdanm 0:eff01767de02 79 */
bogdanm 0:eff01767de02 80 #define BLOCK_COUNT_CHECK(COUNT, SIZE) \
bogdanm 0:eff01767de02 81 if (((COUNT) == 0) || ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_DATA_END_ADDR))) \
bogdanm 0:eff01767de02 82 { \
bogdanm 0:eff01767de02 83 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 84 }
bogdanm 0:eff01767de02 85
bogdanm 0:eff01767de02 86 /**
bogdanm 0:eff01767de02 87 * @brief Verifies size parameter provided by application in API.
bogdanm 0:eff01767de02 88 */
bogdanm 0:eff01767de02 89 #define SIZE_CHECK(ID, SIZE) \
bogdanm 0:eff01767de02 90 if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
bogdanm 0:eff01767de02 91 { \
bogdanm 0:eff01767de02 92 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 93 }
bogdanm 0:eff01767de02 94
bogdanm 0:eff01767de02 95 /**
bogdanm 0:eff01767de02 96 * @brief Verifies offset parameter provided by application in API.
bogdanm 0:eff01767de02 97 */
bogdanm 0:eff01767de02 98 #define OFFSET_CHECK(ID, OFFSET, SIZE) \
bogdanm 0:eff01767de02 99 if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
bogdanm 0:eff01767de02 100 { \
bogdanm 0:eff01767de02 101 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 102 }
bogdanm 0:eff01767de02 103
bogdanm 0:eff01767de02 104 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 105
bogdanm 0:eff01767de02 106 /**
bogdanm 0:eff01767de02 107 * @brief Verifies the module identifier supplied by the application is registered for raw mode.
bogdanm 0:eff01767de02 108 */
bogdanm 0:eff01767de02 109 #define MODULE_RAW_ID_RANGE_CHECK(ID) \
bogdanm 0:eff01767de02 110 if ((PSTORAGE_MAX_APPLICATIONS+1 != ((ID)->module_id)) || \
bogdanm 0:eff01767de02 111 (m_raw_app_table.cb == NULL)) \
bogdanm 0:eff01767de02 112 { \
bogdanm 0:eff01767de02 113 return NRF_ERROR_INVALID_PARAM; \
bogdanm 0:eff01767de02 114 }
bogdanm 0:eff01767de02 115
bogdanm 0:eff01767de02 116 #endif // PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 117
bogdanm 0:eff01767de02 118 /**@} */
bogdanm 0:eff01767de02 119
bogdanm 0:eff01767de02 120 /**@brief Verify module's initialization status.
bogdanm 0:eff01767de02 121 *
bogdanm 0:eff01767de02 122 * @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
bogdanm 0:eff01767de02 123 * module API is called without initializing the module.
bogdanm 0:eff01767de02 124 */
bogdanm 0:eff01767de02 125 #define VERIFY_MODULE_INITIALIZED() \
bogdanm 0:eff01767de02 126 do \
bogdanm 0:eff01767de02 127 { \
bogdanm 0:eff01767de02 128 if (!m_module_initialized) \
bogdanm 0:eff01767de02 129 { \
bogdanm 0:eff01767de02 130 return NRF_ERROR_INVALID_STATE; \
bogdanm 0:eff01767de02 131 } \
bogdanm 0:eff01767de02 132 } while(0)
bogdanm 0:eff01767de02 133
bogdanm 0:eff01767de02 134 /**@brief Macro to fetch the block size registered for the module. */
bogdanm 0:eff01767de02 135 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
bogdanm 0:eff01767de02 136
bogdanm 0:eff01767de02 137 /**@} */
bogdanm 0:eff01767de02 138
bogdanm 0:eff01767de02 139 /**
bogdanm 0:eff01767de02 140 * @brief Application registration information.
bogdanm 0:eff01767de02 141 *
bogdanm 0:eff01767de02 142 * @details Define application specific information that application needs to maintain to be able
bogdanm 0:eff01767de02 143 * to process requests from each one of them.
bogdanm 0:eff01767de02 144 */
bogdanm 0:eff01767de02 145 typedef struct
bogdanm 0:eff01767de02 146 {
bogdanm 0:eff01767de02 147 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
bogdanm 0:eff01767de02 148 pstorage_block_t base_id; /**< Base block id assigned to the module */
bogdanm 0:eff01767de02 149 pstorage_size_t block_size; /**< Size of block for the module */
bogdanm 0:eff01767de02 150 pstorage_size_t block_count; /**< Number of block requested by application */
bogdanm 0:eff01767de02 151 pstorage_size_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
bogdanm 0:eff01767de02 152 } pstorage_module_table_t;
bogdanm 0:eff01767de02 153
bogdanm 0:eff01767de02 154 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 155 /**
bogdanm 0:eff01767de02 156 * @brief Application registration information.
bogdanm 0:eff01767de02 157 *
bogdanm 0:eff01767de02 158 * @details Define application specific information that application registered for raw mode.
bogdanm 0:eff01767de02 159 */
bogdanm 0:eff01767de02 160 typedef struct
bogdanm 0:eff01767de02 161 {
bogdanm 0:eff01767de02 162 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
bogdanm 0:eff01767de02 163 uint16_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
bogdanm 0:eff01767de02 164 } pstorage_raw_module_table_t;
bogdanm 0:eff01767de02 165 #endif // PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 166
bogdanm 0:eff01767de02 167
bogdanm 0:eff01767de02 168
bogdanm 0:eff01767de02 169
bogdanm 0:eff01767de02 170 /**
bogdanm 0:eff01767de02 171 * @brief Defines command queue element.
bogdanm 0:eff01767de02 172 *
bogdanm 0:eff01767de02 173 * @details Defines command queue element. Each element encapsulates needed information to process
bogdanm 0:eff01767de02 174 * a flash access command.
bogdanm 0:eff01767de02 175 */
bogdanm 0:eff01767de02 176 typedef struct
bogdanm 0:eff01767de02 177 {
bogdanm 0:eff01767de02 178 uint8_t op_code; /**< Identifies flash access operation being queued. Element is free is op-code is INVALID_OPCODE */
bogdanm 0:eff01767de02 179 pstorage_size_t size; /**< Identifies size in bytes requested for the operation. */
bogdanm 0:eff01767de02 180 pstorage_size_t offset; /**< Offset requested by the application for access operation. */
bogdanm 0:eff01767de02 181 pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
bogdanm 0:eff01767de02 182 uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
bogdanm 0:eff01767de02 183 } cmd_queue_element_t;
bogdanm 0:eff01767de02 184
bogdanm 0:eff01767de02 185
bogdanm 0:eff01767de02 186 /**
bogdanm 0:eff01767de02 187 * @brief Defines command queue, an element is free is op_code field is not invalid.
bogdanm 0:eff01767de02 188 *
bogdanm 0:eff01767de02 189 * @details Defines commands enqueued for flash access. At any point of time, this queue has one or
bogdanm 0:eff01767de02 190 * more flash access operation pending if the count field is not zero. When the queue is
bogdanm 0:eff01767de02 191 * not empty, the rp (read pointer) field points to the flash access command in progress
bogdanm 0:eff01767de02 192 * or to requested next. The queue implements a simple first in first out algorithm.
bogdanm 0:eff01767de02 193 * Data addresses are assumed to be resident.
bogdanm 0:eff01767de02 194 */
bogdanm 0:eff01767de02 195 typedef struct
bogdanm 0:eff01767de02 196 {
bogdanm 0:eff01767de02 197 uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
bogdanm 0:eff01767de02 198 uint8_t count; /**< Number of elements in the queue. */
bogdanm 0:eff01767de02 199 bool flash_access; /**< Flag to ensure an flash event received is for an request issued by the module. */
bogdanm 0:eff01767de02 200 cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details */
bogdanm 0:eff01767de02 201 }cmd_queue_t;
bogdanm 0:eff01767de02 202
bogdanm 0:eff01767de02 203 static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
bogdanm 0:eff01767de02 204 static pstorage_module_table_t m_app_table[PSTORAGE_MAX_APPLICATIONS]; /**< Registered application information table. */
bogdanm 0:eff01767de02 205
bogdanm 0:eff01767de02 206 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 207 static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
bogdanm 0:eff01767de02 208 #endif // PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 209
bogdanm 0:eff01767de02 210 static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next */
bogdanm 0:eff01767de02 211 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. */
bogdanm 0:eff01767de02 212 static bool m_module_initialized = false; /**< Flag for checking if module has been initialized. */
bogdanm 0:eff01767de02 213 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. */
bogdanm 0:eff01767de02 214
bogdanm 0:eff01767de02 215 static uint32_t process_cmd(void);
bogdanm 0:eff01767de02 216 static void app_notify (uint32_t reason);
bogdanm 0:eff01767de02 217
bogdanm 0:eff01767de02 218 /**
bogdanm 0:eff01767de02 219 * @defgroup utility_functions Utility internal functions.
bogdanm 0:eff01767de02 220 * @{
bogdanm 0:eff01767de02 221 * @details Utility functions needed for interfacing with flash through SoC APIs.
bogdanm 0:eff01767de02 222 * SoC APIs are non blocking and provide the result of flash access through an event.
bogdanm 0:eff01767de02 223 *
bogdanm 0:eff01767de02 224 * @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
bogdanm 0:eff01767de02 225 * maintained by this module.
bogdanm 0:eff01767de02 226 */
bogdanm 0:eff01767de02 227
bogdanm 0:eff01767de02 228 /**
bogdanm 0:eff01767de02 229 * @brief Initializes command queue element.
bogdanm 0:eff01767de02 230 */
bogdanm 0:eff01767de02 231 static void cmd_queue_init_element(uint32_t index)
bogdanm 0:eff01767de02 232 {
bogdanm 0:eff01767de02 233 // Internal function and checks on range of index can be avoided
bogdanm 0:eff01767de02 234 m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
bogdanm 0:eff01767de02 235 m_cmd_queue.cmd[index].size = 0;
bogdanm 0:eff01767de02 236 m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_MAX_APPLICATIONS;
bogdanm 0:eff01767de02 237 m_cmd_queue.cmd[index].storage_addr.block_id = 0;
bogdanm 0:eff01767de02 238 m_cmd_queue.cmd[index].p_data_addr = NULL;
bogdanm 0:eff01767de02 239 m_cmd_queue.cmd[index].offset = 0;
bogdanm 0:eff01767de02 240 }
bogdanm 0:eff01767de02 241
bogdanm 0:eff01767de02 242
bogdanm 0:eff01767de02 243 /**
bogdanm 0:eff01767de02 244 * @brief Initializes command queue.
bogdanm 0:eff01767de02 245 */
bogdanm 0:eff01767de02 246 static void cmd_queue_init (void)
bogdanm 0:eff01767de02 247 {
bogdanm 0:eff01767de02 248 uint32_t cmd_index;
bogdanm 0:eff01767de02 249
bogdanm 0:eff01767de02 250 m_round_val = 0;
bogdanm 0:eff01767de02 251 m_cmd_queue.rp = 0;
bogdanm 0:eff01767de02 252 m_cmd_queue.count = 0;
bogdanm 0:eff01767de02 253 m_cmd_queue.flash_access = false;
bogdanm 0:eff01767de02 254
bogdanm 0:eff01767de02 255 for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
bogdanm 0:eff01767de02 256 {
bogdanm 0:eff01767de02 257 cmd_queue_init_element(cmd_index);
bogdanm 0:eff01767de02 258 }
bogdanm 0:eff01767de02 259 }
bogdanm 0:eff01767de02 260
bogdanm 0:eff01767de02 261
bogdanm 0:eff01767de02 262 /**
bogdanm 0:eff01767de02 263 * @brief Routine to enqueue a flash access operation.
bogdanm 0:eff01767de02 264 */
bogdanm 0:eff01767de02 265 static uint32_t cmd_queue_enqueue(uint8_t opcode, pstorage_handle_t * p_storage_addr,uint8_t * p_data_addr, pstorage_size_t size, pstorage_size_t offset)
bogdanm 0:eff01767de02 266 {
bogdanm 0:eff01767de02 267 uint32_t retval;
bogdanm 0:eff01767de02 268 uint8_t write_index = 0;
bogdanm 0:eff01767de02 269 retval = NRF_ERROR_NO_MEM;
bogdanm 0:eff01767de02 270
bogdanm 0:eff01767de02 271 // Check if flash access is ongoing.
bogdanm 0:eff01767de02 272 if ((m_cmd_queue.flash_access == false) && (m_cmd_queue.count == 0))
bogdanm 0:eff01767de02 273 {
bogdanm 0:eff01767de02 274 m_cmd_queue.rp = 0;
bogdanm 0:eff01767de02 275 m_cmd_queue.cmd[m_cmd_queue.rp].op_code = opcode;
bogdanm 0:eff01767de02 276 m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr = p_data_addr;
bogdanm 0:eff01767de02 277 m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr = (*p_storage_addr);
bogdanm 0:eff01767de02 278 m_cmd_queue.cmd[m_cmd_queue.rp].size = size;
bogdanm 0:eff01767de02 279 m_cmd_queue.cmd[m_cmd_queue.rp].offset = offset;
bogdanm 0:eff01767de02 280 m_cmd_queue.count++;
bogdanm 0:eff01767de02 281 retval = process_cmd();
bogdanm 0:eff01767de02 282 if ((retval == NRF_SUCCESS) || (retval == NRF_ERROR_BUSY))
bogdanm 0:eff01767de02 283 {
bogdanm 0:eff01767de02 284 // In case of busy error code, it is possible to attempt to access flash
bogdanm 0:eff01767de02 285 retval = NRF_SUCCESS;
bogdanm 0:eff01767de02 286 }
bogdanm 0:eff01767de02 287 }
bogdanm 0:eff01767de02 288 else if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
bogdanm 0:eff01767de02 289 {
bogdanm 0:eff01767de02 290 // Enqueue the command if it is queue is not full
bogdanm 0:eff01767de02 291 write_index = m_cmd_queue.rp + m_cmd_queue.count;
bogdanm 0:eff01767de02 292
bogdanm 0:eff01767de02 293 if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
bogdanm 0:eff01767de02 294 {
bogdanm 0:eff01767de02 295 write_index -= PSTORAGE_CMD_QUEUE_SIZE;
bogdanm 0:eff01767de02 296 }
bogdanm 0:eff01767de02 297
bogdanm 0:eff01767de02 298 m_cmd_queue.cmd[write_index].op_code = opcode;
bogdanm 0:eff01767de02 299 m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
bogdanm 0:eff01767de02 300 m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
bogdanm 0:eff01767de02 301 m_cmd_queue.cmd[write_index].size = size;
bogdanm 0:eff01767de02 302 m_cmd_queue.cmd[write_index].offset = offset;
bogdanm 0:eff01767de02 303 m_cmd_queue.count++;
bogdanm 0:eff01767de02 304
bogdanm 0:eff01767de02 305 retval = NRF_SUCCESS;
bogdanm 0:eff01767de02 306
bogdanm 0:eff01767de02 307 }
bogdanm 0:eff01767de02 308
bogdanm 0:eff01767de02 309 return retval;
bogdanm 0:eff01767de02 310 }
bogdanm 0:eff01767de02 311
bogdanm 0:eff01767de02 312
bogdanm 0:eff01767de02 313 /**
bogdanm 0:eff01767de02 314 * @brief Dequeues a command element.
bogdanm 0:eff01767de02 315 */
bogdanm 0:eff01767de02 316 static uint32_t cmd_queue_dequeue(void)
bogdanm 0:eff01767de02 317 {
bogdanm 0:eff01767de02 318 uint32_t retval;
bogdanm 0:eff01767de02 319
bogdanm 0:eff01767de02 320 cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
bogdanm 0:eff01767de02 321 // Update count and read pointer to process any queued requests
bogdanm 0:eff01767de02 322 if(m_round_val >= p_cmd->size)
bogdanm 0:eff01767de02 323 {
bogdanm 0:eff01767de02 324 // Initialize/free the element as it is now processed.
bogdanm 0:eff01767de02 325 cmd_queue_init_element(m_cmd_queue.rp);
bogdanm 0:eff01767de02 326 m_round_val = 0;
bogdanm 0:eff01767de02 327 m_cmd_queue.count--;
bogdanm 0:eff01767de02 328 m_cmd_queue.rp++;
bogdanm 0:eff01767de02 329 }
bogdanm 0:eff01767de02 330
bogdanm 0:eff01767de02 331 retval = NRF_SUCCESS;
bogdanm 0:eff01767de02 332
bogdanm 0:eff01767de02 333 // If any flash operation is enqueued, schedule
bogdanm 0:eff01767de02 334 if (m_cmd_queue.count)
bogdanm 0:eff01767de02 335 {
bogdanm 0:eff01767de02 336 retval = process_cmd();
bogdanm 0:eff01767de02 337
bogdanm 0:eff01767de02 338 if (retval != NRF_SUCCESS)
bogdanm 0:eff01767de02 339 {
bogdanm 0:eff01767de02 340 // Flash could be accessed by modules other than Bond Manager, hence a busy error is
bogdanm 0:eff01767de02 341 // acceptable, but any other error needs to be indicated to the bond manager
bogdanm 0:eff01767de02 342 if (retval != NRF_ERROR_BUSY)
bogdanm 0:eff01767de02 343 {
bogdanm 0:eff01767de02 344 app_notify (retval);
bogdanm 0:eff01767de02 345 }
bogdanm 0:eff01767de02 346 else
bogdanm 0:eff01767de02 347 {
bogdanm 0:eff01767de02 348 // In case of busy next trigger will be a success or a failure event
bogdanm 0:eff01767de02 349 }
bogdanm 0:eff01767de02 350 }
bogdanm 0:eff01767de02 351 }
bogdanm 0:eff01767de02 352 else
bogdanm 0:eff01767de02 353 {
bogdanm 0:eff01767de02 354 // No flash access request pending
bogdanm 0:eff01767de02 355 }
bogdanm 0:eff01767de02 356
bogdanm 0:eff01767de02 357 return retval;
bogdanm 0:eff01767de02 358 }
bogdanm 0:eff01767de02 359
bogdanm 0:eff01767de02 360
bogdanm 0:eff01767de02 361 /**
bogdanm 0:eff01767de02 362 * @brief Routine to notify application of any errors.
bogdanm 0:eff01767de02 363 */
bogdanm 0:eff01767de02 364 static void app_notify (uint32_t result)
bogdanm 0:eff01767de02 365 {
bogdanm 0:eff01767de02 366 pstorage_ntf_cb_t ntf_cb;
bogdanm 0:eff01767de02 367 uint8_t op_code = m_cmd_queue.cmd[m_cmd_queue.rp].op_code;
bogdanm 0:eff01767de02 368
bogdanm 0:eff01767de02 369 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 370 if(m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id == (PSTORAGE_MAX_APPLICATIONS + 1))
bogdanm 0:eff01767de02 371 {
bogdanm 0:eff01767de02 372 ntf_cb = m_raw_app_table.cb;
bogdanm 0:eff01767de02 373 }
bogdanm 0:eff01767de02 374 else
bogdanm 0:eff01767de02 375 #endif // PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 376 {
bogdanm 0:eff01767de02 377 ntf_cb = m_app_table[m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id].cb;
bogdanm 0:eff01767de02 378 }
bogdanm 0:eff01767de02 379
bogdanm 0:eff01767de02 380 // Indicate result to client.
bogdanm 0:eff01767de02 381 // For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally
bogdanm 0:eff01767de02 382 // for clients registering multiple pages.
bogdanm 0:eff01767de02 383 ntf_cb(&m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr,
bogdanm 0:eff01767de02 384 op_code,
bogdanm 0:eff01767de02 385 result,
bogdanm 0:eff01767de02 386 m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr,
bogdanm 0:eff01767de02 387 op_code == PSTORAGE_CLEAR_OP_CODE ? 0 : m_cmd_queue.cmd[m_cmd_queue.rp].size);
bogdanm 0:eff01767de02 388 }
bogdanm 0:eff01767de02 389
bogdanm 0:eff01767de02 390
bogdanm 0:eff01767de02 391 /**
bogdanm 0:eff01767de02 392 * @brief Handles Flash Access Result Events.
bogdanm 0:eff01767de02 393 */
bogdanm 0:eff01767de02 394 void pstorage_sys_event_handler (uint32_t sys_evt)
bogdanm 0:eff01767de02 395 {
bogdanm 0:eff01767de02 396 uint32_t retval;
bogdanm 0:eff01767de02 397
bogdanm 0:eff01767de02 398 retval = NRF_SUCCESS;
bogdanm 0:eff01767de02 399
bogdanm 0:eff01767de02 400 // Its possible the flash access was not initiated by bond manager, hence
bogdanm 0:eff01767de02 401 // event is processed only if the event triggered was for an operation requested by the
bogdanm 0:eff01767de02 402 // bond manager.
bogdanm 0:eff01767de02 403 if (m_cmd_queue.flash_access == true)
bogdanm 0:eff01767de02 404 {
bogdanm 0:eff01767de02 405 cmd_queue_element_t * p_cmd;
bogdanm 0:eff01767de02 406 m_cmd_queue.flash_access = false;
bogdanm 0:eff01767de02 407 switch (sys_evt)
bogdanm 0:eff01767de02 408 {
bogdanm 0:eff01767de02 409 case NRF_EVT_FLASH_OPERATION_SUCCESS:
bogdanm 0:eff01767de02 410 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
bogdanm 0:eff01767de02 411 if ((p_cmd->op_code != PSTORAGE_CLEAR_OP_CODE) || (m_round_val >= p_cmd->size))
bogdanm 0:eff01767de02 412 {
bogdanm 0:eff01767de02 413 app_notify(retval);
bogdanm 0:eff01767de02 414 }
bogdanm 0:eff01767de02 415 // Schedule any queued flash access operations
bogdanm 0:eff01767de02 416 retval = cmd_queue_dequeue ();
bogdanm 0:eff01767de02 417 if (retval != NRF_SUCCESS)
bogdanm 0:eff01767de02 418 {
bogdanm 0:eff01767de02 419 app_notify(retval);
bogdanm 0:eff01767de02 420 }
bogdanm 0:eff01767de02 421
bogdanm 0:eff01767de02 422 break;
bogdanm 0:eff01767de02 423 case NRF_EVT_FLASH_OPERATION_ERROR:
bogdanm 0:eff01767de02 424 app_notify(NRF_ERROR_TIMEOUT);
bogdanm 0:eff01767de02 425 break;
bogdanm 0:eff01767de02 426 default:
bogdanm 0:eff01767de02 427 // No implementation needed.
bogdanm 0:eff01767de02 428 break;
bogdanm 0:eff01767de02 429 }
bogdanm 0:eff01767de02 430 }
bogdanm 0:eff01767de02 431 }
bogdanm 0:eff01767de02 432
bogdanm 0:eff01767de02 433
bogdanm 0:eff01767de02 434 /**
bogdanm 0:eff01767de02 435 * @brief Routine called to actually issue the flash access request to the SoftDevice.
bogdanm 0:eff01767de02 436 */
bogdanm 0:eff01767de02 437 static uint32_t process_cmd(void)
bogdanm 0:eff01767de02 438 {
bogdanm 0:eff01767de02 439 uint32_t retval;
bogdanm 0:eff01767de02 440 uint32_t storage_addr;
bogdanm 0:eff01767de02 441 cmd_queue_element_t * p_cmd;
bogdanm 0:eff01767de02 442
bogdanm 0:eff01767de02 443 retval = NRF_ERROR_FORBIDDEN;
bogdanm 0:eff01767de02 444
bogdanm 0:eff01767de02 445 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
bogdanm 0:eff01767de02 446
bogdanm 0:eff01767de02 447 storage_addr = p_cmd->storage_addr.block_id;
bogdanm 0:eff01767de02 448
bogdanm 0:eff01767de02 449 if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
bogdanm 0:eff01767de02 450 {
bogdanm 0:eff01767de02 451 // Calculate page number before copy.
bogdanm 0:eff01767de02 452 uint32_t page_number;
bogdanm 0:eff01767de02 453
bogdanm 0:eff01767de02 454 page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) +
bogdanm 0:eff01767de02 455 m_round_val);
bogdanm 0:eff01767de02 456
bogdanm 0:eff01767de02 457 retval = sd_flash_page_erase(page_number);
bogdanm 0:eff01767de02 458
bogdanm 0:eff01767de02 459 if (NRF_SUCCESS == retval)
bogdanm 0:eff01767de02 460 {
bogdanm 0:eff01767de02 461 m_round_val++;
bogdanm 0:eff01767de02 462 }
bogdanm 0:eff01767de02 463 }
bogdanm 0:eff01767de02 464 else if (p_cmd->op_code == PSTORAGE_STORE_OP_CODE)
bogdanm 0:eff01767de02 465 {
bogdanm 0:eff01767de02 466 uint32_t size;
bogdanm 0:eff01767de02 467 uint8_t * p_data_addr = p_cmd->p_data_addr;
bogdanm 0:eff01767de02 468
bogdanm 0:eff01767de02 469 p_data_addr += m_round_val;
bogdanm 0:eff01767de02 470
bogdanm 0:eff01767de02 471 storage_addr += (p_cmd->offset + m_round_val);
bogdanm 0:eff01767de02 472
bogdanm 0:eff01767de02 473 size = p_cmd->size - m_round_val;
bogdanm 0:eff01767de02 474
bogdanm 0:eff01767de02 475 if (size < SOC_MAX_WRITE_SIZE)
bogdanm 0:eff01767de02 476 {
bogdanm 0:eff01767de02 477 retval = sd_flash_write(((uint32_t *)storage_addr),
bogdanm 0:eff01767de02 478 (uint32_t *)p_data_addr,
bogdanm 0:eff01767de02 479 size / sizeof(uint32_t));
bogdanm 0:eff01767de02 480 }
bogdanm 0:eff01767de02 481 else
bogdanm 0:eff01767de02 482 {
bogdanm 0:eff01767de02 483 retval = sd_flash_write(((uint32_t *)storage_addr),
bogdanm 0:eff01767de02 484 (uint32_t *)p_data_addr,
bogdanm 0:eff01767de02 485 SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
bogdanm 0:eff01767de02 486 }
bogdanm 0:eff01767de02 487
bogdanm 0:eff01767de02 488
bogdanm 0:eff01767de02 489 if (retval == NRF_SUCCESS)
bogdanm 0:eff01767de02 490 {
bogdanm 0:eff01767de02 491 m_round_val += SOC_MAX_WRITE_SIZE;
bogdanm 0:eff01767de02 492 }
bogdanm 0:eff01767de02 493 }
bogdanm 0:eff01767de02 494 else
bogdanm 0:eff01767de02 495 {
bogdanm 0:eff01767de02 496 // Should never reach here.
bogdanm 0:eff01767de02 497 }
bogdanm 0:eff01767de02 498
bogdanm 0:eff01767de02 499 if (retval == NRF_SUCCESS)
bogdanm 0:eff01767de02 500 {
bogdanm 0:eff01767de02 501 m_cmd_queue.flash_access = true;
bogdanm 0:eff01767de02 502 }
bogdanm 0:eff01767de02 503
bogdanm 0:eff01767de02 504 return retval;
bogdanm 0:eff01767de02 505 }
bogdanm 0:eff01767de02 506 /** @} */
bogdanm 0:eff01767de02 507
bogdanm 0:eff01767de02 508
bogdanm 0:eff01767de02 509 /**
bogdanm 0:eff01767de02 510 * @brief Module initialization routine to be called once by the application.
bogdanm 0:eff01767de02 511 */
bogdanm 0:eff01767de02 512 uint32_t pstorage_init(void)
bogdanm 0:eff01767de02 513 {
bogdanm 0:eff01767de02 514 unsigned int index;
bogdanm 0:eff01767de02 515 cmd_queue_init();
bogdanm 0:eff01767de02 516
bogdanm 0:eff01767de02 517 m_next_app_instance = 0;
bogdanm 0:eff01767de02 518 m_next_page_addr = PSTORAGE_DATA_START_ADDR;
bogdanm 0:eff01767de02 519 m_round_val = 0;
bogdanm 0:eff01767de02 520
bogdanm 0:eff01767de02 521 for(index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++)
bogdanm 0:eff01767de02 522 {
bogdanm 0:eff01767de02 523 m_app_table[index].cb = NULL;
bogdanm 0:eff01767de02 524 m_app_table[index].block_size = 0;
bogdanm 0:eff01767de02 525 m_app_table[index].no_of_pages = 0;
bogdanm 0:eff01767de02 526 m_app_table[index].block_count = 0;
bogdanm 0:eff01767de02 527 }
bogdanm 0:eff01767de02 528
bogdanm 0:eff01767de02 529 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 530 m_raw_app_table.cb = NULL;
bogdanm 0:eff01767de02 531 m_raw_app_table.no_of_pages = 0;
bogdanm 0:eff01767de02 532 #endif //PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 533
bogdanm 0:eff01767de02 534 m_module_initialized = true;
bogdanm 0:eff01767de02 535 return NRF_SUCCESS;
bogdanm 0:eff01767de02 536 }
bogdanm 0:eff01767de02 537
bogdanm 0:eff01767de02 538 /**
bogdanm 0:eff01767de02 539 * @brief Registration routine to request persistent memory of certain sizes based on
bogdanm 0:eff01767de02 540 * application module requirements.
bogdanm 0:eff01767de02 541 */
bogdanm 0:eff01767de02 542 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
bogdanm 0:eff01767de02 543 pstorage_handle_t * p_block_id)
bogdanm 0:eff01767de02 544 {
bogdanm 0:eff01767de02 545 uint16_t page_count;
bogdanm 0:eff01767de02 546 uint32_t total_size;
bogdanm 0:eff01767de02 547
bogdanm 0:eff01767de02 548 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 549 NULL_PARAM_CHECK(p_module_param);
bogdanm 0:eff01767de02 550 NULL_PARAM_CHECK(p_block_id);
bogdanm 0:eff01767de02 551 NULL_PARAM_CHECK(p_module_param->cb);
bogdanm 0:eff01767de02 552 BLOCK_SIZE_CHECK(p_module_param->block_size);
bogdanm 0:eff01767de02 553 BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
bogdanm 0:eff01767de02 554
bogdanm 0:eff01767de02 555 if (m_next_app_instance == PSTORAGE_MAX_APPLICATIONS)
bogdanm 0:eff01767de02 556 {
bogdanm 0:eff01767de02 557 return NRF_ERROR_NO_MEM;
bogdanm 0:eff01767de02 558 }
bogdanm 0:eff01767de02 559
bogdanm 0:eff01767de02 560 p_block_id->module_id = m_next_app_instance;
bogdanm 0:eff01767de02 561 p_block_id->block_id = m_next_page_addr;
bogdanm 0:eff01767de02 562 m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
bogdanm 0:eff01767de02 563 m_app_table[m_next_app_instance].cb = p_module_param->cb;
bogdanm 0:eff01767de02 564 m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
bogdanm 0:eff01767de02 565 m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
bogdanm 0:eff01767de02 566
bogdanm 0:eff01767de02 567 // Calculate number of flash pages allocated for the device.
bogdanm 0:eff01767de02 568 page_count = 0;
bogdanm 0:eff01767de02 569 total_size = p_module_param->block_size * p_module_param->block_count;
bogdanm 0:eff01767de02 570 do
bogdanm 0:eff01767de02 571 {
bogdanm 0:eff01767de02 572 page_count++;
bogdanm 0:eff01767de02 573 if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
bogdanm 0:eff01767de02 574 {
bogdanm 0:eff01767de02 575 total_size -= PSTORAGE_FLASH_PAGE_SIZE;
bogdanm 0:eff01767de02 576 }
bogdanm 0:eff01767de02 577 else
bogdanm 0:eff01767de02 578 {
bogdanm 0:eff01767de02 579 total_size = 0;
bogdanm 0:eff01767de02 580 }
bogdanm 0:eff01767de02 581 m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
bogdanm 0:eff01767de02 582 }while(total_size >= PSTORAGE_FLASH_PAGE_SIZE);
bogdanm 0:eff01767de02 583
bogdanm 0:eff01767de02 584 m_app_table[m_next_app_instance].no_of_pages = page_count;
bogdanm 0:eff01767de02 585 m_next_app_instance++;
bogdanm 0:eff01767de02 586
bogdanm 0:eff01767de02 587 return NRF_SUCCESS;
bogdanm 0:eff01767de02 588 }
bogdanm 0:eff01767de02 589
bogdanm 0:eff01767de02 590
bogdanm 0:eff01767de02 591 /**
bogdanm 0:eff01767de02 592 * @brief API to get the next block identifier.
bogdanm 0:eff01767de02 593 */
bogdanm 0:eff01767de02 594 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
bogdanm 0:eff01767de02 595 pstorage_size_t block_num,
bogdanm 0:eff01767de02 596 pstorage_handle_t * p_block_id)
bogdanm 0:eff01767de02 597 {
bogdanm 0:eff01767de02 598 pstorage_handle_t temp_id;
bogdanm 0:eff01767de02 599
bogdanm 0:eff01767de02 600 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 601 NULL_PARAM_CHECK(p_base_id);
bogdanm 0:eff01767de02 602 NULL_PARAM_CHECK(p_block_id);
bogdanm 0:eff01767de02 603 MODULE_ID_RANGE_CHECK(p_base_id);
bogdanm 0:eff01767de02 604
bogdanm 0:eff01767de02 605 temp_id = (*p_base_id);
bogdanm 0:eff01767de02 606 temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
bogdanm 0:eff01767de02 607 BLOCK_ID_RANGE_CHECK(&temp_id);
bogdanm 0:eff01767de02 608 (*p_block_id) = temp_id;
bogdanm 0:eff01767de02 609
bogdanm 0:eff01767de02 610 return NRF_SUCCESS;
bogdanm 0:eff01767de02 611 }
bogdanm 0:eff01767de02 612
bogdanm 0:eff01767de02 613
bogdanm 0:eff01767de02 614 /**
bogdanm 0:eff01767de02 615 * @brief API to store data persistently.
bogdanm 0:eff01767de02 616 */
bogdanm 0:eff01767de02 617 uint32_t pstorage_store(pstorage_handle_t * p_dest,
bogdanm 0:eff01767de02 618 uint8_t * p_src,
bogdanm 0:eff01767de02 619 pstorage_size_t size,
bogdanm 0:eff01767de02 620 pstorage_size_t offset)
bogdanm 0:eff01767de02 621 {
bogdanm 0:eff01767de02 622 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 623 NULL_PARAM_CHECK(p_src);
bogdanm 0:eff01767de02 624 NULL_PARAM_CHECK(p_dest);
bogdanm 0:eff01767de02 625 MODULE_ID_RANGE_CHECK (p_dest);
bogdanm 0:eff01767de02 626 BLOCK_ID_RANGE_CHECK(p_dest);
bogdanm 0:eff01767de02 627 SIZE_CHECK(p_dest,size);
bogdanm 0:eff01767de02 628 OFFSET_CHECK(p_dest,offset,size);
bogdanm 0:eff01767de02 629
bogdanm 0:eff01767de02 630 // Verify word alignment.
bogdanm 0:eff01767de02 631 if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
bogdanm 0:eff01767de02 632 {
bogdanm 0:eff01767de02 633 return NRF_ERROR_INVALID_ADDR;
bogdanm 0:eff01767de02 634 }
bogdanm 0:eff01767de02 635
bogdanm 0:eff01767de02 636 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
bogdanm 0:eff01767de02 637 }
bogdanm 0:eff01767de02 638
bogdanm 0:eff01767de02 639
bogdanm 0:eff01767de02 640 /**
bogdanm 0:eff01767de02 641 * @brief API to load data from persistent memory.
bogdanm 0:eff01767de02 642 */
bogdanm 0:eff01767de02 643 uint32_t pstorage_load(uint8_t * p_dest,
bogdanm 0:eff01767de02 644 pstorage_handle_t * p_src,
bogdanm 0:eff01767de02 645 pstorage_size_t size,
bogdanm 0:eff01767de02 646 pstorage_size_t offset)
bogdanm 0:eff01767de02 647 {
bogdanm 0:eff01767de02 648 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 649 NULL_PARAM_CHECK(p_src);
bogdanm 0:eff01767de02 650 NULL_PARAM_CHECK(p_dest);
bogdanm 0:eff01767de02 651 MODULE_ID_RANGE_CHECK (p_src);
bogdanm 0:eff01767de02 652 BLOCK_ID_RANGE_CHECK(p_src);
bogdanm 0:eff01767de02 653 SIZE_CHECK(p_src,size);
bogdanm 0:eff01767de02 654 OFFSET_CHECK(p_src,offset,size);
bogdanm 0:eff01767de02 655
bogdanm 0:eff01767de02 656 // Verify word alignment.
bogdanm 0:eff01767de02 657 if ((!is_word_aligned (p_dest)) || (!is_word_aligned (p_dest + offset)))
bogdanm 0:eff01767de02 658 {
bogdanm 0:eff01767de02 659 return NRF_ERROR_INVALID_ADDR;
bogdanm 0:eff01767de02 660 }
bogdanm 0:eff01767de02 661
bogdanm 0:eff01767de02 662 memcpy (p_dest, (((uint8_t *)p_src->block_id) + offset), size);
bogdanm 0:eff01767de02 663
bogdanm 0:eff01767de02 664 return NRF_SUCCESS;
bogdanm 0:eff01767de02 665 }
bogdanm 0:eff01767de02 666
bogdanm 0:eff01767de02 667
bogdanm 0:eff01767de02 668 /**
bogdanm 0:eff01767de02 669 * @brief API to clear data in blocks of persistent memory.
bogdanm 0:eff01767de02 670 */
bogdanm 0:eff01767de02 671 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
bogdanm 0:eff01767de02 672 {
bogdanm 0:eff01767de02 673 uint32_t retval;
bogdanm 0:eff01767de02 674 uint32_t pages;
bogdanm 0:eff01767de02 675
bogdanm 0:eff01767de02 676 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 677 NULL_PARAM_CHECK(p_dest);
bogdanm 0:eff01767de02 678 MODULE_ID_RANGE_CHECK(p_dest);
bogdanm 0:eff01767de02 679 BLOCK_ID_RANGE_CHECK(p_dest);
bogdanm 0:eff01767de02 680
bogdanm 0:eff01767de02 681 pages = m_app_table[p_dest->module_id].no_of_pages;
bogdanm 0:eff01767de02 682
bogdanm 0:eff01767de02 683 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages , 0);
bogdanm 0:eff01767de02 684
bogdanm 0:eff01767de02 685 return retval;
bogdanm 0:eff01767de02 686 }
bogdanm 0:eff01767de02 687
bogdanm 0:eff01767de02 688
bogdanm 0:eff01767de02 689 #ifdef PSTORAGE_RAW_MODE_ENABLE
bogdanm 0:eff01767de02 690
bogdanm 0:eff01767de02 691 /**
bogdanm 0:eff01767de02 692 * @brief Registration routine to request persistent memory of certain sizes based on
bogdanm 0:eff01767de02 693 * application module requirements.
bogdanm 0:eff01767de02 694 */
bogdanm 0:eff01767de02 695 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
bogdanm 0:eff01767de02 696 pstorage_handle_t * p_block_id)
bogdanm 0:eff01767de02 697 {
bogdanm 0:eff01767de02 698 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 699 NULL_PARAM_CHECK(p_module_param);
bogdanm 0:eff01767de02 700 NULL_PARAM_CHECK(p_block_id);
bogdanm 0:eff01767de02 701 NULL_PARAM_CHECK(p_module_param->cb);
bogdanm 0:eff01767de02 702
bogdanm 0:eff01767de02 703 if (m_raw_app_table.cb != NULL)
bogdanm 0:eff01767de02 704 {
bogdanm 0:eff01767de02 705 return NRF_ERROR_NO_MEM;
bogdanm 0:eff01767de02 706 }
bogdanm 0:eff01767de02 707
bogdanm 0:eff01767de02 708 p_block_id->module_id = PSTORAGE_MAX_APPLICATIONS + 1;
bogdanm 0:eff01767de02 709 m_raw_app_table.cb = p_module_param->cb;
bogdanm 0:eff01767de02 710
bogdanm 0:eff01767de02 711 return NRF_SUCCESS;
bogdanm 0:eff01767de02 712 }
bogdanm 0:eff01767de02 713
bogdanm 0:eff01767de02 714
bogdanm 0:eff01767de02 715 /**
bogdanm 0:eff01767de02 716 * @brief API to store data persistently.
bogdanm 0:eff01767de02 717 */
bogdanm 0:eff01767de02 718 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
bogdanm 0:eff01767de02 719 uint8_t * p_src,
bogdanm 0:eff01767de02 720 uint32_t size,
bogdanm 0:eff01767de02 721 uint32_t offset)
bogdanm 0:eff01767de02 722 {
bogdanm 0:eff01767de02 723 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 724 NULL_PARAM_CHECK(p_src);
bogdanm 0:eff01767de02 725 NULL_PARAM_CHECK(p_dest);
bogdanm 0:eff01767de02 726 MODULE_RAW_ID_RANGE_CHECK(p_dest);
bogdanm 0:eff01767de02 727
bogdanm 0:eff01767de02 728 // Verify word alignment.
bogdanm 0:eff01767de02 729 if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
bogdanm 0:eff01767de02 730 {
bogdanm 0:eff01767de02 731 return NRF_ERROR_INVALID_ADDR;
bogdanm 0:eff01767de02 732 }
bogdanm 0:eff01767de02 733
bogdanm 0:eff01767de02 734 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
bogdanm 0:eff01767de02 735 }
bogdanm 0:eff01767de02 736
bogdanm 0:eff01767de02 737
bogdanm 0:eff01767de02 738 /**
bogdanm 0:eff01767de02 739 * @brief API to clear data in blocks of persistent memory.
bogdanm 0:eff01767de02 740 */
bogdanm 0:eff01767de02 741 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, uint32_t size)
bogdanm 0:eff01767de02 742 {
bogdanm 0:eff01767de02 743 uint32_t retval;
bogdanm 0:eff01767de02 744 uint32_t pages;
bogdanm 0:eff01767de02 745
bogdanm 0:eff01767de02 746 VERIFY_MODULE_INITIALIZED();
bogdanm 0:eff01767de02 747 NULL_PARAM_CHECK(p_dest);
bogdanm 0:eff01767de02 748 MODULE_RAW_ID_RANGE_CHECK(p_dest);
bogdanm 0:eff01767de02 749
bogdanm 0:eff01767de02 750 retval = NRF_SUCCESS;
bogdanm 0:eff01767de02 751
bogdanm 0:eff01767de02 752 pages = CEIL_DIV(size, PSTORAGE_FLASH_PAGE_SIZE);
bogdanm 0:eff01767de02 753
bogdanm 0:eff01767de02 754 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages, 0);
bogdanm 0:eff01767de02 755
bogdanm 0:eff01767de02 756 return retval;
bogdanm 0:eff01767de02 757 }
bogdanm 0:eff01767de02 758
bogdanm 0:eff01767de02 759 #endif // PSTORAGE_RAW_MODE_ENABLE