Nordic stack and drivers for the mbed BLE API

Dependents:   BLE_Health_Thermometer2

Fork of nRF51822 by Nordic Semiconductor

Committer:
todotani
Date:
Fri Aug 22 11:24:48 2014 +0000
Revision:
54:f3badab88f02
Parent:
33:8efbbf54b66f
BLE_Health_Thermometer for mbed HRM1017 with new BLE library

Who changed what in which revision?

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