Nordic stack and drivers for the mbed BLE API

Fork of nRF51822 by Nordic Semiconductor

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

Who changed what in which revision?

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