mediCAL's first BLE project

Dependents:   BLE_mediCAL

Fork of nRF51822 by Nordic Semiconductor

Committer:
Rohit Grover
Date:
Tue Sep 02 15:50:05 2014 +0100
Revision:
56:a1071b629aa3
Parent:
33:8efbbf54b66f
Child:
65:98215c4f3a25
Release 0.1.0
=============

We've achieved significant gains in power consumption: the BLE_Beacon demo now
runs at around 35uA of average current broadcasting once a second at 0dB; when
not using the radio, this demo consumes around 7uA.

Features
~~~~~~~~

- Replace initialization of high-frequency external crystal clock-source with
the use of low-frequency clock. This brings in significant gains in power
consumption.

- Re-implement the micro-second timer on nRF51 using the app_timer module
(which internally uses RTC). This limits the precision of the us_Timer to
30uS; but brings in significant gains in power consumption.

- Reduce the number of available app_timers and the event depths for app-timer
events; this will reduce memory consumption for zero-initialized data by
around 1K.

- Remove the call to conn_params_init() at startup. This is not mandatory; and
was causing an unnecessary re-negotiation of connection parameters a few
seconds into every connection.

- Reduce default transmission power level to 0dbB (was 4dbB before).

- Reduce min connection interval to 50ms and max to 500ms (previous values
were much larger).

- Replace a few instances of use of wait() with nrf_delay_us().

- onConnection() callback now receives connection-parameters applicable to the
new connection.

- onDataSent() callback now receives a count parameter containing the number of
times notifications were sent out since the last callback.

- A 'reason' parameter has been added to Gap::disconnect() to indicate the
reason for disconnection; and also to the onDisconnection callback to
receive a reason from the remote host.

- disable the app_gpiote module by default.

Bugfixes
~~~~~~~~

- onDataWritten() callback now passes an additional parameter
(GattServer::WriteEventCallback_t) encapsulating the update. This avoids
having to re-fetch the updated characteristic's value attribute. It also
fixes a bug where multiple updates to the characteristic's value-attribute
could get clobbered if they occurred in quick succession before the
callbacks could be processed.


Compatibility
~~~~~~~~~~~~~

Compatible with revision 0.1.0 of the BLE_API.

Who changed what in which revision?

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