Sukkin Pang / nrf51-sdk

Fork of nrf51-sdk by Lancaster University

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?

UserRevisionLine numberNew 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