Set write permission for 'write without response' characteristics.
Fork of nRF51822 by
nordic/app_common/pstorage.cpp@56:a1071b629aa3, 2014-09-02 (annotated)
- 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?
User | Revision | Line number | New 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 */ |