Nordic stack and drivers for the mbed BLE API

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate writable_gatt ... more

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:39:43 2016 +0100
Revision:
638:c90ae1400bf2
Sync with bdab10dc0f90748b6989c8b577771bb403ca6bd8 from ARMmbed/mbed-os.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 638:c90ae1400bf2 1 /*
Vincent Coubard 638:c90ae1400bf2 2 * Copyright (c) Nordic Semiconductor ASA
Vincent Coubard 638:c90ae1400bf2 3 * All rights reserved.
Vincent Coubard 638:c90ae1400bf2 4 *
Vincent Coubard 638:c90ae1400bf2 5 * Redistribution and use in source and binary forms, with or without modification,
Vincent Coubard 638:c90ae1400bf2 6 * are permitted provided that the following conditions are met:
Vincent Coubard 638:c90ae1400bf2 7 *
Vincent Coubard 638:c90ae1400bf2 8 * 1. Redistributions of source code must retain the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 9 * list of conditions and the following disclaimer.
Vincent Coubard 638:c90ae1400bf2 10 *
Vincent Coubard 638:c90ae1400bf2 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 12 * list of conditions and the following disclaimer in the documentation and/or
Vincent Coubard 638:c90ae1400bf2 13 * other materials provided with the distribution.
Vincent Coubard 638:c90ae1400bf2 14 *
Vincent Coubard 638:c90ae1400bf2 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
Vincent Coubard 638:c90ae1400bf2 16 * contributors to this software may be used to endorse or promote products
Vincent Coubard 638:c90ae1400bf2 17 * derived from this software without specific prior written permission.
Vincent Coubard 638:c90ae1400bf2 18 *
Vincent Coubard 638:c90ae1400bf2 19 *
Vincent Coubard 638:c90ae1400bf2 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Vincent Coubard 638:c90ae1400bf2 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Vincent Coubard 638:c90ae1400bf2 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Vincent Coubard 638:c90ae1400bf2 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
Vincent Coubard 638:c90ae1400bf2 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Vincent Coubard 638:c90ae1400bf2 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Vincent Coubard 638:c90ae1400bf2 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
Vincent Coubard 638:c90ae1400bf2 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Vincent Coubard 638:c90ae1400bf2 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Vincent Coubard 638:c90ae1400bf2 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Vincent Coubard 638:c90ae1400bf2 30 *
Vincent Coubard 638:c90ae1400bf2 31 */
Vincent Coubard 638:c90ae1400bf2 32
Vincent Coubard 638:c90ae1400bf2 33 #include "pstorage.h"
Vincent Coubard 638:c90ae1400bf2 34 #include <stdlib.h>
Vincent Coubard 638:c90ae1400bf2 35 #include <stdint.h>
Vincent Coubard 638:c90ae1400bf2 36 #include <string.h>
Vincent Coubard 638:c90ae1400bf2 37 #include "nordic_common.h"
Vincent Coubard 638:c90ae1400bf2 38 #include "nrf_error.h"
Vincent Coubard 638:c90ae1400bf2 39 #include "nrf_assert.h"
Vincent Coubard 638:c90ae1400bf2 40 #include "nrf.h"
Vincent Coubard 638:c90ae1400bf2 41 #include "nrf_soc.h"
Vincent Coubard 638:c90ae1400bf2 42 #include "app_util.h"
Vincent Coubard 638:c90ae1400bf2 43 #include "app_error.h"
Vincent Coubard 638:c90ae1400bf2 44
Vincent Coubard 638:c90ae1400bf2 45 #define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
Vincent Coubard 638:c90ae1400bf2 46 #define SOC_MAX_WRITE_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API. */
Vincent Coubard 638:c90ae1400bf2 47 #define RAW_MODE_APP_ID (PSTORAGE_NUM_OF_PAGES + 1) /**< Application id for raw mode. */
Vincent Coubard 638:c90ae1400bf2 48
Vincent Coubard 638:c90ae1400bf2 49 #if defined(NRF52)
Vincent Coubard 638:c90ae1400bf2 50 #define SD_CMD_MAX_TRIES 1000 /**< Number of times to try a softdevice flash operatoion, specific for nRF52 to account for longest time of flash page erase*/
Vincent Coubard 638:c90ae1400bf2 51 #else
Vincent Coubard 638:c90ae1400bf2 52 #define SD_CMD_MAX_TRIES 3 /**< Number of times to try a softdevice flash operation when the @ref NRF_EVT_FLASH_OPERATION_ERROR sys_evt is received. */
Vincent Coubard 638:c90ae1400bf2 53 #endif /* defined(NRF52) */
Vincent Coubard 638:c90ae1400bf2 54
Vincent Coubard 638:c90ae1400bf2 55 #define MASK_TAIL_SWAP_DONE (1 << 0) /**< Flag for checking if the tail restore area has been written to swap page. */
Vincent Coubard 638:c90ae1400bf2 56 #define MASK_SINGLE_PAGE_OPERATION (1 << 1) /**< Flag for checking if command is a single flash page operation. */
Vincent Coubard 638:c90ae1400bf2 57 #define MASK_MODULE_INITIALIZED (1 << 2) /**< Flag for checking if the module has been initialized. */
Vincent Coubard 638:c90ae1400bf2 58 #define MASK_FLASH_API_ERR_BUSY (1 << 3) /**< Flag for checking if flash API returned NRF_ERROR_BUSY. */
Vincent Coubard 638:c90ae1400bf2 59
Vincent Coubard 638:c90ae1400bf2 60 /**
Vincent Coubard 638:c90ae1400bf2 61 * @defgroup api_param_check API Parameters check macros.
Vincent Coubard 638:c90ae1400bf2 62 *
Vincent Coubard 638:c90ae1400bf2 63 * @details Macros that verify parameters passed to the module in the APIs. These macros
Vincent Coubard 638:c90ae1400bf2 64 * could be mapped to nothing in final code versions to save execution and size.
Vincent Coubard 638:c90ae1400bf2 65 *
Vincent Coubard 638:c90ae1400bf2 66 * @{
Vincent Coubard 638:c90ae1400bf2 67 */
Vincent Coubard 638:c90ae1400bf2 68
Vincent Coubard 638:c90ae1400bf2 69 /**@brief Check if the input pointer is NULL, if so it returns NRF_ERROR_NULL.
Vincent Coubard 638:c90ae1400bf2 70 */
Vincent Coubard 638:c90ae1400bf2 71 #define NULL_PARAM_CHECK(PARAM) \
Vincent Coubard 638:c90ae1400bf2 72 if ((PARAM) == NULL) \
Vincent Coubard 638:c90ae1400bf2 73 { \
Vincent Coubard 638:c90ae1400bf2 74 return NRF_ERROR_NULL; \
Vincent Coubard 638:c90ae1400bf2 75 }
Vincent Coubard 638:c90ae1400bf2 76
Vincent Coubard 638:c90ae1400bf2 77 /**@brief Verifies that the module identifier supplied by the application is within permissible
Vincent Coubard 638:c90ae1400bf2 78 * range.
Vincent Coubard 638:c90ae1400bf2 79 */
Vincent Coubard 638:c90ae1400bf2 80 #define MODULE_ID_RANGE_CHECK(ID) \
Vincent Coubard 638:c90ae1400bf2 81 if ((((ID)->module_id) >= PSTORAGE_NUM_OF_PAGES) || \
Vincent Coubard 638:c90ae1400bf2 82 (m_app_table[(ID)->module_id].cb == NULL)) \
Vincent Coubard 638:c90ae1400bf2 83 { \
Vincent Coubard 638:c90ae1400bf2 84 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 85 }
Vincent Coubard 638:c90ae1400bf2 86
Vincent Coubard 638:c90ae1400bf2 87 /**@brief Verifies that the block identifier supplied by the application is within the permissible
Vincent Coubard 638:c90ae1400bf2 88 * range.
Vincent Coubard 638:c90ae1400bf2 89 */
Vincent Coubard 638:c90ae1400bf2 90 #define BLOCK_ID_RANGE_CHECK(ID) \
Vincent Coubard 638:c90ae1400bf2 91 if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
Vincent Coubard 638:c90ae1400bf2 92 (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
Vincent Coubard 638:c90ae1400bf2 93 { \
Vincent Coubard 638:c90ae1400bf2 94 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 95 }
Vincent Coubard 638:c90ae1400bf2 96
Vincent Coubard 638:c90ae1400bf2 97 /**@brief Verifies that the block size requested by the application can be supported by the module.
Vincent Coubard 638:c90ae1400bf2 98 */
Vincent Coubard 638:c90ae1400bf2 99 #define BLOCK_SIZE_CHECK(X) \
Vincent Coubard 638:c90ae1400bf2 100 if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
Vincent Coubard 638:c90ae1400bf2 101 { \
Vincent Coubard 638:c90ae1400bf2 102 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 103 }
Vincent Coubard 638:c90ae1400bf2 104
Vincent Coubard 638:c90ae1400bf2 105 /**@brief Verifies the block size requested by the application in registration API.
Vincent Coubard 638:c90ae1400bf2 106 */
Vincent Coubard 638:c90ae1400bf2 107 #define BLOCK_COUNT_CHECK(COUNT, SIZE) \
Vincent Coubard 638:c90ae1400bf2 108 if (((COUNT) == 0) || \
Vincent Coubard 638:c90ae1400bf2 109 ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_SWAP_ADDR))) \
Vincent Coubard 638:c90ae1400bf2 110 { \
Vincent Coubard 638:c90ae1400bf2 111 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 112 }
Vincent Coubard 638:c90ae1400bf2 113
Vincent Coubard 638:c90ae1400bf2 114 /**@brief Verifies the size parameter provided by the application in API.
Vincent Coubard 638:c90ae1400bf2 115 */
Vincent Coubard 638:c90ae1400bf2 116 #define SIZE_CHECK(ID, SIZE) \
Vincent Coubard 638:c90ae1400bf2 117 if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
Vincent Coubard 638:c90ae1400bf2 118 { \
Vincent Coubard 638:c90ae1400bf2 119 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 120 }
Vincent Coubard 638:c90ae1400bf2 121
Vincent Coubard 638:c90ae1400bf2 122 /**@brief Verifies the offset parameter provided by the application in API.
Vincent Coubard 638:c90ae1400bf2 123 */
Vincent Coubard 638:c90ae1400bf2 124 #define OFFSET_CHECK(ID, OFFSET, SIZE) \
Vincent Coubard 638:c90ae1400bf2 125 if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
Vincent Coubard 638:c90ae1400bf2 126 { \
Vincent Coubard 638:c90ae1400bf2 127 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 128 }
Vincent Coubard 638:c90ae1400bf2 129
Vincent Coubard 638:c90ae1400bf2 130 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 131
Vincent Coubard 638:c90ae1400bf2 132 /**@brief Verifies the module identifier supplied by the application.
Vincent Coubard 638:c90ae1400bf2 133 */
Vincent Coubard 638:c90ae1400bf2 134 #define MODULE_RAW_HANDLE_CHECK(ID) \
Vincent Coubard 638:c90ae1400bf2 135 if ((((ID)->module_id) != RAW_MODE_APP_ID)) \
Vincent Coubard 638:c90ae1400bf2 136 { \
Vincent Coubard 638:c90ae1400bf2 137 return NRF_ERROR_INVALID_PARAM; \
Vincent Coubard 638:c90ae1400bf2 138 }
Vincent Coubard 638:c90ae1400bf2 139
Vincent Coubard 638:c90ae1400bf2 140 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 141
Vincent Coubard 638:c90ae1400bf2 142 /**@} */
Vincent Coubard 638:c90ae1400bf2 143
Vincent Coubard 638:c90ae1400bf2 144
Vincent Coubard 638:c90ae1400bf2 145 /**@brief Verify module's initialization status.
Vincent Coubard 638:c90ae1400bf2 146 *
Vincent Coubard 638:c90ae1400bf2 147 * @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE when a
Vincent Coubard 638:c90ae1400bf2 148 * module API is called without initializing the module.
Vincent Coubard 638:c90ae1400bf2 149 */
Vincent Coubard 638:c90ae1400bf2 150 #define VERIFY_MODULE_INITIALIZED() \
Vincent Coubard 638:c90ae1400bf2 151 do \
Vincent Coubard 638:c90ae1400bf2 152 { \
Vincent Coubard 638:c90ae1400bf2 153 if (!(m_flags & MASK_MODULE_INITIALIZED)) \
Vincent Coubard 638:c90ae1400bf2 154 { \
Vincent Coubard 638:c90ae1400bf2 155 return NRF_ERROR_INVALID_STATE; \
Vincent Coubard 638:c90ae1400bf2 156 } \
Vincent Coubard 638:c90ae1400bf2 157 } while(0)
Vincent Coubard 638:c90ae1400bf2 158
Vincent Coubard 638:c90ae1400bf2 159 /**@brief Macro to fetch the block size registered for the module. */
Vincent Coubard 638:c90ae1400bf2 160 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
Vincent Coubard 638:c90ae1400bf2 161
Vincent Coubard 638:c90ae1400bf2 162 /**@brief Main state machine of the component. */
Vincent Coubard 638:c90ae1400bf2 163 typedef enum
Vincent Coubard 638:c90ae1400bf2 164 {
Vincent Coubard 638:c90ae1400bf2 165 STATE_IDLE, /**< State for being idle (no command execution in progress). */
Vincent Coubard 638:c90ae1400bf2 166 STATE_STORE, /**< State for storing data when using store/update API. */
Vincent Coubard 638:c90ae1400bf2 167 STATE_DATA_ERASE_WITH_SWAP, /**< State for erasing the data page when using update/clear API when use of swap page is required. */
Vincent Coubard 638:c90ae1400bf2 168 STATE_DATA_ERASE, /**< State for erasing the data page when using update/clear API without the need to use the swap page. */
Vincent Coubard 638:c90ae1400bf2 169 STATE_ERROR /**< State entered when command processing is terminated abnormally. */
Vincent Coubard 638:c90ae1400bf2 170 } pstorage_state_t;
Vincent Coubard 638:c90ae1400bf2 171
Vincent Coubard 638:c90ae1400bf2 172 /**@brief Sub state machine contained by @ref STATE_DATA_ERASE_WITH_SWAP super state machine. */
Vincent Coubard 638:c90ae1400bf2 173 typedef enum
Vincent Coubard 638:c90ae1400bf2 174 {
Vincent Coubard 638:c90ae1400bf2 175 STATE_ERASE_SWAP, /**< State for erasing the swap page when using the update/clear API. */
Vincent Coubard 638:c90ae1400bf2 176 STATE_WRITE_DATA_TO_SWAP, /**< State for writing the data page into the swap page when using update/clear API. */
Vincent Coubard 638:c90ae1400bf2 177 STATE_ERASE_DATA_PAGE, /**< State for erasing data page when using update/clear API. */
Vincent Coubard 638:c90ae1400bf2 178 STATE_RESTORE_TAIL, /**< State for restoring tail (end) of backed up data from swap to data page when using update/clear API. */
Vincent Coubard 638:c90ae1400bf2 179 STATE_RESTORE_HEAD, /**< State for restoring head (beginning) of backed up data from swap to data page when using update/clear API. */
Vincent Coubard 638:c90ae1400bf2 180 SWAP_SUB_STATE_MAX /**< Enumeration upper bound. */
Vincent Coubard 638:c90ae1400bf2 181 } flash_swap_sub_state_t;
Vincent Coubard 638:c90ae1400bf2 182
Vincent Coubard 638:c90ae1400bf2 183 /**@brief Application registration information.
Vincent Coubard 638:c90ae1400bf2 184 *
Vincent Coubard 638:c90ae1400bf2 185 * @details Defines application specific information that the application needs to maintain to be able
Vincent Coubard 638:c90ae1400bf2 186 * to process requests from each one of them.
Vincent Coubard 638:c90ae1400bf2 187 */
Vincent Coubard 638:c90ae1400bf2 188 typedef struct
Vincent Coubard 638:c90ae1400bf2 189 {
Vincent Coubard 638:c90ae1400bf2 190 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
Vincent Coubard 638:c90ae1400bf2 191 pstorage_block_t base_id; /**< Base block ID assigned to the module. */
Vincent Coubard 638:c90ae1400bf2 192 pstorage_size_t block_size; /**< Size of block for the module. */
Vincent Coubard 638:c90ae1400bf2 193 pstorage_size_t block_count; /**< Number of blocks requested by the application. */
Vincent Coubard 638:c90ae1400bf2 194 } pstorage_module_table_t;
Vincent Coubard 638:c90ae1400bf2 195
Vincent Coubard 638:c90ae1400bf2 196
Vincent Coubard 638:c90ae1400bf2 197 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 198 /**@brief Application registration information.
Vincent Coubard 638:c90ae1400bf2 199 *
Vincent Coubard 638:c90ae1400bf2 200 * @details Defines application specific information that the application registered for raw mode.
Vincent Coubard 638:c90ae1400bf2 201 */
Vincent Coubard 638:c90ae1400bf2 202 typedef struct
Vincent Coubard 638:c90ae1400bf2 203 {
Vincent Coubard 638:c90ae1400bf2 204 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of the result of flash access. */
Vincent Coubard 638:c90ae1400bf2 205 } pstorage_raw_module_table_t;
Vincent Coubard 638:c90ae1400bf2 206 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 207
Vincent Coubard 638:c90ae1400bf2 208
Vincent Coubard 638:c90ae1400bf2 209 /**@brief Defines command queue element.
Vincent Coubard 638:c90ae1400bf2 210 *
Vincent Coubard 638:c90ae1400bf2 211 * @details Defines command queue element. Each element encapsulates needed information to process
Vincent Coubard 638:c90ae1400bf2 212 * a flash access command.
Vincent Coubard 638:c90ae1400bf2 213 */
Vincent Coubard 638:c90ae1400bf2 214 typedef struct
Vincent Coubard 638:c90ae1400bf2 215 {
Vincent Coubard 638:c90ae1400bf2 216 uint8_t op_code; /**< Identifies the flash access operation being queued. Element is free if op-code is INVALID_OPCODE. */
Vincent Coubard 638:c90ae1400bf2 217 pstorage_size_t size; /**< Identifies the size in bytes requested for the operation. */
Vincent Coubard 638:c90ae1400bf2 218 pstorage_size_t offset; /**< Offset requested by the application for the access operation. */
Vincent Coubard 638:c90ae1400bf2 219 pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
Vincent Coubard 638:c90ae1400bf2 220 uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
Vincent Coubard 638:c90ae1400bf2 221 } cmd_queue_element_t;
Vincent Coubard 638:c90ae1400bf2 222
Vincent Coubard 638:c90ae1400bf2 223
Vincent Coubard 638:c90ae1400bf2 224 /**@brief Defines command queue, an element is free if the op_code field is not invalid.
Vincent Coubard 638:c90ae1400bf2 225 *
Vincent Coubard 638:c90ae1400bf2 226 * @details Defines commands enqueued for flash access. At any point in time, this queue has one or
Vincent Coubard 638:c90ae1400bf2 227 * more flash access operations pending if the count field is not zero. When the queue is
Vincent Coubard 638:c90ae1400bf2 228 * not empty, the rp (read pointer) field points to the flash access command in progress
Vincent Coubard 638:c90ae1400bf2 229 * or, if none is in progress, the command to be requested next. The queue implements a
Vincent Coubard 638:c90ae1400bf2 230 * simple first in first out algorithm. Data addresses are assumed to be resident.
Vincent Coubard 638:c90ae1400bf2 231 */
Vincent Coubard 638:c90ae1400bf2 232 typedef struct
Vincent Coubard 638:c90ae1400bf2 233 {
Vincent Coubard 638:c90ae1400bf2 234 uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
Vincent Coubard 638:c90ae1400bf2 235 uint8_t count; /**< Number of elements in the queue. */
Vincent Coubard 638:c90ae1400bf2 236 cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details. */
Vincent Coubard 638:c90ae1400bf2 237 } cmd_queue_t;
Vincent Coubard 638:c90ae1400bf2 238
Vincent Coubard 638:c90ae1400bf2 239 static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
Vincent Coubard 638:c90ae1400bf2 240 static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next. */
Vincent Coubard 638:c90ae1400bf2 241 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 that can span across flash pages. */
Vincent Coubard 638:c90ae1400bf2 242 static pstorage_state_t m_state; /**< Main state tracking variable. */
Vincent Coubard 638:c90ae1400bf2 243 static flash_swap_sub_state_t m_swap_sub_state; /**< Flash swap erase when swap used state tracking variable. */
Vincent Coubard 638:c90ae1400bf2 244 static uint32_t m_head_word_size; /**< Head restore area size in words. */
Vincent Coubard 638:c90ae1400bf2 245 static uint32_t m_tail_word_size; /**< Tail restore area size in words. */
Vincent Coubard 638:c90ae1400bf2 246 static uint32_t m_current_page_id; /**< Variable for tracking the flash page being processed. */
Vincent Coubard 638:c90ae1400bf2 247 static uint32_t m_num_of_command_retries; /**< Variable for tracking flash operation retries upon flash operation failures. */
Vincent Coubard 638:c90ae1400bf2 248 static pstorage_module_table_t m_app_table[PSTORAGE_NUM_OF_PAGES]; /**< Registered application information table. */
Vincent Coubard 638:c90ae1400bf2 249 static uint32_t m_num_of_bytes_written; /**< Variable for tracking the number of bytes written by the store operation. */
Vincent Coubard 638:c90ae1400bf2 250 static uint32_t m_app_data_size; /**< Variable for storing the application command size parameter internally. */
Vincent Coubard 638:c90ae1400bf2 251 static uint32_t m_flags = 0; /**< Storage for boolean flags for state tracking. */
Vincent Coubard 638:c90ae1400bf2 252
Vincent Coubard 638:c90ae1400bf2 253 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 254 static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
Vincent Coubard 638:c90ae1400bf2 255 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 256
Vincent Coubard 638:c90ae1400bf2 257 // Required forward declarations.
Vincent Coubard 638:c90ae1400bf2 258 static void cmd_process(void);
Vincent Coubard 638:c90ae1400bf2 259 static void store_operation_execute(void);
Vincent Coubard 638:c90ae1400bf2 260 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem);
Vincent Coubard 638:c90ae1400bf2 261 static void cmd_queue_element_init(uint32_t index);
Vincent Coubard 638:c90ae1400bf2 262 static void cmd_queue_dequeue(void);
Vincent Coubard 638:c90ae1400bf2 263 static void sm_state_change(pstorage_state_t new_state);
Vincent Coubard 638:c90ae1400bf2 264 static void swap_sub_state_state_change(flash_swap_sub_state_t new_state);
Vincent Coubard 638:c90ae1400bf2 265
Vincent Coubard 638:c90ae1400bf2 266 /**@brief Function for consuming a command queue element.
Vincent Coubard 638:c90ae1400bf2 267 *
Vincent Coubard 638:c90ae1400bf2 268 * @details Function for consuming a command queue element, which has been fully processed.
Vincent Coubard 638:c90ae1400bf2 269 */
Vincent Coubard 638:c90ae1400bf2 270 static void command_queue_element_consume(void)
Vincent Coubard 638:c90ae1400bf2 271 {
Vincent Coubard 638:c90ae1400bf2 272 // Initialize/free the element as it is now processed.
Vincent Coubard 638:c90ae1400bf2 273 cmd_queue_element_init(m_cmd_queue.rp);
Vincent Coubard 638:c90ae1400bf2 274
Vincent Coubard 638:c90ae1400bf2 275 // Adjust command queue state tracking variables.
Vincent Coubard 638:c90ae1400bf2 276 --(m_cmd_queue.count);
Vincent Coubard 638:c90ae1400bf2 277 if (++(m_cmd_queue.rp) == PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 638:c90ae1400bf2 278 {
Vincent Coubard 638:c90ae1400bf2 279 m_cmd_queue.rp = 0;
Vincent Coubard 638:c90ae1400bf2 280 }
Vincent Coubard 638:c90ae1400bf2 281 }
Vincent Coubard 638:c90ae1400bf2 282
Vincent Coubard 638:c90ae1400bf2 283
Vincent Coubard 638:c90ae1400bf2 284 /**@brief Function for executing the finalization procedure for the command executed.
Vincent Coubard 638:c90ae1400bf2 285 *
Vincent Coubard 638:c90ae1400bf2 286 * @details Function for executing the finalization procedure for command executed, which includes
Vincent Coubard 638:c90ae1400bf2 287 * notifying the application of command completion, consuming the command queue element,
Vincent Coubard 638:c90ae1400bf2 288 * and changing the internal state.
Vincent Coubard 638:c90ae1400bf2 289 */
Vincent Coubard 638:c90ae1400bf2 290 static void command_end_procedure_run(void)
Vincent Coubard 638:c90ae1400bf2 291 {
Vincent Coubard 638:c90ae1400bf2 292 app_notify(NRF_SUCCESS, &m_cmd_queue.cmd[m_cmd_queue.rp]);
Vincent Coubard 638:c90ae1400bf2 293
Vincent Coubard 638:c90ae1400bf2 294 command_queue_element_consume();
Vincent Coubard 638:c90ae1400bf2 295
Vincent Coubard 638:c90ae1400bf2 296 sm_state_change(STATE_IDLE);
Vincent Coubard 638:c90ae1400bf2 297 }
Vincent Coubard 638:c90ae1400bf2 298
Vincent Coubard 638:c90ae1400bf2 299
Vincent Coubard 638:c90ae1400bf2 300 /**@brief Function for idle state entry actions.
Vincent Coubard 638:c90ae1400bf2 301 *
Vincent Coubard 638:c90ae1400bf2 302 * @details Function for idle state entry actions, which include resetting relevant state data and
Vincent Coubard 638:c90ae1400bf2 303 * scheduling any possible queued flash access operation.
Vincent Coubard 638:c90ae1400bf2 304 */
Vincent Coubard 638:c90ae1400bf2 305 static void state_idle_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 306 {
Vincent Coubard 638:c90ae1400bf2 307 m_num_of_command_retries = 0;
Vincent Coubard 638:c90ae1400bf2 308 m_num_of_bytes_written = 0;
Vincent Coubard 638:c90ae1400bf2 309
Vincent Coubard 638:c90ae1400bf2 310 // Schedule any possible queued flash access operation.
Vincent Coubard 638:c90ae1400bf2 311 cmd_queue_dequeue();
Vincent Coubard 638:c90ae1400bf2 312 }
Vincent Coubard 638:c90ae1400bf2 313
Vincent Coubard 638:c90ae1400bf2 314
Vincent Coubard 638:c90ae1400bf2 315 /**@brief Function for notifying an application of command completion and transitioning to an error
Vincent Coubard 638:c90ae1400bf2 316 * state.
Vincent Coubard 638:c90ae1400bf2 317 *
Vincent Coubard 638:c90ae1400bf2 318 * @param[in] result Result code of the operation for the application.
Vincent Coubard 638:c90ae1400bf2 319 */
Vincent Coubard 638:c90ae1400bf2 320 static void app_notify_error_state_transit(uint32_t result)
Vincent Coubard 638:c90ae1400bf2 321 {
Vincent Coubard 638:c90ae1400bf2 322 app_notify(result, &m_cmd_queue.cmd[m_cmd_queue.rp]);
Vincent Coubard 638:c90ae1400bf2 323 sm_state_change(STATE_ERROR);
Vincent Coubard 638:c90ae1400bf2 324 }
Vincent Coubard 638:c90ae1400bf2 325
Vincent Coubard 638:c90ae1400bf2 326
Vincent Coubard 638:c90ae1400bf2 327 /**@brief Function for processing flash API error code.
Vincent Coubard 638:c90ae1400bf2 328 *
Vincent Coubard 638:c90ae1400bf2 329 * @param[in] err_code Error code from the flash API.
Vincent Coubard 638:c90ae1400bf2 330 */
Vincent Coubard 638:c90ae1400bf2 331 static void flash_api_err_code_process(uint32_t err_code)
Vincent Coubard 638:c90ae1400bf2 332 {
Vincent Coubard 638:c90ae1400bf2 333 switch (err_code)
Vincent Coubard 638:c90ae1400bf2 334 {
Vincent Coubard 638:c90ae1400bf2 335 case NRF_SUCCESS:
Vincent Coubard 638:c90ae1400bf2 336 break;
Vincent Coubard 638:c90ae1400bf2 337
Vincent Coubard 638:c90ae1400bf2 338 case NRF_ERROR_BUSY:
Vincent Coubard 638:c90ae1400bf2 339 // Flash access operation was not accepted and must be reissued upon flash operation
Vincent Coubard 638:c90ae1400bf2 340 // complete event.
Vincent Coubard 638:c90ae1400bf2 341 m_flags |= MASK_FLASH_API_ERR_BUSY;
Vincent Coubard 638:c90ae1400bf2 342 break;
Vincent Coubard 638:c90ae1400bf2 343
Vincent Coubard 638:c90ae1400bf2 344 default:
Vincent Coubard 638:c90ae1400bf2 345 // Complete the operation with appropriate result code and transit to an error state.
Vincent Coubard 638:c90ae1400bf2 346 app_notify_error_state_transit(err_code);
Vincent Coubard 638:c90ae1400bf2 347 break;
Vincent Coubard 638:c90ae1400bf2 348 }
Vincent Coubard 638:c90ae1400bf2 349 }
Vincent Coubard 638:c90ae1400bf2 350
Vincent Coubard 638:c90ae1400bf2 351 /**@brief Function for writing data to flash.
Vincent Coubard 638:c90ae1400bf2 352 *
Vincent Coubard 638:c90ae1400bf2 353 * @param[in] p_dst Pointer to start of flash location to be written.
Vincent Coubard 638:c90ae1400bf2 354 * @param[in] p_src Pointer to buffer with data to be written.
Vincent Coubard 638:c90ae1400bf2 355 * @param[in] size_in_words Number of 32-bit words to write.
Vincent Coubard 638:c90ae1400bf2 356 */
Vincent Coubard 638:c90ae1400bf2 357 static void flash_write(uint32_t * const p_dst,
Vincent Coubard 638:c90ae1400bf2 358 uint32_t const * const p_src,
Vincent Coubard 638:c90ae1400bf2 359 uint32_t size_in_words)
Vincent Coubard 638:c90ae1400bf2 360 {
Vincent Coubard 638:c90ae1400bf2 361 flash_api_err_code_process(sd_flash_write(p_dst, p_src, size_in_words));
Vincent Coubard 638:c90ae1400bf2 362 }
Vincent Coubard 638:c90ae1400bf2 363
Vincent Coubard 638:c90ae1400bf2 364
Vincent Coubard 638:c90ae1400bf2 365 /**@brief Function for writing data to flash upon store command.
Vincent Coubard 638:c90ae1400bf2 366 *
Vincent Coubard 638:c90ae1400bf2 367 * @details Function for writing data to flash upon executing store command. Data is written to
Vincent Coubard 638:c90ae1400bf2 368 * flash in reverse order, meaning starting at the end. If the data that is to be written
Vincent Coubard 638:c90ae1400bf2 369 * is greater than the flash page size, it will be fragmented to fit the flash page size.
Vincent Coubard 638:c90ae1400bf2 370 */
Vincent Coubard 638:c90ae1400bf2 371 static void store_cmd_flash_write_execute(void)
Vincent Coubard 638:c90ae1400bf2 372 {
Vincent Coubard 638:c90ae1400bf2 373 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 374
Vincent Coubard 638:c90ae1400bf2 375 if (p_cmd->size > SOC_MAX_WRITE_SIZE)
Vincent Coubard 638:c90ae1400bf2 376 {
Vincent Coubard 638:c90ae1400bf2 377 const uint32_t offset = p_cmd->size - PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 378 flash_write((uint32_t *)(p_cmd->storage_addr.block_id + p_cmd->offset + offset),
Vincent Coubard 638:c90ae1400bf2 379 (uint32_t *)(p_cmd->p_data_addr + offset),
Vincent Coubard 638:c90ae1400bf2 380 PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
Vincent Coubard 638:c90ae1400bf2 381
Vincent Coubard 638:c90ae1400bf2 382 m_num_of_bytes_written = PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 383 }
Vincent Coubard 638:c90ae1400bf2 384 else
Vincent Coubard 638:c90ae1400bf2 385 {
Vincent Coubard 638:c90ae1400bf2 386 flash_write((uint32_t *)(p_cmd->storage_addr.block_id + p_cmd->offset),
Vincent Coubard 638:c90ae1400bf2 387 (uint32_t *)(p_cmd->p_data_addr),
Vincent Coubard 638:c90ae1400bf2 388 p_cmd->size / sizeof(uint32_t));
Vincent Coubard 638:c90ae1400bf2 389
Vincent Coubard 638:c90ae1400bf2 390 m_num_of_bytes_written = p_cmd->size;
Vincent Coubard 638:c90ae1400bf2 391 }
Vincent Coubard 638:c90ae1400bf2 392 }
Vincent Coubard 638:c90ae1400bf2 393
Vincent Coubard 638:c90ae1400bf2 394
Vincent Coubard 638:c90ae1400bf2 395 /**@brief Function for store state entry action.
Vincent Coubard 638:c90ae1400bf2 396 *
Vincent Coubard 638:c90ae1400bf2 397 * @details Function for store state entry action, which includes writing data to a flash page.
Vincent Coubard 638:c90ae1400bf2 398 */
Vincent Coubard 638:c90ae1400bf2 399 static void state_store_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 400 {
Vincent Coubard 638:c90ae1400bf2 401 store_cmd_flash_write_execute();
Vincent Coubard 638:c90ae1400bf2 402 }
Vincent Coubard 638:c90ae1400bf2 403
Vincent Coubard 638:c90ae1400bf2 404
Vincent Coubard 638:c90ae1400bf2 405 /**@brief Function for data erase with swap state entry actions.
Vincent Coubard 638:c90ae1400bf2 406 *
Vincent Coubard 638:c90ae1400bf2 407 * @details Function for data erase with swap state entry actions. This includes adjusting relevant
Vincent Coubard 638:c90ae1400bf2 408 * state and data variables and transitioning to the correct sub state.
Vincent Coubard 638:c90ae1400bf2 409 */
Vincent Coubard 638:c90ae1400bf2 410 static void state_data_erase_swap_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 411 {
Vincent Coubard 638:c90ae1400bf2 412 m_flags &= ~MASK_TAIL_SWAP_DONE;
Vincent Coubard 638:c90ae1400bf2 413
Vincent Coubard 638:c90ae1400bf2 414 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 415 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
Vincent Coubard 638:c90ae1400bf2 416
Vincent Coubard 638:c90ae1400bf2 417 const uint32_t clear_start_page_id = cmd_block_id / PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 418 m_current_page_id = clear_start_page_id;
Vincent Coubard 638:c90ae1400bf2 419
Vincent Coubard 638:c90ae1400bf2 420 // @note: No need to include p_cmd->offset when calculating clear_end_page_id as:
Vincent Coubard 638:c90ae1400bf2 421 // - clear API does not include offset parameter
Vincent Coubard 638:c90ae1400bf2 422 // - update and store APIs are limited to operate on single block boundary thus the boolean
Vincent Coubard 638:c90ae1400bf2 423 // clause ((m_head_word_size == 0) && is_more_than_one_page) below in this function will never
Vincent Coubard 638:c90ae1400bf2 424 // evaluate as true as if is_more_than_one_page == true m_head_word_size is always != 0
Vincent Coubard 638:c90ae1400bf2 425 const uint32_t clear_end_page_id = (cmd_block_id + p_cmd->size - 1u) /
Vincent Coubard 638:c90ae1400bf2 426 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 427
Vincent Coubard 638:c90ae1400bf2 428 if (clear_start_page_id == clear_end_page_id)
Vincent Coubard 638:c90ae1400bf2 429 {
Vincent Coubard 638:c90ae1400bf2 430 m_flags |= MASK_SINGLE_PAGE_OPERATION;
Vincent Coubard 638:c90ae1400bf2 431 }
Vincent Coubard 638:c90ae1400bf2 432 else
Vincent Coubard 638:c90ae1400bf2 433 {
Vincent Coubard 638:c90ae1400bf2 434 m_flags &= ~MASK_SINGLE_PAGE_OPERATION;
Vincent Coubard 638:c90ae1400bf2 435 }
Vincent Coubard 638:c90ae1400bf2 436
Vincent Coubard 638:c90ae1400bf2 437 if ((m_head_word_size == 0) && !(m_flags & MASK_SINGLE_PAGE_OPERATION))
Vincent Coubard 638:c90ae1400bf2 438 {
Vincent Coubard 638:c90ae1400bf2 439 // No head restore required and clear/update area is shared by multiple flash pages, which
Vincent Coubard 638:c90ae1400bf2 440 // means the current flash page does not have any tail area to restore. You can proceed with
Vincent Coubard 638:c90ae1400bf2 441 // data page erase directly as no swap is needed for the current flash page.
Vincent Coubard 638:c90ae1400bf2 442 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
Vincent Coubard 638:c90ae1400bf2 443 }
Vincent Coubard 638:c90ae1400bf2 444 else
Vincent Coubard 638:c90ae1400bf2 445 {
Vincent Coubard 638:c90ae1400bf2 446 swap_sub_state_state_change(STATE_ERASE_SWAP);
Vincent Coubard 638:c90ae1400bf2 447 }
Vincent Coubard 638:c90ae1400bf2 448 }
Vincent Coubard 638:c90ae1400bf2 449
Vincent Coubard 638:c90ae1400bf2 450
Vincent Coubard 638:c90ae1400bf2 451 /**@brief Function for erasing flash page.
Vincent Coubard 638:c90ae1400bf2 452 *
Vincent Coubard 638:c90ae1400bf2 453 * @param[in] page_number Page number of the page to be erased.
Vincent Coubard 638:c90ae1400bf2 454 */
Vincent Coubard 638:c90ae1400bf2 455 static void flash_page_erase(uint32_t page_number)
Vincent Coubard 638:c90ae1400bf2 456 {
Vincent Coubard 638:c90ae1400bf2 457 flash_api_err_code_process(sd_flash_page_erase(page_number));
Vincent Coubard 638:c90ae1400bf2 458 }
Vincent Coubard 638:c90ae1400bf2 459
Vincent Coubard 638:c90ae1400bf2 460
Vincent Coubard 638:c90ae1400bf2 461 /**@brief Function for data erase state entry action.
Vincent Coubard 638:c90ae1400bf2 462 *
Vincent Coubard 638:c90ae1400bf2 463 * @details Function for data erase state entry action, which includes erasing the data flash page.
Vincent Coubard 638:c90ae1400bf2 464 */
Vincent Coubard 638:c90ae1400bf2 465 static void state_data_erase_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 466 {
Vincent Coubard 638:c90ae1400bf2 467 flash_page_erase(m_current_page_id);
Vincent Coubard 638:c90ae1400bf2 468 }
Vincent Coubard 638:c90ae1400bf2 469
Vincent Coubard 638:c90ae1400bf2 470
Vincent Coubard 638:c90ae1400bf2 471 /**@brief Function for dispatching the correct application main state entry action.
Vincent Coubard 638:c90ae1400bf2 472 */
Vincent Coubard 638:c90ae1400bf2 473 static void state_entry_action_run(void)
Vincent Coubard 638:c90ae1400bf2 474 {
Vincent Coubard 638:c90ae1400bf2 475 switch (m_state)
Vincent Coubard 638:c90ae1400bf2 476 {
Vincent Coubard 638:c90ae1400bf2 477 case STATE_IDLE:
Vincent Coubard 638:c90ae1400bf2 478 state_idle_entry_run();
Vincent Coubard 638:c90ae1400bf2 479 break;
Vincent Coubard 638:c90ae1400bf2 480
Vincent Coubard 638:c90ae1400bf2 481 case STATE_STORE:
Vincent Coubard 638:c90ae1400bf2 482 state_store_entry_run();
Vincent Coubard 638:c90ae1400bf2 483 break;
Vincent Coubard 638:c90ae1400bf2 484
Vincent Coubard 638:c90ae1400bf2 485 case STATE_DATA_ERASE_WITH_SWAP:
Vincent Coubard 638:c90ae1400bf2 486 state_data_erase_swap_entry_run();
Vincent Coubard 638:c90ae1400bf2 487 break;
Vincent Coubard 638:c90ae1400bf2 488
Vincent Coubard 638:c90ae1400bf2 489 case STATE_DATA_ERASE:
Vincent Coubard 638:c90ae1400bf2 490 state_data_erase_entry_run();
Vincent Coubard 638:c90ae1400bf2 491 break;
Vincent Coubard 638:c90ae1400bf2 492
Vincent Coubard 638:c90ae1400bf2 493 default:
Vincent Coubard 638:c90ae1400bf2 494 // No action needed.
Vincent Coubard 638:c90ae1400bf2 495 break;
Vincent Coubard 638:c90ae1400bf2 496 }
Vincent Coubard 638:c90ae1400bf2 497 }
Vincent Coubard 638:c90ae1400bf2 498
Vincent Coubard 638:c90ae1400bf2 499
Vincent Coubard 638:c90ae1400bf2 500 /**@brief Function for changing application main state and dispatching state entry action.
Vincent Coubard 638:c90ae1400bf2 501 *
Vincent Coubard 638:c90ae1400bf2 502 * @param[in] new_state New application main state to transit to.
Vincent Coubard 638:c90ae1400bf2 503 */
Vincent Coubard 638:c90ae1400bf2 504 static void sm_state_change(pstorage_state_t new_state)
Vincent Coubard 638:c90ae1400bf2 505 {
Vincent Coubard 638:c90ae1400bf2 506 m_state = new_state;
Vincent Coubard 638:c90ae1400bf2 507 state_entry_action_run();
Vincent Coubard 638:c90ae1400bf2 508 }
Vincent Coubard 638:c90ae1400bf2 509
Vincent Coubard 638:c90ae1400bf2 510
Vincent Coubard 638:c90ae1400bf2 511 /**@brief Function for swap erase state entry action.
Vincent Coubard 638:c90ae1400bf2 512 *
Vincent Coubard 638:c90ae1400bf2 513 * @details Function for swap erase state entry action, which includes erasing swap flash
Vincent Coubard 638:c90ae1400bf2 514 * page.
Vincent Coubard 638:c90ae1400bf2 515 */
Vincent Coubard 638:c90ae1400bf2 516 static void state_swap_erase_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 517 {
Vincent Coubard 638:c90ae1400bf2 518 flash_page_erase(PSTORAGE_SWAP_ADDR / PSTORAGE_FLASH_PAGE_SIZE);
Vincent Coubard 638:c90ae1400bf2 519 }
Vincent Coubard 638:c90ae1400bf2 520
Vincent Coubard 638:c90ae1400bf2 521
Vincent Coubard 638:c90ae1400bf2 522 /**@brief Function for write data to the swap state entry action.
Vincent Coubard 638:c90ae1400bf2 523 *
Vincent Coubard 638:c90ae1400bf2 524 * @details Function for write data to the swap state entry action, which includes writing the
Vincent Coubard 638:c90ae1400bf2 525 * current data page to the swap flash page.
Vincent Coubard 638:c90ae1400bf2 526 */
Vincent Coubard 638:c90ae1400bf2 527 static void state_write_data_swap_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 528 {
Vincent Coubard 638:c90ae1400bf2 529 // @note: There is room for further optimization here as there is only need to write the
Vincent Coubard 638:c90ae1400bf2 530 // whole flash page to swap area if there is both head and tail area to be restored. In any
Vincent Coubard 638:c90ae1400bf2 531 // other case we can omit some data from the head or end of the page as that is the clear area.
Vincent Coubard 638:c90ae1400bf2 532 flash_write((uint32_t *)(PSTORAGE_SWAP_ADDR),
Vincent Coubard 638:c90ae1400bf2 533 (uint32_t *)(m_current_page_id * PSTORAGE_FLASH_PAGE_SIZE),
Vincent Coubard 638:c90ae1400bf2 534 PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
Vincent Coubard 638:c90ae1400bf2 535 }
Vincent Coubard 638:c90ae1400bf2 536
Vincent Coubard 638:c90ae1400bf2 537
Vincent Coubard 638:c90ae1400bf2 538 /**@brief Function for erase data page state entry action.
Vincent Coubard 638:c90ae1400bf2 539 *
Vincent Coubard 638:c90ae1400bf2 540 * @details Function for erase data page state entry action, which includes erasing the data flash
Vincent Coubard 638:c90ae1400bf2 541 * page.
Vincent Coubard 638:c90ae1400bf2 542 */
Vincent Coubard 638:c90ae1400bf2 543 static void state_erase_data_page_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 544 {
Vincent Coubard 638:c90ae1400bf2 545 flash_page_erase(m_current_page_id);
Vincent Coubard 638:c90ae1400bf2 546 }
Vincent Coubard 638:c90ae1400bf2 547
Vincent Coubard 638:c90ae1400bf2 548
Vincent Coubard 638:c90ae1400bf2 549 /**@brief Function for restore tail state entry action.
Vincent Coubard 638:c90ae1400bf2 550 *
Vincent Coubard 638:c90ae1400bf2 551 * @details Function for restore tail state entry action, which includes writing the tail section
Vincent Coubard 638:c90ae1400bf2 552 * back from swap to the data page.
Vincent Coubard 638:c90ae1400bf2 553 */
Vincent Coubard 638:c90ae1400bf2 554 static void state_restore_tail_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 555 {
Vincent Coubard 638:c90ae1400bf2 556 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 557 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
Vincent Coubard 638:c90ae1400bf2 558
Vincent Coubard 638:c90ae1400bf2 559 const uint32_t tail_offset = (cmd_block_id + p_cmd->size + p_cmd->offset) %
Vincent Coubard 638:c90ae1400bf2 560 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 561
Vincent Coubard 638:c90ae1400bf2 562 flash_write((uint32_t *)(cmd_block_id + p_cmd->size + p_cmd->offset),
Vincent Coubard 638:c90ae1400bf2 563 (uint32_t *)(PSTORAGE_SWAP_ADDR + tail_offset),
Vincent Coubard 638:c90ae1400bf2 564 m_tail_word_size);
Vincent Coubard 638:c90ae1400bf2 565 }
Vincent Coubard 638:c90ae1400bf2 566
Vincent Coubard 638:c90ae1400bf2 567
Vincent Coubard 638:c90ae1400bf2 568 /**@brief Function for restore head state entry action.
Vincent Coubard 638:c90ae1400bf2 569 *
Vincent Coubard 638:c90ae1400bf2 570 * @details Function for restore head state entry action, which includes writing the head section
Vincent Coubard 638:c90ae1400bf2 571 * back from swap to the data page.
Vincent Coubard 638:c90ae1400bf2 572 */
Vincent Coubard 638:c90ae1400bf2 573 static void state_restore_head_entry_run(void)
Vincent Coubard 638:c90ae1400bf2 574 {
Vincent Coubard 638:c90ae1400bf2 575 flash_write((uint32_t *)((m_current_page_id - 1u) * PSTORAGE_FLASH_PAGE_SIZE),
Vincent Coubard 638:c90ae1400bf2 576 (uint32_t *)PSTORAGE_SWAP_ADDR,
Vincent Coubard 638:c90ae1400bf2 577 m_head_word_size);
Vincent Coubard 638:c90ae1400bf2 578 }
Vincent Coubard 638:c90ae1400bf2 579
Vincent Coubard 638:c90ae1400bf2 580
Vincent Coubard 638:c90ae1400bf2 581 /**@brief Function for dispatching the correct swap sub state entry action.
Vincent Coubard 638:c90ae1400bf2 582 */
Vincent Coubard 638:c90ae1400bf2 583 static void swap_sub_state_entry_action_run(void)
Vincent Coubard 638:c90ae1400bf2 584 {
Vincent Coubard 638:c90ae1400bf2 585 static void (* const swap_sub_state_sm_lut[SWAP_SUB_STATE_MAX])(void) =
Vincent Coubard 638:c90ae1400bf2 586 {
Vincent Coubard 638:c90ae1400bf2 587 state_swap_erase_entry_run,
Vincent Coubard 638:c90ae1400bf2 588 state_write_data_swap_entry_run,
Vincent Coubard 638:c90ae1400bf2 589 state_erase_data_page_entry_run,
Vincent Coubard 638:c90ae1400bf2 590 state_restore_tail_entry_run,
Vincent Coubard 638:c90ae1400bf2 591 state_restore_head_entry_run
Vincent Coubard 638:c90ae1400bf2 592 };
Vincent Coubard 638:c90ae1400bf2 593
Vincent Coubard 638:c90ae1400bf2 594 swap_sub_state_sm_lut[m_swap_sub_state]();
Vincent Coubard 638:c90ae1400bf2 595 }
Vincent Coubard 638:c90ae1400bf2 596
Vincent Coubard 638:c90ae1400bf2 597
Vincent Coubard 638:c90ae1400bf2 598 /**@brief Function for changing the swap sub state and dispatching state entry action.
Vincent Coubard 638:c90ae1400bf2 599 *
Vincent Coubard 638:c90ae1400bf2 600 * @param[in] new_state New swap sub state to transit to.
Vincent Coubard 638:c90ae1400bf2 601 */
Vincent Coubard 638:c90ae1400bf2 602 static void swap_sub_state_state_change(flash_swap_sub_state_t new_state)
Vincent Coubard 638:c90ae1400bf2 603 {
Vincent Coubard 638:c90ae1400bf2 604 m_swap_sub_state = new_state;
Vincent Coubard 638:c90ae1400bf2 605 swap_sub_state_entry_action_run();
Vincent Coubard 638:c90ae1400bf2 606 }
Vincent Coubard 638:c90ae1400bf2 607
Vincent Coubard 638:c90ae1400bf2 608
Vincent Coubard 638:c90ae1400bf2 609 /**@brief Function for initializing the command queue element.
Vincent Coubard 638:c90ae1400bf2 610 *
Vincent Coubard 638:c90ae1400bf2 611 * @param[in] index Index of the element to be initialized.
Vincent Coubard 638:c90ae1400bf2 612 */
Vincent Coubard 638:c90ae1400bf2 613 static void cmd_queue_element_init(uint32_t index)
Vincent Coubard 638:c90ae1400bf2 614 {
Vincent Coubard 638:c90ae1400bf2 615 // Internal function and checks on range of index can be avoided.
Vincent Coubard 638:c90ae1400bf2 616 m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
Vincent Coubard 638:c90ae1400bf2 617 m_cmd_queue.cmd[index].size = 0;
Vincent Coubard 638:c90ae1400bf2 618 m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_NUM_OF_PAGES;
Vincent Coubard 638:c90ae1400bf2 619 m_cmd_queue.cmd[index].storage_addr.block_id = 0;
Vincent Coubard 638:c90ae1400bf2 620 m_cmd_queue.cmd[index].p_data_addr = NULL;
Vincent Coubard 638:c90ae1400bf2 621 m_cmd_queue.cmd[index].offset = 0;
Vincent Coubard 638:c90ae1400bf2 622 }
Vincent Coubard 638:c90ae1400bf2 623
Vincent Coubard 638:c90ae1400bf2 624
Vincent Coubard 638:c90ae1400bf2 625 /**@brief Function for initializing the command queue.
Vincent Coubard 638:c90ae1400bf2 626 */
Vincent Coubard 638:c90ae1400bf2 627 static void cmd_queue_init(void)
Vincent Coubard 638:c90ae1400bf2 628 {
Vincent Coubard 638:c90ae1400bf2 629 m_cmd_queue.rp = 0;
Vincent Coubard 638:c90ae1400bf2 630 m_cmd_queue.count = 0;
Vincent Coubard 638:c90ae1400bf2 631
Vincent Coubard 638:c90ae1400bf2 632 for (uint32_t cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; ++cmd_index)
Vincent Coubard 638:c90ae1400bf2 633 {
Vincent Coubard 638:c90ae1400bf2 634 cmd_queue_element_init(cmd_index);
Vincent Coubard 638:c90ae1400bf2 635 }
Vincent Coubard 638:c90ae1400bf2 636 }
Vincent Coubard 638:c90ae1400bf2 637
Vincent Coubard 638:c90ae1400bf2 638
Vincent Coubard 638:c90ae1400bf2 639 /**@brief Function for enqueuing, and possibly dispatching, a flash access operation.
Vincent Coubard 638:c90ae1400bf2 640 *
Vincent Coubard 638:c90ae1400bf2 641 * @param[in] opcode Identifies the operation requested to be enqueued.
Vincent Coubard 638:c90ae1400bf2 642 * @param[in] p_storage_addr Identifies the module and flash address on which the operation is
Vincent Coubard 638:c90ae1400bf2 643 * requested.
Vincent Coubard 638:c90ae1400bf2 644 * @param[in] p_data_addr Identifies the data address for flash access.
Vincent Coubard 638:c90ae1400bf2 645 * @param[in] size Size in bytes of data requested for the access operation.
Vincent Coubard 638:c90ae1400bf2 646 * @param[in] offset Offset within the flash memory block at which operation is requested.
Vincent Coubard 638:c90ae1400bf2 647 *
Vincent Coubard 638:c90ae1400bf2 648 * @retval NRF_SUCCESS Upon success.
Vincent Coubard 638:c90ae1400bf2 649 * @retval NRF_ERROR_NO_MEM Upon failure, when no space is available in the command queue.
Vincent Coubard 638:c90ae1400bf2 650 */
Vincent Coubard 638:c90ae1400bf2 651 static uint32_t cmd_queue_enqueue(uint8_t opcode,
Vincent Coubard 638:c90ae1400bf2 652 pstorage_handle_t * p_storage_addr,
Vincent Coubard 638:c90ae1400bf2 653 uint8_t * p_data_addr,
Vincent Coubard 638:c90ae1400bf2 654 pstorage_size_t size,
Vincent Coubard 638:c90ae1400bf2 655 pstorage_size_t offset)
Vincent Coubard 638:c90ae1400bf2 656 {
Vincent Coubard 638:c90ae1400bf2 657 uint32_t err_code;
Vincent Coubard 638:c90ae1400bf2 658
Vincent Coubard 638:c90ae1400bf2 659 if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 638:c90ae1400bf2 660 {
Vincent Coubard 638:c90ae1400bf2 661 // Enqueue the command if it the queue is not full.
Vincent Coubard 638:c90ae1400bf2 662 uint32_t write_index = m_cmd_queue.rp + m_cmd_queue.count;
Vincent Coubard 638:c90ae1400bf2 663
Vincent Coubard 638:c90ae1400bf2 664 if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
Vincent Coubard 638:c90ae1400bf2 665 {
Vincent Coubard 638:c90ae1400bf2 666 write_index -= PSTORAGE_CMD_QUEUE_SIZE;
Vincent Coubard 638:c90ae1400bf2 667 }
Vincent Coubard 638:c90ae1400bf2 668
Vincent Coubard 638:c90ae1400bf2 669 m_cmd_queue.cmd[write_index].op_code = opcode;
Vincent Coubard 638:c90ae1400bf2 670 m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
Vincent Coubard 638:c90ae1400bf2 671 m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
Vincent Coubard 638:c90ae1400bf2 672 m_cmd_queue.cmd[write_index].size = size;
Vincent Coubard 638:c90ae1400bf2 673 m_cmd_queue.cmd[write_index].offset = offset;
Vincent Coubard 638:c90ae1400bf2 674
Vincent Coubard 638:c90ae1400bf2 675 m_cmd_queue.count++;
Vincent Coubard 638:c90ae1400bf2 676
Vincent Coubard 638:c90ae1400bf2 677 if (m_state == STATE_IDLE)
Vincent Coubard 638:c90ae1400bf2 678 {
Vincent Coubard 638:c90ae1400bf2 679 cmd_process();
Vincent Coubard 638:c90ae1400bf2 680 }
Vincent Coubard 638:c90ae1400bf2 681
Vincent Coubard 638:c90ae1400bf2 682 err_code = NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 683 }
Vincent Coubard 638:c90ae1400bf2 684 else
Vincent Coubard 638:c90ae1400bf2 685 {
Vincent Coubard 638:c90ae1400bf2 686 err_code = NRF_ERROR_NO_MEM;
Vincent Coubard 638:c90ae1400bf2 687 }
Vincent Coubard 638:c90ae1400bf2 688
Vincent Coubard 638:c90ae1400bf2 689 return err_code;
Vincent Coubard 638:c90ae1400bf2 690 }
Vincent Coubard 638:c90ae1400bf2 691
Vincent Coubard 638:c90ae1400bf2 692
Vincent Coubard 638:c90ae1400bf2 693 /**@brief Function for dequeing a possible pending flash access operation.
Vincent Coubard 638:c90ae1400bf2 694 */
Vincent Coubard 638:c90ae1400bf2 695 static void cmd_queue_dequeue(void)
Vincent Coubard 638:c90ae1400bf2 696 {
Vincent Coubard 638:c90ae1400bf2 697 if ((m_cmd_queue.count != 0))
Vincent Coubard 638:c90ae1400bf2 698 {
Vincent Coubard 638:c90ae1400bf2 699 cmd_process();
Vincent Coubard 638:c90ae1400bf2 700 }
Vincent Coubard 638:c90ae1400bf2 701 }
Vincent Coubard 638:c90ae1400bf2 702
Vincent Coubard 638:c90ae1400bf2 703
Vincent Coubard 638:c90ae1400bf2 704 /**@brief Function for notifying an application of command completion.
Vincent Coubard 638:c90ae1400bf2 705 *
Vincent Coubard 638:c90ae1400bf2 706 * @param[in] result Result code of the operation for the application.
Vincent Coubard 638:c90ae1400bf2 707 * @param[in] p_elem Pointer to the command queue element for which this result was received.
Vincent Coubard 638:c90ae1400bf2 708 */
Vincent Coubard 638:c90ae1400bf2 709 static void app_notify(uint32_t result, cmd_queue_element_t * p_elem)
Vincent Coubard 638:c90ae1400bf2 710 {
Vincent Coubard 638:c90ae1400bf2 711 pstorage_ntf_cb_t ntf_cb;
Vincent Coubard 638:c90ae1400bf2 712 const uint8_t op_code = p_elem->op_code;
Vincent Coubard 638:c90ae1400bf2 713
Vincent Coubard 638:c90ae1400bf2 714 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 715 if (p_elem->storage_addr.module_id == RAW_MODE_APP_ID)
Vincent Coubard 638:c90ae1400bf2 716 {
Vincent Coubard 638:c90ae1400bf2 717 ntf_cb = m_raw_app_table.cb;
Vincent Coubard 638:c90ae1400bf2 718 }
Vincent Coubard 638:c90ae1400bf2 719 else
Vincent Coubard 638:c90ae1400bf2 720 #endif // PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 721 {
Vincent Coubard 638:c90ae1400bf2 722 ntf_cb = m_app_table[p_elem->storage_addr.module_id].cb;
Vincent Coubard 638:c90ae1400bf2 723 }
Vincent Coubard 638:c90ae1400bf2 724
Vincent Coubard 638:c90ae1400bf2 725 ntf_cb(&p_elem->storage_addr, op_code, result, p_elem->p_data_addr, m_app_data_size);
Vincent Coubard 638:c90ae1400bf2 726 }
Vincent Coubard 638:c90ae1400bf2 727
Vincent Coubard 638:c90ae1400bf2 728
Vincent Coubard 638:c90ae1400bf2 729 /**@brief Function for evaluating if a data page swap is required for the tail section on the
Vincent Coubard 638:c90ae1400bf2 730 * current page.
Vincent Coubard 638:c90ae1400bf2 731 *
Vincent Coubard 638:c90ae1400bf2 732 * @retval true If data page swap is required.
Vincent Coubard 638:c90ae1400bf2 733 * @retval false If data page swap is not required.
Vincent Coubard 638:c90ae1400bf2 734 */
Vincent Coubard 638:c90ae1400bf2 735 static bool is_tail_data_page_swap_required(void)
Vincent Coubard 638:c90ae1400bf2 736 {
Vincent Coubard 638:c90ae1400bf2 737 bool ret_value;
Vincent Coubard 638:c90ae1400bf2 738
Vincent Coubard 638:c90ae1400bf2 739 // Extract id of the last page command is executed upon.
Vincent Coubard 638:c90ae1400bf2 740 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 741 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
Vincent Coubard 638:c90ae1400bf2 742 const uint32_t last_page_id = (cmd_block_id + p_cmd->size + p_cmd->offset - 1u) /
Vincent Coubard 638:c90ae1400bf2 743 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 744
Vincent Coubard 638:c90ae1400bf2 745 // If tail section area exists and the current page is the last page then tail data page swap is
Vincent Coubard 638:c90ae1400bf2 746 // required.
Vincent Coubard 638:c90ae1400bf2 747 if ((m_tail_word_size != 0) && (m_current_page_id == last_page_id))
Vincent Coubard 638:c90ae1400bf2 748 {
Vincent Coubard 638:c90ae1400bf2 749 ret_value = true;
Vincent Coubard 638:c90ae1400bf2 750 }
Vincent Coubard 638:c90ae1400bf2 751 else
Vincent Coubard 638:c90ae1400bf2 752 {
Vincent Coubard 638:c90ae1400bf2 753 ret_value = false;
Vincent Coubard 638:c90ae1400bf2 754 }
Vincent Coubard 638:c90ae1400bf2 755
Vincent Coubard 638:c90ae1400bf2 756 return ret_value;
Vincent Coubard 638:c90ae1400bf2 757 }
Vincent Coubard 638:c90ae1400bf2 758
Vincent Coubard 638:c90ae1400bf2 759
Vincent Coubard 638:c90ae1400bf2 760 /**@brief Function for performing post processing for the update and clear commands.
Vincent Coubard 638:c90ae1400bf2 761 *
Vincent Coubard 638:c90ae1400bf2 762 * @details Function for performing post processing for the update and clear commands, which implies
Vincent Coubard 638:c90ae1400bf2 763 * executing the correct execution path depending on the command.
Vincent Coubard 638:c90ae1400bf2 764 */
Vincent Coubard 638:c90ae1400bf2 765 static void clear_post_processing_run(void)
Vincent Coubard 638:c90ae1400bf2 766 {
Vincent Coubard 638:c90ae1400bf2 767 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 768
Vincent Coubard 638:c90ae1400bf2 769 if (p_cmd->op_code != PSTORAGE_UPDATE_OP_CODE)
Vincent Coubard 638:c90ae1400bf2 770 {
Vincent Coubard 638:c90ae1400bf2 771 command_end_procedure_run();
Vincent Coubard 638:c90ae1400bf2 772 }
Vincent Coubard 638:c90ae1400bf2 773 else
Vincent Coubard 638:c90ae1400bf2 774 {
Vincent Coubard 638:c90ae1400bf2 775 store_operation_execute();
Vincent Coubard 638:c90ae1400bf2 776 }
Vincent Coubard 638:c90ae1400bf2 777 }
Vincent Coubard 638:c90ae1400bf2 778
Vincent Coubard 638:c90ae1400bf2 779
Vincent Coubard 638:c90ae1400bf2 780 /**@brief Function for doing swap sub state exit action.
Vincent Coubard 638:c90ae1400bf2 781 */
Vincent Coubard 638:c90ae1400bf2 782 static void swap_sub_sm_exit_action_run(void)
Vincent Coubard 638:c90ae1400bf2 783 {
Vincent Coubard 638:c90ae1400bf2 784 clear_post_processing_run();
Vincent Coubard 638:c90ae1400bf2 785 }
Vincent Coubard 638:c90ae1400bf2 786
Vincent Coubard 638:c90ae1400bf2 787
Vincent Coubard 638:c90ae1400bf2 788 /**@brief Function for evaluating if the page erase operation is required for the current page.
Vincent Coubard 638:c90ae1400bf2 789 *
Vincent Coubard 638:c90ae1400bf2 790 * @retval true If page erase is required.
Vincent Coubard 638:c90ae1400bf2 791 * @retval false If page erase is not required.
Vincent Coubard 638:c90ae1400bf2 792 */
Vincent Coubard 638:c90ae1400bf2 793 static bool is_page_erase_required(void)
Vincent Coubard 638:c90ae1400bf2 794 {
Vincent Coubard 638:c90ae1400bf2 795 bool ret;
Vincent Coubard 638:c90ae1400bf2 796
Vincent Coubard 638:c90ae1400bf2 797 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 798 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
Vincent Coubard 638:c90ae1400bf2 799 const uint32_t id_last_page_to_be_cleared = (cmd_block_id + p_cmd->size +
Vincent Coubard 638:c90ae1400bf2 800 p_cmd->offset - 1u) /
Vincent Coubard 638:c90ae1400bf2 801 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 802
Vincent Coubard 638:c90ae1400bf2 803 // True if:
Vincent Coubard 638:c90ae1400bf2 804 // - current page is not the last page OR
Vincent Coubard 638:c90ae1400bf2 805 // - current page is the last page AND no tail exists
Vincent Coubard 638:c90ae1400bf2 806 if ((m_current_page_id < id_last_page_to_be_cleared) ||
Vincent Coubard 638:c90ae1400bf2 807 ((m_current_page_id == id_last_page_to_be_cleared) && (m_tail_word_size == 0)))
Vincent Coubard 638:c90ae1400bf2 808 {
Vincent Coubard 638:c90ae1400bf2 809 ret = true;
Vincent Coubard 638:c90ae1400bf2 810 }
Vincent Coubard 638:c90ae1400bf2 811 else
Vincent Coubard 638:c90ae1400bf2 812 {
Vincent Coubard 638:c90ae1400bf2 813 ret = false;
Vincent Coubard 638:c90ae1400bf2 814 }
Vincent Coubard 638:c90ae1400bf2 815
Vincent Coubard 638:c90ae1400bf2 816 return ret;
Vincent Coubard 638:c90ae1400bf2 817 }
Vincent Coubard 638:c90ae1400bf2 818
Vincent Coubard 638:c90ae1400bf2 819
Vincent Coubard 638:c90ae1400bf2 820 /**@brief Function for reissuing the last flash operation request, which was rejected by the flash
Vincent Coubard 638:c90ae1400bf2 821 * API, in swap sub sate.
Vincent Coubard 638:c90ae1400bf2 822 */
Vincent Coubard 638:c90ae1400bf2 823 static void swap_sub_state_err_busy_process(void)
Vincent Coubard 638:c90ae1400bf2 824 {
Vincent Coubard 638:c90ae1400bf2 825 // Reissue the request by doing a self transition to the current state.
Vincent Coubard 638:c90ae1400bf2 826 m_flags &= ~MASK_FLASH_API_ERR_BUSY;
Vincent Coubard 638:c90ae1400bf2 827 swap_sub_state_state_change(m_swap_sub_state);
Vincent Coubard 638:c90ae1400bf2 828 }
Vincent Coubard 638:c90ae1400bf2 829
Vincent Coubard 638:c90ae1400bf2 830
Vincent Coubard 638:c90ae1400bf2 831 /**@brief Function for doing restore head state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 832 *
Vincent Coubard 638:c90ae1400bf2 833 * @details Function for doing restore head state action upon flash operation success event, which
Vincent Coubard 638:c90ae1400bf2 834 * includes making a state transition depending on the current state.
Vincent Coubard 638:c90ae1400bf2 835 */
Vincent Coubard 638:c90ae1400bf2 836 static void head_restore_state_run(void)
Vincent Coubard 638:c90ae1400bf2 837 {
Vincent Coubard 638:c90ae1400bf2 838 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 839 {
Vincent Coubard 638:c90ae1400bf2 840 if (is_tail_data_page_swap_required())
Vincent Coubard 638:c90ae1400bf2 841 {
Vincent Coubard 638:c90ae1400bf2 842 // Additional data page needs to be swapped for tail section as we are clearing a block,
Vincent Coubard 638:c90ae1400bf2 843 // which is shared between 2 flash pages.
Vincent Coubard 638:c90ae1400bf2 844
Vincent Coubard 638:c90ae1400bf2 845 // Adjust variables to ensure correct state transition path is taken after the tail
Vincent Coubard 638:c90ae1400bf2 846 // section swap has completed.
Vincent Coubard 638:c90ae1400bf2 847 m_head_word_size = 0;
Vincent Coubard 638:c90ae1400bf2 848 m_flags |= MASK_TAIL_SWAP_DONE;
Vincent Coubard 638:c90ae1400bf2 849
Vincent Coubard 638:c90ae1400bf2 850 swap_sub_state_state_change(STATE_ERASE_SWAP);
Vincent Coubard 638:c90ae1400bf2 851 }
Vincent Coubard 638:c90ae1400bf2 852 else if (is_page_erase_required())
Vincent Coubard 638:c90ae1400bf2 853 {
Vincent Coubard 638:c90ae1400bf2 854 // Additional page erase operation is required.
Vincent Coubard 638:c90ae1400bf2 855
Vincent Coubard 638:c90ae1400bf2 856 // Adjust variable to ensure correct state transition path is taken after the additional
Vincent Coubard 638:c90ae1400bf2 857 // page erase operation has completed.
Vincent Coubard 638:c90ae1400bf2 858 m_head_word_size = 0;
Vincent Coubard 638:c90ae1400bf2 859 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
Vincent Coubard 638:c90ae1400bf2 860 }
Vincent Coubard 638:c90ae1400bf2 861 else if (m_tail_word_size != 0)
Vincent Coubard 638:c90ae1400bf2 862 {
Vincent Coubard 638:c90ae1400bf2 863 // Proceed with restoring tail from swap to data page.
Vincent Coubard 638:c90ae1400bf2 864 swap_sub_state_state_change(STATE_RESTORE_TAIL);
Vincent Coubard 638:c90ae1400bf2 865 }
Vincent Coubard 638:c90ae1400bf2 866 else
Vincent Coubard 638:c90ae1400bf2 867 {
Vincent Coubard 638:c90ae1400bf2 868 // Swap statemachine execution end reached.
Vincent Coubard 638:c90ae1400bf2 869 swap_sub_sm_exit_action_run();
Vincent Coubard 638:c90ae1400bf2 870 }
Vincent Coubard 638:c90ae1400bf2 871 }
Vincent Coubard 638:c90ae1400bf2 872 else
Vincent Coubard 638:c90ae1400bf2 873 {
Vincent Coubard 638:c90ae1400bf2 874 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 875 swap_sub_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 876 }
Vincent Coubard 638:c90ae1400bf2 877 }
Vincent Coubard 638:c90ae1400bf2 878
Vincent Coubard 638:c90ae1400bf2 879
Vincent Coubard 638:c90ae1400bf2 880 /**@brief Function for doing restore tail state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 881 */
Vincent Coubard 638:c90ae1400bf2 882 static void tail_restore_state_run(void)
Vincent Coubard 638:c90ae1400bf2 883 {
Vincent Coubard 638:c90ae1400bf2 884 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 885 {
Vincent Coubard 638:c90ae1400bf2 886 swap_sub_sm_exit_action_run();
Vincent Coubard 638:c90ae1400bf2 887 }
Vincent Coubard 638:c90ae1400bf2 888 else
Vincent Coubard 638:c90ae1400bf2 889 {
Vincent Coubard 638:c90ae1400bf2 890 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 891 swap_sub_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 892 }
Vincent Coubard 638:c90ae1400bf2 893 }
Vincent Coubard 638:c90ae1400bf2 894
Vincent Coubard 638:c90ae1400bf2 895
Vincent Coubard 638:c90ae1400bf2 896 /**@brief Function for doing data page erase state action upon a flash operation success event.
Vincent Coubard 638:c90ae1400bf2 897 *
Vincent Coubard 638:c90ae1400bf2 898 * @details Function for doing data page erase state action upon a flash operation success event,
Vincent Coubard 638:c90ae1400bf2 899 * which includes making a state transit to a new state depending on the current state.
Vincent Coubard 638:c90ae1400bf2 900 */
Vincent Coubard 638:c90ae1400bf2 901 static void data_page_erase_state_run(void)
Vincent Coubard 638:c90ae1400bf2 902 {
Vincent Coubard 638:c90ae1400bf2 903 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 904 {
Vincent Coubard 638:c90ae1400bf2 905 ++m_current_page_id;
Vincent Coubard 638:c90ae1400bf2 906
Vincent Coubard 638:c90ae1400bf2 907 if (m_head_word_size != 0)
Vincent Coubard 638:c90ae1400bf2 908 {
Vincent Coubard 638:c90ae1400bf2 909 swap_sub_state_state_change(STATE_RESTORE_HEAD);
Vincent Coubard 638:c90ae1400bf2 910 }
Vincent Coubard 638:c90ae1400bf2 911 else if (is_page_erase_required())
Vincent Coubard 638:c90ae1400bf2 912 {
Vincent Coubard 638:c90ae1400bf2 913 // Additional page erase operation is required.
Vincent Coubard 638:c90ae1400bf2 914 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
Vincent Coubard 638:c90ae1400bf2 915 }
Vincent Coubard 638:c90ae1400bf2 916 else if (m_tail_word_size != 0)
Vincent Coubard 638:c90ae1400bf2 917 {
Vincent Coubard 638:c90ae1400bf2 918 if (!(m_flags & MASK_TAIL_SWAP_DONE))
Vincent Coubard 638:c90ae1400bf2 919 {
Vincent Coubard 638:c90ae1400bf2 920 // Tail area restore is required and we have not yet written the relevant data page
Vincent Coubard 638:c90ae1400bf2 921 // to swap area. Start the process of writing the data page to swap.
Vincent Coubard 638:c90ae1400bf2 922 m_flags |= MASK_TAIL_SWAP_DONE;
Vincent Coubard 638:c90ae1400bf2 923
Vincent Coubard 638:c90ae1400bf2 924 swap_sub_state_state_change(STATE_ERASE_SWAP);
Vincent Coubard 638:c90ae1400bf2 925 }
Vincent Coubard 638:c90ae1400bf2 926 else
Vincent Coubard 638:c90ae1400bf2 927 {
Vincent Coubard 638:c90ae1400bf2 928 // Tail area restore is required and we have already written the relevant data page
Vincent Coubard 638:c90ae1400bf2 929 // to swap area. Proceed by restoring the tail area.
Vincent Coubard 638:c90ae1400bf2 930 swap_sub_state_state_change(STATE_RESTORE_TAIL);
Vincent Coubard 638:c90ae1400bf2 931 }
Vincent Coubard 638:c90ae1400bf2 932 }
Vincent Coubard 638:c90ae1400bf2 933 else
Vincent Coubard 638:c90ae1400bf2 934 {
Vincent Coubard 638:c90ae1400bf2 935 swap_sub_sm_exit_action_run();
Vincent Coubard 638:c90ae1400bf2 936 }
Vincent Coubard 638:c90ae1400bf2 937 }
Vincent Coubard 638:c90ae1400bf2 938 else
Vincent Coubard 638:c90ae1400bf2 939 {
Vincent Coubard 638:c90ae1400bf2 940 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 941 swap_sub_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 942 }
Vincent Coubard 638:c90ae1400bf2 943 }
Vincent Coubard 638:c90ae1400bf2 944
Vincent Coubard 638:c90ae1400bf2 945
Vincent Coubard 638:c90ae1400bf2 946 /**@brief Function for doing data to swap write state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 947 */
Vincent Coubard 638:c90ae1400bf2 948 static void data_to_swap_write_state_run(void)
Vincent Coubard 638:c90ae1400bf2 949 {
Vincent Coubard 638:c90ae1400bf2 950 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 951 {
Vincent Coubard 638:c90ae1400bf2 952 // If the operation is executed only on 1 single flash page it automatically means that tail
Vincent Coubard 638:c90ae1400bf2 953 // area is written to the swap, which we store to flags.
Vincent Coubard 638:c90ae1400bf2 954 if (m_flags & MASK_SINGLE_PAGE_OPERATION)
Vincent Coubard 638:c90ae1400bf2 955 {
Vincent Coubard 638:c90ae1400bf2 956 m_flags |= MASK_TAIL_SWAP_DONE;
Vincent Coubard 638:c90ae1400bf2 957 }
Vincent Coubard 638:c90ae1400bf2 958
Vincent Coubard 638:c90ae1400bf2 959 swap_sub_state_state_change(STATE_ERASE_DATA_PAGE);
Vincent Coubard 638:c90ae1400bf2 960 }
Vincent Coubard 638:c90ae1400bf2 961 else
Vincent Coubard 638:c90ae1400bf2 962 {
Vincent Coubard 638:c90ae1400bf2 963 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 964 swap_sub_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 965 }
Vincent Coubard 638:c90ae1400bf2 966 }
Vincent Coubard 638:c90ae1400bf2 967
Vincent Coubard 638:c90ae1400bf2 968
Vincent Coubard 638:c90ae1400bf2 969 /**@brief Function for doing swap erase state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 970 */
Vincent Coubard 638:c90ae1400bf2 971 static void swap_erase_state_run(void)
Vincent Coubard 638:c90ae1400bf2 972 {
Vincent Coubard 638:c90ae1400bf2 973 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 974 {
Vincent Coubard 638:c90ae1400bf2 975 swap_sub_state_state_change(STATE_WRITE_DATA_TO_SWAP);
Vincent Coubard 638:c90ae1400bf2 976 }
Vincent Coubard 638:c90ae1400bf2 977 else
Vincent Coubard 638:c90ae1400bf2 978 {
Vincent Coubard 638:c90ae1400bf2 979 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 980 swap_sub_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 981 }
Vincent Coubard 638:c90ae1400bf2 982 }
Vincent Coubard 638:c90ae1400bf2 983
Vincent Coubard 638:c90ae1400bf2 984
Vincent Coubard 638:c90ae1400bf2 985 /**@brief Function for dispatching the correct state action for data erase with a swap composite
Vincent Coubard 638:c90ae1400bf2 986 * state upon a flash operation success event.
Vincent Coubard 638:c90ae1400bf2 987 */
Vincent Coubard 638:c90ae1400bf2 988 static void swap_sub_state_sm_run(void)
Vincent Coubard 638:c90ae1400bf2 989 {
Vincent Coubard 638:c90ae1400bf2 990 static void (* const swap_sub_state_sm_lut[SWAP_SUB_STATE_MAX])(void) =
Vincent Coubard 638:c90ae1400bf2 991 {
Vincent Coubard 638:c90ae1400bf2 992 swap_erase_state_run,
Vincent Coubard 638:c90ae1400bf2 993 data_to_swap_write_state_run,
Vincent Coubard 638:c90ae1400bf2 994 data_page_erase_state_run,
Vincent Coubard 638:c90ae1400bf2 995 tail_restore_state_run,
Vincent Coubard 638:c90ae1400bf2 996 head_restore_state_run
Vincent Coubard 638:c90ae1400bf2 997 };
Vincent Coubard 638:c90ae1400bf2 998
Vincent Coubard 638:c90ae1400bf2 999 swap_sub_state_sm_lut[m_swap_sub_state]();
Vincent Coubard 638:c90ae1400bf2 1000 }
Vincent Coubard 638:c90ae1400bf2 1001
Vincent Coubard 638:c90ae1400bf2 1002
Vincent Coubard 638:c90ae1400bf2 1003 /**@brief Function for reissuing the last flash operation request, which was rejected by the flash
Vincent Coubard 638:c90ae1400bf2 1004 * API, in main sate.
Vincent Coubard 638:c90ae1400bf2 1005 */
Vincent Coubard 638:c90ae1400bf2 1006 static void main_state_err_busy_process(void)
Vincent Coubard 638:c90ae1400bf2 1007 {
Vincent Coubard 638:c90ae1400bf2 1008 // Reissue the request by doing a self transition to the current state.
Vincent Coubard 638:c90ae1400bf2 1009 m_flags &= ~MASK_FLASH_API_ERR_BUSY;
Vincent Coubard 638:c90ae1400bf2 1010 sm_state_change(m_state);
Vincent Coubard 638:c90ae1400bf2 1011 }
Vincent Coubard 638:c90ae1400bf2 1012
Vincent Coubard 638:c90ae1400bf2 1013
Vincent Coubard 638:c90ae1400bf2 1014 /**@brief Function for doing erase state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 1015 *
Vincent Coubard 638:c90ae1400bf2 1016 * @details Function for doing erase state action upon flash operation success event, which includes
Vincent Coubard 638:c90ae1400bf2 1017 * making a state transition depending on the current state.
Vincent Coubard 638:c90ae1400bf2 1018 */
Vincent Coubard 638:c90ae1400bf2 1019 static void erase_sub_state_sm_run(void)
Vincent Coubard 638:c90ae1400bf2 1020 {
Vincent Coubard 638:c90ae1400bf2 1021 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 1022 {
Vincent Coubard 638:c90ae1400bf2 1023 // Clear operation request has succeeded.
Vincent Coubard 638:c90ae1400bf2 1024 ++m_current_page_id;
Vincent Coubard 638:c90ae1400bf2 1025
Vincent Coubard 638:c90ae1400bf2 1026 if (!is_page_erase_required())
Vincent Coubard 638:c90ae1400bf2 1027 {
Vincent Coubard 638:c90ae1400bf2 1028 clear_post_processing_run();
Vincent Coubard 638:c90ae1400bf2 1029 }
Vincent Coubard 638:c90ae1400bf2 1030 else
Vincent Coubard 638:c90ae1400bf2 1031 {
Vincent Coubard 638:c90ae1400bf2 1032 // All required flash pages have not yet been erased, issue erase by doing a self
Vincent Coubard 638:c90ae1400bf2 1033 // transit.
Vincent Coubard 638:c90ae1400bf2 1034 sm_state_change(m_state);
Vincent Coubard 638:c90ae1400bf2 1035 }
Vincent Coubard 638:c90ae1400bf2 1036 }
Vincent Coubard 638:c90ae1400bf2 1037 else
Vincent Coubard 638:c90ae1400bf2 1038 {
Vincent Coubard 638:c90ae1400bf2 1039 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 1040 main_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 1041 }
Vincent Coubard 638:c90ae1400bf2 1042 }
Vincent Coubard 638:c90ae1400bf2 1043
Vincent Coubard 638:c90ae1400bf2 1044
Vincent Coubard 638:c90ae1400bf2 1045 /**@brief Function for doing store state action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 1046 */
Vincent Coubard 638:c90ae1400bf2 1047 static void store_sub_state_sm_run(void)
Vincent Coubard 638:c90ae1400bf2 1048 {
Vincent Coubard 638:c90ae1400bf2 1049 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 1050 {
Vincent Coubard 638:c90ae1400bf2 1051 // As write operation request has succeeded, adjust the size tracking state information
Vincent Coubard 638:c90ae1400bf2 1052 // accordingly.
Vincent Coubard 638:c90ae1400bf2 1053 cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 1054 p_cmd->size -= m_num_of_bytes_written;
Vincent Coubard 638:c90ae1400bf2 1055
Vincent Coubard 638:c90ae1400bf2 1056 if (p_cmd->size == 0)
Vincent Coubard 638:c90ae1400bf2 1057 {
Vincent Coubard 638:c90ae1400bf2 1058 command_end_procedure_run();
Vincent Coubard 638:c90ae1400bf2 1059 }
Vincent Coubard 638:c90ae1400bf2 1060 else
Vincent Coubard 638:c90ae1400bf2 1061 {
Vincent Coubard 638:c90ae1400bf2 1062 store_cmd_flash_write_execute();
Vincent Coubard 638:c90ae1400bf2 1063 }
Vincent Coubard 638:c90ae1400bf2 1064 }
Vincent Coubard 638:c90ae1400bf2 1065 else
Vincent Coubard 638:c90ae1400bf2 1066 {
Vincent Coubard 638:c90ae1400bf2 1067 // As operation request was rejected by the flash API reissue the request.
Vincent Coubard 638:c90ae1400bf2 1068 main_state_err_busy_process();
Vincent Coubard 638:c90ae1400bf2 1069 }
Vincent Coubard 638:c90ae1400bf2 1070 }
Vincent Coubard 638:c90ae1400bf2 1071
Vincent Coubard 638:c90ae1400bf2 1072
Vincent Coubard 638:c90ae1400bf2 1073 /**@brief Function for doing action upon flash operation success event.
Vincent Coubard 638:c90ae1400bf2 1074 */
Vincent Coubard 638:c90ae1400bf2 1075 static void flash_operation_success_run(void)
Vincent Coubard 638:c90ae1400bf2 1076 {
Vincent Coubard 638:c90ae1400bf2 1077 switch (m_state)
Vincent Coubard 638:c90ae1400bf2 1078 {
Vincent Coubard 638:c90ae1400bf2 1079 case STATE_STORE:
Vincent Coubard 638:c90ae1400bf2 1080 store_sub_state_sm_run();
Vincent Coubard 638:c90ae1400bf2 1081 break;
Vincent Coubard 638:c90ae1400bf2 1082
Vincent Coubard 638:c90ae1400bf2 1083 case STATE_DATA_ERASE:
Vincent Coubard 638:c90ae1400bf2 1084 erase_sub_state_sm_run();
Vincent Coubard 638:c90ae1400bf2 1085 break;
Vincent Coubard 638:c90ae1400bf2 1086
Vincent Coubard 638:c90ae1400bf2 1087 case STATE_DATA_ERASE_WITH_SWAP:
Vincent Coubard 638:c90ae1400bf2 1088 swap_sub_state_sm_run();
Vincent Coubard 638:c90ae1400bf2 1089 break;
Vincent Coubard 638:c90ae1400bf2 1090
Vincent Coubard 638:c90ae1400bf2 1091 default:
Vincent Coubard 638:c90ae1400bf2 1092 // No implementation needed.
Vincent Coubard 638:c90ae1400bf2 1093 break;
Vincent Coubard 638:c90ae1400bf2 1094 }
Vincent Coubard 638:c90ae1400bf2 1095 }
Vincent Coubard 638:c90ae1400bf2 1096
Vincent Coubard 638:c90ae1400bf2 1097
Vincent Coubard 638:c90ae1400bf2 1098 /**@brief Function for doing action upon flash operation failure event.
Vincent Coubard 638:c90ae1400bf2 1099 *
Vincent Coubard 638:c90ae1400bf2 1100 * @details Function for doing action upon flash operation failure event, which includes retrying
Vincent Coubard 638:c90ae1400bf2 1101 * the last operation or if retry count has been reached completing the operation with
Vincent Coubard 638:c90ae1400bf2 1102 * appropriate result code and transitioning to an error state.
Vincent Coubard 638:c90ae1400bf2 1103 *
Vincent Coubard 638:c90ae1400bf2 1104 * @note The command is not removed from the command queue, which will result to stalling of the
Vincent Coubard 638:c90ae1400bf2 1105 * command pipeline and the appropriate application recovery procedure for this is to reset
Vincent Coubard 638:c90ae1400bf2 1106 * the system by issuing @ref pstorage_init which will also result to flushing of the
Vincent Coubard 638:c90ae1400bf2 1107 * command queue.
Vincent Coubard 638:c90ae1400bf2 1108 */
Vincent Coubard 638:c90ae1400bf2 1109 static void flash_operation_failure_run(void)
Vincent Coubard 638:c90ae1400bf2 1110 {
Vincent Coubard 638:c90ae1400bf2 1111 if (++m_num_of_command_retries != SD_CMD_MAX_TRIES)
Vincent Coubard 638:c90ae1400bf2 1112 {
Vincent Coubard 638:c90ae1400bf2 1113 // Retry the last operation by doing a self transition to the current state.
Vincent Coubard 638:c90ae1400bf2 1114
Vincent Coubard 638:c90ae1400bf2 1115 if (m_state != STATE_DATA_ERASE_WITH_SWAP)
Vincent Coubard 638:c90ae1400bf2 1116 {
Vincent Coubard 638:c90ae1400bf2 1117 sm_state_change(m_state);
Vincent Coubard 638:c90ae1400bf2 1118 }
Vincent Coubard 638:c90ae1400bf2 1119 else
Vincent Coubard 638:c90ae1400bf2 1120 {
Vincent Coubard 638:c90ae1400bf2 1121 swap_sub_state_state_change(m_swap_sub_state);
Vincent Coubard 638:c90ae1400bf2 1122 }
Vincent Coubard 638:c90ae1400bf2 1123 }
Vincent Coubard 638:c90ae1400bf2 1124 else
Vincent Coubard 638:c90ae1400bf2 1125 {
Vincent Coubard 638:c90ae1400bf2 1126 // Complete the operation with appropriate result code and transit to an error state.
Vincent Coubard 638:c90ae1400bf2 1127 app_notify_error_state_transit(NRF_ERROR_TIMEOUT);
Vincent Coubard 638:c90ae1400bf2 1128 }
Vincent Coubard 638:c90ae1400bf2 1129 }
Vincent Coubard 638:c90ae1400bf2 1130
Vincent Coubard 638:c90ae1400bf2 1131
Vincent Coubard 638:c90ae1400bf2 1132 /**@brief Function for handling flash access result events.
Vincent Coubard 638:c90ae1400bf2 1133 *
Vincent Coubard 638:c90ae1400bf2 1134 * @param[in] sys_evt System event to be handled.
Vincent Coubard 638:c90ae1400bf2 1135 */
Vincent Coubard 638:c90ae1400bf2 1136 void pstorage_sys_event_handler(uint32_t sys_evt)
Vincent Coubard 638:c90ae1400bf2 1137 {
Vincent Coubard 638:c90ae1400bf2 1138 if (m_state != STATE_IDLE && m_state != STATE_ERROR)
Vincent Coubard 638:c90ae1400bf2 1139 {
Vincent Coubard 638:c90ae1400bf2 1140 switch (sys_evt)
Vincent Coubard 638:c90ae1400bf2 1141 {
Vincent Coubard 638:c90ae1400bf2 1142 case NRF_EVT_FLASH_OPERATION_SUCCESS:
Vincent Coubard 638:c90ae1400bf2 1143 flash_operation_success_run();
Vincent Coubard 638:c90ae1400bf2 1144 break;
Vincent Coubard 638:c90ae1400bf2 1145
Vincent Coubard 638:c90ae1400bf2 1146 case NRF_EVT_FLASH_OPERATION_ERROR:
Vincent Coubard 638:c90ae1400bf2 1147 if (!(m_flags & MASK_FLASH_API_ERR_BUSY))
Vincent Coubard 638:c90ae1400bf2 1148 {
Vincent Coubard 638:c90ae1400bf2 1149 flash_operation_failure_run();
Vincent Coubard 638:c90ae1400bf2 1150 }
Vincent Coubard 638:c90ae1400bf2 1151 else
Vincent Coubard 638:c90ae1400bf2 1152 {
Vincent Coubard 638:c90ae1400bf2 1153 // As our last flash operation request was rejected by the flash API reissue the
Vincent Coubard 638:c90ae1400bf2 1154 // request by doing same code execution path as for flash operation sucess
Vincent Coubard 638:c90ae1400bf2 1155 // event. This will promote code reuse in the implementation.
Vincent Coubard 638:c90ae1400bf2 1156 flash_operation_success_run();
Vincent Coubard 638:c90ae1400bf2 1157 }
Vincent Coubard 638:c90ae1400bf2 1158 break;
Vincent Coubard 638:c90ae1400bf2 1159
Vincent Coubard 638:c90ae1400bf2 1160 default:
Vincent Coubard 638:c90ae1400bf2 1161 // No implementation needed.
Vincent Coubard 638:c90ae1400bf2 1162 break;
Vincent Coubard 638:c90ae1400bf2 1163 }
Vincent Coubard 638:c90ae1400bf2 1164
Vincent Coubard 638:c90ae1400bf2 1165 }
Vincent Coubard 638:c90ae1400bf2 1166 }
Vincent Coubard 638:c90ae1400bf2 1167
Vincent Coubard 638:c90ae1400bf2 1168
Vincent Coubard 638:c90ae1400bf2 1169 /**@brief Function for calculating the tail area size in number of 32-bit words.
Vincent Coubard 638:c90ae1400bf2 1170 *
Vincent Coubard 638:c90ae1400bf2 1171 * @param[in] cmd_end_of_storage_address End of storage area within the scope of the command.
Vincent Coubard 638:c90ae1400bf2 1172 * @param[in] end_of_storage_address End of allocated storage area for the application.
Vincent Coubard 638:c90ae1400bf2 1173 */
Vincent Coubard 638:c90ae1400bf2 1174 static void tail_word_size_calculate(pstorage_size_t cmd_end_of_storage_address,
Vincent Coubard 638:c90ae1400bf2 1175 pstorage_size_t end_of_storage_address)
Vincent Coubard 638:c90ae1400bf2 1176 {
Vincent Coubard 638:c90ae1400bf2 1177 // Two different cases to resolve when calculating correct size for restore tail section:
Vincent Coubard 638:c90ae1400bf2 1178 // 1) End of storage area and command end area are in the same page.
Vincent Coubard 638:c90ae1400bf2 1179 // 2) End of storage area and command end area are not in the same page.
Vincent Coubard 638:c90ae1400bf2 1180
Vincent Coubard 638:c90ae1400bf2 1181 const uint32_t end_of_storage_area_page = end_of_storage_address /
Vincent Coubard 638:c90ae1400bf2 1182 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 1183 const uint32_t command_end_of_storage_area_page = cmd_end_of_storage_address /
Vincent Coubard 638:c90ae1400bf2 1184 PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 1185
Vincent Coubard 638:c90ae1400bf2 1186 if (end_of_storage_area_page == command_end_of_storage_area_page)
Vincent Coubard 638:c90ae1400bf2 1187 {
Vincent Coubard 638:c90ae1400bf2 1188 //lint -e{573} suppress "Signed-unsigned mix with divide".
Vincent Coubard 638:c90ae1400bf2 1189 m_tail_word_size = (end_of_storage_address - cmd_end_of_storage_address) / sizeof(uint32_t);
Vincent Coubard 638:c90ae1400bf2 1190 }
Vincent Coubard 638:c90ae1400bf2 1191 else
Vincent Coubard 638:c90ae1400bf2 1192 {
Vincent Coubard 638:c90ae1400bf2 1193 //lint -e{573} suppress "Signed-unsigned mix with divide".
Vincent Coubard 638:c90ae1400bf2 1194 m_tail_word_size = (PSTORAGE_FLASH_PAGE_SIZE -
Vincent Coubard 638:c90ae1400bf2 1195 (cmd_end_of_storage_address % PSTORAGE_FLASH_PAGE_SIZE)) /
Vincent Coubard 638:c90ae1400bf2 1196 sizeof(uint32_t);
Vincent Coubard 638:c90ae1400bf2 1197 }
Vincent Coubard 638:c90ae1400bf2 1198 }
Vincent Coubard 638:c90ae1400bf2 1199
Vincent Coubard 638:c90ae1400bf2 1200
Vincent Coubard 638:c90ae1400bf2 1201 /**@brief Function for executing the clear operation.
Vincent Coubard 638:c90ae1400bf2 1202 */
Vincent Coubard 638:c90ae1400bf2 1203 static void clear_operation_execute(void)
Vincent Coubard 638:c90ae1400bf2 1204 {
Vincent Coubard 638:c90ae1400bf2 1205 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 1206 const pstorage_block_t cmd_block_id = p_cmd->storage_addr.block_id;
Vincent Coubard 638:c90ae1400bf2 1207
Vincent Coubard 638:c90ae1400bf2 1208 const pstorage_size_t block_size = m_app_table[p_cmd->storage_addr.module_id].block_size;
Vincent Coubard 638:c90ae1400bf2 1209 const pstorage_size_t block_count = m_app_table[p_cmd->storage_addr.module_id].block_count;
Vincent Coubard 638:c90ae1400bf2 1210 const pstorage_block_t block_base_id = m_app_table[p_cmd->storage_addr.module_id].base_id;
Vincent Coubard 638:c90ae1400bf2 1211
Vincent Coubard 638:c90ae1400bf2 1212 const bool is_start_address_page_aligned = (cmd_block_id % PSTORAGE_FLASH_PAGE_SIZE) == 0;
Vincent Coubard 638:c90ae1400bf2 1213
Vincent Coubard 638:c90ae1400bf2 1214 // Calculate the end (1 beyond allocated area) for complete storage area and to the area only
Vincent Coubard 638:c90ae1400bf2 1215 // within scope of this command.
Vincent Coubard 638:c90ae1400bf2 1216 const pstorage_block_t end_of_storage_address = block_base_id + (block_size * block_count);
Vincent Coubard 638:c90ae1400bf2 1217 const pstorage_block_t cmd_end_of_storage_address = cmd_block_id + p_cmd->size + p_cmd->offset;
Vincent Coubard 638:c90ae1400bf2 1218
Vincent Coubard 638:c90ae1400bf2 1219 // Zero tail to make sure no extra erase is done erroneously.
Vincent Coubard 638:c90ae1400bf2 1220 m_tail_word_size = 0;
Vincent Coubard 638:c90ae1400bf2 1221
Vincent Coubard 638:c90ae1400bf2 1222 // If the following is true no swap access is needed:
Vincent Coubard 638:c90ae1400bf2 1223 // - 1st logical test covers the case of: clear/update 1 complete single page.
Vincent Coubard 638:c90ae1400bf2 1224 // - 2nd logical test covers the case of:
Vincent Coubard 638:c90ae1400bf2 1225 // 1) Clear/update last allocated page and page is not full (page can't be shared between
Vincent Coubard 638:c90ae1400bf2 1226 // multiple clients so the end of the page is unused area).
Vincent Coubard 638:c90ae1400bf2 1227 // 2) Clear/update all allocated storage.
Vincent Coubard 638:c90ae1400bf2 1228 if ((is_start_address_page_aligned && (p_cmd->size == PSTORAGE_FLASH_PAGE_SIZE)) ||
Vincent Coubard 638:c90ae1400bf2 1229 (is_start_address_page_aligned && (cmd_end_of_storage_address == end_of_storage_address) &&
Vincent Coubard 638:c90ae1400bf2 1230 (p_cmd->offset == 0)) || (p_cmd->storage_addr.module_id == RAW_MODE_APP_ID))
Vincent Coubard 638:c90ae1400bf2 1231 {
Vincent Coubard 638:c90ae1400bf2 1232 // Nothing to put to the swap and we can just erase the pages(s).
Vincent Coubard 638:c90ae1400bf2 1233
Vincent Coubard 638:c90ae1400bf2 1234 m_current_page_id = cmd_block_id / PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 1235
Vincent Coubard 638:c90ae1400bf2 1236 sm_state_change(STATE_DATA_ERASE);
Vincent Coubard 638:c90ae1400bf2 1237 }
Vincent Coubard 638:c90ae1400bf2 1238 else
Vincent Coubard 638:c90ae1400bf2 1239 {
Vincent Coubard 638:c90ae1400bf2 1240 // Not all the blocks for the module can be cleared, we need to use swap page for storing
Vincent Coubard 638:c90ae1400bf2 1241 // data temporarily.
Vincent Coubard 638:c90ae1400bf2 1242
Vincent Coubard 638:c90ae1400bf2 1243 m_head_word_size = ((cmd_block_id + p_cmd->offset) % PSTORAGE_FLASH_PAGE_SIZE) /
Vincent Coubard 638:c90ae1400bf2 1244 sizeof(uint32_t);
Vincent Coubard 638:c90ae1400bf2 1245
Vincent Coubard 638:c90ae1400bf2 1246 const bool is_cmd_end_address_page_aligned = ((cmd_end_of_storage_address %
Vincent Coubard 638:c90ae1400bf2 1247 PSTORAGE_FLASH_PAGE_SIZE) == 0);
Vincent Coubard 638:c90ae1400bf2 1248 if ((cmd_end_of_storage_address != end_of_storage_address) &&
Vincent Coubard 638:c90ae1400bf2 1249 !is_cmd_end_address_page_aligned)
Vincent Coubard 638:c90ae1400bf2 1250 {
Vincent Coubard 638:c90ae1400bf2 1251 // When command area is not equal to end of the storage allocation area and not ending
Vincent Coubard 638:c90ae1400bf2 1252 // to page boundary there is a need to restore the tail area.
Vincent Coubard 638:c90ae1400bf2 1253 tail_word_size_calculate(cmd_end_of_storage_address, end_of_storage_address);
Vincent Coubard 638:c90ae1400bf2 1254 }
Vincent Coubard 638:c90ae1400bf2 1255
Vincent Coubard 638:c90ae1400bf2 1256 sm_state_change(STATE_DATA_ERASE_WITH_SWAP);
Vincent Coubard 638:c90ae1400bf2 1257 }
Vincent Coubard 638:c90ae1400bf2 1258 }
Vincent Coubard 638:c90ae1400bf2 1259
Vincent Coubard 638:c90ae1400bf2 1260
Vincent Coubard 638:c90ae1400bf2 1261 /**@brief Function for executing the store operation.
Vincent Coubard 638:c90ae1400bf2 1262 */
Vincent Coubard 638:c90ae1400bf2 1263 static void store_operation_execute(void)
Vincent Coubard 638:c90ae1400bf2 1264 {
Vincent Coubard 638:c90ae1400bf2 1265 sm_state_change(STATE_STORE);
Vincent Coubard 638:c90ae1400bf2 1266 }
Vincent Coubard 638:c90ae1400bf2 1267
Vincent Coubard 638:c90ae1400bf2 1268
Vincent Coubard 638:c90ae1400bf2 1269 /**@brief Function for executing the update operation.
Vincent Coubard 638:c90ae1400bf2 1270 */
Vincent Coubard 638:c90ae1400bf2 1271 static void update_operation_execute(void)
Vincent Coubard 638:c90ae1400bf2 1272 {
Vincent Coubard 638:c90ae1400bf2 1273 clear_operation_execute();
Vincent Coubard 638:c90ae1400bf2 1274 }
Vincent Coubard 638:c90ae1400bf2 1275
Vincent Coubard 638:c90ae1400bf2 1276
Vincent Coubard 638:c90ae1400bf2 1277 /**@brief Function for dispatching the flash access operation.
Vincent Coubard 638:c90ae1400bf2 1278 */
Vincent Coubard 638:c90ae1400bf2 1279 static void cmd_process(void)
Vincent Coubard 638:c90ae1400bf2 1280 {
Vincent Coubard 638:c90ae1400bf2 1281 const cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
Vincent Coubard 638:c90ae1400bf2 1282 m_app_data_size = p_cmd->size;
Vincent Coubard 638:c90ae1400bf2 1283
Vincent Coubard 638:c90ae1400bf2 1284 switch (p_cmd->op_code)
Vincent Coubard 638:c90ae1400bf2 1285 {
Vincent Coubard 638:c90ae1400bf2 1286 case PSTORAGE_STORE_OP_CODE:
Vincent Coubard 638:c90ae1400bf2 1287 store_operation_execute();
Vincent Coubard 638:c90ae1400bf2 1288 break;
Vincent Coubard 638:c90ae1400bf2 1289
Vincent Coubard 638:c90ae1400bf2 1290 case PSTORAGE_CLEAR_OP_CODE:
Vincent Coubard 638:c90ae1400bf2 1291 clear_operation_execute();
Vincent Coubard 638:c90ae1400bf2 1292 break;
Vincent Coubard 638:c90ae1400bf2 1293
Vincent Coubard 638:c90ae1400bf2 1294 case PSTORAGE_UPDATE_OP_CODE:
Vincent Coubard 638:c90ae1400bf2 1295 update_operation_execute();
Vincent Coubard 638:c90ae1400bf2 1296 break;
Vincent Coubard 638:c90ae1400bf2 1297
Vincent Coubard 638:c90ae1400bf2 1298 default:
Vincent Coubard 638:c90ae1400bf2 1299 // No action required.
Vincent Coubard 638:c90ae1400bf2 1300 break;
Vincent Coubard 638:c90ae1400bf2 1301 }
Vincent Coubard 638:c90ae1400bf2 1302 }
Vincent Coubard 638:c90ae1400bf2 1303
Vincent Coubard 638:c90ae1400bf2 1304
Vincent Coubard 638:c90ae1400bf2 1305 uint32_t pstorage_init(void)
Vincent Coubard 638:c90ae1400bf2 1306 {
Vincent Coubard 638:c90ae1400bf2 1307 cmd_queue_init();
Vincent Coubard 638:c90ae1400bf2 1308
Vincent Coubard 638:c90ae1400bf2 1309 m_next_app_instance = 0;
Vincent Coubard 638:c90ae1400bf2 1310 m_next_page_addr = PSTORAGE_DATA_START_ADDR;
Vincent Coubard 638:c90ae1400bf2 1311 m_current_page_id = 0;
Vincent Coubard 638:c90ae1400bf2 1312
Vincent Coubard 638:c90ae1400bf2 1313 for (uint32_t index = 0; index < PSTORAGE_NUM_OF_PAGES; index++)
Vincent Coubard 638:c90ae1400bf2 1314 {
Vincent Coubard 638:c90ae1400bf2 1315 m_app_table[index].cb = NULL;
Vincent Coubard 638:c90ae1400bf2 1316 m_app_table[index].block_size = 0;
Vincent Coubard 638:c90ae1400bf2 1317 m_app_table[index].block_count = 0;
Vincent Coubard 638:c90ae1400bf2 1318 }
Vincent Coubard 638:c90ae1400bf2 1319
Vincent Coubard 638:c90ae1400bf2 1320 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 1321 m_raw_app_table.cb = NULL;
Vincent Coubard 638:c90ae1400bf2 1322 #endif //PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 1323
Vincent Coubard 638:c90ae1400bf2 1324 m_state = STATE_IDLE;
Vincent Coubard 638:c90ae1400bf2 1325 m_num_of_command_retries = 0;
Vincent Coubard 638:c90ae1400bf2 1326 m_flags = 0;
Vincent Coubard 638:c90ae1400bf2 1327 m_num_of_bytes_written = 0;
Vincent Coubard 638:c90ae1400bf2 1328 m_flags |= MASK_MODULE_INITIALIZED;
Vincent Coubard 638:c90ae1400bf2 1329
Vincent Coubard 638:c90ae1400bf2 1330 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1331 }
Vincent Coubard 638:c90ae1400bf2 1332
Vincent Coubard 638:c90ae1400bf2 1333
Vincent Coubard 638:c90ae1400bf2 1334 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 638:c90ae1400bf2 1335 pstorage_handle_t * p_block_id)
Vincent Coubard 638:c90ae1400bf2 1336 {
Vincent Coubard 638:c90ae1400bf2 1337 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1338 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 638:c90ae1400bf2 1339 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 638:c90ae1400bf2 1340 NULL_PARAM_CHECK(p_module_param->cb);
Vincent Coubard 638:c90ae1400bf2 1341 BLOCK_SIZE_CHECK(p_module_param->block_size);
Vincent Coubard 638:c90ae1400bf2 1342 BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
Vincent Coubard 638:c90ae1400bf2 1343
Vincent Coubard 638:c90ae1400bf2 1344 if (!((p_module_param->block_size % sizeof(uint32_t)) == 0))
Vincent Coubard 638:c90ae1400bf2 1345 {
Vincent Coubard 638:c90ae1400bf2 1346 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 1347 }
Vincent Coubard 638:c90ae1400bf2 1348
Vincent Coubard 638:c90ae1400bf2 1349 if (m_next_app_instance == PSTORAGE_NUM_OF_PAGES)
Vincent Coubard 638:c90ae1400bf2 1350 {
Vincent Coubard 638:c90ae1400bf2 1351 return NRF_ERROR_NO_MEM;
Vincent Coubard 638:c90ae1400bf2 1352 }
Vincent Coubard 638:c90ae1400bf2 1353
Vincent Coubard 638:c90ae1400bf2 1354 p_block_id->module_id = m_next_app_instance;
Vincent Coubard 638:c90ae1400bf2 1355 p_block_id->block_id = m_next_page_addr;
Vincent Coubard 638:c90ae1400bf2 1356
Vincent Coubard 638:c90ae1400bf2 1357 m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
Vincent Coubard 638:c90ae1400bf2 1358 m_app_table[m_next_app_instance].cb = p_module_param->cb;
Vincent Coubard 638:c90ae1400bf2 1359 m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
Vincent Coubard 638:c90ae1400bf2 1360 m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
Vincent Coubard 638:c90ae1400bf2 1361
Vincent Coubard 638:c90ae1400bf2 1362 // Calculate number of flash pages allocated for the device and adjust next free page address.
Vincent Coubard 638:c90ae1400bf2 1363 /*lint -save -e666 */
Vincent Coubard 638:c90ae1400bf2 1364 const uint32_t page_count = CEIL_DIV((p_module_param->block_size * p_module_param->block_count),
Vincent Coubard 638:c90ae1400bf2 1365 PSTORAGE_FLASH_PAGE_SIZE);
Vincent Coubard 638:c90ae1400bf2 1366 /*lint -restore */
Vincent Coubard 638:c90ae1400bf2 1367 m_next_page_addr += page_count * PSTORAGE_FLASH_PAGE_SIZE;
Vincent Coubard 638:c90ae1400bf2 1368
Vincent Coubard 638:c90ae1400bf2 1369 ++m_next_app_instance;
Vincent Coubard 638:c90ae1400bf2 1370
Vincent Coubard 638:c90ae1400bf2 1371 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1372 }
Vincent Coubard 638:c90ae1400bf2 1373
Vincent Coubard 638:c90ae1400bf2 1374
Vincent Coubard 638:c90ae1400bf2 1375 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
Vincent Coubard 638:c90ae1400bf2 1376 pstorage_size_t block_num,
Vincent Coubard 638:c90ae1400bf2 1377 pstorage_handle_t * p_block_id)
Vincent Coubard 638:c90ae1400bf2 1378 {
Vincent Coubard 638:c90ae1400bf2 1379 pstorage_handle_t temp_id;
Vincent Coubard 638:c90ae1400bf2 1380
Vincent Coubard 638:c90ae1400bf2 1381 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1382 NULL_PARAM_CHECK(p_base_id);
Vincent Coubard 638:c90ae1400bf2 1383 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 638:c90ae1400bf2 1384 MODULE_ID_RANGE_CHECK(p_base_id);
Vincent Coubard 638:c90ae1400bf2 1385
Vincent Coubard 638:c90ae1400bf2 1386 temp_id = (*p_base_id);
Vincent Coubard 638:c90ae1400bf2 1387 temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
Vincent Coubard 638:c90ae1400bf2 1388
Vincent Coubard 638:c90ae1400bf2 1389 BLOCK_ID_RANGE_CHECK(&temp_id);
Vincent Coubard 638:c90ae1400bf2 1390
Vincent Coubard 638:c90ae1400bf2 1391 (*p_block_id) = temp_id;
Vincent Coubard 638:c90ae1400bf2 1392
Vincent Coubard 638:c90ae1400bf2 1393 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1394 }
Vincent Coubard 638:c90ae1400bf2 1395
Vincent Coubard 638:c90ae1400bf2 1396
Vincent Coubard 638:c90ae1400bf2 1397 uint32_t pstorage_store(pstorage_handle_t * p_dest,
Vincent Coubard 638:c90ae1400bf2 1398 uint8_t * p_src,
Vincent Coubard 638:c90ae1400bf2 1399 pstorage_size_t size,
Vincent Coubard 638:c90ae1400bf2 1400 pstorage_size_t offset)
Vincent Coubard 638:c90ae1400bf2 1401 {
Vincent Coubard 638:c90ae1400bf2 1402 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1403 NULL_PARAM_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1404 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1405 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1406 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1407 SIZE_CHECK(p_dest, size);
Vincent Coubard 638:c90ae1400bf2 1408 OFFSET_CHECK(p_dest, offset, size);
Vincent Coubard 638:c90ae1400bf2 1409
Vincent Coubard 638:c90ae1400bf2 1410 if ((!is_word_aligned(p_src)) ||
Vincent Coubard 638:c90ae1400bf2 1411 (!is_word_aligned((void *)(uint32_t)offset)) ||
Vincent Coubard 638:c90ae1400bf2 1412 (!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 638:c90ae1400bf2 1413 {
Vincent Coubard 638:c90ae1400bf2 1414 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1415 }
Vincent Coubard 638:c90ae1400bf2 1416
Vincent Coubard 638:c90ae1400bf2 1417 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 638:c90ae1400bf2 1418 }
Vincent Coubard 638:c90ae1400bf2 1419
Vincent Coubard 638:c90ae1400bf2 1420
Vincent Coubard 638:c90ae1400bf2 1421 uint32_t pstorage_update(pstorage_handle_t * p_dest,
Vincent Coubard 638:c90ae1400bf2 1422 uint8_t * p_src,
Vincent Coubard 638:c90ae1400bf2 1423 pstorage_size_t size,
Vincent Coubard 638:c90ae1400bf2 1424 pstorage_size_t offset)
Vincent Coubard 638:c90ae1400bf2 1425 {
Vincent Coubard 638:c90ae1400bf2 1426 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1427 NULL_PARAM_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1428 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1429 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1430 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1431 SIZE_CHECK(p_dest, size);
Vincent Coubard 638:c90ae1400bf2 1432 OFFSET_CHECK(p_dest, offset, size);
Vincent Coubard 638:c90ae1400bf2 1433
Vincent Coubard 638:c90ae1400bf2 1434 if ((!is_word_aligned(p_src)) ||
Vincent Coubard 638:c90ae1400bf2 1435 (!is_word_aligned((void *)(uint32_t)offset)) ||
Vincent Coubard 638:c90ae1400bf2 1436 (!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 638:c90ae1400bf2 1437 {
Vincent Coubard 638:c90ae1400bf2 1438 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1439 }
Vincent Coubard 638:c90ae1400bf2 1440
Vincent Coubard 638:c90ae1400bf2 1441 return cmd_queue_enqueue(PSTORAGE_UPDATE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 638:c90ae1400bf2 1442 }
Vincent Coubard 638:c90ae1400bf2 1443
Vincent Coubard 638:c90ae1400bf2 1444
Vincent Coubard 638:c90ae1400bf2 1445 uint32_t pstorage_load(uint8_t * p_dest,
Vincent Coubard 638:c90ae1400bf2 1446 pstorage_handle_t * p_src,
Vincent Coubard 638:c90ae1400bf2 1447 pstorage_size_t size,
Vincent Coubard 638:c90ae1400bf2 1448 pstorage_size_t offset)
Vincent Coubard 638:c90ae1400bf2 1449 {
Vincent Coubard 638:c90ae1400bf2 1450 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1451 NULL_PARAM_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1452 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1453 MODULE_ID_RANGE_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1454 BLOCK_ID_RANGE_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1455 SIZE_CHECK(p_src, size);
Vincent Coubard 638:c90ae1400bf2 1456 OFFSET_CHECK(p_src, offset, size);
Vincent Coubard 638:c90ae1400bf2 1457
Vincent Coubard 638:c90ae1400bf2 1458 if ((!is_word_aligned(p_dest)) ||
Vincent Coubard 638:c90ae1400bf2 1459 (!is_word_aligned((void *)(uint32_t)offset)) ||
Vincent Coubard 638:c90ae1400bf2 1460 (!is_word_aligned((uint32_t *)p_src->block_id)))
Vincent Coubard 638:c90ae1400bf2 1461 {
Vincent Coubard 638:c90ae1400bf2 1462 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1463 }
Vincent Coubard 638:c90ae1400bf2 1464
Vincent Coubard 638:c90ae1400bf2 1465 memcpy(p_dest, (((uint8_t *)p_src->block_id) + offset), size);
Vincent Coubard 638:c90ae1400bf2 1466
Vincent Coubard 638:c90ae1400bf2 1467 m_app_table[p_src->module_id].cb(p_src, PSTORAGE_LOAD_OP_CODE, NRF_SUCCESS, p_dest, size);
Vincent Coubard 638:c90ae1400bf2 1468
Vincent Coubard 638:c90ae1400bf2 1469 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1470 }
Vincent Coubard 638:c90ae1400bf2 1471
Vincent Coubard 638:c90ae1400bf2 1472
Vincent Coubard 638:c90ae1400bf2 1473 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 638:c90ae1400bf2 1474 {
Vincent Coubard 638:c90ae1400bf2 1475 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1476 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1477 MODULE_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1478 BLOCK_ID_RANGE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1479
Vincent Coubard 638:c90ae1400bf2 1480 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 638:c90ae1400bf2 1481 {
Vincent Coubard 638:c90ae1400bf2 1482 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1483 }
Vincent Coubard 638:c90ae1400bf2 1484
Vincent Coubard 638:c90ae1400bf2 1485 // Check is the area starting from block_id multiple of block_size.
Vincent Coubard 638:c90ae1400bf2 1486 if (
Vincent Coubard 638:c90ae1400bf2 1487 !(
Vincent Coubard 638:c90ae1400bf2 1488 ((p_dest->block_id - m_app_table[p_dest->module_id].base_id) %
Vincent Coubard 638:c90ae1400bf2 1489 m_app_table[p_dest->module_id].block_size) == 0
Vincent Coubard 638:c90ae1400bf2 1490 )
Vincent Coubard 638:c90ae1400bf2 1491 )
Vincent Coubard 638:c90ae1400bf2 1492 {
Vincent Coubard 638:c90ae1400bf2 1493 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 1494 }
Vincent Coubard 638:c90ae1400bf2 1495
Vincent Coubard 638:c90ae1400bf2 1496 // Check is requested size multiple of registered block size or 0.
Vincent Coubard 638:c90ae1400bf2 1497 if (((size % m_app_table[p_dest->module_id].block_size) != 0) || (size == 0))
Vincent Coubard 638:c90ae1400bf2 1498 {
Vincent Coubard 638:c90ae1400bf2 1499 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 1500 }
Vincent Coubard 638:c90ae1400bf2 1501
Vincent Coubard 638:c90ae1400bf2 1502 const uint32_t registered_allocation_size = m_app_table[p_dest->module_id].block_size *
Vincent Coubard 638:c90ae1400bf2 1503 m_app_table[p_dest->module_id].block_count;
Vincent Coubard 638:c90ae1400bf2 1504
Vincent Coubard 638:c90ae1400bf2 1505 const pstorage_block_t clear_request_end_address = p_dest->block_id + size;
Vincent Coubard 638:c90ae1400bf2 1506 const pstorage_block_t allocation_end_address = m_app_table[p_dest->module_id].base_id +
Vincent Coubard 638:c90ae1400bf2 1507 registered_allocation_size;
Vincent Coubard 638:c90ae1400bf2 1508 // Check if request would lead to a buffer overrun.
Vincent Coubard 638:c90ae1400bf2 1509 if (clear_request_end_address > allocation_end_address)
Vincent Coubard 638:c90ae1400bf2 1510 {
Vincent Coubard 638:c90ae1400bf2 1511 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 1512 }
Vincent Coubard 638:c90ae1400bf2 1513
Vincent Coubard 638:c90ae1400bf2 1514 return cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
Vincent Coubard 638:c90ae1400bf2 1515 }
Vincent Coubard 638:c90ae1400bf2 1516
Vincent Coubard 638:c90ae1400bf2 1517
Vincent Coubard 638:c90ae1400bf2 1518 uint32_t pstorage_access_status_get(uint32_t * p_count)
Vincent Coubard 638:c90ae1400bf2 1519 {
Vincent Coubard 638:c90ae1400bf2 1520 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1521 NULL_PARAM_CHECK(p_count);
Vincent Coubard 638:c90ae1400bf2 1522
Vincent Coubard 638:c90ae1400bf2 1523 (*p_count) = m_cmd_queue.count;
Vincent Coubard 638:c90ae1400bf2 1524
Vincent Coubard 638:c90ae1400bf2 1525 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1526 }
Vincent Coubard 638:c90ae1400bf2 1527
Vincent Coubard 638:c90ae1400bf2 1528 #ifdef PSTORAGE_RAW_MODE_ENABLE
Vincent Coubard 638:c90ae1400bf2 1529
Vincent Coubard 638:c90ae1400bf2 1530 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
Vincent Coubard 638:c90ae1400bf2 1531 pstorage_handle_t * p_block_id)
Vincent Coubard 638:c90ae1400bf2 1532 {
Vincent Coubard 638:c90ae1400bf2 1533 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1534 NULL_PARAM_CHECK(p_module_param);
Vincent Coubard 638:c90ae1400bf2 1535 NULL_PARAM_CHECK(p_block_id);
Vincent Coubard 638:c90ae1400bf2 1536 NULL_PARAM_CHECK(p_module_param->cb);
Vincent Coubard 638:c90ae1400bf2 1537
Vincent Coubard 638:c90ae1400bf2 1538 if (m_raw_app_table.cb != NULL)
Vincent Coubard 638:c90ae1400bf2 1539 {
Vincent Coubard 638:c90ae1400bf2 1540 return NRF_ERROR_NO_MEM;
Vincent Coubard 638:c90ae1400bf2 1541 }
Vincent Coubard 638:c90ae1400bf2 1542
Vincent Coubard 638:c90ae1400bf2 1543 p_block_id->module_id = RAW_MODE_APP_ID;
Vincent Coubard 638:c90ae1400bf2 1544 m_raw_app_table.cb = p_module_param->cb;
Vincent Coubard 638:c90ae1400bf2 1545
Vincent Coubard 638:c90ae1400bf2 1546 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 1547 }
Vincent Coubard 638:c90ae1400bf2 1548
Vincent Coubard 638:c90ae1400bf2 1549
Vincent Coubard 638:c90ae1400bf2 1550 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
Vincent Coubard 638:c90ae1400bf2 1551 uint8_t * p_src,
Vincent Coubard 638:c90ae1400bf2 1552 pstorage_size_t size,
Vincent Coubard 638:c90ae1400bf2 1553 pstorage_size_t offset)
Vincent Coubard 638:c90ae1400bf2 1554 {
Vincent Coubard 638:c90ae1400bf2 1555 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1556 NULL_PARAM_CHECK(p_src);
Vincent Coubard 638:c90ae1400bf2 1557 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1558 MODULE_RAW_HANDLE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1559
Vincent Coubard 638:c90ae1400bf2 1560 if (size == 0)
Vincent Coubard 638:c90ae1400bf2 1561 {
Vincent Coubard 638:c90ae1400bf2 1562 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 1563 }
Vincent Coubard 638:c90ae1400bf2 1564
Vincent Coubard 638:c90ae1400bf2 1565 // Verify word alignment.
Vincent Coubard 638:c90ae1400bf2 1566 if ((!is_word_aligned(p_src)) ||
Vincent Coubard 638:c90ae1400bf2 1567 (!is_word_aligned((void *)(uint32_t)size)) ||
Vincent Coubard 638:c90ae1400bf2 1568 (!is_word_aligned((void *)(uint32_t)offset)) ||
Vincent Coubard 638:c90ae1400bf2 1569 (!is_word_aligned((void *)(p_dest->block_id))))
Vincent Coubard 638:c90ae1400bf2 1570 {
Vincent Coubard 638:c90ae1400bf2 1571 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1572 }
Vincent Coubard 638:c90ae1400bf2 1573
Vincent Coubard 638:c90ae1400bf2 1574 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
Vincent Coubard 638:c90ae1400bf2 1575 }
Vincent Coubard 638:c90ae1400bf2 1576
Vincent Coubard 638:c90ae1400bf2 1577
Vincent Coubard 638:c90ae1400bf2 1578 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
Vincent Coubard 638:c90ae1400bf2 1579 {
Vincent Coubard 638:c90ae1400bf2 1580 VERIFY_MODULE_INITIALIZED();
Vincent Coubard 638:c90ae1400bf2 1581 NULL_PARAM_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1582 MODULE_RAW_HANDLE_CHECK(p_dest);
Vincent Coubard 638:c90ae1400bf2 1583
Vincent Coubard 638:c90ae1400bf2 1584 if ((!is_word_aligned((uint32_t *)p_dest->block_id)))
Vincent Coubard 638:c90ae1400bf2 1585 {
Vincent Coubard 638:c90ae1400bf2 1586 return NRF_ERROR_INVALID_ADDR;
Vincent Coubard 638:c90ae1400bf2 1587 }
Vincent Coubard 638:c90ae1400bf2 1588
Vincent Coubard 638:c90ae1400bf2 1589 return cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0);
Vincent Coubard 638:c90ae1400bf2 1590 }
Vincent Coubard 638:c90ae1400bf2 1591
Vincent Coubard 638:c90ae1400bf2 1592 #endif // PSTORAGE_RAW_MODE_ENABLE