Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nvstore.h Source File

nvstore.h

00001 /*
00002  * Copyright (c) 2018 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef MBED_NVSTORE_H
00018 #define MBED_NVSTORE_H
00019 
00020 // These addresses need to be configured according to board (in mbed_lib.json)
00021 #ifndef DEVICE_FLASH
00022 #undef NVSTORE_ENABLED
00023 #define NVSTORE_ENABLED 0
00024 #endif
00025 
00026 #if (NVSTORE_ENABLED) || defined(DOXYGEN_ONLY)
00027 #include <stdint.h>
00028 #include <stdio.h>
00029 #include "platform/NonCopyable.h"
00030 #include "PlatformMutex.h"
00031 #include "FlashIAP.h"
00032 
00033 typedef enum {
00034     NVSTORE_SUCCESS                =  0,
00035     NVSTORE_READ_ERROR             = -1,
00036     NVSTORE_WRITE_ERROR            = -2,
00037     NVSTORE_NOT_FOUND              = -3,
00038     NVSTORE_DATA_CORRUPT           = -4,
00039     NVSTORE_BAD_VALUE              = -5,
00040     NVSTORE_BUFF_TOO_SMALL         = -6,
00041     NVSTORE_FLASH_AREA_TOO_SMALL   = -7,
00042     NVSTORE_OS_ERROR               = -8,
00043     NVSTORE_ALREADY_EXISTS         = -9,
00044     NVSTORE_NO_FREE_KEY            = -10,
00045 } nvstore_status_e;
00046 
00047 typedef enum {
00048     NVSTORE_FIRST_PREDEFINED_KEY        = 0,
00049 
00050     // All predefined keys used for internal features should be defined here
00051 
00052     NVSTORE_DEVICEKEY_KEY               = 4,
00053 
00054     NVSTORE_LAST_PREDEFINED_KEY         = 15,
00055     NVSTORE_NUM_PREDEFINED_KEYS
00056 } nvstore_predefined_keys_e;
00057 
00058 typedef enum {
00059     NVSTORE_UNSPECIFIED_OWNER           = 0,
00060     // All owners (by features) should be specified here.
00061     NVSTORE_MAX_OWNERS                  = 16
00062 } nvstore_owner_e;
00063 
00064 #ifndef NVSTORE_MAX_KEYS
00065 #define NVSTORE_MAX_KEYS ((uint16_t)NVSTORE_NUM_PREDEFINED_KEYS)
00066 #endif
00067 
00068 // defines 2 areas - active and nonactive, not configurable
00069 #define NVSTORE_NUM_AREAS        2
00070 
00071 /** NVStore class
00072  *
00073  *  Class for storing data by keys in the internal flash
00074  */
00075 
00076 class NVStore : private mbed::NonCopyable<NVStore> {
00077 public:
00078 
00079     /**
00080     * @brief As a singleton, return the single instance of the class.
00081     *        Reason for this class being a singleton is the following:
00082     *        - Ease the use for users of this class not having to coordinate instantiations.
00083     *        - Lazy instantiation of internal data (which we can't achieve with simple static classes).
00084     *
00085     * @returns Singleton instance reference.
00086     */
00087     static NVStore& get_instance()
00088     {
00089         // Use this implementation of singleton (Meyer's) rather than the one that allocates
00090         // the instance on the heap because it ensures destruction at program end (preventing warnings
00091         // from memory checking tools).
00092         static NVStore instance;
00093         return instance;
00094     }
00095 
00096     virtual ~NVStore();
00097 
00098     /**
00099      * @brief Returns number of keys.
00100      *
00101      * @returns Number of keys.
00102      */
00103     uint16_t get_max_keys() const;
00104 
00105     /**
00106      * @brief Set number of keys.
00107      *
00108      * @returns None.
00109      */
00110     void set_max_keys(uint16_t num_keys);
00111 
00112     /**
00113      * @brief Return maximal possible number of keys (in this flash configuration).
00114      *
00115      * @returns Max possible number of keys.
00116      */
00117     uint16_t get_max_possible_keys();
00118 
00119     /**
00120      * @brief Returns one item of data programmed on Flash, given key.
00121      *
00122      * @param[in]  key                  Key of stored item.
00123      * @param[in]  buf_size             Length of input buffer in bytes.
00124      * @param[in]  buf                  Buffer to store data on.
00125      *
00126      * @param[out] actual_size          Actual size of returned data.
00127      *
00128      * @returns NVSTORE_SUCCESS           Value was found on Flash.
00129      *          NVSTORE_NOT_FOUND         Value was not found on Flash.
00130      *          NVSTORE_READ_ERROR        Physical error reading data.
00131      *          NVSTORE_DATA_CORRUPT      Data on Flash is corrupt.
00132      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00133      *          NVSTORE_BUFF_TOO_SMALL    Not enough memory in user buffer.
00134      */
00135     int get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual_size);
00136 
00137     /**
00138      * @brief Returns size of the data programmed on Flash, given key.
00139      *
00140      * @param[in]  key                  Key of stored item.
00141      * @param[out] actual_size          Actual size of item
00142      *
00143      * @returns NVSTORE_SUCCESS           Value was found on Flash.
00144      *          NVSTORE_NOT_FOUND         Value was not found on Flash.
00145      *          NVSTORE_READ_ERROR        Physical error reading data.
00146      *          NVSTORE_DATA_CORRUPT      Data on Flash is corrupt.
00147      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00148      */
00149     int get_item_size(uint16_t key, uint16_t &actual_size);
00150 
00151 
00152     /**
00153      * @brief Programs one item of data on Flash, given key.
00154      *
00155      * @param[in]  key                  Key of stored item.
00156      * @param[in]  buf_size             Item size in bytes.
00157      * @param[in]  buf                  Buffer containing data.
00158      *
00159      * @returns NVSTORE_SUCCESS           Value was successfully written on Flash.
00160      *          NVSTORE_WRITE_ERROR       Physical error writing data.
00161      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00162      *          NVSTORE_FLASH_AREA_TOO_SMALL
00163      *                                    Not enough space in Flash area.
00164      *          NVSTORE_ALREADY_EXISTS    Item set with write once API already exists.
00165      *
00166      */
00167     int set(uint16_t key, uint16_t buf_size, const void *buf);
00168 
00169     /**
00170      * @brief Allocate a free key (to be used later in a set operation).
00171      *
00172      * @param[out] key                  Returned key of stored item.
00173      * @param[in]  owner                Owner of allocated key.
00174      *
00175      * @returns NVSTORE_SUCCESS           Key was successfully allocated.
00176      *          NVSTORE_NO_FREE_KEY       Couldn't allocate a key for this call.
00177      *
00178      */
00179     int allocate_key(uint16_t &key, uint8_t owner = NVSTORE_UNSPECIFIED_OWNER);
00180 
00181     /**
00182      * @brief Free all allocated keys that belong to a specific owner.
00183      *
00184      * @param[in]  owner                Owner.
00185      *
00186      * @returns NVSTORE_SUCCESS           Value was successfully written on Flash.
00187      *          NVSTORE_WRITE_ERROR       Physical error writing data.
00188      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00189      *
00190      */
00191     int free_all_keys_by_owner(uint8_t owner);
00192 
00193     /**
00194      * @brief Programs one item of data on Flash, given key, allowing no consequent sets to this key.
00195      *
00196      * @param[in]  key                  Key of stored item.
00197      * @param[in]  buf_size             Item size in bytes.
00198      * @param[in]  buf                  Buffer containing data.
00199      *
00200      * @returns NVSTORE_SUCCESS           Value was successfully written on Flash.
00201      *          NVSTORE_WRITE_ERROR       Physical error writing data.
00202      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00203      *          NVSTORE_FLASH_AREA_TOO_SMALL
00204      *                                    Not enough space in Flash area.
00205      *          NVSTORE_ALREADY_EXISTS    Item set with write once API already exists.
00206      *
00207      */
00208     int set_once(uint16_t key, uint16_t buf_size, const void *buf);
00209 
00210 
00211     /**
00212      * @brief Remove an item from flash.
00213      *
00214      * @param[in]  key                  Key of stored item.
00215      *
00216      * @returns NVSTORE_SUCCESS           Value was successfully written on Flash.
00217      *          NVSTORE_WRITE_ERROR       Physical error writing data.
00218      *          NVSTORE_BAD_VALUE         Bad value in any of the parameters.
00219      *          NVSTORE_FLASH_AREA_TOO_SMALL
00220      *                                    Not enough space in Flash area.
00221      *
00222      */
00223     int remove(uint16_t key);
00224 
00225     /**
00226      * @brief Initializes NVStore component.
00227      *
00228      * @returns NVSTORE_SUCCESS       Initialization completed successfully.
00229      *          NVSTORE_READ_ERROR    Physical error reading data.
00230      *          NVSTORE_WRITE_ERROR   Physical error writing data (on recovery).
00231      *          NVSTORE_FLASH_AREA_TOO_SMALL
00232      *                                Not enough space in Flash area.
00233      */
00234     int init();
00235 
00236     /**
00237      * @brief Deinitializes NVStore component.
00238      *        Warning: This function is not thread safe and should not be called
00239      *        concurrently with other NVStore functions.
00240      *
00241      * @returns NVSTORE_SUCCESS       Deinitialization completed successfully.
00242      */
00243     int deinit();
00244 
00245     /**
00246      * @brief Reset Flash NVStore areas.
00247      *        Warning: This function is not thread safe and should not be called
00248      *        concurrently with other NVStore functions.
00249      *
00250      * @returns NVSTORE_SUCCESS       Reset completed successfully.
00251      *          NVSTORE_READ_ERROR    Physical error reading data.
00252      *          NVSTORE_WRITE_ERROR   Physical error writing data.
00253      */
00254     int reset();
00255 
00256     /**
00257      * @brief Return NVStore size (area size).
00258      *
00259      * @returns NVStore size.
00260      */
00261     size_t size();
00262 
00263     /**
00264      * @brief Return address and size of an NVStore area.
00265      *
00266      * @param[in]  area                   Area.
00267      * @param[out] address                Area address.
00268      * @param[out] size                   Area size (bytes).
00269      *
00270      * @returns NVSTORE_SUCCESS           Success.
00271      *          NVSTORE_BAD_VALUE         Bad area parameter.
00272      */
00273     int get_area_params(uint8_t area, uint32_t &address, size_t &size);
00274 
00275 
00276 private:
00277     typedef struct {
00278         uint32_t address;
00279         size_t   size;
00280     } nvstore_area_data_t;
00281 
00282     int _init_done;
00283     uint32_t _init_attempts;
00284     uint8_t _active_area;
00285     uint16_t _max_keys;
00286     uint16_t _active_area_version;
00287     uint32_t _free_space_offset;
00288     size_t _size;
00289     PlatformMutex *_mutex;
00290     uint32_t *_offset_by_key;
00291     nvstore_area_data_t _flash_area_params[NVSTORE_NUM_AREAS];
00292     static nvstore_area_data_t initial_area_params[NVSTORE_NUM_AREAS];
00293     mbed::FlashIAP *_flash;
00294     uint32_t _min_prog_size;
00295     uint8_t *_page_buf;
00296 
00297     // Private constructor, as class is a singleton
00298     NVStore();
00299 
00300     /**
00301      * @brief Read a block from an area.
00302      *
00303      * @param[in]  area                   Area.
00304      * @param[in]  offset                 Offset in area.
00305      * @param[in]  size                   Number of bytes to read.
00306      * @param[in]  buf                    Output buffer.
00307      *
00308      * @returns 0 for success, nonzero for failure.
00309      */
00310     int flash_read_area(uint8_t area, uint32_t offset, uint32_t size, void *buf);
00311 
00312     /**
00313      * @brief Write a block to an area.
00314      *
00315      * @param[in]  area                   Area.
00316      * @param[in]  offset                 Offset in area.
00317      * @param[in]  size                   Number of bytes to write.
00318      * @param[in]  buf                    Input buffer.
00319      *
00320      * @returns 0 for success, non-zero for failure.
00321      */
00322     int flash_write_area(uint8_t area, uint32_t offset, uint32_t size, const void *buf);
00323 
00324     /**
00325      * @brief Erase an area.
00326      *
00327      * @param[in]  area                   Area.
00328      *
00329      * @returns 0 for success, nonzero for failure.
00330      */
00331     int flash_erase_area(uint8_t area);
00332 
00333     /**
00334      * @brief Calculate addresses and sizes of areas (in case no user configuration is given),
00335      *        or validate user configuration (if given).
00336      */
00337     void calc_validate_area_params();
00338 
00339     /**
00340      * @brief Calculate empty (unprogrammed) continuous space at the end of the area.
00341      *
00342      * @param[in]  area                   Area.
00343      * @param[out] offset                 Offset of empty space.
00344      *
00345      * @returns 0 for success, nonzero for failure.
00346      */
00347     int calc_empty_space(uint8_t area, uint32_t &offset);
00348 
00349     /**
00350      * @brief Read an NVStore record from a given location.
00351      *
00352      * @param[in]  area                   Area.
00353      * @param[in]  offset                 Offset of record in area.
00354      * @param[in]  buf_size               Buffer size (bytes).
00355      * @param[in]  buf                    Output Buffer.
00356      * @param[out] actual_size            Actual data size (bytes).
00357      * @param[in]  validate_only          Just validate (without reading to buffer).
00358      * @param[out] valid                  Is the record valid.
00359      * @param[out] key                    Record key.
00360      * @param[out] flags                  Record flags.
00361      * @param[out] owner                  Owner.
00362      * @param[out] next_offset            Offset of next record.
00363      *
00364      * @returns 0 for success, nonzero for failure.
00365      */
00366     int read_record(uint8_t area, uint32_t offset, uint16_t buf_size, void *buf,
00367                     uint16_t &actual_size, int validate_only, int &valid,
00368                     uint16_t &key, uint16_t &flags, uint8_t &owner, uint32_t &next_offset);
00369 
00370     /**
00371      * @brief Write an NVStore record from a given location.
00372      *
00373      * @param[in]  area                   Area.
00374      * @param[in]  offset                 Offset of record in area.
00375      * @param[in]  key                    Record key.
00376      * @param[in]  flags                  Record flags.
00377      * @param[in]  owner                  Owner.
00378      * @param[in]  data_size              Data size (bytes).
00379      * @param[in]  data_buf               Data buffer.
00380      * @param[out] next_offset            Offset of next record.
00381      *
00382      * @returns 0 for success, nonzero for failure.
00383      */
00384     int write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t flags, uint8_t owner,
00385                      uint32_t data_size, const void *data_buf, uint32_t &next_offset);
00386 
00387     /**
00388      * @brief Write a master record of a given area.
00389      *
00390      * @param[in]  area                   Area.
00391      * @param[in]  version                Area version.
00392      * @param[out] next_offset            Offset of next record.
00393      *
00394      * @returns 0 for success, nonzero for failure.
00395      */
00396     int write_master_record(uint8_t area, uint16_t version, uint32_t &next_offset);
00397 
00398     /**
00399      * @brief Copy a record from one area to the other one.
00400      *
00401      * @param[in]  from_area              Area to copy record from.
00402      * @param[in]  from_offset            Offset in source area.
00403      * @param[in]  to_offset              Offset in destination area.
00404      * @param[out] next_offset            Offset of next record.
00405      *
00406      * @returns 0 for success, nonzero for failure.
00407      */
00408     int copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset,
00409                     uint32_t &next_offset);
00410 
00411     /**
00412      * @brief Garbage collection (compact all records from active area to nonactive ones).
00413      *        All parameters belong to a record that needs to be written before the process.
00414      *
00415      * @param[in]  key                    Record key.
00416      * @param[in]  flags                  Record flags.
00417      * @param[in]  owner                  Owner.
00418      * @param[in]  buf_size               Data size (bytes).
00419      * @param[in]  buf                    Data buffer.
00420      *
00421      * @returns 0 for success, nonzero for failure.
00422      */
00423     int garbage_collection(uint16_t key, uint16_t flags, uint8_t owner, uint16_t buf_size, const void *buf);
00424 
00425     /**
00426      * @brief Actual logics of get API (covers also get size API).
00427      *
00428      * @param[in]  key                    key.
00429      * @param[in]  buf_size               Buffer size (bytes).
00430      * @param[in]  buf                    Output Buffer.
00431      * @param[out] actual_size            Actual data size (bytes).
00432      * @param[in]  validate_only          Just validate (without reading to buffer).
00433      *
00434      * @returns 0 for success, nonzero for failure.
00435      */
00436     int do_get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual_size,
00437                int validate_only);
00438 
00439     /**
00440      * @brief Actual logics of set API (covers also set_once and remove APIs).
00441      *
00442      * @param[in]  key                    key.
00443      * @param[in]  buf_size               Buffer size (bytes).
00444      * @param[in]  buf                    Input Buffer.
00445      * @param[in]  flags                  Record flags.
00446      *
00447      * @returns 0 for success, nonzero for failure.
00448      */
00449     int do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t flags);
00450 
00451 };
00452 /** @}*/
00453 
00454 #endif // NVSTORE_ENABLED
00455 
00456 #endif