Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
source/nordic_sdk/components/libraries/fstorage/fstorage.c@46:7f3d63792fc3, 2016-08-12 (annotated)
- Committer:
- sclassen
- Date:
- Fri Aug 12 23:43:43 2016 +0000
- Revision:
- 46:7f3d63792fc3
- Parent:
- 38:2b762c52e657
- bug 272: increase sensitivity of tap for exiting low power mode; - updated BLE_API, nRF51822, and mbed libraries
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| vcoubard | 38:2b762c52e657 | 1 | /* |
| vcoubard | 38:2b762c52e657 | 2 | * Copyright (c) Nordic Semiconductor ASA |
| vcoubard | 38:2b762c52e657 | 3 | * All rights reserved. |
| vcoubard | 38:2b762c52e657 | 4 | * |
| vcoubard | 38:2b762c52e657 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
| vcoubard | 38:2b762c52e657 | 6 | * are permitted provided that the following conditions are met: |
| vcoubard | 38:2b762c52e657 | 7 | * |
| vcoubard | 38:2b762c52e657 | 8 | * 1. Redistributions of source code must retain the above copyright notice, this |
| vcoubard | 38:2b762c52e657 | 9 | * list of conditions and the following disclaimer. |
| vcoubard | 38:2b762c52e657 | 10 | * |
| vcoubard | 38:2b762c52e657 | 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this |
| vcoubard | 38:2b762c52e657 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
| vcoubard | 38:2b762c52e657 | 13 | * other materials provided with the distribution. |
| vcoubard | 38:2b762c52e657 | 14 | * |
| vcoubard | 38:2b762c52e657 | 15 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of other |
| vcoubard | 38:2b762c52e657 | 16 | * contributors to this software may be used to endorse or promote products |
| vcoubard | 38:2b762c52e657 | 17 | * derived from this software without specific prior written permission. |
| vcoubard | 38:2b762c52e657 | 18 | * |
| vcoubard | 38:2b762c52e657 | 19 | * |
| vcoubard | 38:2b762c52e657 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| vcoubard | 38:2b762c52e657 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| vcoubard | 38:2b762c52e657 | 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| vcoubard | 38:2b762c52e657 | 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| vcoubard | 38:2b762c52e657 | 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| vcoubard | 38:2b762c52e657 | 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| vcoubard | 38:2b762c52e657 | 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| vcoubard | 38:2b762c52e657 | 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| vcoubard | 38:2b762c52e657 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| vcoubard | 38:2b762c52e657 | 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| vcoubard | 38:2b762c52e657 | 30 | * |
| vcoubard | 38:2b762c52e657 | 31 | */ |
| vcoubard | 38:2b762c52e657 | 32 | |
| vcoubard | 38:2b762c52e657 | 33 | #include "fstorage.h" |
| vcoubard | 38:2b762c52e657 | 34 | #include <stdio.h> |
| vcoubard | 38:2b762c52e657 | 35 | #include <string.h> |
| vcoubard | 38:2b762c52e657 | 36 | #include <stdbool.h> |
| vcoubard | 38:2b762c52e657 | 37 | #include "fstorage_config.h" |
| vcoubard | 38:2b762c52e657 | 38 | #include "nrf_error.h" |
| vcoubard | 38:2b762c52e657 | 39 | #include "nrf_soc.h" |
| vcoubard | 38:2b762c52e657 | 40 | |
| vcoubard | 38:2b762c52e657 | 41 | |
| vcoubard | 38:2b762c52e657 | 42 | #define FS_FLAG_INIT (1 << 0) /**< fstorage has been initialized. */ |
| vcoubard | 38:2b762c52e657 | 43 | #define FS_FLAG_PROCESSING (1 << 1) /**< fstorage is executing queued flash operations. */ |
| vcoubard | 38:2b762c52e657 | 44 | #define FS_FLAG_FLASH_REQ_PENDING (1 << 2) /**< fstorage is waiting for a flash operation initiated by another module to complete. */ |
| vcoubard | 38:2b762c52e657 | 45 | |
| vcoubard | 38:2b762c52e657 | 46 | |
| vcoubard | 38:2b762c52e657 | 47 | /**@brief Macro invocation that registers section fs_data. |
| vcoubard | 38:2b762c52e657 | 48 | * |
| vcoubard | 38:2b762c52e657 | 49 | * @details Required for compilation. |
| vcoubard | 38:2b762c52e657 | 50 | */ |
| vcoubard | 38:2b762c52e657 | 51 | NRF_SECTION_VARS_REGISTER_SECTION(fs_data); |
| vcoubard | 38:2b762c52e657 | 52 | |
| vcoubard | 38:2b762c52e657 | 53 | |
| vcoubard | 38:2b762c52e657 | 54 | /**@brief Macro invocation that declares symbols used to find the beginning and end of the section fs_data. |
| vcoubard | 38:2b762c52e657 | 55 | * |
| vcoubard | 38:2b762c52e657 | 56 | * @details Required for compilation. |
| vcoubard | 38:2b762c52e657 | 57 | */ |
| vcoubard | 38:2b762c52e657 | 58 | NRF_SECTION_VARS_REGISTER_SYMBOLS(fs_config_t, fs_data); |
| vcoubard | 38:2b762c52e657 | 59 | |
| vcoubard | 38:2b762c52e657 | 60 | |
| vcoubard | 38:2b762c52e657 | 61 | /**@defgroup Section vars helper macros. |
| vcoubard | 38:2b762c52e657 | 62 | * |
| vcoubard | 38:2b762c52e657 | 63 | * @details Macros used to manipulate registered section variables. |
| vcoubard | 38:2b762c52e657 | 64 | */ |
| vcoubard | 38:2b762c52e657 | 65 | /**@brief Get section variable with fstorage configuration by index. */ |
| vcoubard | 38:2b762c52e657 | 66 | #define FS_SECTION_VARS_GET(i) NRF_SECTION_VARS_GET(i, fs_config_t, fs_data) |
| vcoubard | 38:2b762c52e657 | 67 | /**@brief Get the number of registered section variables. */ |
| vcoubard | 38:2b762c52e657 | 68 | #define FS_SECTION_VARS_COUNT NRF_SECTION_VARS_COUNT(fs_config_t, fs_data) |
| vcoubard | 38:2b762c52e657 | 69 | /**@brief Get the start address of the registered section variables. */ |
| vcoubard | 38:2b762c52e657 | 70 | #define FS_SECTION_VARS_START_ADDR NRF_SECTION_VARS_START_ADDR(fs_data) |
| vcoubard | 38:2b762c52e657 | 71 | /**@brief Get the end address of the registered section variables. */ |
| vcoubard | 38:2b762c52e657 | 72 | #define FS_SECTION_VARS_END_ADDR NRF_SECTION_VARS_END_ADDR(fs_data) |
| vcoubard | 38:2b762c52e657 | 73 | |
| vcoubard | 38:2b762c52e657 | 74 | /** @} */ |
| vcoubard | 38:2b762c52e657 | 75 | |
| vcoubard | 38:2b762c52e657 | 76 | |
| vcoubard | 38:2b762c52e657 | 77 | /**@brief The command queue element. |
| vcoubard | 38:2b762c52e657 | 78 | * |
| vcoubard | 38:2b762c52e657 | 79 | * @details Encapsulate details of a command requested to this module. |
| vcoubard | 38:2b762c52e657 | 80 | */ |
| vcoubard | 38:2b762c52e657 | 81 | typedef struct |
| vcoubard | 38:2b762c52e657 | 82 | { |
| vcoubard | 38:2b762c52e657 | 83 | fs_config_t const * p_config; /**< The configuration of the user who requested the operation. */ |
| vcoubard | 38:2b762c52e657 | 84 | uint8_t op_code; /**< Operation code. */ |
| vcoubard | 38:2b762c52e657 | 85 | uint32_t const * p_src; /**< Pointer to the data to be written to flash. The data must be kept in memory until the operation has finished. */ |
| vcoubard | 38:2b762c52e657 | 86 | uint32_t const * p_addr; /**< Destination of the data in flash. */ |
| vcoubard | 38:2b762c52e657 | 87 | fs_length_t length_words; /**< Length of the operation */ |
| vcoubard | 38:2b762c52e657 | 88 | fs_length_t offset; /**< Offset of the operation if operation is done in chunks */ |
| vcoubard | 38:2b762c52e657 | 89 | } fs_cmd_t; |
| vcoubard | 38:2b762c52e657 | 90 | |
| vcoubard | 38:2b762c52e657 | 91 | |
| vcoubard | 38:2b762c52e657 | 92 | /**@brief Structure that defines the command queue |
| vcoubard | 38:2b762c52e657 | 93 | * |
| vcoubard | 38:2b762c52e657 | 94 | * @details This queue holds flash operations requested to the module. |
| vcoubard | 38:2b762c52e657 | 95 | * The data to be written must be kept in memory until the write operation is completed, |
| vcoubard | 38:2b762c52e657 | 96 | * i.e., a callback indicating completion is received by the application. |
| vcoubard | 38:2b762c52e657 | 97 | */ |
| vcoubard | 38:2b762c52e657 | 98 | typedef struct |
| vcoubard | 38:2b762c52e657 | 99 | { |
| vcoubard | 38:2b762c52e657 | 100 | uint8_t rp; /**< The current element being processed. */ |
| vcoubard | 38:2b762c52e657 | 101 | uint8_t count; /**< Number of elements in the queue. */ |
| vcoubard | 38:2b762c52e657 | 102 | fs_cmd_t cmd[FS_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details. */ |
| vcoubard | 38:2b762c52e657 | 103 | } fs_cmd_queue_t; |
| vcoubard | 38:2b762c52e657 | 104 | |
| vcoubard | 38:2b762c52e657 | 105 | |
| vcoubard | 38:2b762c52e657 | 106 | static uint8_t m_flags; /**< FStorage status flags. */ |
| vcoubard | 38:2b762c52e657 | 107 | static fs_cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */ |
| vcoubard | 38:2b762c52e657 | 108 | static uint16_t m_retry_count = 0; /**< Number of times a single flash operation was retried. */ |
| vcoubard | 38:2b762c52e657 | 109 | |
| vcoubard | 38:2b762c52e657 | 110 | |
| vcoubard | 38:2b762c52e657 | 111 | // Function prototypes |
| vcoubard | 38:2b762c52e657 | 112 | static ret_code_t queue_process(void); |
| vcoubard | 38:2b762c52e657 | 113 | static ret_code_t queue_process_impl(void); |
| vcoubard | 38:2b762c52e657 | 114 | static void app_notify(uint32_t result, fs_cmd_t const * p_cmd); |
| vcoubard | 38:2b762c52e657 | 115 | |
| vcoubard | 38:2b762c52e657 | 116 | |
| vcoubard | 38:2b762c52e657 | 117 | /**@brief Macro to check that the configuration is non-NULL and within |
| vcoubard | 38:2b762c52e657 | 118 | * valid section variable memory bounds. |
| vcoubard | 38:2b762c52e657 | 119 | * |
| vcoubard | 38:2b762c52e657 | 120 | * @param[in] config Configuration to check. |
| vcoubard | 38:2b762c52e657 | 121 | */ |
| vcoubard | 38:2b762c52e657 | 122 | #define FS_CHECK_CONFIG(config) \ |
| vcoubard | 38:2b762c52e657 | 123 | ((FS_SECTION_VARS_START_ADDR < config) && (config < FS_SECTION_VARS_END_ADDR)) |
| vcoubard | 38:2b762c52e657 | 124 | |
| vcoubard | 38:2b762c52e657 | 125 | |
| vcoubard | 38:2b762c52e657 | 126 | /**@brief Function to check that the configuration is non-NULL and within |
| vcoubard | 38:2b762c52e657 | 127 | * valid section variable memory bounds. |
| vcoubard | 38:2b762c52e657 | 128 | * |
| vcoubard | 38:2b762c52e657 | 129 | * @param[in] config Configuration to check. |
| vcoubard | 38:2b762c52e657 | 130 | */ |
| vcoubard | 38:2b762c52e657 | 131 | static bool check_config(fs_config_t const * const config) |
| vcoubard | 38:2b762c52e657 | 132 | { |
| vcoubard | 38:2b762c52e657 | 133 | if (config == NULL) |
| vcoubard | 38:2b762c52e657 | 134 | { |
| vcoubard | 38:2b762c52e657 | 135 | return false; |
| vcoubard | 38:2b762c52e657 | 136 | } |
| vcoubard | 38:2b762c52e657 | 137 | |
| vcoubard | 38:2b762c52e657 | 138 | if ((FS_SECTION_VARS_START_ADDR <= (uint32_t)config) && ((uint32_t)config < FS_SECTION_VARS_END_ADDR)) |
| vcoubard | 38:2b762c52e657 | 139 | { |
| vcoubard | 38:2b762c52e657 | 140 | return true; |
| vcoubard | 38:2b762c52e657 | 141 | } |
| vcoubard | 38:2b762c52e657 | 142 | else |
| vcoubard | 38:2b762c52e657 | 143 | { |
| vcoubard | 38:2b762c52e657 | 144 | return false; |
| vcoubard | 38:2b762c52e657 | 145 | } |
| vcoubard | 38:2b762c52e657 | 146 | } |
| vcoubard | 38:2b762c52e657 | 147 | |
| vcoubard | 38:2b762c52e657 | 148 | |
| vcoubard | 38:2b762c52e657 | 149 | /**@brief Function to initialize the queue. */ |
| vcoubard | 38:2b762c52e657 | 150 | static void queue_init(void) |
| vcoubard | 38:2b762c52e657 | 151 | { |
| vcoubard | 38:2b762c52e657 | 152 | memset(&m_cmd_queue, 0, sizeof(fs_cmd_queue_t)); |
| vcoubard | 38:2b762c52e657 | 153 | } |
| vcoubard | 38:2b762c52e657 | 154 | |
| vcoubard | 38:2b762c52e657 | 155 | |
| vcoubard | 38:2b762c52e657 | 156 | /**@brief Function to reset a queue item to its default values. |
| vcoubard | 38:2b762c52e657 | 157 | * |
| vcoubard | 38:2b762c52e657 | 158 | * @param index Index of the queue element. |
| vcoubard | 38:2b762c52e657 | 159 | */ |
| vcoubard | 38:2b762c52e657 | 160 | static void cmd_reset(uint32_t index) |
| vcoubard | 38:2b762c52e657 | 161 | { |
| vcoubard | 38:2b762c52e657 | 162 | memset(&m_cmd_queue.cmd[index], 0, sizeof(fs_cmd_t)); |
| vcoubard | 38:2b762c52e657 | 163 | } |
| vcoubard | 38:2b762c52e657 | 164 | |
| vcoubard | 38:2b762c52e657 | 165 | |
| vcoubard | 38:2b762c52e657 | 166 | /**@brief Function to enqueue flash access command |
| vcoubard | 38:2b762c52e657 | 167 | * |
| vcoubard | 38:2b762c52e657 | 168 | * @param[in] config Registered configuration. |
| vcoubard | 38:2b762c52e657 | 169 | * @param[in] op_code Operation code. |
| vcoubard | 38:2b762c52e657 | 170 | * @param[in] address Destination of the data. |
| vcoubard | 38:2b762c52e657 | 171 | * @param[in] p_src Source of data or NULL if n/a. |
| vcoubard | 38:2b762c52e657 | 172 | * @param[in] length Length of the data, in 4 byte words. |
| vcoubard | 38:2b762c52e657 | 173 | * |
| vcoubard | 38:2b762c52e657 | 174 | * @retval NRF_SUCCESS Success. Command enqueued. |
| vcoubard | 38:2b762c52e657 | 175 | * @retval NRF_ERROR_NO_MEM Error. Queue is full. |
| vcoubard | 38:2b762c52e657 | 176 | * @retval Any error returned by the SoftDevice flash API. |
| vcoubard | 38:2b762c52e657 | 177 | */ |
| vcoubard | 38:2b762c52e657 | 178 | static ret_code_t cmd_enqueue(fs_config_t const * p_config, |
| vcoubard | 38:2b762c52e657 | 179 | uint8_t op_code, |
| vcoubard | 38:2b762c52e657 | 180 | uint32_t const * p_addr, |
| vcoubard | 38:2b762c52e657 | 181 | uint32_t const * p_src, |
| vcoubard | 38:2b762c52e657 | 182 | fs_length_t length_words) |
| vcoubard | 38:2b762c52e657 | 183 | { |
| vcoubard | 38:2b762c52e657 | 184 | fs_cmd_t * p_cmd; |
| vcoubard | 38:2b762c52e657 | 185 | uint8_t write_pos; |
| vcoubard | 38:2b762c52e657 | 186 | |
| vcoubard | 38:2b762c52e657 | 187 | if (m_cmd_queue.count == FS_CMD_QUEUE_SIZE - 1) |
| vcoubard | 38:2b762c52e657 | 188 | { |
| vcoubard | 38:2b762c52e657 | 189 | return NRF_ERROR_NO_MEM; |
| vcoubard | 38:2b762c52e657 | 190 | } |
| vcoubard | 38:2b762c52e657 | 191 | |
| vcoubard | 38:2b762c52e657 | 192 | write_pos = (m_cmd_queue.rp + m_cmd_queue.count) % FS_CMD_QUEUE_SIZE; |
| vcoubard | 38:2b762c52e657 | 193 | |
| vcoubard | 38:2b762c52e657 | 194 | p_cmd = &m_cmd_queue.cmd[write_pos]; |
| vcoubard | 38:2b762c52e657 | 195 | |
| vcoubard | 38:2b762c52e657 | 196 | p_cmd->p_config = p_config; |
| vcoubard | 38:2b762c52e657 | 197 | p_cmd->op_code = op_code; |
| vcoubard | 38:2b762c52e657 | 198 | p_cmd->p_src = p_src; |
| vcoubard | 38:2b762c52e657 | 199 | p_cmd->p_addr = p_addr; |
| vcoubard | 38:2b762c52e657 | 200 | p_cmd->length_words = length_words; |
| vcoubard | 38:2b762c52e657 | 201 | |
| vcoubard | 38:2b762c52e657 | 202 | m_cmd_queue.count++; |
| vcoubard | 38:2b762c52e657 | 203 | |
| vcoubard | 38:2b762c52e657 | 204 | return queue_process(); |
| vcoubard | 38:2b762c52e657 | 205 | } |
| vcoubard | 38:2b762c52e657 | 206 | |
| vcoubard | 38:2b762c52e657 | 207 | |
| vcoubard | 38:2b762c52e657 | 208 | /**@brief Function to consume queue item and notify the return value of the operation. |
| vcoubard | 38:2b762c52e657 | 209 | * |
| vcoubard | 38:2b762c52e657 | 210 | * @details This function will report the result and remove the command from the queue after |
| vcoubard | 38:2b762c52e657 | 211 | * notification. |
| vcoubard | 38:2b762c52e657 | 212 | */ |
| vcoubard | 38:2b762c52e657 | 213 | static void cmd_consume(uint32_t result, const fs_cmd_t * p_cmd) |
| vcoubard | 38:2b762c52e657 | 214 | { |
| vcoubard | 38:2b762c52e657 | 215 | // Consume the current item on the queue. |
| vcoubard | 38:2b762c52e657 | 216 | uint8_t rp = m_cmd_queue.rp; |
| vcoubard | 38:2b762c52e657 | 217 | |
| vcoubard | 38:2b762c52e657 | 218 | m_cmd_queue.count--; |
| vcoubard | 38:2b762c52e657 | 219 | if (m_cmd_queue.count == 0) |
| vcoubard | 38:2b762c52e657 | 220 | { |
| vcoubard | 38:2b762c52e657 | 221 | // There are no elements left. Stop processing the queue. |
| vcoubard | 38:2b762c52e657 | 222 | m_flags &= ~FS_FLAG_PROCESSING; |
| vcoubard | 38:2b762c52e657 | 223 | } |
| vcoubard | 38:2b762c52e657 | 224 | |
| vcoubard | 38:2b762c52e657 | 225 | if (++(m_cmd_queue.rp) == FS_CMD_QUEUE_SIZE) |
| vcoubard | 38:2b762c52e657 | 226 | { |
| vcoubard | 38:2b762c52e657 | 227 | m_cmd_queue.rp = 0; |
| vcoubard | 38:2b762c52e657 | 228 | } |
| vcoubard | 38:2b762c52e657 | 229 | |
| vcoubard | 38:2b762c52e657 | 230 | // Notify upon successful operation. |
| vcoubard | 38:2b762c52e657 | 231 | app_notify(result, p_cmd); |
| vcoubard | 38:2b762c52e657 | 232 | |
| vcoubard | 38:2b762c52e657 | 233 | // Reset the queue element. |
| vcoubard | 38:2b762c52e657 | 234 | cmd_reset(rp); |
| vcoubard | 38:2b762c52e657 | 235 | } |
| vcoubard | 38:2b762c52e657 | 236 | |
| vcoubard | 38:2b762c52e657 | 237 | |
| vcoubard | 38:2b762c52e657 | 238 | /**@brief Function to store data to flash. |
| vcoubard | 38:2b762c52e657 | 239 | * |
| vcoubard | 38:2b762c52e657 | 240 | * @param[in] p_cmd The queue element associated with the operation. |
| vcoubard | 38:2b762c52e657 | 241 | * |
| vcoubard | 38:2b762c52e657 | 242 | * @retval NRF_SUCCESS Success. The request was sent to the SoftDevice. |
| vcoubard | 38:2b762c52e657 | 243 | * @retval Any error returned by the SoftDevice flash API. |
| vcoubard | 38:2b762c52e657 | 244 | */ |
| vcoubard | 38:2b762c52e657 | 245 | static __INLINE uint32_t store_execute(fs_cmd_t const * const p_cmd) |
| vcoubard | 38:2b762c52e657 | 246 | { |
| vcoubard | 38:2b762c52e657 | 247 | // Write in chunks if write-size is larger than FS_MAX_WRITE_SIZE. |
| vcoubard | 38:2b762c52e657 | 248 | fs_length_t const length = ((p_cmd->length_words - p_cmd->offset) < FS_MAX_WRITE_SIZE_WORDS) ? |
| vcoubard | 38:2b762c52e657 | 249 | (p_cmd->length_words - p_cmd->offset) : FS_MAX_WRITE_SIZE_WORDS; |
| vcoubard | 38:2b762c52e657 | 250 | |
| vcoubard | 38:2b762c52e657 | 251 | return sd_flash_write((uint32_t*)p_cmd->p_addr + p_cmd->offset /* destination */, |
| vcoubard | 38:2b762c52e657 | 252 | (uint32_t*)p_cmd->p_src + p_cmd->offset /* source */, |
| vcoubard | 38:2b762c52e657 | 253 | length); |
| vcoubard | 38:2b762c52e657 | 254 | } |
| vcoubard | 38:2b762c52e657 | 255 | |
| vcoubard | 38:2b762c52e657 | 256 | |
| vcoubard | 38:2b762c52e657 | 257 | /**@brief Function to erase a page. |
| vcoubard | 38:2b762c52e657 | 258 | * |
| vcoubard | 38:2b762c52e657 | 259 | * @param[in] p_cmd The queue element associated with the operation. |
| vcoubard | 38:2b762c52e657 | 260 | * |
| vcoubard | 38:2b762c52e657 | 261 | * @retval NRF_SUCCESS Success. The request was sent to the SoftDevice. |
| vcoubard | 38:2b762c52e657 | 262 | * @retval Any error returned by the SoftDevice flash API. |
| vcoubard | 38:2b762c52e657 | 263 | */ |
| vcoubard | 38:2b762c52e657 | 264 | static __INLINE uint32_t erase_execute(fs_cmd_t const * const p_cmd) |
| vcoubard | 38:2b762c52e657 | 265 | { |
| vcoubard | 38:2b762c52e657 | 266 | // Erase the page. |
| vcoubard | 38:2b762c52e657 | 267 | return sd_flash_page_erase((uint32_t)(p_cmd->p_addr + p_cmd->offset) / FS_PAGE_SIZE); |
| vcoubard | 38:2b762c52e657 | 268 | } |
| vcoubard | 38:2b762c52e657 | 269 | |
| vcoubard | 38:2b762c52e657 | 270 | |
| vcoubard | 38:2b762c52e657 | 271 | /**@brief Function to process the current element in the queue and return the result. |
| vcoubard | 38:2b762c52e657 | 272 | * |
| vcoubard | 38:2b762c52e657 | 273 | * @retval NRF_SUCCESS Success. |
| vcoubard | 38:2b762c52e657 | 274 | * @retval NRF_ERROR_FORBIDDEN Error. Undefined command. |
| vcoubard | 38:2b762c52e657 | 275 | * @retval Any error returned by the SoftDevice flash API. |
| vcoubard | 38:2b762c52e657 | 276 | */ |
| vcoubard | 38:2b762c52e657 | 277 | static uint32_t queue_process_impl(void) |
| vcoubard | 38:2b762c52e657 | 278 | { |
| vcoubard | 38:2b762c52e657 | 279 | uint32_t ret; |
| vcoubard | 38:2b762c52e657 | 280 | |
| vcoubard | 38:2b762c52e657 | 281 | fs_cmd_t const * const p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; |
| vcoubard | 38:2b762c52e657 | 282 | |
| vcoubard | 38:2b762c52e657 | 283 | switch (p_cmd->op_code) |
| vcoubard | 38:2b762c52e657 | 284 | { |
| vcoubard | 38:2b762c52e657 | 285 | case FS_OP_STORE: |
| vcoubard | 38:2b762c52e657 | 286 | ret = store_execute(p_cmd); |
| vcoubard | 38:2b762c52e657 | 287 | break; |
| vcoubard | 38:2b762c52e657 | 288 | |
| vcoubard | 38:2b762c52e657 | 289 | case FS_OP_ERASE: |
| vcoubard | 38:2b762c52e657 | 290 | ret = erase_execute(p_cmd); |
| vcoubard | 38:2b762c52e657 | 291 | break; |
| vcoubard | 38:2b762c52e657 | 292 | |
| vcoubard | 38:2b762c52e657 | 293 | case FS_OP_NONE: |
| vcoubard | 38:2b762c52e657 | 294 | ret = NRF_SUCCESS; |
| vcoubard | 38:2b762c52e657 | 295 | break; |
| vcoubard | 38:2b762c52e657 | 296 | |
| vcoubard | 38:2b762c52e657 | 297 | default: |
| vcoubard | 38:2b762c52e657 | 298 | ret = NRF_ERROR_FORBIDDEN; |
| vcoubard | 38:2b762c52e657 | 299 | break; |
| vcoubard | 38:2b762c52e657 | 300 | } |
| vcoubard | 38:2b762c52e657 | 301 | |
| vcoubard | 38:2b762c52e657 | 302 | return ret; |
| vcoubard | 38:2b762c52e657 | 303 | } |
| vcoubard | 38:2b762c52e657 | 304 | |
| vcoubard | 38:2b762c52e657 | 305 | |
| vcoubard | 38:2b762c52e657 | 306 | /**@brief Starts processing the queue if there are no pending flash operations |
| vcoubard | 38:2b762c52e657 | 307 | * for which we are awaiting a callback. |
| vcoubard | 38:2b762c52e657 | 308 | */ |
| vcoubard | 38:2b762c52e657 | 309 | static ret_code_t queue_process(void) |
| vcoubard | 38:2b762c52e657 | 310 | { |
| vcoubard | 38:2b762c52e657 | 311 | ret_code_t ret = NRF_SUCCESS; |
| vcoubard | 38:2b762c52e657 | 312 | |
| vcoubard | 38:2b762c52e657 | 313 | /** If the queue is not being processed, and there are still |
| vcoubard | 38:2b762c52e657 | 314 | * some elements in it, then start processing. */ |
| vcoubard | 38:2b762c52e657 | 315 | if ( !(m_flags & FS_FLAG_PROCESSING) && |
| vcoubard | 38:2b762c52e657 | 316 | (m_cmd_queue.count > 0)) |
| vcoubard | 38:2b762c52e657 | 317 | { |
| vcoubard | 38:2b762c52e657 | 318 | m_flags |= FS_FLAG_PROCESSING; |
| vcoubard | 38:2b762c52e657 | 319 | |
| vcoubard | 38:2b762c52e657 | 320 | ret = queue_process_impl(); |
| vcoubard | 38:2b762c52e657 | 321 | |
| vcoubard | 38:2b762c52e657 | 322 | /** There is ongoing flash-operation which was not |
| vcoubard | 38:2b762c52e657 | 323 | * initiated by fstorage. */ |
| vcoubard | 38:2b762c52e657 | 324 | if (ret == NRF_ERROR_BUSY) |
| vcoubard | 38:2b762c52e657 | 325 | { |
| vcoubard | 38:2b762c52e657 | 326 | // Wait for a system callback. |
| vcoubard | 38:2b762c52e657 | 327 | m_flags |= FS_FLAG_FLASH_REQ_PENDING; |
| vcoubard | 38:2b762c52e657 | 328 | |
| vcoubard | 38:2b762c52e657 | 329 | // Stop processing the queue. |
| vcoubard | 38:2b762c52e657 | 330 | m_flags &= ~FS_FLAG_PROCESSING; |
| vcoubard | 38:2b762c52e657 | 331 | |
| vcoubard | 38:2b762c52e657 | 332 | ret = NRF_SUCCESS; |
| vcoubard | 38:2b762c52e657 | 333 | } |
| vcoubard | 38:2b762c52e657 | 334 | else if (ret != NRF_SUCCESS) |
| vcoubard | 38:2b762c52e657 | 335 | { |
| vcoubard | 38:2b762c52e657 | 336 | // Another error has occurred. |
| vcoubard | 38:2b762c52e657 | 337 | app_notify(ret, &m_cmd_queue.cmd[m_cmd_queue.rp]); |
| vcoubard | 38:2b762c52e657 | 338 | } |
| vcoubard | 38:2b762c52e657 | 339 | } |
| vcoubard | 38:2b762c52e657 | 340 | |
| vcoubard | 38:2b762c52e657 | 341 | // If we are already processing the queue, return immediately. |
| vcoubard | 38:2b762c52e657 | 342 | return ret; |
| vcoubard | 38:2b762c52e657 | 343 | } |
| vcoubard | 38:2b762c52e657 | 344 | |
| vcoubard | 38:2b762c52e657 | 345 | |
| vcoubard | 38:2b762c52e657 | 346 | /**@brief Flash operation success callback handler. |
| vcoubard | 38:2b762c52e657 | 347 | * |
| vcoubard | 38:2b762c52e657 | 348 | * @details This function updates read/write pointers. |
| vcoubard | 38:2b762c52e657 | 349 | * This function resets retry count. |
| vcoubard | 38:2b762c52e657 | 350 | */ |
| vcoubard | 38:2b762c52e657 | 351 | static __INLINE void on_operation_success(void) |
| vcoubard | 38:2b762c52e657 | 352 | { |
| vcoubard | 38:2b762c52e657 | 353 | fs_cmd_t * const p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; |
| vcoubard | 38:2b762c52e657 | 354 | |
| vcoubard | 38:2b762c52e657 | 355 | m_retry_count = 0; |
| vcoubard | 38:2b762c52e657 | 356 | |
| vcoubard | 38:2b762c52e657 | 357 | switch (p_cmd->op_code) |
| vcoubard | 38:2b762c52e657 | 358 | { |
| vcoubard | 38:2b762c52e657 | 359 | case FS_OP_STORE: |
| vcoubard | 38:2b762c52e657 | 360 | // Update the offset on successful write. |
| vcoubard | 38:2b762c52e657 | 361 | p_cmd->offset += FS_MAX_WRITE_SIZE_WORDS; |
| vcoubard | 38:2b762c52e657 | 362 | break; |
| vcoubard | 38:2b762c52e657 | 363 | |
| vcoubard | 38:2b762c52e657 | 364 | case FS_OP_ERASE: |
| vcoubard | 38:2b762c52e657 | 365 | // Update the offset to correspond to the page that has been erased. |
| vcoubard | 38:2b762c52e657 | 366 | p_cmd->offset += FS_PAGE_SIZE_WORDS; |
| vcoubard | 38:2b762c52e657 | 367 | break; |
| vcoubard | 38:2b762c52e657 | 368 | } |
| vcoubard | 38:2b762c52e657 | 369 | |
| vcoubard | 38:2b762c52e657 | 370 | // If offset is equal to or larger than length, then the operation has finished. |
| vcoubard | 38:2b762c52e657 | 371 | if (p_cmd->offset >= p_cmd->length_words) |
| vcoubard | 38:2b762c52e657 | 372 | { |
| vcoubard | 38:2b762c52e657 | 373 | cmd_consume(NRF_SUCCESS, p_cmd); |
| vcoubard | 38:2b762c52e657 | 374 | } |
| vcoubard | 38:2b762c52e657 | 375 | |
| vcoubard | 38:2b762c52e657 | 376 | queue_process(); |
| vcoubard | 38:2b762c52e657 | 377 | } |
| vcoubard | 38:2b762c52e657 | 378 | |
| vcoubard | 38:2b762c52e657 | 379 | |
| vcoubard | 38:2b762c52e657 | 380 | /**@brief Flash operation failure callback handler. |
| vcoubard | 38:2b762c52e657 | 381 | * |
| vcoubard | 38:2b762c52e657 | 382 | * @details Function to keep track of retries and notify failures. |
| vcoubard | 38:2b762c52e657 | 383 | */ |
| vcoubard | 38:2b762c52e657 | 384 | static __INLINE void on_operation_failure(uint32_t sys_evt) |
| vcoubard | 38:2b762c52e657 | 385 | { |
| vcoubard | 38:2b762c52e657 | 386 | const fs_cmd_t * p_cmd; |
| vcoubard | 38:2b762c52e657 | 387 | |
| vcoubard | 38:2b762c52e657 | 388 | if (++m_retry_count > FS_CMD_MAX_RETRIES) |
| vcoubard | 38:2b762c52e657 | 389 | { |
| vcoubard | 38:2b762c52e657 | 390 | p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; |
| vcoubard | 38:2b762c52e657 | 391 | cmd_consume(NRF_ERROR_TIMEOUT, p_cmd); |
| vcoubard | 38:2b762c52e657 | 392 | } |
| vcoubard | 38:2b762c52e657 | 393 | |
| vcoubard | 38:2b762c52e657 | 394 | queue_process(); |
| vcoubard | 38:2b762c52e657 | 395 | } |
| vcoubard | 38:2b762c52e657 | 396 | |
| vcoubard | 38:2b762c52e657 | 397 | |
| vcoubard | 38:2b762c52e657 | 398 | /**@brief Function to notify users. |
| vcoubard | 38:2b762c52e657 | 399 | * |
| vcoubard | 38:2b762c52e657 | 400 | * @param[in] result Result of the flash operation. |
| vcoubard | 38:2b762c52e657 | 401 | * @param[in] p_cmd The command associated with the callback. |
| vcoubard | 38:2b762c52e657 | 402 | */ |
| vcoubard | 38:2b762c52e657 | 403 | static void app_notify(uint32_t result, fs_cmd_t const * const p_cmd) |
| vcoubard | 38:2b762c52e657 | 404 | { |
| vcoubard | 38:2b762c52e657 | 405 | p_cmd->p_config->cb(p_cmd->op_code, result, p_cmd->p_addr, p_cmd->length_words); |
| vcoubard | 38:2b762c52e657 | 406 | } |
| vcoubard | 38:2b762c52e657 | 407 | |
| vcoubard | 38:2b762c52e657 | 408 | |
| vcoubard | 38:2b762c52e657 | 409 | ret_code_t fs_init(void) |
| vcoubard | 38:2b762c52e657 | 410 | { |
| vcoubard | 38:2b762c52e657 | 411 | uint16_t lowest_index = 0; |
| vcoubard | 38:2b762c52e657 | 412 | uint16_t lowest_order = 0xFFFF; |
| vcoubard | 38:2b762c52e657 | 413 | uint32_t * current_end = (uint32_t*)FS_PAGE_END_ADDR; |
| vcoubard | 38:2b762c52e657 | 414 | uint32_t num_left = FS_SECTION_VARS_COUNT; |
| vcoubard | 38:2b762c52e657 | 415 | |
| vcoubard | 38:2b762c52e657 | 416 | queue_init(); |
| vcoubard | 38:2b762c52e657 | 417 | |
| vcoubard | 38:2b762c52e657 | 418 | /** Assign pages to registered users, beginning with the ones with the lowest |
| vcoubard | 38:2b762c52e657 | 419 | * order, which will be assigned pages with the lowest memory address. */ |
| vcoubard | 38:2b762c52e657 | 420 | do |
| vcoubard | 38:2b762c52e657 | 421 | { |
| vcoubard | 38:2b762c52e657 | 422 | fs_config_t * p_config; |
| vcoubard | 38:2b762c52e657 | 423 | for (uint16_t i = 0; i < FS_SECTION_VARS_COUNT; i++) |
| vcoubard | 38:2b762c52e657 | 424 | { |
| vcoubard | 38:2b762c52e657 | 425 | p_config = FS_SECTION_VARS_GET(i); |
| vcoubard | 38:2b762c52e657 | 426 | |
| vcoubard | 38:2b762c52e657 | 427 | // Skip the ones which have the end-address already set. |
| vcoubard | 38:2b762c52e657 | 428 | if (p_config->p_end_addr != NULL) |
| vcoubard | 38:2b762c52e657 | 429 | continue; |
| vcoubard | 38:2b762c52e657 | 430 | |
| vcoubard | 38:2b762c52e657 | 431 | if (p_config->page_order < lowest_order) |
| vcoubard | 38:2b762c52e657 | 432 | { |
| vcoubard | 38:2b762c52e657 | 433 | lowest_order = p_config->page_order; |
| vcoubard | 38:2b762c52e657 | 434 | lowest_index = i; |
| vcoubard | 38:2b762c52e657 | 435 | } |
| vcoubard | 38:2b762c52e657 | 436 | } |
| vcoubard | 38:2b762c52e657 | 437 | |
| vcoubard | 38:2b762c52e657 | 438 | p_config = FS_SECTION_VARS_GET(lowest_index); |
| vcoubard | 38:2b762c52e657 | 439 | |
| vcoubard | 38:2b762c52e657 | 440 | p_config->p_end_addr = current_end; |
| vcoubard | 38:2b762c52e657 | 441 | p_config->p_start_addr = p_config->p_end_addr - (p_config->num_pages * FS_PAGE_SIZE_WORDS); |
| vcoubard | 38:2b762c52e657 | 442 | |
| vcoubard | 38:2b762c52e657 | 443 | current_end = p_config->p_start_addr; |
| vcoubard | 38:2b762c52e657 | 444 | lowest_order = 0xFFFF; |
| vcoubard | 38:2b762c52e657 | 445 | |
| vcoubard | 38:2b762c52e657 | 446 | } while ( --num_left > 0 ); |
| vcoubard | 38:2b762c52e657 | 447 | |
| vcoubard | 38:2b762c52e657 | 448 | m_flags |= FS_FLAG_INIT; |
| vcoubard | 38:2b762c52e657 | 449 | |
| vcoubard | 38:2b762c52e657 | 450 | return NRF_SUCCESS; |
| vcoubard | 38:2b762c52e657 | 451 | } |
| vcoubard | 38:2b762c52e657 | 452 | |
| vcoubard | 38:2b762c52e657 | 453 | |
| vcoubard | 38:2b762c52e657 | 454 | ret_code_t fs_store(fs_config_t const * p_config, |
| vcoubard | 38:2b762c52e657 | 455 | uint32_t const * p_addr, |
| vcoubard | 38:2b762c52e657 | 456 | uint32_t const * const p_data, |
| vcoubard | 38:2b762c52e657 | 457 | fs_length_t length_words) |
| vcoubard | 38:2b762c52e657 | 458 | { |
| vcoubard | 38:2b762c52e657 | 459 | if ((m_flags & FS_FLAG_INIT) == 0) |
| vcoubard | 38:2b762c52e657 | 460 | { |
| vcoubard | 38:2b762c52e657 | 461 | return NRF_ERROR_INVALID_STATE; |
| vcoubard | 38:2b762c52e657 | 462 | } |
| vcoubard | 38:2b762c52e657 | 463 | |
| vcoubard | 38:2b762c52e657 | 464 | if (!check_config(p_config)) |
| vcoubard | 38:2b762c52e657 | 465 | { |
| vcoubard | 38:2b762c52e657 | 466 | return NRF_ERROR_FORBIDDEN; |
| vcoubard | 38:2b762c52e657 | 467 | } |
| vcoubard | 38:2b762c52e657 | 468 | |
| vcoubard | 38:2b762c52e657 | 469 | if (!is_word_aligned(p_addr)) |
| vcoubard | 38:2b762c52e657 | 470 | { |
| vcoubard | 38:2b762c52e657 | 471 | return NRF_ERROR_INVALID_ADDR; |
| vcoubard | 38:2b762c52e657 | 472 | } |
| vcoubard | 38:2b762c52e657 | 473 | |
| vcoubard | 38:2b762c52e657 | 474 | // Check that the erase operation is on pages owned by this user (configuration). |
| vcoubard | 38:2b762c52e657 | 475 | if ((p_addr < p_config->p_start_addr) || ((p_addr + length_words) > p_config->p_end_addr)) |
| vcoubard | 38:2b762c52e657 | 476 | { |
| vcoubard | 38:2b762c52e657 | 477 | return NRF_ERROR_INVALID_ADDR; |
| vcoubard | 38:2b762c52e657 | 478 | } |
| vcoubard | 38:2b762c52e657 | 479 | |
| vcoubard | 38:2b762c52e657 | 480 | return cmd_enqueue(p_config, FS_OP_STORE, p_addr, p_data, length_words); |
| vcoubard | 38:2b762c52e657 | 481 | } |
| vcoubard | 38:2b762c52e657 | 482 | |
| vcoubard | 38:2b762c52e657 | 483 | |
| vcoubard | 38:2b762c52e657 | 484 | ret_code_t fs_erase(fs_config_t const * p_config, |
| vcoubard | 38:2b762c52e657 | 485 | uint32_t * const p_addr, |
| vcoubard | 38:2b762c52e657 | 486 | fs_length_t const length_words) |
| vcoubard | 38:2b762c52e657 | 487 | { |
| vcoubard | 38:2b762c52e657 | 488 | if ((m_flags & FS_FLAG_INIT) == 0) |
| vcoubard | 38:2b762c52e657 | 489 | { |
| vcoubard | 38:2b762c52e657 | 490 | return NRF_ERROR_INVALID_STATE; |
| vcoubard | 38:2b762c52e657 | 491 | } |
| vcoubard | 38:2b762c52e657 | 492 | |
| vcoubard | 38:2b762c52e657 | 493 | if (!check_config(p_config)) |
| vcoubard | 38:2b762c52e657 | 494 | { |
| vcoubard | 38:2b762c52e657 | 495 | return NRF_ERROR_FORBIDDEN; |
| vcoubard | 38:2b762c52e657 | 496 | } |
| vcoubard | 38:2b762c52e657 | 497 | |
| vcoubard | 38:2b762c52e657 | 498 | /** Check that the address is aligned on a page boundary and the length to erase |
| vcoubard | 38:2b762c52e657 | 499 | * is a multiple of the page size. */ |
| vcoubard | 38:2b762c52e657 | 500 | if (((uint32_t)p_addr & (FS_PAGE_SIZE - 1)) || |
| vcoubard | 38:2b762c52e657 | 501 | (length_words & (FS_PAGE_SIZE_WORDS - 1))) |
| vcoubard | 38:2b762c52e657 | 502 | { |
| vcoubard | 38:2b762c52e657 | 503 | return NRF_ERROR_INVALID_ADDR; |
| vcoubard | 38:2b762c52e657 | 504 | } |
| vcoubard | 38:2b762c52e657 | 505 | |
| vcoubard | 38:2b762c52e657 | 506 | // Check that the erase operation is on pages owned by this user (configuration). |
| vcoubard | 38:2b762c52e657 | 507 | if ((p_addr < p_config->p_start_addr) || ((p_addr + length_words) > p_config->p_end_addr)) |
| vcoubard | 38:2b762c52e657 | 508 | { |
| vcoubard | 38:2b762c52e657 | 509 | return NRF_ERROR_INVALID_ADDR; |
| vcoubard | 38:2b762c52e657 | 510 | } |
| vcoubard | 38:2b762c52e657 | 511 | |
| vcoubard | 38:2b762c52e657 | 512 | return cmd_enqueue(p_config, FS_OP_ERASE, p_addr, NULL, length_words); |
| vcoubard | 38:2b762c52e657 | 513 | } |
| vcoubard | 38:2b762c52e657 | 514 | |
| vcoubard | 38:2b762c52e657 | 515 | |
| vcoubard | 38:2b762c52e657 | 516 | /**@brief Function to handle system events from the SoftDevice. |
| vcoubard | 38:2b762c52e657 | 517 | * |
| vcoubard | 38:2b762c52e657 | 518 | * @details This function should be dispatched system events if any of the modules used by |
| vcoubard | 38:2b762c52e657 | 519 | * the application rely on FStorage. Examples include @ref Peer Manager and |
| vcoubard | 38:2b762c52e657 | 520 | * @ref Flash Data Storage. |
| vcoubard | 38:2b762c52e657 | 521 | * |
| vcoubard | 38:2b762c52e657 | 522 | * @param[in] sys_evt System Event received. |
| vcoubard | 38:2b762c52e657 | 523 | */ |
| vcoubard | 38:2b762c52e657 | 524 | void fs_sys_event_handler(uint32_t sys_evt) |
| vcoubard | 38:2b762c52e657 | 525 | { |
| vcoubard | 38:2b762c52e657 | 526 | if (m_flags & FS_FLAG_PROCESSING) |
| vcoubard | 38:2b762c52e657 | 527 | { |
| vcoubard | 38:2b762c52e657 | 528 | /** A flash operation was initiated by this module. |
| vcoubard | 38:2b762c52e657 | 529 | * Handle its result. */ |
| vcoubard | 38:2b762c52e657 | 530 | switch (sys_evt) |
| vcoubard | 38:2b762c52e657 | 531 | { |
| vcoubard | 38:2b762c52e657 | 532 | case NRF_EVT_FLASH_OPERATION_SUCCESS: |
| vcoubard | 38:2b762c52e657 | 533 | on_operation_success(); |
| vcoubard | 38:2b762c52e657 | 534 | break; |
| vcoubard | 38:2b762c52e657 | 535 | |
| vcoubard | 38:2b762c52e657 | 536 | case NRF_EVT_FLASH_OPERATION_ERROR: |
| vcoubard | 38:2b762c52e657 | 537 | on_operation_failure(sys_evt); |
| vcoubard | 38:2b762c52e657 | 538 | break; |
| vcoubard | 38:2b762c52e657 | 539 | } |
| vcoubard | 38:2b762c52e657 | 540 | } |
| vcoubard | 38:2b762c52e657 | 541 | else if ((m_flags & FS_FLAG_FLASH_REQ_PENDING)) |
| vcoubard | 38:2b762c52e657 | 542 | { |
| vcoubard | 38:2b762c52e657 | 543 | /** A flash operation was initiated outside this module. |
| vcoubard | 38:2b762c52e657 | 544 | * We have now receveid a callback which indicates it has |
| vcoubard | 38:2b762c52e657 | 545 | * finished. Clear the FS_FLAG_FLASH_REQ_PENDING flag. */ |
| vcoubard | 38:2b762c52e657 | 546 | m_flags &= ~FS_FLAG_FLASH_REQ_PENDING; |
| vcoubard | 38:2b762c52e657 | 547 | |
| vcoubard | 38:2b762c52e657 | 548 | // Resume processing the queue, if necessary. |
| vcoubard | 38:2b762c52e657 | 549 | queue_process(); |
| vcoubard | 38:2b762c52e657 | 550 | } |
| vcoubard | 38:2b762c52e657 | 551 | } |
| vcoubard | 38:2b762c52e657 | 552 | |
| vcoubard | 38:2b762c52e657 | 553 | |
| vcoubard | 38:2b762c52e657 | 554 | // Just for testing out section vars (across many compilers). |
| vcoubard | 38:2b762c52e657 | 555 | void fs_debug_print() |
| vcoubard | 38:2b762c52e657 | 556 | { |
| vcoubard | 38:2b762c52e657 | 557 | printf("fs start address: 0x%08lx\r\n", (unsigned long)FS_SECTION_VARS_START_ADDR); |
| vcoubard | 38:2b762c52e657 | 558 | printf("fs end address: 0x%08lx\r\n", (unsigned long)FS_SECTION_VARS_END_ADDR); |
| vcoubard | 38:2b762c52e657 | 559 | printf("Num items: 0x%08lx\r\n", (unsigned long)FS_SECTION_VARS_COUNT); |
| vcoubard | 38:2b762c52e657 | 560 | printf("===== ITEMS %lu =====\r\n", (unsigned long)FS_SECTION_VARS_COUNT); |
| vcoubard | 38:2b762c52e657 | 561 | |
| vcoubard | 38:2b762c52e657 | 562 | for(int i = 0; i < FS_SECTION_VARS_COUNT; i++) |
| vcoubard | 38:2b762c52e657 | 563 | { |
| vcoubard | 38:2b762c52e657 | 564 | fs_config_t* config = FS_SECTION_VARS_GET(i); |
| vcoubard | 38:2b762c52e657 | 565 | printf( "Address: 0x%08lx, CB: 0x%08lx\r\n", |
| vcoubard | 38:2b762c52e657 | 566 | (unsigned long)config, (unsigned long)config->cb ); |
| vcoubard | 38:2b762c52e657 | 567 | } |
| vcoubard | 38:2b762c52e657 | 568 | printf("\r\n"); |
| vcoubard | 38:2b762c52e657 | 569 | } |
