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/fds/fds.c@9:7935d1749ea8, 2016-09-29 (annotated)
- Committer:
- pangsk
- Date:
- Thu Sep 29 15:33:32 2016 +0000
- Revision:
- 9:7935d1749ea8
- Parent:
- 0:bc2961fa1ef0
Initial release
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
0:bc2961fa1ef0 | 1 | /* |
Jonathan Austin |
0:bc2961fa1ef0 | 2 | * Copyright (c) Nordic Semiconductor ASA |
Jonathan Austin |
0:bc2961fa1ef0 | 3 | * All rights reserved. |
Jonathan Austin |
0:bc2961fa1ef0 | 4 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
Jonathan Austin |
0:bc2961fa1ef0 | 6 | * are permitted provided that the following conditions are met: |
Jonathan Austin |
0:bc2961fa1ef0 | 7 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 8 | * 1. Redistributions of source code must retain the above copyright notice, this |
Jonathan Austin |
0:bc2961fa1ef0 | 9 | * list of conditions and the following disclaimer. |
Jonathan Austin |
0:bc2961fa1ef0 | 10 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this |
Jonathan Austin |
0:bc2961fa1ef0 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
Jonathan Austin |
0:bc2961fa1ef0 | 13 | * other materials provided with the distribution. |
Jonathan Austin |
0:bc2961fa1ef0 | 14 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 15 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of other |
Jonathan Austin |
0:bc2961fa1ef0 | 16 | * contributors to this software may be used to endorse or promote products |
Jonathan Austin |
0:bc2961fa1ef0 | 17 | * derived from this software without specific prior written permission. |
Jonathan Austin |
0:bc2961fa1ef0 | 18 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 19 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
Jonathan Austin |
0:bc2961fa1ef0 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
Jonathan Austin |
0:bc2961fa1ef0 | 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
Jonathan Austin |
0:bc2961fa1ef0 | 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
Jonathan Austin |
0:bc2961fa1ef0 | 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
Jonathan Austin |
0:bc2961fa1ef0 | 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
Jonathan Austin |
0:bc2961fa1ef0 | 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
Jonathan Austin |
0:bc2961fa1ef0 | 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
Jonathan Austin |
0:bc2961fa1ef0 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
Jonathan Austin |
0:bc2961fa1ef0 | 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Jonathan Austin |
0:bc2961fa1ef0 | 30 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 31 | */ |
Jonathan Austin |
0:bc2961fa1ef0 | 32 | |
Jonathan Austin |
0:bc2961fa1ef0 | 33 | #include "fds.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 34 | #include <stdint.h> |
Jonathan Austin |
0:bc2961fa1ef0 | 35 | #include <string.h> |
Jonathan Austin |
0:bc2961fa1ef0 | 36 | #include <stdbool.h> |
Jonathan Austin |
0:bc2961fa1ef0 | 37 | #include "fds_config.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 38 | #include "fds_types_internal.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 39 | #include "fstorage.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 40 | #include "nrf_error.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 41 | #include "app_util.h" |
Jonathan Austin |
0:bc2961fa1ef0 | 42 | |
Jonathan Austin |
0:bc2961fa1ef0 | 43 | |
Jonathan Austin |
0:bc2961fa1ef0 | 44 | /** Our fstorage configuration. |
Jonathan Austin |
0:bc2961fa1ef0 | 45 | * The other fields will be assigned automatically during compilation. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 46 | FS_SECTION_VARS_ADD(fs_config_t fs_config) = { .cb = fs_callback, .num_pages = FDS_MAX_PAGES }; |
Jonathan Austin |
0:bc2961fa1ef0 | 47 | |
Jonathan Austin |
0:bc2961fa1ef0 | 48 | static uint32_t const fds_page_tag_swap[] = {FDS_PAGE_TAG_WORD_0_SWAP, FDS_PAGE_TAG_WORD_1, |
Jonathan Austin |
0:bc2961fa1ef0 | 49 | FDS_PAGE_TAG_WORD_2, FDS_PAGE_TAG_WORD_3}; |
Jonathan Austin |
0:bc2961fa1ef0 | 50 | |
Jonathan Austin |
0:bc2961fa1ef0 | 51 | static uint32_t const fds_page_tag_valid[] = {FDS_PAGE_TAG_WORD_0_VALID, FDS_PAGE_TAG_WORD_1, |
Jonathan Austin |
0:bc2961fa1ef0 | 52 | FDS_PAGE_TAG_WORD_2, FDS_PAGE_TAG_WORD_3}; |
Jonathan Austin |
0:bc2961fa1ef0 | 53 | |
Jonathan Austin |
0:bc2961fa1ef0 | 54 | static uint32_t const fds_page_tag_gc = FDS_PAGE_TAG_WORD_3_GC; |
Jonathan Austin |
0:bc2961fa1ef0 | 55 | |
Jonathan Austin |
0:bc2961fa1ef0 | 56 | static fds_tl_t const m_fds_tl_invalid = { .type = FDS_TYPE_ID_INVALID, |
Jonathan Austin |
0:bc2961fa1ef0 | 57 | .length_words = 0xFFFF }; |
Jonathan Austin |
0:bc2961fa1ef0 | 58 | |
Jonathan Austin |
0:bc2961fa1ef0 | 59 | /**@brief Internal status flags. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 60 | static uint8_t volatile m_flags; |
Jonathan Austin |
0:bc2961fa1ef0 | 61 | |
Jonathan Austin |
0:bc2961fa1ef0 | 62 | static uint8_t m_users; |
Jonathan Austin |
0:bc2961fa1ef0 | 63 | static fds_cb_t m_cb_table[FDS_MAX_USERS]; |
Jonathan Austin |
0:bc2961fa1ef0 | 64 | |
Jonathan Austin |
0:bc2961fa1ef0 | 65 | /**@brief The last record ID. Setup page by page_scan() during pages_init(). */ |
Jonathan Austin |
0:bc2961fa1ef0 | 66 | static fds_record_id_t m_last_rec_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 67 | |
Jonathan Austin |
0:bc2961fa1ef0 | 68 | /**@brief The internal queues. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 69 | static fds_cmd_queue_t m_cmd_queue; |
Jonathan Austin |
0:bc2961fa1ef0 | 70 | static fds_chunk_queue_t m_chunk_queue; |
Jonathan Austin |
0:bc2961fa1ef0 | 71 | |
Jonathan Austin |
0:bc2961fa1ef0 | 72 | /**@brief Holds the state of pages. Setup by fds_init(). */ |
Jonathan Austin |
0:bc2961fa1ef0 | 73 | static fds_page_t m_pages[FDS_MAX_PAGES]; |
Jonathan Austin |
0:bc2961fa1ef0 | 74 | static bool m_swap_page_avail = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 75 | |
Jonathan Austin |
0:bc2961fa1ef0 | 76 | static fds_gc_data_t m_gc; |
Jonathan Austin |
0:bc2961fa1ef0 | 77 | static uint16_t m_gc_runs; |
Jonathan Austin |
0:bc2961fa1ef0 | 78 | |
Jonathan Austin |
0:bc2961fa1ef0 | 79 | static uint8_t volatile m_counter; |
Jonathan Austin |
0:bc2961fa1ef0 | 80 | |
Jonathan Austin |
0:bc2961fa1ef0 | 81 | |
Jonathan Austin |
0:bc2961fa1ef0 | 82 | static void app_notify(ret_code_t result, |
Jonathan Austin |
0:bc2961fa1ef0 | 83 | fds_cmd_id_t cmd, |
Jonathan Austin |
0:bc2961fa1ef0 | 84 | fds_record_id_t record_id, |
Jonathan Austin |
0:bc2961fa1ef0 | 85 | fds_record_key_t record_key) |
Jonathan Austin |
0:bc2961fa1ef0 | 86 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 87 | for (uint8_t user = 0; user < FDS_MAX_USERS; user++) |
Jonathan Austin |
0:bc2961fa1ef0 | 88 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 89 | if (m_cb_table[user] != NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 90 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 91 | m_cb_table[user](result, cmd, record_id, record_key); |
Jonathan Austin |
0:bc2961fa1ef0 | 92 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 93 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 94 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 95 | |
Jonathan Austin |
0:bc2961fa1ef0 | 96 | |
Jonathan Austin |
0:bc2961fa1ef0 | 97 | static void atomic_counter_inc() |
Jonathan Austin |
0:bc2961fa1ef0 | 98 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 99 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 100 | m_counter++; |
Jonathan Austin |
0:bc2961fa1ef0 | 101 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 102 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 103 | |
Jonathan Austin |
0:bc2961fa1ef0 | 104 | |
Jonathan Austin |
0:bc2961fa1ef0 | 105 | static void atomic_counter_dec() |
Jonathan Austin |
0:bc2961fa1ef0 | 106 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 107 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 108 | m_counter--; |
Jonathan Austin |
0:bc2961fa1ef0 | 109 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 110 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 111 | |
Jonathan Austin |
0:bc2961fa1ef0 | 112 | |
Jonathan Austin |
0:bc2961fa1ef0 | 113 | static bool atomic_counter_is_zero() |
Jonathan Austin |
0:bc2961fa1ef0 | 114 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 115 | bool ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 116 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 117 | ret = (m_counter == 0); |
Jonathan Austin |
0:bc2961fa1ef0 | 118 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 119 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 120 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 121 | |
Jonathan Austin |
0:bc2961fa1ef0 | 122 | |
Jonathan Austin |
0:bc2961fa1ef0 | 123 | static void flag_set(fds_flags_t flag) |
Jonathan Austin |
0:bc2961fa1ef0 | 124 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 125 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 126 | m_flags |= flag; |
Jonathan Austin |
0:bc2961fa1ef0 | 127 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 128 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 129 | |
Jonathan Austin |
0:bc2961fa1ef0 | 130 | |
Jonathan Austin |
0:bc2961fa1ef0 | 131 | static void flag_clear(fds_flags_t flag) |
Jonathan Austin |
0:bc2961fa1ef0 | 132 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 133 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 134 | m_flags &= ~(flag); |
Jonathan Austin |
0:bc2961fa1ef0 | 135 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 136 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 137 | |
Jonathan Austin |
0:bc2961fa1ef0 | 138 | |
Jonathan Austin |
0:bc2961fa1ef0 | 139 | static bool flag_is_set(fds_flags_t flag) |
Jonathan Austin |
0:bc2961fa1ef0 | 140 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 141 | bool ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 142 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 143 | ret = (m_flags & flag); |
Jonathan Austin |
0:bc2961fa1ef0 | 144 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 145 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 146 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 147 | |
Jonathan Austin |
0:bc2961fa1ef0 | 148 | |
Jonathan Austin |
0:bc2961fa1ef0 | 149 | /**@brief Function to check if a header has valid information. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 150 | static __INLINE bool header_is_valid(fds_header_t const * const p_header) |
Jonathan Austin |
0:bc2961fa1ef0 | 151 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 152 | return ((p_header->tl.type != FDS_TYPE_ID_INVALID) && |
Jonathan Austin |
0:bc2961fa1ef0 | 153 | (p_header->ic.instance != FDS_INSTANCE_ID_INVALID)); |
Jonathan Austin |
0:bc2961fa1ef0 | 154 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 155 | |
Jonathan Austin |
0:bc2961fa1ef0 | 156 | |
Jonathan Austin |
0:bc2961fa1ef0 | 157 | static bool address_within_page_bounds(uint32_t const * const p_addr) |
Jonathan Austin |
0:bc2961fa1ef0 | 158 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 159 | return (p_addr >= fs_config.p_start_addr) && |
Jonathan Austin |
0:bc2961fa1ef0 | 160 | (p_addr <= fs_config.p_end_addr) && |
Jonathan Austin |
0:bc2961fa1ef0 | 161 | (is_word_aligned(p_addr)); |
Jonathan Austin |
0:bc2961fa1ef0 | 162 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 163 | |
Jonathan Austin |
0:bc2961fa1ef0 | 164 | |
Jonathan Austin |
0:bc2961fa1ef0 | 165 | /**@brief Internal function to identify the page type. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 166 | static fds_page_type_t page_identify(uint16_t page_number) |
Jonathan Austin |
0:bc2961fa1ef0 | 167 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 168 | uint32_t const * const p_page_addr = m_pages[page_number].start_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 169 | |
Jonathan Austin |
0:bc2961fa1ef0 | 170 | uint32_t const word0 = *(p_page_addr); |
Jonathan Austin |
0:bc2961fa1ef0 | 171 | uint32_t const word1 = *(p_page_addr + 1); |
Jonathan Austin |
0:bc2961fa1ef0 | 172 | uint32_t const word2 = *(p_page_addr + 2); |
Jonathan Austin |
0:bc2961fa1ef0 | 173 | uint32_t const word3 = *(p_page_addr + 3); |
Jonathan Austin |
0:bc2961fa1ef0 | 174 | |
Jonathan Austin |
0:bc2961fa1ef0 | 175 | if (word1 != FDS_PAGE_TAG_WORD_1) |
Jonathan Austin |
0:bc2961fa1ef0 | 176 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 177 | return FDS_PAGE_UNDEFINED; |
Jonathan Austin |
0:bc2961fa1ef0 | 178 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 179 | |
Jonathan Austin |
0:bc2961fa1ef0 | 180 | if (word2 != FDS_PAGE_TAG_WORD_2) |
Jonathan Austin |
0:bc2961fa1ef0 | 181 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 182 | return FDS_PAGE_UNDEFINED; |
Jonathan Austin |
0:bc2961fa1ef0 | 183 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 184 | |
Jonathan Austin |
0:bc2961fa1ef0 | 185 | if (word3 == FDS_PAGE_TAG_WORD_3) |
Jonathan Austin |
0:bc2961fa1ef0 | 186 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 187 | if (word0 == FDS_PAGE_TAG_WORD_0_SWAP) |
Jonathan Austin |
0:bc2961fa1ef0 | 188 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 189 | return FDS_PAGE_SWAP; |
Jonathan Austin |
0:bc2961fa1ef0 | 190 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 191 | |
Jonathan Austin |
0:bc2961fa1ef0 | 192 | if (word0 == FDS_PAGE_TAG_WORD_0_VALID) |
Jonathan Austin |
0:bc2961fa1ef0 | 193 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 194 | return FDS_PAGE_VALID; |
Jonathan Austin |
0:bc2961fa1ef0 | 195 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 196 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 197 | else if (word3 == FDS_PAGE_TAG_WORD_3_GC) |
Jonathan Austin |
0:bc2961fa1ef0 | 198 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 199 | if (word0 == FDS_PAGE_TAG_WORD_0_SWAP || word0 == FDS_PAGE_TAG_WORD_0_VALID) |
Jonathan Austin |
0:bc2961fa1ef0 | 200 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 201 | return FDS_PAGE_GC; |
Jonathan Austin |
0:bc2961fa1ef0 | 202 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 203 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 204 | |
Jonathan Austin |
0:bc2961fa1ef0 | 205 | return FDS_PAGE_UNDEFINED; |
Jonathan Austin |
0:bc2961fa1ef0 | 206 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 207 | |
Jonathan Austin |
0:bc2961fa1ef0 | 208 | |
Jonathan Austin |
0:bc2961fa1ef0 | 209 | static uint16_t page_by_addr(uint32_t const * const p_addr) |
Jonathan Austin |
0:bc2961fa1ef0 | 210 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 211 | if (p_addr == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 212 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 213 | return 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 214 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 215 | |
Jonathan Austin |
0:bc2961fa1ef0 | 216 | // Compute the BYTES offset from the beginning of the first page. |
Jonathan Austin |
0:bc2961fa1ef0 | 217 | uint32_t const byte_offset = (uint32_t)p_addr - (uint32_t)m_pages[0].start_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 218 | |
Jonathan Austin |
0:bc2961fa1ef0 | 219 | // See nrf.h. |
Jonathan Austin |
0:bc2961fa1ef0 | 220 | #if defined (NRF51) |
Jonathan Austin |
0:bc2961fa1ef0 | 221 | return byte_offset >> 10; // Divide by page size (1024). |
Jonathan Austin |
0:bc2961fa1ef0 | 222 | #elif defined (NRF52) |
Jonathan Austin |
0:bc2961fa1ef0 | 223 | return byte_offset >> 12; // Divide by page size (4096). |
Jonathan Austin |
0:bc2961fa1ef0 | 224 | #else |
Jonathan Austin |
0:bc2961fa1ef0 | 225 | #error "Device family must be defined. See nrf.h." |
Jonathan Austin |
0:bc2961fa1ef0 | 226 | #endif |
Jonathan Austin |
0:bc2961fa1ef0 | 227 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 228 | |
Jonathan Austin |
0:bc2961fa1ef0 | 229 | |
Jonathan Austin |
0:bc2961fa1ef0 | 230 | // NOTE: depends on m_pages.write_offset to function. |
Jonathan Austin |
0:bc2961fa1ef0 | 231 | static bool page_has_space(uint16_t page, fds_length_t length_words) |
Jonathan Austin |
0:bc2961fa1ef0 | 232 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 233 | if (page >= FDS_MAX_PAGES) |
Jonathan Austin |
0:bc2961fa1ef0 | 234 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 235 | return false; |
Jonathan Austin |
0:bc2961fa1ef0 | 236 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 237 | |
Jonathan Austin |
0:bc2961fa1ef0 | 238 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 239 | length_words += m_pages[page].write_offset; |
Jonathan Austin |
0:bc2961fa1ef0 | 240 | length_words += m_pages[page].words_reserved; |
Jonathan Austin |
0:bc2961fa1ef0 | 241 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 242 | |
Jonathan Austin |
0:bc2961fa1ef0 | 243 | return (length_words < FS_PAGE_SIZE_WORDS); |
Jonathan Austin |
0:bc2961fa1ef0 | 244 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 245 | |
Jonathan Austin |
0:bc2961fa1ef0 | 246 | |
Jonathan Austin |
0:bc2961fa1ef0 | 247 | /**@brief This function scans a page to determine how many words have |
Jonathan Austin |
0:bc2961fa1ef0 | 248 | * been written to it. This information is used to set the page |
Jonathan Austin |
0:bc2961fa1ef0 | 249 | * write offset during initialization (mount). Additionally, this |
Jonathan Austin |
0:bc2961fa1ef0 | 250 | * function will update the last known record ID as it proceeds. |
Jonathan Austin |
0:bc2961fa1ef0 | 251 | */ |
Jonathan Austin |
0:bc2961fa1ef0 | 252 | static void page_scan(uint16_t page, uint16_t volatile * words_written) |
Jonathan Austin |
0:bc2961fa1ef0 | 253 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 254 | uint32_t const * p_addr = (m_pages[page].start_addr + FDS_PAGE_TAG_SIZE); |
Jonathan Austin |
0:bc2961fa1ef0 | 255 | |
Jonathan Austin |
0:bc2961fa1ef0 | 256 | *words_written = FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 257 | |
Jonathan Austin |
0:bc2961fa1ef0 | 258 | // A corrupt TL might cause problems. |
Jonathan Austin |
0:bc2961fa1ef0 | 259 | while ((p_addr < m_pages[page].start_addr + FS_PAGE_SIZE_WORDS) && |
Jonathan Austin |
0:bc2961fa1ef0 | 260 | (*p_addr != FDS_ERASED_WORD)) |
Jonathan Austin |
0:bc2961fa1ef0 | 261 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 262 | fds_header_t const * const p_header = (fds_header_t*)p_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 263 | |
Jonathan Austin |
0:bc2961fa1ef0 | 264 | /** Note: DO NOT check for the validity of the header using |
Jonathan Austin |
0:bc2961fa1ef0 | 265 | * header_is_valid() here. If an header has an invalid type (0x0000) |
Jonathan Austin |
0:bc2961fa1ef0 | 266 | * or a missing instance (0xFFFF) then we WANT to skip it. |
Jonathan Austin |
0:bc2961fa1ef0 | 267 | */ |
Jonathan Austin |
0:bc2961fa1ef0 | 268 | |
Jonathan Austin |
0:bc2961fa1ef0 | 269 | // Update the last known record id. |
Jonathan Austin |
0:bc2961fa1ef0 | 270 | if (p_header->id > m_last_rec_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 271 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 272 | m_last_rec_id = p_header->id; |
Jonathan Austin |
0:bc2961fa1ef0 | 273 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 274 | |
Jonathan Austin |
0:bc2961fa1ef0 | 275 | // Jump to the next record. |
Jonathan Austin |
0:bc2961fa1ef0 | 276 | p_addr += (FDS_HEADER_SIZE + p_header->tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 277 | *words_written += (FDS_HEADER_SIZE + p_header->tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 278 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 279 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 280 | |
Jonathan Austin |
0:bc2961fa1ef0 | 281 | |
Jonathan Austin |
0:bc2961fa1ef0 | 282 | static bool page_is_empty(uint16_t page) |
Jonathan Austin |
0:bc2961fa1ef0 | 283 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 284 | uint32_t const * const p_addr = m_pages[page].start_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 285 | |
Jonathan Austin |
0:bc2961fa1ef0 | 286 | for (uint16_t i = 0; i < FS_PAGE_SIZE_WORDS; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 287 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 288 | if (*(p_addr + i) != FDS_ERASED_WORD) |
Jonathan Austin |
0:bc2961fa1ef0 | 289 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 290 | return false; |
Jonathan Austin |
0:bc2961fa1ef0 | 291 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 292 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 293 | |
Jonathan Austin |
0:bc2961fa1ef0 | 294 | return true; |
Jonathan Austin |
0:bc2961fa1ef0 | 295 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 296 | |
Jonathan Austin |
0:bc2961fa1ef0 | 297 | |
Jonathan Austin |
0:bc2961fa1ef0 | 298 | static ret_code_t page_id_from_virtual_id(uint16_t vpage_id, uint16_t * p_page_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 299 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 300 | for (uint16_t i = 0; i < FDS_MAX_PAGES; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 301 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 302 | if (m_pages[i].vpage_id == vpage_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 303 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 304 | *p_page_id = i; |
Jonathan Austin |
0:bc2961fa1ef0 | 305 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 306 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 307 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 308 | |
Jonathan Austin |
0:bc2961fa1ef0 | 309 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 310 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 311 | |
Jonathan Austin |
0:bc2961fa1ef0 | 312 | |
Jonathan Austin |
0:bc2961fa1ef0 | 313 | static ret_code_t page_from_virtual_id(uint16_t vpage_id, fds_page_t ** p_page) |
Jonathan Austin |
0:bc2961fa1ef0 | 314 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 315 | for (uint16_t i = 0; i < FDS_MAX_PAGES; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 316 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 317 | if (m_pages[i].vpage_id == vpage_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 318 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 319 | *p_page = &m_pages[i]; |
Jonathan Austin |
0:bc2961fa1ef0 | 320 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 321 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 322 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 323 | |
Jonathan Austin |
0:bc2961fa1ef0 | 324 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 325 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 326 | |
Jonathan Austin |
0:bc2961fa1ef0 | 327 | |
Jonathan Austin |
0:bc2961fa1ef0 | 328 | static uint32_t record_id_new() |
Jonathan Austin |
0:bc2961fa1ef0 | 329 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 330 | return ++m_last_rec_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 331 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 332 | |
Jonathan Austin |
0:bc2961fa1ef0 | 333 | |
Jonathan Austin |
0:bc2961fa1ef0 | 334 | /**@brief Tags a page as swap, i.e., reserved for GC. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 335 | static ret_code_t page_tag_write_swap(uint16_t page) |
Jonathan Austin |
0:bc2961fa1ef0 | 336 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 337 | return fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 338 | m_pages[page].start_addr, |
Jonathan Austin |
0:bc2961fa1ef0 | 339 | (uint32_t const *)&fds_page_tag_swap, |
Jonathan Austin |
0:bc2961fa1ef0 | 340 | FDS_PAGE_TAG_SIZE); |
Jonathan Austin |
0:bc2961fa1ef0 | 341 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 342 | |
Jonathan Austin |
0:bc2961fa1ef0 | 343 | |
Jonathan Austin |
0:bc2961fa1ef0 | 344 | /**@brief Tags a page as valid, i.e, ready for storage. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 345 | static ret_code_t page_tag_write_valid(uint16_t page) |
Jonathan Austin |
0:bc2961fa1ef0 | 346 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 347 | return fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 348 | m_pages[page].start_addr, |
Jonathan Austin |
0:bc2961fa1ef0 | 349 | (uint32_t const *)&fds_page_tag_valid, |
Jonathan Austin |
0:bc2961fa1ef0 | 350 | FDS_PAGE_TAG_SIZE); |
Jonathan Austin |
0:bc2961fa1ef0 | 351 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 352 | |
Jonathan Austin |
0:bc2961fa1ef0 | 353 | |
Jonathan Austin |
0:bc2961fa1ef0 | 354 | /**@brief Tags a valid page as being garbage collected. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 355 | static ret_code_t page_tag_write_gc(uint16_t page) |
Jonathan Austin |
0:bc2961fa1ef0 | 356 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 357 | return fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 358 | m_pages[page].start_addr + 3, |
Jonathan Austin |
0:bc2961fa1ef0 | 359 | (uint32_t const *)&fds_page_tag_gc, |
Jonathan Austin |
0:bc2961fa1ef0 | 360 | 1 /*Words*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 361 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 362 | |
Jonathan Austin |
0:bc2961fa1ef0 | 363 | |
Jonathan Austin |
0:bc2961fa1ef0 | 364 | /**@brief Given a page and a record, finds the next valid record. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 365 | static ret_code_t scan_next_valid(uint16_t page, uint32_t const ** p_record) |
Jonathan Austin |
0:bc2961fa1ef0 | 366 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 367 | uint32_t const * p_next_rec = (*p_record); |
Jonathan Austin |
0:bc2961fa1ef0 | 368 | |
Jonathan Austin |
0:bc2961fa1ef0 | 369 | if (p_next_rec == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 370 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 371 | // This if the first invocation on this page, start from the beginning. |
Jonathan Austin |
0:bc2961fa1ef0 | 372 | p_next_rec = m_pages[page].start_addr + FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 373 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 374 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 375 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 376 | // Jump to the next record. |
Jonathan Austin |
0:bc2961fa1ef0 | 377 | p_next_rec += (FDS_HEADER_SIZE + ((fds_header_t*)(*p_record))->tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 378 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 379 | |
Jonathan Austin |
0:bc2961fa1ef0 | 380 | // Scan until we find a valid record or until the end of the page. |
Jonathan Austin |
0:bc2961fa1ef0 | 381 | |
Jonathan Austin |
0:bc2961fa1ef0 | 382 | /** README: We might seek until the write_offset is reached, but it might not |
Jonathan Austin |
0:bc2961fa1ef0 | 383 | * known at this point. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 384 | while ((p_next_rec < (m_pages[page].start_addr + FS_PAGE_SIZE_WORDS)) && |
Jonathan Austin |
0:bc2961fa1ef0 | 385 | (*p_next_rec != FDS_ERASED_WORD)) // Did we jump to an erased word? |
Jonathan Austin |
0:bc2961fa1ef0 | 386 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 387 | fds_header_t const * const p_header = (fds_header_t*)p_next_rec; |
Jonathan Austin |
0:bc2961fa1ef0 | 388 | |
Jonathan Austin |
0:bc2961fa1ef0 | 389 | if (header_is_valid(p_header)) |
Jonathan Austin |
0:bc2961fa1ef0 | 390 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 391 | // Bingo! |
Jonathan Austin |
0:bc2961fa1ef0 | 392 | *p_record = p_next_rec; |
Jonathan Austin |
0:bc2961fa1ef0 | 393 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 394 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 395 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 396 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 397 | // The item is not valid, jump to the next. |
Jonathan Austin |
0:bc2961fa1ef0 | 398 | p_next_rec += (FDS_HEADER_SIZE + (p_header->tl.length_words)); |
Jonathan Austin |
0:bc2961fa1ef0 | 399 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 400 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 401 | |
Jonathan Austin |
0:bc2961fa1ef0 | 402 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 403 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 404 | |
Jonathan Austin |
0:bc2961fa1ef0 | 405 | |
Jonathan Austin |
0:bc2961fa1ef0 | 406 | static ret_code_t seek_record(fds_record_desc_t * const p_desc) |
Jonathan Austin |
0:bc2961fa1ef0 | 407 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 408 | uint32_t const * p_record; |
Jonathan Austin |
0:bc2961fa1ef0 | 409 | uint16_t page; |
Jonathan Austin |
0:bc2961fa1ef0 | 410 | bool seek_all_pages = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 411 | |
Jonathan Austin |
0:bc2961fa1ef0 | 412 | if ((p_desc->ptr_magic == FDS_MAGIC_HWORD) && |
Jonathan Austin |
0:bc2961fa1ef0 | 413 | (p_desc->gc_magic == m_gc_runs)) |
Jonathan Austin |
0:bc2961fa1ef0 | 414 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 415 | // No need to seek the file. |
Jonathan Austin |
0:bc2961fa1ef0 | 416 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 417 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 418 | |
Jonathan Austin |
0:bc2961fa1ef0 | 419 | /** The pointer in the descriptor is not initialized, or GC |
Jonathan Austin |
0:bc2961fa1ef0 | 420 | * has been run since the last time it was retrieved. |
Jonathan Austin |
0:bc2961fa1ef0 | 421 | * We must seek the record again. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 422 | |
Jonathan Austin |
0:bc2961fa1ef0 | 423 | // Obtain the physical page ID. |
Jonathan Austin |
0:bc2961fa1ef0 | 424 | if (page_id_from_virtual_id(p_desc->vpage_id, &page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 425 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 426 | page = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 427 | seek_all_pages = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 428 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 429 | |
Jonathan Austin |
0:bc2961fa1ef0 | 430 | do { |
Jonathan Austin |
0:bc2961fa1ef0 | 431 | // Let's find the address from where we should start seeking the record. |
Jonathan Austin |
0:bc2961fa1ef0 | 432 | p_record = m_pages[page].start_addr + FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 433 | |
Jonathan Austin |
0:bc2961fa1ef0 | 434 | /** Seek for a record with matching ID. |
Jonathan Austin |
0:bc2961fa1ef0 | 435 | * We might get away with seeking to the page write offset, if it is known. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 436 | |
Jonathan Austin |
0:bc2961fa1ef0 | 437 | while ((p_record < (m_pages[page].start_addr + FS_PAGE_SIZE_WORDS)) && |
Jonathan Austin |
0:bc2961fa1ef0 | 438 | (*p_record != FDS_ERASED_WORD)) |
Jonathan Austin |
0:bc2961fa1ef0 | 439 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 440 | fds_header_t const * const p_header = (fds_header_t*)p_record; |
Jonathan Austin |
0:bc2961fa1ef0 | 441 | |
Jonathan Austin |
0:bc2961fa1ef0 | 442 | if ((p_header->id != p_desc->record_id) || |
Jonathan Austin |
0:bc2961fa1ef0 | 443 | (!header_is_valid(p_header))) |
Jonathan Austin |
0:bc2961fa1ef0 | 444 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 445 | // ID doesnt't match or the record has been cleared. Jump to the next record. |
Jonathan Austin |
0:bc2961fa1ef0 | 446 | p_record += FDS_HEADER_SIZE + p_header->tl.length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 447 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 448 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 449 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 450 | // Update the pointer in the descriptor. |
Jonathan Austin |
0:bc2961fa1ef0 | 451 | p_desc->p_rec = p_record; |
Jonathan Austin |
0:bc2961fa1ef0 | 452 | p_desc->ptr_magic = FDS_MAGIC_HWORD; |
Jonathan Austin |
0:bc2961fa1ef0 | 453 | p_desc->gc_magic = m_gc_runs; |
Jonathan Austin |
0:bc2961fa1ef0 | 454 | |
Jonathan Austin |
0:bc2961fa1ef0 | 455 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 456 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 457 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 458 | } while (seek_all_pages ? page++ < FDS_MAX_PAGES : 0); |
Jonathan Austin |
0:bc2961fa1ef0 | 459 | |
Jonathan Austin |
0:bc2961fa1ef0 | 460 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 461 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 462 | |
Jonathan Austin |
0:bc2961fa1ef0 | 463 | |
Jonathan Austin |
0:bc2961fa1ef0 | 464 | static ret_code_t find_record(fds_type_id_t const * const p_type, |
Jonathan Austin |
0:bc2961fa1ef0 | 465 | fds_instance_id_t const * const p_inst, |
Jonathan Austin |
0:bc2961fa1ef0 | 466 | fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 467 | fds_find_token_t * const p_token) |
Jonathan Austin |
0:bc2961fa1ef0 | 468 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 469 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 470 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 471 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 472 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 473 | |
Jonathan Austin |
0:bc2961fa1ef0 | 474 | // Here we distinguish between the first invocation and the and the others. |
Jonathan Austin |
0:bc2961fa1ef0 | 475 | if ((p_token->magic != FDS_MAGIC_WORD) || |
Jonathan Austin |
0:bc2961fa1ef0 | 476 | !address_within_page_bounds(p_token->p_addr)) // Is the address is really okay? |
Jonathan Austin |
0:bc2961fa1ef0 | 477 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 478 | // Initialize the token. |
Jonathan Austin |
0:bc2961fa1ef0 | 479 | p_token->magic = FDS_MAGIC_WORD; |
Jonathan Austin |
0:bc2961fa1ef0 | 480 | p_token->vpage_id = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 481 | p_token->p_addr = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 482 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 483 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 484 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 485 | // Look past the last record address. |
Jonathan Austin |
0:bc2961fa1ef0 | 486 | p_token->p_addr += (FDS_HEADER_SIZE + ((fds_header_t*)p_token->p_addr)->tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 487 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 488 | |
Jonathan Austin |
0:bc2961fa1ef0 | 489 | // Begin (or resume) searching for a record. |
Jonathan Austin |
0:bc2961fa1ef0 | 490 | for (; p_token->vpage_id < FDS_MAX_PAGES; p_token->vpage_id++) |
Jonathan Austin |
0:bc2961fa1ef0 | 491 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 492 | uint16_t page = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 493 | |
Jonathan Austin |
0:bc2961fa1ef0 | 494 | // Obtain the physical page ID. |
Jonathan Austin |
0:bc2961fa1ef0 | 495 | page_id_from_virtual_id(p_token->vpage_id, &page); |
Jonathan Austin |
0:bc2961fa1ef0 | 496 | |
Jonathan Austin |
0:bc2961fa1ef0 | 497 | if (m_pages[page].page_type != FDS_PAGE_VALID) |
Jonathan Austin |
0:bc2961fa1ef0 | 498 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 499 | // Skip this page. |
Jonathan Austin |
0:bc2961fa1ef0 | 500 | continue; |
Jonathan Austin |
0:bc2961fa1ef0 | 501 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 502 | |
Jonathan Austin |
0:bc2961fa1ef0 | 503 | if (p_token->p_addr == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 504 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 505 | // If it's the first time the function is run, initialize the pointer. |
Jonathan Austin |
0:bc2961fa1ef0 | 506 | p_token->p_addr = m_pages[page].start_addr + FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 507 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 508 | |
Jonathan Austin |
0:bc2961fa1ef0 | 509 | // Seek a valid record on this page, starting from the address stored in the token. |
Jonathan Austin |
0:bc2961fa1ef0 | 510 | while ((p_token->p_addr < (m_pages[page].start_addr + FS_PAGE_SIZE_WORDS)) && |
Jonathan Austin |
0:bc2961fa1ef0 | 511 | (*p_token->p_addr != FDS_ERASED_WORD)) // Did we jump to an erased word? |
Jonathan Austin |
0:bc2961fa1ef0 | 512 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 513 | fds_header_t const * const p_header = (fds_header_t*)p_token->p_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 514 | |
Jonathan Austin |
0:bc2961fa1ef0 | 515 | if (header_is_valid(p_header)) |
Jonathan Austin |
0:bc2961fa1ef0 | 516 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 517 | // A valid record was found, check its header for a match. |
Jonathan Austin |
0:bc2961fa1ef0 | 518 | bool item_match = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 519 | |
Jonathan Austin |
0:bc2961fa1ef0 | 520 | if (p_type != NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 521 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 522 | if (p_header->tl.type == *p_type) |
Jonathan Austin |
0:bc2961fa1ef0 | 523 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 524 | item_match = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 525 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 526 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 527 | |
Jonathan Austin |
0:bc2961fa1ef0 | 528 | if (p_inst != NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 529 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 530 | if (p_header->ic.instance == *p_inst) |
Jonathan Austin |
0:bc2961fa1ef0 | 531 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 532 | item_match = (p_type == NULL) ? true : item_match && true; |
Jonathan Austin |
0:bc2961fa1ef0 | 533 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 534 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 535 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 536 | item_match = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 537 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 538 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 539 | |
Jonathan Austin |
0:bc2961fa1ef0 | 540 | if (item_match) |
Jonathan Austin |
0:bc2961fa1ef0 | 541 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 542 | // We found the record! Update the descriptor. |
Jonathan Austin |
0:bc2961fa1ef0 | 543 | p_desc->vpage_id = m_pages[page].vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 544 | p_desc->record_id = p_header->id; |
Jonathan Austin |
0:bc2961fa1ef0 | 545 | |
Jonathan Austin |
0:bc2961fa1ef0 | 546 | p_desc->p_rec = p_token->p_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 547 | p_desc->ptr_magic = FDS_MAGIC_HWORD; |
Jonathan Austin |
0:bc2961fa1ef0 | 548 | p_desc->gc_magic = m_gc_runs; |
Jonathan Austin |
0:bc2961fa1ef0 | 549 | |
Jonathan Austin |
0:bc2961fa1ef0 | 550 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 551 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 552 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 553 | // Jump to the next record. |
Jonathan Austin |
0:bc2961fa1ef0 | 554 | p_token->p_addr += (FDS_HEADER_SIZE + (p_header->tl.length_words)); |
Jonathan Austin |
0:bc2961fa1ef0 | 555 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 556 | |
Jonathan Austin |
0:bc2961fa1ef0 | 557 | /** We have seeked an entire page. Set the address in the token to NULL |
Jonathan Austin |
0:bc2961fa1ef0 | 558 | * so that it will be set again on the next iteration. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 559 | p_token->p_addr = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 560 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 561 | |
Jonathan Austin |
0:bc2961fa1ef0 | 562 | /** If we couldn't find the record, zero the token structure |
Jonathan Austin |
0:bc2961fa1ef0 | 563 | * so that it can be reused. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 564 | p_token->magic = 0x00; |
Jonathan Austin |
0:bc2961fa1ef0 | 565 | |
Jonathan Austin |
0:bc2961fa1ef0 | 566 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 567 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 568 | |
Jonathan Austin |
0:bc2961fa1ef0 | 569 | |
Jonathan Austin |
0:bc2961fa1ef0 | 570 | static void gc_init() |
Jonathan Austin |
0:bc2961fa1ef0 | 571 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 572 | // Set which pages to GC. |
Jonathan Austin |
0:bc2961fa1ef0 | 573 | for (uint16_t i = 0; i < FDS_MAX_PAGES; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 574 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 575 | m_gc.do_gc_page[i] = (m_pages[i].page_type == FDS_PAGE_VALID); |
Jonathan Austin |
0:bc2961fa1ef0 | 576 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 577 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 578 | |
Jonathan Austin |
0:bc2961fa1ef0 | 579 | |
Jonathan Austin |
0:bc2961fa1ef0 | 580 | static void gc_reset() |
Jonathan Austin |
0:bc2961fa1ef0 | 581 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 582 | m_gc.state = BEGIN; |
Jonathan Austin |
0:bc2961fa1ef0 | 583 | m_gc.cur_page = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 584 | m_gc.p_scan_addr = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 585 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 586 | |
Jonathan Austin |
0:bc2961fa1ef0 | 587 | |
Jonathan Austin |
0:bc2961fa1ef0 | 588 | static void gc_set_state(fds_gc_state_t new_state) |
Jonathan Austin |
0:bc2961fa1ef0 | 589 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 590 | m_gc.state = new_state; |
Jonathan Austin |
0:bc2961fa1ef0 | 591 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 592 | |
Jonathan Austin |
0:bc2961fa1ef0 | 593 | |
Jonathan Austin |
0:bc2961fa1ef0 | 594 | static ret_code_t gc_get_next_page(uint16_t * const next_page) |
Jonathan Austin |
0:bc2961fa1ef0 | 595 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 596 | for (uint16_t i = 0; i < FDS_MAX_PAGES; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 597 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 598 | if (m_gc.do_gc_page[i]) |
Jonathan Austin |
0:bc2961fa1ef0 | 599 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 600 | uint16_t records_open; |
Jonathan Austin |
0:bc2961fa1ef0 | 601 | |
Jonathan Austin |
0:bc2961fa1ef0 | 602 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 603 | records_open = m_pages[i].records_open; |
Jonathan Austin |
0:bc2961fa1ef0 | 604 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 605 | |
Jonathan Austin |
0:bc2961fa1ef0 | 606 | // Do not attempt to GC this page anymore. |
Jonathan Austin |
0:bc2961fa1ef0 | 607 | m_gc.do_gc_page[i] = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 608 | |
Jonathan Austin |
0:bc2961fa1ef0 | 609 | // Only GC pages with no open records. |
Jonathan Austin |
0:bc2961fa1ef0 | 610 | if (records_open == 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 611 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 612 | *next_page = i; |
Jonathan Austin |
0:bc2961fa1ef0 | 613 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 614 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 615 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 616 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 617 | |
Jonathan Austin |
0:bc2961fa1ef0 | 618 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 619 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 620 | |
Jonathan Austin |
0:bc2961fa1ef0 | 621 | |
Jonathan Austin |
0:bc2961fa1ef0 | 622 | static ret_code_t gc_page() |
Jonathan Austin |
0:bc2961fa1ef0 | 623 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 624 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 625 | |
Jonathan Austin |
0:bc2961fa1ef0 | 626 | ret = gc_get_next_page(&m_gc.cur_page); |
Jonathan Austin |
0:bc2961fa1ef0 | 627 | |
Jonathan Austin |
0:bc2961fa1ef0 | 628 | // No pages left to GC. GC has terminated. Reset GC data. |
Jonathan Austin |
0:bc2961fa1ef0 | 629 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 630 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 631 | gc_reset(); |
Jonathan Austin |
0:bc2961fa1ef0 | 632 | |
Jonathan Austin |
0:bc2961fa1ef0 | 633 | return COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 634 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 635 | |
Jonathan Austin |
0:bc2961fa1ef0 | 636 | // Prepare to GC the page. |
Jonathan Austin |
0:bc2961fa1ef0 | 637 | gc_set_state(GC_PAGE); |
Jonathan Austin |
0:bc2961fa1ef0 | 638 | |
Jonathan Austin |
0:bc2961fa1ef0 | 639 | // Flag the page as being garbage collected. |
Jonathan Austin |
0:bc2961fa1ef0 | 640 | ret = page_tag_write_gc(m_gc.cur_page); |
Jonathan Austin |
0:bc2961fa1ef0 | 641 | |
Jonathan Austin |
0:bc2961fa1ef0 | 642 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 643 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 644 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 645 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 646 | |
Jonathan Austin |
0:bc2961fa1ef0 | 647 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 648 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 649 | |
Jonathan Austin |
0:bc2961fa1ef0 | 650 | |
Jonathan Austin |
0:bc2961fa1ef0 | 651 | static ret_code_t gc_copy_record() |
Jonathan Austin |
0:bc2961fa1ef0 | 652 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 653 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 654 | |
Jonathan Austin |
0:bc2961fa1ef0 | 655 | // We have found a record to copy. |
Jonathan Austin |
0:bc2961fa1ef0 | 656 | fds_record_t const * const p_record = (fds_record_t*)m_gc.p_scan_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 657 | |
Jonathan Austin |
0:bc2961fa1ef0 | 658 | gc_set_state(COPY_RECORD); |
Jonathan Austin |
0:bc2961fa1ef0 | 659 | |
Jonathan Austin |
0:bc2961fa1ef0 | 660 | // Copy the item to swap. |
Jonathan Austin |
0:bc2961fa1ef0 | 661 | fs_ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 662 | m_pages[m_gc.swap_page].start_addr + m_pages[m_gc.swap_page].write_offset, |
Jonathan Austin |
0:bc2961fa1ef0 | 663 | (uint32_t*)p_record, |
Jonathan Austin |
0:bc2961fa1ef0 | 664 | FDS_HEADER_SIZE + p_record->header.tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 665 | |
Jonathan Austin |
0:bc2961fa1ef0 | 666 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 667 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 668 | // Oops :( |
Jonathan Austin |
0:bc2961fa1ef0 | 669 | // This is an error. Can we recover? |
Jonathan Austin |
0:bc2961fa1ef0 | 670 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 671 | |
Jonathan Austin |
0:bc2961fa1ef0 | 672 | // Remember to update the swap page write offset. |
Jonathan Austin |
0:bc2961fa1ef0 | 673 | m_pages[m_gc.swap_page].write_offset += (FDS_HEADER_SIZE + p_record->header.tl.length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 674 | |
Jonathan Austin |
0:bc2961fa1ef0 | 675 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 676 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 677 | |
Jonathan Austin |
0:bc2961fa1ef0 | 678 | |
Jonathan Austin |
0:bc2961fa1ef0 | 679 | static ret_code_t gc_ready_swap_page() |
Jonathan Austin |
0:bc2961fa1ef0 | 680 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 681 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 682 | |
Jonathan Austin |
0:bc2961fa1ef0 | 683 | /** A page has been scanned through. All valid records found were copied to swap. |
Jonathan Austin |
0:bc2961fa1ef0 | 684 | * The swap page can now be flagged as a valid page. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 685 | gc_set_state(READY_SWAP); |
Jonathan Austin |
0:bc2961fa1ef0 | 686 | |
Jonathan Austin |
0:bc2961fa1ef0 | 687 | fs_ret = page_tag_write_valid(m_gc.swap_page); |
Jonathan Austin |
0:bc2961fa1ef0 | 688 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 689 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 690 | return fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 691 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 692 | |
Jonathan Austin |
0:bc2961fa1ef0 | 693 | /** Do not update the page type in the internal page structure (m_pages) |
Jonathan Austin |
0:bc2961fa1ef0 | 694 | * right away. (why?) */ |
Jonathan Austin |
0:bc2961fa1ef0 | 695 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 696 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 697 | |
Jonathan Austin |
0:bc2961fa1ef0 | 698 | |
Jonathan Austin |
0:bc2961fa1ef0 | 699 | static ret_code_t gc_seek_record() |
Jonathan Austin |
0:bc2961fa1ef0 | 700 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 701 | // Let's find a valid record which has not been copied yet. |
Jonathan Austin |
0:bc2961fa1ef0 | 702 | if (scan_next_valid(m_gc.cur_page, &m_gc.p_scan_addr) == NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 703 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 704 | /** The record is guaranteed to fit in the destination page, |
Jonathan Austin |
0:bc2961fa1ef0 | 705 | * so we don't need to check its size. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 706 | return gc_copy_record(); |
Jonathan Austin |
0:bc2961fa1ef0 | 707 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 708 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 709 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 710 | /** No more (uncopied) records left on this page. |
Jonathan Austin |
0:bc2961fa1ef0 | 711 | * The swap page can now be marked as a valid page. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 712 | return gc_ready_swap_page(); |
Jonathan Austin |
0:bc2961fa1ef0 | 713 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 714 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 715 | |
Jonathan Austin |
0:bc2961fa1ef0 | 716 | |
Jonathan Austin |
0:bc2961fa1ef0 | 717 | static ret_code_t gc_new_swap_page() |
Jonathan Austin |
0:bc2961fa1ef0 | 718 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 719 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 720 | uint16_t vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 721 | |
Jonathan Austin |
0:bc2961fa1ef0 | 722 | gc_set_state(NEW_SWAP); |
Jonathan Austin |
0:bc2961fa1ef0 | 723 | |
Jonathan Austin |
0:bc2961fa1ef0 | 724 | // Save the swap page virtual page ID. |
Jonathan Austin |
0:bc2961fa1ef0 | 725 | vpage_id = m_pages[m_gc.swap_page].vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 726 | |
Jonathan Austin |
0:bc2961fa1ef0 | 727 | /** The swap page has been marked as valid in Flash. We copy the GC'ed page |
Jonathan Austin |
0:bc2961fa1ef0 | 728 | * write_offset and virtual page ID. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 729 | m_pages[m_gc.swap_page].page_type = FDS_PAGE_VALID; |
Jonathan Austin |
0:bc2961fa1ef0 | 730 | m_pages[m_gc.swap_page].vpage_id = m_pages[m_gc.cur_page].vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 731 | m_pages[m_gc.swap_page].words_reserved = m_pages[m_gc.cur_page].words_reserved; |
Jonathan Austin |
0:bc2961fa1ef0 | 732 | |
Jonathan Austin |
0:bc2961fa1ef0 | 733 | // The new swap page is now the page we just GC. |
Jonathan Austin |
0:bc2961fa1ef0 | 734 | m_gc.swap_page = m_gc.cur_page; |
Jonathan Austin |
0:bc2961fa1ef0 | 735 | |
Jonathan Austin |
0:bc2961fa1ef0 | 736 | // Update the write_offset, words_reserved and vpage_id fields for the new swap page. |
Jonathan Austin |
0:bc2961fa1ef0 | 737 | m_pages[m_gc.swap_page].page_type = FDS_PAGE_SWAP; |
Jonathan Austin |
0:bc2961fa1ef0 | 738 | m_pages[m_gc.swap_page].vpage_id = vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 739 | m_pages[m_gc.swap_page].write_offset = FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 740 | m_pages[m_gc.swap_page].words_reserved = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 741 | |
Jonathan Austin |
0:bc2961fa1ef0 | 742 | /** Finally, erase the new swap page. Remember we still have to flag this |
Jonathan Austin |
0:bc2961fa1ef0 | 743 | * new page as swap, but we'll wait the callback for this operation to do so. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 744 | fs_ret = fs_erase(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 745 | (uint32_t*)m_pages[m_gc.swap_page].start_addr, |
Jonathan Austin |
0:bc2961fa1ef0 | 746 | FS_PAGE_SIZE_WORDS); |
Jonathan Austin |
0:bc2961fa1ef0 | 747 | |
Jonathan Austin |
0:bc2961fa1ef0 | 748 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 749 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 750 | return fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 751 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 752 | |
Jonathan Austin |
0:bc2961fa1ef0 | 753 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 754 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 755 | |
Jonathan Austin |
0:bc2961fa1ef0 | 756 | |
Jonathan Austin |
0:bc2961fa1ef0 | 757 | static ret_code_t gc_new_swap_page_init() |
Jonathan Austin |
0:bc2961fa1ef0 | 758 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 759 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 760 | |
Jonathan Austin |
0:bc2961fa1ef0 | 761 | gc_set_state(INIT_SWAP); |
Jonathan Austin |
0:bc2961fa1ef0 | 762 | |
Jonathan Austin |
0:bc2961fa1ef0 | 763 | fs_ret = page_tag_write_swap(m_gc.swap_page); |
Jonathan Austin |
0:bc2961fa1ef0 | 764 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 765 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 766 | return fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 767 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 768 | |
Jonathan Austin |
0:bc2961fa1ef0 | 769 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 770 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 771 | |
Jonathan Austin |
0:bc2961fa1ef0 | 772 | |
Jonathan Austin |
0:bc2961fa1ef0 | 773 | static ret_code_t gc_execute(uint32_t result) |
Jonathan Austin |
0:bc2961fa1ef0 | 774 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 775 | // TODO: Handle resuming GC. |
Jonathan Austin |
0:bc2961fa1ef0 | 776 | |
Jonathan Austin |
0:bc2961fa1ef0 | 777 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 778 | |
Jonathan Austin |
0:bc2961fa1ef0 | 779 | if (result != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 780 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 781 | // An operation failed. Report to the application. |
Jonathan Austin |
0:bc2961fa1ef0 | 782 | return result; |
Jonathan Austin |
0:bc2961fa1ef0 | 783 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 784 | |
Jonathan Austin |
0:bc2961fa1ef0 | 785 | switch (m_gc.state) |
Jonathan Austin |
0:bc2961fa1ef0 | 786 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 787 | case BEGIN: |
Jonathan Austin |
0:bc2961fa1ef0 | 788 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 789 | // Increment the number of times the GC has been run. |
Jonathan Austin |
0:bc2961fa1ef0 | 790 | m_gc_runs++; |
Jonathan Austin |
0:bc2961fa1ef0 | 791 | // Sets up a list of pages to GC. |
Jonathan Austin |
0:bc2961fa1ef0 | 792 | gc_init(); |
Jonathan Austin |
0:bc2961fa1ef0 | 793 | // Go ! |
Jonathan Austin |
0:bc2961fa1ef0 | 794 | ret = gc_page(); |
Jonathan Austin |
0:bc2961fa1ef0 | 795 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 796 | |
Jonathan Austin |
0:bc2961fa1ef0 | 797 | case GC_PAGE: |
Jonathan Austin |
0:bc2961fa1ef0 | 798 | /** A page has been successfully flagged as being GC. |
Jonathan Austin |
0:bc2961fa1ef0 | 799 | * Look for valid records to copy. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 800 | ret = gc_seek_record(); |
Jonathan Austin |
0:bc2961fa1ef0 | 801 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 802 | |
Jonathan Austin |
0:bc2961fa1ef0 | 803 | case COPY_RECORD: |
Jonathan Austin |
0:bc2961fa1ef0 | 804 | /** A record has been copied to swap. |
Jonathan Austin |
0:bc2961fa1ef0 | 805 | * Look for more records to copy. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 806 | ret = gc_seek_record(); |
Jonathan Austin |
0:bc2961fa1ef0 | 807 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 808 | |
Jonathan Austin |
0:bc2961fa1ef0 | 809 | case READY_SWAP: |
Jonathan Austin |
0:bc2961fa1ef0 | 810 | /** The swap page has been flagged as 'valid' (ready). |
Jonathan Austin |
0:bc2961fa1ef0 | 811 | * Let's prepare a new swap page. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 812 | ret = gc_new_swap_page(); |
Jonathan Austin |
0:bc2961fa1ef0 | 813 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 814 | |
Jonathan Austin |
0:bc2961fa1ef0 | 815 | case NEW_SWAP: |
Jonathan Austin |
0:bc2961fa1ef0 | 816 | // A new swap page has been prepared. Let's flag it as swap. |
Jonathan Austin |
0:bc2961fa1ef0 | 817 | ret = gc_new_swap_page_init(); |
Jonathan Austin |
0:bc2961fa1ef0 | 818 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 819 | |
Jonathan Austin |
0:bc2961fa1ef0 | 820 | case INIT_SWAP: |
Jonathan Austin |
0:bc2961fa1ef0 | 821 | /** The swap was flagged as swap in flash. Let's compress another page. |
Jonathan Austin |
0:bc2961fa1ef0 | 822 | * Be sure to update the address where to scan from. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 823 | m_gc.p_scan_addr = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 824 | ret = gc_page(); |
Jonathan Austin |
0:bc2961fa1ef0 | 825 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 826 | |
Jonathan Austin |
0:bc2961fa1ef0 | 827 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 828 | // Should really not happen. |
Jonathan Austin |
0:bc2961fa1ef0 | 829 | ret = NRF_ERROR_INTERNAL; |
Jonathan Austin |
0:bc2961fa1ef0 | 830 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 831 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 832 | |
Jonathan Austin |
0:bc2961fa1ef0 | 833 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 834 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 835 | |
Jonathan Austin |
0:bc2961fa1ef0 | 836 | |
Jonathan Austin |
0:bc2961fa1ef0 | 837 | /**@brief Function for initializing the command queue. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 838 | static void queues_init(void) |
Jonathan Austin |
0:bc2961fa1ef0 | 839 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 840 | memset(&m_cmd_queue, 0, sizeof(fds_cmd_queue_t)); |
Jonathan Austin |
0:bc2961fa1ef0 | 841 | memset(&m_chunk_queue, 0, sizeof(fds_chunk_queue_t)); |
Jonathan Austin |
0:bc2961fa1ef0 | 842 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 843 | |
Jonathan Austin |
0:bc2961fa1ef0 | 844 | |
Jonathan Austin |
0:bc2961fa1ef0 | 845 | void cmd_queue_next(fds_cmd_t ** pp_cmd) |
Jonathan Austin |
0:bc2961fa1ef0 | 846 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 847 | if (*pp_cmd != &m_cmd_queue.cmd[FDS_CMD_QUEUE_SIZE - 1]) |
Jonathan Austin |
0:bc2961fa1ef0 | 848 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 849 | (*pp_cmd)++; |
Jonathan Austin |
0:bc2961fa1ef0 | 850 | return; |
Jonathan Austin |
0:bc2961fa1ef0 | 851 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 852 | |
Jonathan Austin |
0:bc2961fa1ef0 | 853 | *pp_cmd = &m_cmd_queue.cmd[0]; |
Jonathan Austin |
0:bc2961fa1ef0 | 854 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 855 | |
Jonathan Austin |
0:bc2961fa1ef0 | 856 | |
Jonathan Austin |
0:bc2961fa1ef0 | 857 | void chunk_queue_next(fds_record_chunk_t ** pp_chunk) |
Jonathan Austin |
0:bc2961fa1ef0 | 858 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 859 | if ((*pp_chunk) != &m_chunk_queue.chunk[FDS_CHUNK_QUEUE_SIZE - 1]) |
Jonathan Austin |
0:bc2961fa1ef0 | 860 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 861 | (*pp_chunk)++; |
Jonathan Austin |
0:bc2961fa1ef0 | 862 | return; |
Jonathan Austin |
0:bc2961fa1ef0 | 863 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 864 | |
Jonathan Austin |
0:bc2961fa1ef0 | 865 | *pp_chunk = &m_chunk_queue.chunk[0]; |
Jonathan Austin |
0:bc2961fa1ef0 | 866 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 867 | |
Jonathan Austin |
0:bc2961fa1ef0 | 868 | |
Jonathan Austin |
0:bc2961fa1ef0 | 869 | /**@brief Advances one position in the command queue. Returns true if the queue is not empty. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 870 | static bool cmd_queue_advance(void) |
Jonathan Austin |
0:bc2961fa1ef0 | 871 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 872 | // Reset the current element. |
Jonathan Austin |
0:bc2961fa1ef0 | 873 | memset(&m_cmd_queue.cmd[m_cmd_queue.rp], 0, sizeof(fds_cmd_t)); |
Jonathan Austin |
0:bc2961fa1ef0 | 874 | |
Jonathan Austin |
0:bc2961fa1ef0 | 875 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 876 | if (m_cmd_queue.count != 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 877 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 878 | // Advance in the queue, wrapping around if necessary. |
Jonathan Austin |
0:bc2961fa1ef0 | 879 | m_cmd_queue.rp = (m_cmd_queue.rp + 1) % FDS_CMD_QUEUE_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 880 | m_cmd_queue.count--; |
Jonathan Austin |
0:bc2961fa1ef0 | 881 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 882 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 883 | |
Jonathan Austin |
0:bc2961fa1ef0 | 884 | return m_cmd_queue.count != 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 885 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 886 | |
Jonathan Austin |
0:bc2961fa1ef0 | 887 | |
Jonathan Austin |
0:bc2961fa1ef0 | 888 | /**@brief Returns the current chunk, and advances to the next in the queue. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 889 | static bool chunk_queue_get_and_advance(fds_record_chunk_t ** pp_chunk) |
Jonathan Austin |
0:bc2961fa1ef0 | 890 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 891 | bool chunk_popped = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 892 | |
Jonathan Austin |
0:bc2961fa1ef0 | 893 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 894 | if (m_chunk_queue.count != 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 895 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 896 | // Point to the current chunk and advance the queue. |
Jonathan Austin |
0:bc2961fa1ef0 | 897 | *pp_chunk = &m_chunk_queue.chunk[m_chunk_queue.rp]; |
Jonathan Austin |
0:bc2961fa1ef0 | 898 | |
Jonathan Austin |
0:bc2961fa1ef0 | 899 | m_chunk_queue.rp = (m_chunk_queue.rp + 1) % FDS_CHUNK_QUEUE_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 900 | m_chunk_queue.count--; |
Jonathan Austin |
0:bc2961fa1ef0 | 901 | |
Jonathan Austin |
0:bc2961fa1ef0 | 902 | chunk_popped = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 903 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 904 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 905 | |
Jonathan Austin |
0:bc2961fa1ef0 | 906 | return chunk_popped; |
Jonathan Austin |
0:bc2961fa1ef0 | 907 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 908 | |
Jonathan Austin |
0:bc2961fa1ef0 | 909 | |
Jonathan Austin |
0:bc2961fa1ef0 | 910 | static bool chunk_queue_skip(uint8_t num_op) |
Jonathan Austin |
0:bc2961fa1ef0 | 911 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 912 | bool chunk_skipped = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 913 | |
Jonathan Austin |
0:bc2961fa1ef0 | 914 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 915 | if (num_op <= m_chunk_queue.count) |
Jonathan Austin |
0:bc2961fa1ef0 | 916 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 917 | m_chunk_queue.count -= num_op; |
Jonathan Austin |
0:bc2961fa1ef0 | 918 | chunk_skipped = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 919 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 920 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 921 | |
Jonathan Austin |
0:bc2961fa1ef0 | 922 | return chunk_skipped; |
Jonathan Austin |
0:bc2961fa1ef0 | 923 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 924 | |
Jonathan Austin |
0:bc2961fa1ef0 | 925 | |
Jonathan Austin |
0:bc2961fa1ef0 | 926 | /**@brief Reserves resources on both queues. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 927 | static ret_code_t queue_reserve(uint8_t num_cmd, |
Jonathan Austin |
0:bc2961fa1ef0 | 928 | uint8_t num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 929 | fds_cmd_t ** pp_cmd, |
Jonathan Austin |
0:bc2961fa1ef0 | 930 | fds_record_chunk_t ** pp_chunk) |
Jonathan Austin |
0:bc2961fa1ef0 | 931 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 932 | uint8_t cmd_index; |
Jonathan Austin |
0:bc2961fa1ef0 | 933 | uint8_t chunk_index; |
Jonathan Austin |
0:bc2961fa1ef0 | 934 | |
Jonathan Austin |
0:bc2961fa1ef0 | 935 | // This is really just being safe. |
Jonathan Austin |
0:bc2961fa1ef0 | 936 | if (pp_cmd == NULL || ((pp_chunk == NULL) && (num_chunks != 0))) |
Jonathan Austin |
0:bc2961fa1ef0 | 937 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 938 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 939 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 940 | |
Jonathan Austin |
0:bc2961fa1ef0 | 941 | if (num_cmd == 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 942 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 943 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 944 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 945 | |
Jonathan Austin |
0:bc2961fa1ef0 | 946 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 947 | |
Jonathan Austin |
0:bc2961fa1ef0 | 948 | // Ensure there is enough space in the queues. |
Jonathan Austin |
0:bc2961fa1ef0 | 949 | if ((m_cmd_queue.count > FDS_CMD_QUEUE_SIZE - num_cmd) || |
Jonathan Austin |
0:bc2961fa1ef0 | 950 | (m_chunk_queue.count > FDS_CHUNK_QUEUE_SIZE - num_chunks)) |
Jonathan Austin |
0:bc2961fa1ef0 | 951 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 952 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 953 | return NRF_ERROR_BUSY; |
Jonathan Austin |
0:bc2961fa1ef0 | 954 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 955 | |
Jonathan Austin |
0:bc2961fa1ef0 | 956 | // Find the write position in the commands queue. |
Jonathan Austin |
0:bc2961fa1ef0 | 957 | cmd_index = m_cmd_queue.count; |
Jonathan Austin |
0:bc2961fa1ef0 | 958 | cmd_index += m_cmd_queue.rp; |
Jonathan Austin |
0:bc2961fa1ef0 | 959 | cmd_index = cmd_index % FDS_CMD_QUEUE_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 960 | |
Jonathan Austin |
0:bc2961fa1ef0 | 961 | *pp_cmd = &m_cmd_queue.cmd[cmd_index]; |
Jonathan Austin |
0:bc2961fa1ef0 | 962 | m_cmd_queue.count += num_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 963 | |
Jonathan Austin |
0:bc2961fa1ef0 | 964 | /* If no operations are associated with the command, such as is the case |
Jonathan Austin |
0:bc2961fa1ef0 | 965 | * for initialization and compression, pp_chunk can be NULL. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 966 | if (num_chunks != 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 967 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 968 | chunk_index = m_chunk_queue.count; |
Jonathan Austin |
0:bc2961fa1ef0 | 969 | chunk_index += m_chunk_queue.rp; |
Jonathan Austin |
0:bc2961fa1ef0 | 970 | chunk_index = chunk_index % FDS_CHUNK_QUEUE_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 971 | |
Jonathan Austin |
0:bc2961fa1ef0 | 972 | *pp_chunk = &m_chunk_queue.chunk[chunk_index]; |
Jonathan Austin |
0:bc2961fa1ef0 | 973 | m_chunk_queue.count += num_chunks; |
Jonathan Austin |
0:bc2961fa1ef0 | 974 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 975 | |
Jonathan Austin |
0:bc2961fa1ef0 | 976 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 977 | |
Jonathan Austin |
0:bc2961fa1ef0 | 978 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 979 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 980 | |
Jonathan Austin |
0:bc2961fa1ef0 | 981 | |
Jonathan Austin |
0:bc2961fa1ef0 | 982 | /**@brief Cancel the reservation on resources on queues. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 983 | static void queue_reserve_cancel(uint8_t num_cmd, uint8_t num_chunks) |
Jonathan Austin |
0:bc2961fa1ef0 | 984 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 985 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 986 | m_cmd_queue.count -= num_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 987 | m_chunk_queue.count -= num_chunks; |
Jonathan Austin |
0:bc2961fa1ef0 | 988 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 989 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 990 | |
Jonathan Austin |
0:bc2961fa1ef0 | 991 | |
Jonathan Austin |
0:bc2961fa1ef0 | 992 | static void pages_init(uint16_t * const p_pages_avail, |
Jonathan Austin |
0:bc2961fa1ef0 | 993 | bool * const p_write_page_tag, |
Jonathan Austin |
0:bc2961fa1ef0 | 994 | bool * const p_resume_comp) |
Jonathan Austin |
0:bc2961fa1ef0 | 995 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 996 | *p_pages_avail = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 997 | *p_write_page_tag = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 998 | *p_resume_comp = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 999 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1000 | /** Scan pages and setup page data. |
Jonathan Austin |
0:bc2961fa1ef0 | 1001 | * This function does NOT perform write operations in flash. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1002 | for (uint16_t i = 0; i < FDS_MAX_PAGES; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 1003 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1004 | // Initialize page data. Note that start_addr must be set BEFORE invoking page_identify(). |
Jonathan Austin |
0:bc2961fa1ef0 | 1005 | m_pages[i].start_addr = fs_config.p_start_addr + (i * FS_PAGE_SIZE_WORDS); |
Jonathan Austin |
0:bc2961fa1ef0 | 1006 | m_pages[i].write_offset = FDS_PAGE_TAG_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1007 | m_pages[i].vpage_id = i; |
Jonathan Austin |
0:bc2961fa1ef0 | 1008 | m_pages[i].records_open = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1009 | m_pages[i].words_reserved = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1010 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1011 | m_pages[i].page_type = page_identify(i); |
Jonathan Austin |
0:bc2961fa1ef0 | 1012 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1013 | switch (m_pages[i].page_type) |
Jonathan Austin |
0:bc2961fa1ef0 | 1014 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1015 | case FDS_PAGE_UNDEFINED: |
Jonathan Austin |
0:bc2961fa1ef0 | 1016 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1017 | if (page_is_empty(i)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1018 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1019 | /* We have found an erased page, which can be initialized. |
Jonathan Austin |
0:bc2961fa1ef0 | 1020 | * This will require a write in flash. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1021 | m_pages[i].page_type = FDS_PAGE_ERASED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1022 | *p_write_page_tag = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1023 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1024 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1025 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1026 | case FDS_PAGE_VALID: |
Jonathan Austin |
0:bc2961fa1ef0 | 1027 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1028 | /** If a page is valid, we update its write offset. |
Jonathan Austin |
0:bc2961fa1ef0 | 1029 | * Additionally, page_scan will update the last known record ID. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1030 | page_scan(i, &m_pages[i].write_offset); |
Jonathan Austin |
0:bc2961fa1ef0 | 1031 | (*p_pages_avail)++; |
Jonathan Austin |
0:bc2961fa1ef0 | 1032 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1033 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1034 | case FDS_PAGE_SWAP: |
Jonathan Austin |
0:bc2961fa1ef0 | 1035 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1036 | m_gc.swap_page = i; |
Jonathan Austin |
0:bc2961fa1ef0 | 1037 | m_swap_page_avail = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1038 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1039 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1040 | case FDS_PAGE_GC: |
Jonathan Austin |
0:bc2961fa1ef0 | 1041 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1042 | /** There is an ongoing garbage collection. |
Jonathan Austin |
0:bc2961fa1ef0 | 1043 | * We should resume the operation, which we don't yet. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1044 | m_gc.cur_page = i; |
Jonathan Austin |
0:bc2961fa1ef0 | 1045 | m_gc.state = GC_PAGE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1046 | *p_resume_comp = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1047 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1048 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1049 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 1050 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1051 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1052 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1053 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1054 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1055 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1056 | // NOTE: Adds FDS_HEADER_SIZE automatically. |
Jonathan Austin |
0:bc2961fa1ef0 | 1057 | static ret_code_t write_space_reserve(uint16_t length_words, uint16_t * vpage_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 1058 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1059 | bool space_reserved = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 1060 | uint16_t total_len_words = length_words + FDS_HEADER_SIZE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1061 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1062 | if (total_len_words >= FS_PAGE_SIZE_WORDS - FDS_PAGE_TAG_SIZE) |
Jonathan Austin |
0:bc2961fa1ef0 | 1063 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1064 | return NRF_ERROR_INVALID_LENGTH; |
Jonathan Austin |
0:bc2961fa1ef0 | 1065 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1066 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1067 | for (uint16_t page = 0; page < FDS_MAX_PAGES; page++) |
Jonathan Austin |
0:bc2961fa1ef0 | 1068 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1069 | if ((m_pages[page].page_type == FDS_PAGE_VALID) && |
Jonathan Austin |
0:bc2961fa1ef0 | 1070 | (page_has_space(page, total_len_words))) |
Jonathan Austin |
0:bc2961fa1ef0 | 1071 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1072 | space_reserved = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1073 | *vpage_id = m_pages[page].vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1074 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1075 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1076 | m_pages[page].words_reserved += total_len_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1077 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1078 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1079 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1080 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1081 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1082 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1083 | return space_reserved ? NRF_SUCCESS : NRF_ERROR_NO_MEM; |
Jonathan Austin |
0:bc2961fa1ef0 | 1084 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1085 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1086 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1087 | static bool chunk_is_aligned(fds_record_chunk_t const * const p_chunk, uint8_t num_parts) |
Jonathan Austin |
0:bc2961fa1ef0 | 1088 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1089 | for (uint8_t i = 0; i < num_parts; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 1090 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1091 | if (!is_word_aligned(p_chunk[i].p_data)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1092 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1093 | return false; |
Jonathan Austin |
0:bc2961fa1ef0 | 1094 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1095 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1096 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1097 | return true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1098 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1099 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1100 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1101 | static ret_code_t init_execute(uint32_t result, uint32_t const * p_page_addr) |
Jonathan Austin |
0:bc2961fa1ef0 | 1102 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1103 | uint16_t cur_page; |
Jonathan Austin |
0:bc2961fa1ef0 | 1104 | bool page_tag_written = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 1105 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1106 | if (result != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1107 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1108 | // Oops. Error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1109 | return result; |
Jonathan Austin |
0:bc2961fa1ef0 | 1110 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1111 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1112 | // Here we just distinguish between the first invocation and the others. |
Jonathan Austin |
0:bc2961fa1ef0 | 1113 | cur_page = p_page_addr == NULL ? 0 : page_by_addr(p_page_addr) + 1; |
Jonathan Austin |
0:bc2961fa1ef0 | 1114 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1115 | if (cur_page == FDS_MAX_PAGES) |
Jonathan Austin |
0:bc2961fa1ef0 | 1116 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1117 | // We have finished. We'd need to set some flags. |
Jonathan Austin |
0:bc2961fa1ef0 | 1118 | flag_set(FDS_FLAG_INITIALIZED); |
Jonathan Austin |
0:bc2961fa1ef0 | 1119 | flag_clear(FDS_FLAG_INITIALIZING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1120 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1121 | return COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1122 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1123 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1124 | while (cur_page < FDS_MAX_PAGES && !page_tag_written) |
Jonathan Austin |
0:bc2961fa1ef0 | 1125 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1126 | if (m_pages[cur_page].page_type == FDS_PAGE_ERASED) |
Jonathan Austin |
0:bc2961fa1ef0 | 1127 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1128 | page_tag_written = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1129 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1130 | if (m_swap_page_avail) |
Jonathan Austin |
0:bc2961fa1ef0 | 1131 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1132 | if (page_tag_write_valid(cur_page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1133 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1134 | // Oops. Error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1135 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1136 | // Update the page type. |
Jonathan Austin |
0:bc2961fa1ef0 | 1137 | m_pages[cur_page].page_type = FDS_PAGE_VALID; |
Jonathan Austin |
0:bc2961fa1ef0 | 1138 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1139 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1140 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1141 | if (page_tag_write_swap(cur_page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1142 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1143 | // Oops. Error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1144 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1145 | // Update the page type. |
Jonathan Austin |
0:bc2961fa1ef0 | 1146 | m_pages[cur_page].page_type = FDS_PAGE_SWAP; |
Jonathan Austin |
0:bc2961fa1ef0 | 1147 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1148 | /** Update compression data. We set this information in init_pages |
Jonathan Austin |
0:bc2961fa1ef0 | 1149 | * if it is available, otherwise, we should set it here. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1150 | m_swap_page_avail = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1151 | m_gc.swap_page = cur_page; |
Jonathan Austin |
0:bc2961fa1ef0 | 1152 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1153 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1154 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1155 | cur_page++; |
Jonathan Austin |
0:bc2961fa1ef0 | 1156 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1157 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1158 | if (!page_tag_written) |
Jonathan Austin |
0:bc2961fa1ef0 | 1159 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1160 | if (m_swap_page_avail) |
Jonathan Austin |
0:bc2961fa1ef0 | 1161 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1162 | return COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1163 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1164 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1165 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1166 | // There is no empty space to use as swap. |
Jonathan Austin |
0:bc2961fa1ef0 | 1167 | // Notify user that no compression is available? |
Jonathan Austin |
0:bc2961fa1ef0 | 1168 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1169 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1170 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1171 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 1172 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1173 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1174 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1175 | /**@brief Function to execute write and update commands. |
Jonathan Austin |
0:bc2961fa1ef0 | 1176 | * |
Jonathan Austin |
0:bc2961fa1ef0 | 1177 | */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1178 | static ret_code_t store_execute(uint32_t result, fds_cmd_t * const p_cmd) |
Jonathan Austin |
0:bc2961fa1ef0 | 1179 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1180 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1181 | fds_record_chunk_t * p_chunk = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1182 | fds_page_t * p_page = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1183 | uint32_t * p_write_addr; |
Jonathan Austin |
0:bc2961fa1ef0 | 1184 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1185 | // Using virtual page IDs allows other operations to be queued even if GC has been requested. |
Jonathan Austin |
0:bc2961fa1ef0 | 1186 | page_from_virtual_id(p_cmd->vpage_id, &p_page); |
Jonathan Austin |
0:bc2961fa1ef0 | 1187 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1188 | if (result != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1189 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1190 | // The previous operation has failed, update the page data. |
Jonathan Austin |
0:bc2961fa1ef0 | 1191 | p_page->write_offset += (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1192 | p_page->words_reserved -= (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1193 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1194 | return result; |
Jonathan Austin |
0:bc2961fa1ef0 | 1195 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1196 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1197 | // Compute the write address (just syntatic sugar). |
Jonathan Austin |
0:bc2961fa1ef0 | 1198 | p_write_addr = (uint32_t*)(p_page->start_addr + p_page->write_offset); |
Jonathan Austin |
0:bc2961fa1ef0 | 1199 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1200 | // Execute the operation. |
Jonathan Austin |
0:bc2961fa1ef0 | 1201 | switch (p_cmd->op_code) |
Jonathan Austin |
0:bc2961fa1ef0 | 1202 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1203 | case FDS_OP_WRITE_TL: |
Jonathan Austin |
0:bc2961fa1ef0 | 1204 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1205 | fs_ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1206 | p_write_addr + FDS_WRITE_OFFSET_TL, |
Jonathan Austin |
0:bc2961fa1ef0 | 1207 | (uint32_t*)&p_cmd->record_header.tl, |
Jonathan Austin |
0:bc2961fa1ef0 | 1208 | FDS_HEADER_SIZE_TL /*Words*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1209 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1210 | // Set the next operation to be executed. |
Jonathan Austin |
0:bc2961fa1ef0 | 1211 | p_cmd->op_code = FDS_OP_WRITE_ID; |
Jonathan Austin |
0:bc2961fa1ef0 | 1212 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1213 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1214 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1215 | case FDS_OP_WRITE_ID: |
Jonathan Austin |
0:bc2961fa1ef0 | 1216 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1217 | fs_ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1218 | p_write_addr + FDS_WRITE_OFFSET_ID, |
Jonathan Austin |
0:bc2961fa1ef0 | 1219 | (uint32_t*)&p_cmd->record_header.id, |
Jonathan Austin |
0:bc2961fa1ef0 | 1220 | FDS_HEADER_SIZE_ID /*Words*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1221 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1222 | p_cmd->op_code = FDS_OP_WRITE_CHUNK; |
Jonathan Austin |
0:bc2961fa1ef0 | 1223 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1224 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1225 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1226 | case FDS_OP_WRITE_CHUNK: |
Jonathan Austin |
0:bc2961fa1ef0 | 1227 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1228 | // Decrement the number of chunks left to write. |
Jonathan Austin |
0:bc2961fa1ef0 | 1229 | p_cmd->num_chunks--; |
Jonathan Austin |
0:bc2961fa1ef0 | 1230 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1231 | // Retrieve the chunk to be written. |
Jonathan Austin |
0:bc2961fa1ef0 | 1232 | chunk_queue_get_and_advance(&p_chunk); |
Jonathan Austin |
0:bc2961fa1ef0 | 1233 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1234 | fs_ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1235 | p_write_addr + p_cmd->chunk_offset, |
Jonathan Austin |
0:bc2961fa1ef0 | 1236 | p_chunk->p_data, |
Jonathan Austin |
0:bc2961fa1ef0 | 1237 | p_chunk->length_words); |
Jonathan Austin |
0:bc2961fa1ef0 | 1238 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1239 | // Accumulate the offset. |
Jonathan Austin |
0:bc2961fa1ef0 | 1240 | p_cmd->chunk_offset += p_chunk->length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1241 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1242 | if (p_cmd->num_chunks == 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 1243 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1244 | /** We have written all the record chunks; we'll write |
Jonathan Austin |
0:bc2961fa1ef0 | 1245 | * IC last as a mean to 'validate' the record. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1246 | p_cmd->op_code = FDS_OP_WRITE_IC; |
Jonathan Austin |
0:bc2961fa1ef0 | 1247 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1248 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1249 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1250 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1251 | case FDS_OP_WRITE_IC: |
Jonathan Austin |
0:bc2961fa1ef0 | 1252 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1253 | fs_ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1254 | p_write_addr + FDS_WRITE_OFFSET_IC, |
Jonathan Austin |
0:bc2961fa1ef0 | 1255 | (uint32_t*)&p_cmd->record_header.ic, |
Jonathan Austin |
0:bc2961fa1ef0 | 1256 | FDS_HEADER_SIZE_IC /*Words*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1257 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1258 | // This is the final operation. |
Jonathan Austin |
0:bc2961fa1ef0 | 1259 | p_cmd->op_code = FDS_OP_DONE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1260 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1261 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1262 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1263 | case FDS_OP_DONE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1264 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1265 | // We have successfully written down the IC. The command has completed successfully. |
Jonathan Austin |
0:bc2961fa1ef0 | 1266 | p_page->write_offset += (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1267 | p_page->words_reserved -= (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1268 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1269 | return COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1270 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1271 | }; |
Jonathan Austin |
0:bc2961fa1ef0 | 1272 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1273 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 1274 | fs_ret = NRF_ERROR_INTERNAL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1275 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1276 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1277 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1278 | // If fs_store did not succeed, the command has failed. |
Jonathan Austin |
0:bc2961fa1ef0 | 1279 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1280 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1281 | /** We're not going to receive a callback from fstorage |
Jonathan Austin |
0:bc2961fa1ef0 | 1282 | * so we update the page data right away. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1283 | p_page->write_offset += (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1284 | p_page->words_reserved -= (FDS_HEADER_SIZE + (p_cmd->chunk_offset - FDS_WRITE_OFFSET_DATA)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1285 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1286 | // We should propagate the error from fstorage. |
Jonathan Austin |
0:bc2961fa1ef0 | 1287 | return fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1288 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1289 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1290 | // An operation has successfully been executed. Wait for the callback. |
Jonathan Austin |
0:bc2961fa1ef0 | 1291 | return COMMAND_EXECUTING; |
Jonathan Austin |
0:bc2961fa1ef0 | 1292 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1293 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1294 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1295 | static ret_code_t clear_execute(ret_code_t result, fds_cmd_t * const p_cmd) |
Jonathan Austin |
0:bc2961fa1ef0 | 1296 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1297 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1298 | fds_record_desc_t desc; |
Jonathan Austin |
0:bc2961fa1ef0 | 1299 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1300 | // This must persist across calls. |
Jonathan Austin |
0:bc2961fa1ef0 | 1301 | static fds_find_token_t tok; |
Jonathan Austin |
0:bc2961fa1ef0 | 1302 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1303 | if (result != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1304 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1305 | // A previous operation has failed. Propagate the error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1306 | return result; |
Jonathan Austin |
0:bc2961fa1ef0 | 1307 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1308 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1309 | switch (p_cmd->op_code) |
Jonathan Austin |
0:bc2961fa1ef0 | 1310 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1311 | case FDS_OP_CLEAR_TL: |
Jonathan Austin |
0:bc2961fa1ef0 | 1312 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1313 | // We were provided a descriptor for the record. |
Jonathan Austin |
0:bc2961fa1ef0 | 1314 | desc.vpage_id = p_cmd->vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1315 | desc.record_id = p_cmd->record_header.id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1316 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1317 | /** Unfortunately, we always seek the record in this case, |
Jonathan Austin |
0:bc2961fa1ef0 | 1318 | * because we don't buffer an entire record descriptor in the |
Jonathan Austin |
0:bc2961fa1ef0 | 1319 | * fds_cmd_t structure. Keep in mind though, that we will |
Jonathan Austin |
0:bc2961fa1ef0 | 1320 | * seek one page at most. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1321 | if (seek_record(&desc) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1322 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1323 | // The record never existed, or it is already cleared. |
Jonathan Austin |
0:bc2961fa1ef0 | 1324 | ret = NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 1325 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1326 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1327 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1328 | // Copy the record key, so that it may be returned in the callback. |
Jonathan Austin |
0:bc2961fa1ef0 | 1329 | p_cmd->record_header.tl.type = ((fds_header_t*)desc.p_rec)->tl.type; |
Jonathan Austin |
0:bc2961fa1ef0 | 1330 | p_cmd->record_header.ic.instance = ((fds_header_t*)desc.p_rec)->ic.instance; |
Jonathan Austin |
0:bc2961fa1ef0 | 1331 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1332 | ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1333 | desc.p_rec, |
Jonathan Austin |
0:bc2961fa1ef0 | 1334 | (uint32_t*)&m_fds_tl_invalid, |
Jonathan Austin |
0:bc2961fa1ef0 | 1335 | FDS_HEADER_SIZE_TL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1336 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1337 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1338 | p_cmd->op_code = FDS_OP_DONE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1339 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1340 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1341 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1342 | case FDS_OP_CLEAR_INSTANCE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1343 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1344 | if (find_record(NULL, &p_cmd->record_header.ic.instance, |
Jonathan Austin |
0:bc2961fa1ef0 | 1345 | &desc, &tok) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1346 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1347 | // No more records to be found. |
Jonathan Austin |
0:bc2961fa1ef0 | 1348 | p_cmd->op_code = FDS_OP_DONE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1349 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1350 | // Zero the token, so that we may reuse it. |
Jonathan Austin |
0:bc2961fa1ef0 | 1351 | memset(&tok, 0, sizeof(fds_find_token_t)); |
Jonathan Austin |
0:bc2961fa1ef0 | 1352 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1353 | /** We won't receive a callback, since no flash operation |
Jonathan Austin |
0:bc2961fa1ef0 | 1354 | * was initiated. The command has finished. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1355 | ret = COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1356 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1357 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1358 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1359 | ret = fs_store(&fs_config, |
Jonathan Austin |
0:bc2961fa1ef0 | 1360 | desc.p_rec, |
Jonathan Austin |
0:bc2961fa1ef0 | 1361 | (uint32_t*)&m_fds_tl_invalid, |
Jonathan Austin |
0:bc2961fa1ef0 | 1362 | FDS_HEADER_SIZE_TL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1363 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1364 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1365 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1366 | case FDS_OP_DONE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1367 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1368 | /** The last operation completed successfully. |
Jonathan Austin |
0:bc2961fa1ef0 | 1369 | * The command has finished. Return. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1370 | ret = COMMAND_COMPLETED; |
Jonathan Austin |
0:bc2961fa1ef0 | 1371 | } break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1372 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1373 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 1374 | ret = NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1375 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1376 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1377 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1378 | // Await for the operation result. |
Jonathan Austin |
0:bc2961fa1ef0 | 1379 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1380 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1381 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1382 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1383 | static ret_code_t cmd_queue_process(void) |
Jonathan Austin |
0:bc2961fa1ef0 | 1384 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1385 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1386 | fds_cmd_t * const p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; |
Jonathan Austin |
0:bc2961fa1ef0 | 1387 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1388 | switch (p_cmd->id) |
Jonathan Austin |
0:bc2961fa1ef0 | 1389 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1390 | case FDS_CMD_INIT: |
Jonathan Austin |
0:bc2961fa1ef0 | 1391 | ret = init_execute(NRF_SUCCESS, NULL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1392 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1393 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1394 | case FDS_CMD_WRITE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1395 | case FDS_CMD_UPDATE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1396 | ret = store_execute(NRF_SUCCESS, p_cmd); |
Jonathan Austin |
0:bc2961fa1ef0 | 1397 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1398 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1399 | case FDS_CMD_CLEAR: |
Jonathan Austin |
0:bc2961fa1ef0 | 1400 | case FDS_CMD_CLEAR_INST: |
Jonathan Austin |
0:bc2961fa1ef0 | 1401 | ret = clear_execute(NRF_SUCCESS, p_cmd); |
Jonathan Austin |
0:bc2961fa1ef0 | 1402 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1403 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1404 | case FDS_CMD_GC: |
Jonathan Austin |
0:bc2961fa1ef0 | 1405 | ret = gc_execute(NRF_SUCCESS); |
Jonathan Austin |
0:bc2961fa1ef0 | 1406 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1407 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1408 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 1409 | ret = NRF_ERROR_FORBIDDEN; |
Jonathan Austin |
0:bc2961fa1ef0 | 1410 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1411 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1412 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1413 | if ((ret == COMMAND_EXECUTING) || (ret == COMMAND_COMPLETED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1414 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1415 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1416 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1417 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1418 | // This is an error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1419 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1420 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1421 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1422 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1423 | static ret_code_t cmd_queue_process_start(void) |
Jonathan Austin |
0:bc2961fa1ef0 | 1424 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1425 | bool start_processing = false; |
Jonathan Austin |
0:bc2961fa1ef0 | 1426 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1427 | if (!flag_is_set(FDS_FLAG_PROCESSING)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1428 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1429 | flag_set(FDS_FLAG_PROCESSING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1430 | start_processing = true; |
Jonathan Austin |
0:bc2961fa1ef0 | 1431 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1432 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1433 | if (!start_processing) |
Jonathan Austin |
0:bc2961fa1ef0 | 1434 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1435 | // We are awaiting a callback, so there is no need to manually start queue processing. |
Jonathan Austin |
0:bc2961fa1ef0 | 1436 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1437 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1438 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1439 | return cmd_queue_process(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1440 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1441 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1442 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1443 | static void fs_callback(uint8_t op_code, |
Jonathan Austin |
0:bc2961fa1ef0 | 1444 | uint32_t result, |
Jonathan Austin |
0:bc2961fa1ef0 | 1445 | uint32_t const * p_data, |
Jonathan Austin |
0:bc2961fa1ef0 | 1446 | fs_length_t length) |
Jonathan Austin |
0:bc2961fa1ef0 | 1447 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1448 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1449 | fds_cmd_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp]; |
Jonathan Austin |
0:bc2961fa1ef0 | 1450 | fds_record_key_t record_key; |
Jonathan Austin |
0:bc2961fa1ef0 | 1451 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1452 | switch (p_cmd->id) |
Jonathan Austin |
0:bc2961fa1ef0 | 1453 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1454 | case FDS_CMD_INIT: |
Jonathan Austin |
0:bc2961fa1ef0 | 1455 | ret = init_execute(result, p_data); |
Jonathan Austin |
0:bc2961fa1ef0 | 1456 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1457 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1458 | case FDS_CMD_WRITE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1459 | case FDS_CMD_UPDATE: |
Jonathan Austin |
0:bc2961fa1ef0 | 1460 | ret = store_execute(result, p_cmd); |
Jonathan Austin |
0:bc2961fa1ef0 | 1461 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1462 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1463 | case FDS_CMD_CLEAR: |
Jonathan Austin |
0:bc2961fa1ef0 | 1464 | case FDS_CMD_CLEAR_INST: |
Jonathan Austin |
0:bc2961fa1ef0 | 1465 | ret = clear_execute(result, p_cmd); |
Jonathan Austin |
0:bc2961fa1ef0 | 1466 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1467 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1468 | case FDS_CMD_GC: |
Jonathan Austin |
0:bc2961fa1ef0 | 1469 | ret = gc_execute(result); |
Jonathan Austin |
0:bc2961fa1ef0 | 1470 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1471 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1472 | default: |
Jonathan Austin |
0:bc2961fa1ef0 | 1473 | // Should not happen. |
Jonathan Austin |
0:bc2961fa1ef0 | 1474 | ret = NRF_ERROR_INTERNAL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1475 | break; |
Jonathan Austin |
0:bc2961fa1ef0 | 1476 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1477 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1478 | if (ret == COMMAND_EXECUTING /*=NRF_SUCCESS*/) |
Jonathan Austin |
0:bc2961fa1ef0 | 1479 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1480 | /** The current command is still being processed. |
Jonathan Austin |
0:bc2961fa1ef0 | 1481 | * The command queue does not need to advance. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1482 | return; |
Jonathan Austin |
0:bc2961fa1ef0 | 1483 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1484 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1485 | // Initialize the fds_record_key_t structure needed for the callback. |
Jonathan Austin |
0:bc2961fa1ef0 | 1486 | record_key.type = p_cmd->record_header.tl.type; |
Jonathan Austin |
0:bc2961fa1ef0 | 1487 | record_key.instance = p_cmd->record_header.ic.instance; |
Jonathan Austin |
0:bc2961fa1ef0 | 1488 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1489 | // The command has either completed or an operation (and thus the command) has failed. |
Jonathan Austin |
0:bc2961fa1ef0 | 1490 | if (ret == COMMAND_COMPLETED) |
Jonathan Austin |
0:bc2961fa1ef0 | 1491 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1492 | // The command has completed successfully. Notify the application. |
Jonathan Austin |
0:bc2961fa1ef0 | 1493 | app_notify(NRF_SUCCESS, p_cmd->id, p_cmd->record_header.id, record_key); |
Jonathan Austin |
0:bc2961fa1ef0 | 1494 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1495 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1496 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1497 | /** An operation has failed. This is fatal for the execution of a command. |
Jonathan Austin |
0:bc2961fa1ef0 | 1498 | * Skip other operations associated with the current command. |
Jonathan Austin |
0:bc2961fa1ef0 | 1499 | * Notify the user of the failure. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1500 | chunk_queue_skip(p_cmd->num_chunks); |
Jonathan Austin |
0:bc2961fa1ef0 | 1501 | app_notify(ret /*=result*/, p_cmd->id, p_cmd->record_header.id, record_key); |
Jonathan Austin |
0:bc2961fa1ef0 | 1502 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1503 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1504 | // Advance the command queue, and if there is still something in the queue, process it. |
Jonathan Austin |
0:bc2961fa1ef0 | 1505 | if (cmd_queue_advance()) |
Jonathan Austin |
0:bc2961fa1ef0 | 1506 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1507 | /** Only process the queue if there are no pending commands being queued, since they |
Jonathan Austin |
0:bc2961fa1ef0 | 1508 | * will begin to process the queue on their own. Be sure to clear |
Jonathan Austin |
0:bc2961fa1ef0 | 1509 | * the flag FDS_FLAG_PROCESSING though ! */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1510 | if (atomic_counter_is_zero()) |
Jonathan Austin |
0:bc2961fa1ef0 | 1511 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1512 | cmd_queue_process(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1513 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1514 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1515 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1516 | flag_clear(FDS_FLAG_PROCESSING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1517 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1518 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1519 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1520 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1521 | /** No more elements in the queue. Clear the FDS_FLAG_PROCESSING flag, |
Jonathan Austin |
0:bc2961fa1ef0 | 1522 | * so that new commands can start the queue processing. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1523 | flag_clear(FDS_FLAG_PROCESSING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1524 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1525 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1526 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1527 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1528 | ret_code_t fds_init() |
Jonathan Austin |
0:bc2961fa1ef0 | 1529 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1530 | ret_code_t fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1531 | fds_cmd_t * p_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 1532 | uint16_t pages_avail; |
Jonathan Austin |
0:bc2961fa1ef0 | 1533 | bool write_page_tag; |
Jonathan Austin |
0:bc2961fa1ef0 | 1534 | bool resume_compression; |
Jonathan Austin |
0:bc2961fa1ef0 | 1535 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1536 | fds_record_key_t const dummy_key = {.type = FDS_TYPE_ID_INVALID, |
Jonathan Austin |
0:bc2961fa1ef0 | 1537 | .instance = FDS_INSTANCE_ID_INVALID}; |
Jonathan Austin |
0:bc2961fa1ef0 | 1538 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1539 | if (flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1540 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1541 | // Notify immediately. |
Jonathan Austin |
0:bc2961fa1ef0 | 1542 | app_notify(NRF_SUCCESS, FDS_CMD_INIT, 0 /*unused*/, dummy_key /*unused*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1543 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1544 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1545 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1546 | if (flag_is_set(FDS_FLAG_INITIALIZING)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1547 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1548 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1549 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1550 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1551 | fs_ret = fs_init(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1552 | if (fs_ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1553 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1554 | // fs_init() failed, propagate the error. |
Jonathan Austin |
0:bc2961fa1ef0 | 1555 | return fs_ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1556 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1557 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1558 | queues_init(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1559 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1560 | /** Initialize the last known record to zero. |
Jonathan Austin |
0:bc2961fa1ef0 | 1561 | * Its value will be updated by page_scan() called in pages_init(). */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1562 | m_last_rec_id = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1563 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1564 | // Initialize the page table containing all info on pages (address, type etc). |
Jonathan Austin |
0:bc2961fa1ef0 | 1565 | pages_init(&pages_avail, &write_page_tag, &resume_compression); |
Jonathan Austin |
0:bc2961fa1ef0 | 1566 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1567 | if (pages_avail == 0 && !write_page_tag) |
Jonathan Austin |
0:bc2961fa1ef0 | 1568 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1569 | return NRF_ERROR_NO_MEM; |
Jonathan Austin |
0:bc2961fa1ef0 | 1570 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1571 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1572 | /** This flag means fds_init() has been called. However, |
Jonathan Austin |
0:bc2961fa1ef0 | 1573 | * the module is NOT yet initialized. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1574 | flag_set(FDS_FLAG_INITIALIZING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1575 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1576 | if (resume_compression) |
Jonathan Austin |
0:bc2961fa1ef0 | 1577 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1578 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1579 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1580 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1581 | if (write_page_tag) |
Jonathan Austin |
0:bc2961fa1ef0 | 1582 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1583 | if (queue_reserve(FDS_CMD_QUEUE_SIZE_INIT, 0, &p_cmd, NULL) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1584 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1585 | // Should never happen. |
Jonathan Austin |
0:bc2961fa1ef0 | 1586 | return NRF_ERROR_BUSY; |
Jonathan Austin |
0:bc2961fa1ef0 | 1587 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1588 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1589 | // Initialize the command in the queue. |
Jonathan Austin |
0:bc2961fa1ef0 | 1590 | p_cmd->id = FDS_CMD_INIT; |
Jonathan Austin |
0:bc2961fa1ef0 | 1591 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1592 | return cmd_queue_process_start(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1593 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1594 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1595 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1596 | /* No flash operation is necessary for initialization. |
Jonathan Austin |
0:bc2961fa1ef0 | 1597 | * We can notify the application immediately. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1598 | flag_set (FDS_FLAG_INITIALIZED); |
Jonathan Austin |
0:bc2961fa1ef0 | 1599 | flag_clear(FDS_FLAG_INITIALIZING); |
Jonathan Austin |
0:bc2961fa1ef0 | 1600 | app_notify(NRF_SUCCESS, FDS_CMD_INIT, 0 /*unused*/, dummy_key /*unused*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1601 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1602 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1603 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1604 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1605 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1606 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1607 | ret_code_t fds_open(fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 1608 | fds_record_t * const p_record) |
Jonathan Austin |
0:bc2961fa1ef0 | 1609 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1610 | uint16_t page; |
Jonathan Austin |
0:bc2961fa1ef0 | 1611 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1612 | if (p_desc == NULL || p_record == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1613 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1614 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1615 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1616 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1617 | if (page_id_from_virtual_id(p_desc->vpage_id, &page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1618 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1619 | // Should not happen. |
Jonathan Austin |
0:bc2961fa1ef0 | 1620 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1621 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1622 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1623 | // Seek the record if necessary. |
Jonathan Austin |
0:bc2961fa1ef0 | 1624 | if (seek_record(p_desc) == NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1625 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1626 | if (header_is_valid((fds_header_t*)p_desc->p_rec)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1627 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1628 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1629 | m_pages[page].records_open++; |
Jonathan Austin |
0:bc2961fa1ef0 | 1630 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1631 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1632 | p_record->header = *((fds_header_t*)p_desc->p_rec); |
Jonathan Austin |
0:bc2961fa1ef0 | 1633 | p_record->p_data = (p_desc->p_rec + FDS_HEADER_SIZE); |
Jonathan Austin |
0:bc2961fa1ef0 | 1634 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1635 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1636 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1637 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1638 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1639 | /** The record could not be found. |
Jonathan Austin |
0:bc2961fa1ef0 | 1640 | * It either never existed or it has been cleared. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1641 | return NRF_ERROR_NOT_FOUND; |
Jonathan Austin |
0:bc2961fa1ef0 | 1642 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1643 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1644 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1645 | ret_code_t fds_close(fds_record_desc_t const * const p_desc) |
Jonathan Austin |
0:bc2961fa1ef0 | 1646 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1647 | uint16_t page; |
Jonathan Austin |
0:bc2961fa1ef0 | 1648 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1649 | if (p_desc == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1650 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1651 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1652 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1653 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1654 | if (page_id_from_virtual_id(p_desc->vpage_id, &page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1655 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1656 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1657 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1658 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1659 | CRITICAL_SECTION_ENTER(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1660 | m_pages[page].records_open--; |
Jonathan Austin |
0:bc2961fa1ef0 | 1661 | CRITICAL_SECTION_EXIT(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1662 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1663 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1664 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1665 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1666 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1667 | static ret_code_t write_enqueue(fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 1668 | fds_record_key_t key, |
Jonathan Austin |
0:bc2961fa1ef0 | 1669 | uint8_t num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 1670 | fds_record_chunk_t chunks[], |
Jonathan Austin |
0:bc2961fa1ef0 | 1671 | fds_write_token_t const * const p_tok, |
Jonathan Austin |
0:bc2961fa1ef0 | 1672 | bool do_update) |
Jonathan Austin |
0:bc2961fa1ef0 | 1673 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1674 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1675 | fds_cmd_t * p_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 1676 | fds_record_chunk_t * p_chunk = NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1677 | uint16_t vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1678 | uint16_t length_words = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1679 | uint8_t cmd_queue_elems; |
Jonathan Austin |
0:bc2961fa1ef0 | 1680 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1681 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1682 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1683 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1684 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1685 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1686 | if ((key.type == FDS_TYPE_ID_INVALID) || |
Jonathan Austin |
0:bc2961fa1ef0 | 1687 | (key.instance == FDS_INSTANCE_ID_INVALID)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1688 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1689 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1690 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1691 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1692 | if (!chunk_is_aligned(chunks, num_chunks)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1693 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1694 | return NRF_ERROR_INVALID_ADDR; |
Jonathan Austin |
0:bc2961fa1ef0 | 1695 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1696 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1697 | cmd_queue_elems = do_update ? FDS_CMD_QUEUE_SIZE_UPDATE : FDS_CMD_QUEUE_SIZE_WRITE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1698 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1699 | // Reserve space on both queues, and obtain pointers to the first elements reserved. |
Jonathan Austin |
0:bc2961fa1ef0 | 1700 | ret = queue_reserve(cmd_queue_elems, |
Jonathan Austin |
0:bc2961fa1ef0 | 1701 | num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 1702 | &p_cmd, |
Jonathan Austin |
0:bc2961fa1ef0 | 1703 | &p_chunk); |
Jonathan Austin |
0:bc2961fa1ef0 | 1704 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1705 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1706 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1707 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1708 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1709 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1710 | // No space was previously reserved for this operation. |
Jonathan Austin |
0:bc2961fa1ef0 | 1711 | if (p_tok == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1712 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1713 | // Compute the total length of the record. |
Jonathan Austin |
0:bc2961fa1ef0 | 1714 | for (uint8_t i = 0; i < num_chunks; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 1715 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1716 | length_words += chunks[i].length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1717 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1718 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1719 | /** Find a page where we can write the data. Reserve the space necessary |
Jonathan Austin |
0:bc2961fa1ef0 | 1720 | * to write the metadata as well. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1721 | ret = write_space_reserve(length_words, &vpage_id); |
Jonathan Austin |
0:bc2961fa1ef0 | 1722 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1723 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1724 | // If there is no space available, cancel the queue reservation. |
Jonathan Austin |
0:bc2961fa1ef0 | 1725 | queue_reserve_cancel(cmd_queue_elems, num_chunks); |
Jonathan Austin |
0:bc2961fa1ef0 | 1726 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1727 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1728 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1729 | else |
Jonathan Austin |
0:bc2961fa1ef0 | 1730 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1731 | length_words = p_tok->length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1732 | vpage_id = p_tok->vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1733 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1734 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1735 | // Initialize the command. |
Jonathan Austin |
0:bc2961fa1ef0 | 1736 | p_cmd->id = do_update ? FDS_CMD_UPDATE : FDS_CMD_WRITE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1737 | p_cmd->op_code = FDS_OP_WRITE_TL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1738 | p_cmd->num_chunks = num_chunks; |
Jonathan Austin |
0:bc2961fa1ef0 | 1739 | p_cmd->chunk_offset = FDS_WRITE_OFFSET_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1740 | p_cmd->vpage_id = vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1741 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1742 | // Fill in the header information. |
Jonathan Austin |
0:bc2961fa1ef0 | 1743 | p_cmd->record_header.id = record_id_new(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1744 | p_cmd->record_header.tl.type = key.type; |
Jonathan Austin |
0:bc2961fa1ef0 | 1745 | p_cmd->record_header.tl.length_words = length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1746 | p_cmd->record_header.ic.instance = key.instance; |
Jonathan Austin |
0:bc2961fa1ef0 | 1747 | p_cmd->record_header.ic.checksum = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1748 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1749 | // Buffer the record chunks in the queue. |
Jonathan Austin |
0:bc2961fa1ef0 | 1750 | for (uint8_t i = 0; i < num_chunks; i++) |
Jonathan Austin |
0:bc2961fa1ef0 | 1751 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1752 | p_chunk->p_data = chunks[i].p_data; |
Jonathan Austin |
0:bc2961fa1ef0 | 1753 | p_chunk->length_words = chunks[i].length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1754 | chunk_queue_next(&p_chunk); |
Jonathan Austin |
0:bc2961fa1ef0 | 1755 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1756 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1757 | if (do_update) |
Jonathan Austin |
0:bc2961fa1ef0 | 1758 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1759 | // Clear |
Jonathan Austin |
0:bc2961fa1ef0 | 1760 | cmd_queue_next(&p_cmd); |
Jonathan Austin |
0:bc2961fa1ef0 | 1761 | p_cmd->id = FDS_CMD_CLEAR; |
Jonathan Austin |
0:bc2961fa1ef0 | 1762 | p_cmd->op_code = FDS_OP_CLEAR_TL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1763 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1764 | p_cmd->vpage_id = p_desc->vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1765 | p_cmd->record_header.id = p_desc->record_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1766 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1767 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1768 | // Initialize the record descriptor, if provided. |
Jonathan Austin |
0:bc2961fa1ef0 | 1769 | if (p_desc != NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1770 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1771 | p_desc->vpage_id = vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1772 | // Don't invoke record_id_new() again. |
Jonathan Austin |
0:bc2961fa1ef0 | 1773 | p_desc->record_id = p_cmd->record_header.id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1774 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1775 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1776 | return cmd_queue_process_start(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1777 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1778 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1779 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1780 | ret_code_t fds_reserve(fds_write_token_t * const p_tok, uint16_t length_words) |
Jonathan Austin |
0:bc2961fa1ef0 | 1781 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1782 | uint16_t vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1783 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1784 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1785 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1786 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1787 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1788 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1789 | if (p_tok == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1790 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1791 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1792 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1793 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1794 | // Reserve space on the page. write_space_reserve() accounts for the header. |
Jonathan Austin |
0:bc2961fa1ef0 | 1795 | if (write_space_reserve(length_words, &vpage_id) == NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1796 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1797 | p_tok->vpage_id = vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1798 | p_tok->length_words = length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1799 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1800 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1801 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1802 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1803 | return NRF_ERROR_NO_MEM; |
Jonathan Austin |
0:bc2961fa1ef0 | 1804 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1805 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1806 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1807 | ret_code_t fds_reserve_cancel(fds_write_token_t * const p_tok) |
Jonathan Austin |
0:bc2961fa1ef0 | 1808 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1809 | fds_page_t * p_page; |
Jonathan Austin |
0:bc2961fa1ef0 | 1810 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1811 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1812 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1813 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1814 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1815 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1816 | if (p_tok == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1817 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1818 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1819 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1820 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1821 | if (page_from_virtual_id(p_tok->vpage_id, &p_page) != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1822 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1823 | // Could not find the virtual page. This shouldn't happen. |
Jonathan Austin |
0:bc2961fa1ef0 | 1824 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1825 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1826 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1827 | if ((p_page->words_reserved - p_tok->length_words) < 0) |
Jonathan Austin |
0:bc2961fa1ef0 | 1828 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1829 | /** We are trying to cancel a reservation for more words than how many are |
Jonathan Austin |
0:bc2961fa1ef0 | 1830 | * currently reserved on the page. This is shouldn't happen. */ |
Jonathan Austin |
0:bc2961fa1ef0 | 1831 | return NRF_ERROR_INVALID_DATA; |
Jonathan Austin |
0:bc2961fa1ef0 | 1832 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1833 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1834 | // Free the space which had been reserved. |
Jonathan Austin |
0:bc2961fa1ef0 | 1835 | p_page->words_reserved -= p_tok->length_words; |
Jonathan Austin |
0:bc2961fa1ef0 | 1836 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1837 | // Clean the token. |
Jonathan Austin |
0:bc2961fa1ef0 | 1838 | p_tok->vpage_id = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1839 | p_tok->length_words = 0; |
Jonathan Austin |
0:bc2961fa1ef0 | 1840 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1841 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 1842 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1843 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1844 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1845 | ret_code_t fds_write(fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 1846 | fds_record_key_t key, |
Jonathan Austin |
0:bc2961fa1ef0 | 1847 | uint8_t num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 1848 | fds_record_chunk_t chunks[]) |
Jonathan Austin |
0:bc2961fa1ef0 | 1849 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1850 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1851 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1852 | ret = write_enqueue(p_desc, key, num_chunks, chunks, NULL, false /*not an update*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1853 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1854 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1855 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1856 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1857 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1858 | ret_code_t fds_write_reserved(fds_write_token_t const * const p_tok, |
Jonathan Austin |
0:bc2961fa1ef0 | 1859 | fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 1860 | fds_record_key_t key, |
Jonathan Austin |
0:bc2961fa1ef0 | 1861 | uint8_t num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 1862 | fds_record_chunk_t chunks[]) |
Jonathan Austin |
0:bc2961fa1ef0 | 1863 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1864 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1865 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1866 | ret = write_enqueue(p_desc, key, num_chunks, chunks, p_tok, false /*not an update*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1867 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1868 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1869 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1870 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1871 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1872 | static ret_code_t clear_enqueue(fds_record_desc_t * const p_desc) |
Jonathan Austin |
0:bc2961fa1ef0 | 1873 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1874 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1875 | fds_cmd_t * p_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 1876 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1877 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1878 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1879 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1880 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1881 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1882 | if (p_desc == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 1883 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1884 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1885 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1886 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1887 | ret = queue_reserve(FDS_CMD_QUEUE_SIZE_CLEAR, 0, &p_cmd, NULL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1888 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1889 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1890 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1891 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1892 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1893 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1894 | // Initialize the command. |
Jonathan Austin |
0:bc2961fa1ef0 | 1895 | p_cmd->id = FDS_CMD_CLEAR; |
Jonathan Austin |
0:bc2961fa1ef0 | 1896 | p_cmd->op_code = FDS_OP_CLEAR_TL; |
Jonathan Austin |
0:bc2961fa1ef0 | 1897 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1898 | p_cmd->record_header.id = p_desc->record_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1899 | p_cmd->vpage_id = p_desc->vpage_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 1900 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1901 | return cmd_queue_process_start(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1902 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1903 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1904 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1905 | ret_code_t fds_clear(fds_record_desc_t * const p_desc) |
Jonathan Austin |
0:bc2961fa1ef0 | 1906 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1907 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1908 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1909 | ret = clear_enqueue(p_desc); |
Jonathan Austin |
0:bc2961fa1ef0 | 1910 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1911 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1912 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1913 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1914 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1915 | static ret_code_t clear_by_instance_enqueue(fds_instance_id_t instance) |
Jonathan Austin |
0:bc2961fa1ef0 | 1916 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1917 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1918 | fds_cmd_t * p_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 1919 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1920 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1921 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1922 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1923 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1924 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1925 | ret = queue_reserve(FDS_CMD_QUEUE_SIZE_CLEAR, 0, &p_cmd, NULL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1926 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1927 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1928 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1929 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1930 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1931 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1932 | p_cmd->id = FDS_CMD_CLEAR_INST; |
Jonathan Austin |
0:bc2961fa1ef0 | 1933 | p_cmd->op_code = FDS_OP_CLEAR_INSTANCE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1934 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1935 | p_cmd->record_header.ic.instance = instance; |
Jonathan Austin |
0:bc2961fa1ef0 | 1936 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1937 | return cmd_queue_process_start(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1938 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1939 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1940 | ret_code_t fds_clear_by_instance(fds_instance_id_t instance) |
Jonathan Austin |
0:bc2961fa1ef0 | 1941 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1942 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1943 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1944 | ret = clear_by_instance_enqueue(instance); |
Jonathan Austin |
0:bc2961fa1ef0 | 1945 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1946 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1947 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1948 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1949 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1950 | ret_code_t fds_update(fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 1951 | fds_record_key_t key, |
Jonathan Austin |
0:bc2961fa1ef0 | 1952 | uint8_t num_chunks, |
Jonathan Austin |
0:bc2961fa1ef0 | 1953 | fds_record_chunk_t chunks[]) |
Jonathan Austin |
0:bc2961fa1ef0 | 1954 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1955 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1956 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1957 | ret = write_enqueue(p_desc, key, num_chunks, chunks, NULL, true /*update*/); |
Jonathan Austin |
0:bc2961fa1ef0 | 1958 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1959 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1960 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1961 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1962 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1963 | static ret_code_t gc_enqueue() |
Jonathan Austin |
0:bc2961fa1ef0 | 1964 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1965 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1966 | fds_cmd_t * p_cmd; |
Jonathan Austin |
0:bc2961fa1ef0 | 1967 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1968 | if (!flag_is_set(FDS_FLAG_INITIALIZED)) |
Jonathan Austin |
0:bc2961fa1ef0 | 1969 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1970 | return NRF_ERROR_INVALID_STATE; |
Jonathan Austin |
0:bc2961fa1ef0 | 1971 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1972 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1973 | ret = queue_reserve(FDS_CMD_QUEUE_SIZE_GC, 0, &p_cmd, NULL); |
Jonathan Austin |
0:bc2961fa1ef0 | 1974 | if (ret != NRF_SUCCESS) |
Jonathan Austin |
0:bc2961fa1ef0 | 1975 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1976 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1977 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1978 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1979 | p_cmd->id = FDS_CMD_GC; |
Jonathan Austin |
0:bc2961fa1ef0 | 1980 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1981 | // Set compression parameters. |
Jonathan Austin |
0:bc2961fa1ef0 | 1982 | m_gc.state = BEGIN; |
Jonathan Austin |
0:bc2961fa1ef0 | 1983 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1984 | return cmd_queue_process_start(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1985 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1986 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1987 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1988 | ret_code_t fds_gc() |
Jonathan Austin |
0:bc2961fa1ef0 | 1989 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 1990 | ret_code_t ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1991 | atomic_counter_inc(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1992 | ret = gc_enqueue(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1993 | atomic_counter_dec(); |
Jonathan Austin |
0:bc2961fa1ef0 | 1994 | return ret; |
Jonathan Austin |
0:bc2961fa1ef0 | 1995 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 1996 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1997 | |
Jonathan Austin |
0:bc2961fa1ef0 | 1998 | ret_code_t fds_find(fds_type_id_t type, |
Jonathan Austin |
0:bc2961fa1ef0 | 1999 | fds_instance_id_t instance, |
Jonathan Austin |
0:bc2961fa1ef0 | 2000 | fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 2001 | fds_find_token_t * const p_token) |
Jonathan Austin |
0:bc2961fa1ef0 | 2002 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2003 | if (p_desc == NULL || p_token == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 2004 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2005 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 2006 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2007 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2008 | return find_record(&type, &instance, p_desc, p_token); |
Jonathan Austin |
0:bc2961fa1ef0 | 2009 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2010 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2011 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2012 | ret_code_t fds_find_by_type(fds_type_id_t type, |
Jonathan Austin |
0:bc2961fa1ef0 | 2013 | fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 2014 | fds_find_token_t * const p_token) |
Jonathan Austin |
0:bc2961fa1ef0 | 2015 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2016 | if (p_desc == NULL || p_token == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 2017 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2018 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 2019 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2020 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2021 | return find_record(&type, NULL, p_desc, p_token); |
Jonathan Austin |
0:bc2961fa1ef0 | 2022 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2023 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2024 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2025 | ret_code_t fds_find_by_instance(fds_instance_id_t instance, |
Jonathan Austin |
0:bc2961fa1ef0 | 2026 | fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 2027 | fds_find_token_t * const p_token) |
Jonathan Austin |
0:bc2961fa1ef0 | 2028 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2029 | if (p_desc == NULL || p_token == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 2030 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2031 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 2032 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2033 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2034 | return find_record(NULL, &instance, p_desc, p_token); |
Jonathan Austin |
0:bc2961fa1ef0 | 2035 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2036 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2037 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2038 | ret_code_t fds_register(fds_cb_t cb) |
Jonathan Austin |
0:bc2961fa1ef0 | 2039 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2040 | if (m_users == FDS_MAX_USERS) |
Jonathan Austin |
0:bc2961fa1ef0 | 2041 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2042 | return NRF_ERROR_NO_MEM; |
Jonathan Austin |
0:bc2961fa1ef0 | 2043 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2044 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2045 | m_cb_table[m_users] = cb; |
Jonathan Austin |
0:bc2961fa1ef0 | 2046 | m_users++; |
Jonathan Austin |
0:bc2961fa1ef0 | 2047 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2048 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 2049 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2050 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2051 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2052 | bool fds_descriptor_match(fds_record_desc_t const * const p_desc1, |
Jonathan Austin |
0:bc2961fa1ef0 | 2053 | fds_record_desc_t const * const p_desc2) |
Jonathan Austin |
0:bc2961fa1ef0 | 2054 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2055 | if ((p_desc1 == NULL) || (p_desc2 == NULL)) |
Jonathan Austin |
0:bc2961fa1ef0 | 2056 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2057 | return false; |
Jonathan Austin |
0:bc2961fa1ef0 | 2058 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2059 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2060 | return (p_desc1->record_id == p_desc2->record_id); |
Jonathan Austin |
0:bc2961fa1ef0 | 2061 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2062 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2063 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2064 | ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 2065 | fds_record_id_t record_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 2066 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2067 | if (p_desc == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 2068 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2069 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 2070 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2071 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2072 | p_desc->record_id = record_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 2073 | p_desc->vpage_id = FDS_VPAGE_ID_UNKNOWN; |
Jonathan Austin |
0:bc2961fa1ef0 | 2074 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2075 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 2076 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2077 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2078 | ret_code_t fds_record_id_from_desc(fds_record_desc_t const * const p_desc, |
Jonathan Austin |
0:bc2961fa1ef0 | 2079 | fds_record_id_t * const p_record_id) |
Jonathan Austin |
0:bc2961fa1ef0 | 2080 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2081 | if (p_desc == NULL || p_record_id == NULL) |
Jonathan Austin |
0:bc2961fa1ef0 | 2082 | { |
Jonathan Austin |
0:bc2961fa1ef0 | 2083 | return NRF_ERROR_NULL; |
Jonathan Austin |
0:bc2961fa1ef0 | 2084 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2085 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2086 | *p_record_id = p_desc->record_id; |
Jonathan Austin |
0:bc2961fa1ef0 | 2087 | |
Jonathan Austin |
0:bc2961fa1ef0 | 2088 | return NRF_SUCCESS; |
Jonathan Austin |
0:bc2961fa1ef0 | 2089 | } |
Jonathan Austin |
0:bc2961fa1ef0 | 2090 |