/*
 * Copyright (c) 2015-2017, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*!****************************************************************************
 *  @file       NVS.h
 *  @brief      Non-Volatile Storage driver interface
 *
 *  To use the NVS driver, ensure that the correct driver library for your
 *  device is linked in and include this header file as follows:
 *  @code
 *  #include <ti/drivers/NVS.h>
 *  @endcode
 *
 *  This module serves as the main interface for applications. Its purpose
 *  is to redirect the NVS APIs to specific driver implementations
 *  which are specified using a pointer to a #NVS_FxnTable.
 *
 *  # Overview #
 *
 *  The NVS module allows you to manage non-volatile memory.  Using the
 *  NVS APIs, you can read and write data from and to persistent storage.
 *
 *  Each NVS object manages a 'region' of non-volatile memory of a size
 *  specified in the NVS object's hardware attributes.  A 'sector' refers to
 *  the smallest unit of non-volatile storage that can be erased at one time,
 *  and the 'sectorSize' is the size of this unit. Flash sector size is
 *  hardware specific and may be meaningless for some persistent storage
 *  systems.  However, in the case of flash memory devices, the size
 *  of a managed region must be an integer multiple of the sector size.
 *
 *  # Thread Safety #
 *
 *  All NVS APIs are globally thread safe. Consequently, only one write,
 *  erase, or read in the case of SPI flash operation is allowed to be
 *  performed at a time, even for distinct NVS regions. Threads initiating
 *  new NVS writes or erases will block until any current operation completes.
 *
 *  # Interrupt Latency During Flash Operations #
 *
 *  When writing to or erasing internal flash, interrupts must be disabled
 *  to avoid executing code in flash while the flash is being reprogrammed.
 *  This constraint is met internally by the driver. User code does not need
 *  to safeguard against this.
 *
 *  Care must be taken by the user to not perform flash write or erase
 *  operations during latency critical phases of an application. See the
 *  NVS_lock() and NVS_unlock() API descriptions for more information.
 *
 *  # Usage #
 *
 *  The NVS driver interface provides device independent APIs, data types,
 *  and macros.  The following code example opens an NVS region instance,
 *  writes a string into it, then prints the string after reading it back
 *  into a local buffer, and also prints the string from its directly
 *  addressable location in flash memory.
 *
 *  @code
 *    NVS_Handle rHandle;
 *    NVS_Attrs regionAttrs;
 *    NVS_Params nvsParams;
 *    uint_fast16_t status;
 *    char buf[32];
 *
 *    // Initialize the NVS driver
 *    NVS_init();
 *
 *    //
 *    // Open the NVS region specified by the 0th element in the NVS_config[] array
 *    // in Board.c
 *    //
 *    rHandle = NVS_open(0, NULL); // use default NVS_Params to open this flash region
 *
 *    // confirm that the NVS region opened properly
 *    if (rHandle == NULL) {
 *        ...
 *    }
 *
 *    // fetch the generic NVS region attributes
 *    NVS_getAttrs(rHandle, &regionAttrs);
 *
 *    // erase the first sector of the NVS region
 *    status = NVS_erase(rHandle, 0, regionAttrs.sectorSize);
 *    if (status != NVS_STATUS_SUCCESS) {
 *        ...
 *    }
 *
 *    // write "Hello" to the base address of region 0, verify after write
 *    status = NVS_write(rHandle, 0, "Hello", strlen("Hello")+1, NVS_POST_VERIFY);
 *    if (status != NVS_STATUS_SUCCESS) {
 *        ...
 *    }
 *
 *    // copy "Hello" from region0 into local 'buf'
 *    status = NVS_read(rHandle, 0, buf, strlen("Hello")+1);
 *    if (status != NVS_STATUS_SUCCESS) {
 *        ...
 *    }
 *
 *    // print string from fetched NVS storage
 *    System_printf("%s\n", buf);
 *
 *    // print string using direct address reference if valid
 *    if (regionAttrs.regionBase != NVS_REGION_NOT_ADDRESSABLE) {
 *       System_printf("%s\n", regionAttrs.regionBase);
 *    }
 *
 *    // close the region
 *    NVS_close(rHandle);
 *
 *  @endcode
 *
 *  Details for the example code above are described in the following
 *  subsections.
 *
 *  ### NVS Driver Configuration #
 *
 *  In order to use the NVS APIs, the application is required
 *  to provide device-specific NVS configuration in the Board.c file.
 *  The NVS driver interface defines a configuration data structure:
 *
 *  @code
 *  typedef struct NVS_Config_ {
 *      NVS_FxnTable const    *fxnTablePtr;
 *      void                  *object;
 *      void                  *hwAttrs;
 *  } NVS_Config;
 *  @endcode
 *
 *  The application must declare an array of NVS_Config elements, named
 *  NVS_config[].  Each element of NVS_config[] is populated with
 *  pointers to a device specific NVS driver implementation's function
 *  table, driver object, and hardware attributes.  The hardware attributes
 *  define properties such as the NVS region's base address and size,
 *  Each element in NVS_config[] corresponds to a NVS instance, and none
 *  of the elements should have NULL pointers.
 *
 *  You will need to check the device-specific NVS driver implementation's
 *  header file for example configuration.  Please also refer to the
 *  Board.c file of any of the provided examples to see the NVS configuration.
 *
 *  ### Initializing the NVS Driver #
 *
 *  NVS_init() must be called before any other NVS APIs.  This function
 *  calls the device implementation's NVS initialization function, for each
 *  element of NVS_config[].
 *
 *  ### Opening the NVS Driver #
 *
 *  Opening a NVS requires four steps:
 *  1.  Optionally create and initialize a NVS_Params structure.
 *  2.  Fill in the desired parameters.
 *  3.  Call NVS_open(), passing the index of the NVS region in the NVS_config
 *      structure, and the address of the NVS_Params structure.
 *  4.  Check that the NVS handle returned by NVS_open() is non-NULL,
 *      and save it.  The handle will be used to read and write to the
 *      NVS you just opened.
 *
 *  Only one NVS index can be used at a time; calling NVS_open() a second
 *  time with the same index previously passed to NVS_open() will result in
 *  an error.  You can, though, re-use the index if the instance is closed
 *  via NVS_close().
 *
 *****************************************************************************
 */

#ifndef ti_drivers_NVS__include
#define ti_drivers_NVS__include

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#if defined (__cplusplus)
extern "C" {
#endif

/**
 *  @defgroup NVS_CONTROL NVS_control command and status codes
 *  These NVS macros are reservations for NVS.h
 *  @{
 */

/*!
 *  Common NVS_control command code reservation offset.
 *  NVS driver implementations should offset command codes with NVS_CMD_RESERVED
 *  growing positively
 *
 *  Example implementation specific command codes:
 *  @code
 *  #define NVSXYZ_CMD_COMMAND0     NVS_CMD_RESERVED + 0
 *  #define NVSXYZ_CMD_COMMAND1     NVS_CMD_RESERVED + 1
 *  @endcode
 */
#define NVS_CMD_RESERVED            (32)

/*!
 *  Common NVS_control status code reservation offset.
 *  NVS driver implementations should offset status codes with
 *  NVS_STATUS_RESERVED growing negatively.
 *
 *  Example implementation specific status codes:
 *  @code
 *  #define NVSXYZ_STATUS_ERROR0    NVS_STATUS_RESERVED - 0
 *  #define NVSXYZ_STATUS_ERROR1    NVS_STATUS_RESERVED - 1
 *  #define NVSXYZ_STATUS_ERROR2    NVS_STATUS_RESERVED - 2
 *  @endcode
 */
#define NVS_STATUS_RESERVED         (-32)

/**
 *  @defgroup NVS_STATUS Status Codes
 *  NVS_STATUS_* macros are general status codes returned by NVS_control()
 *  @{
 *  @ingroup NVS_CONTROL
 */

/*!
 *  @brief   Successful status code returned by:
 *  NVS_control(), NVS_read(), NVS_write(), NVS_erase(),
 *  NVS_lock().
 *
 *  APIs returns NVS_STATUS_SUCCESS if the API was executed
 *  successfully.
 */
#define NVS_STATUS_SUCCESS          (0)

/*!
 *  @brief   Generic error status code returned by:
 *  NVS_control(), NVS_erase(), NVS_write(),
 *
 *  APIs return NVS_STATUS_ERROR if the API was not executed
 *  successfully.
 */
#define NVS_STATUS_ERROR            (-1)

/*!
 *  @brief   An error status code returned by NVS_control() for undefined
 *  command codes.
 *
 *  NVS_control() returns NVS_STATUS_UNDEFINEDCMD if the control code is not
 *  recognized by the driver implementation.
 */
#define NVS_STATUS_UNDEFINEDCMD     (-2)

/*!
 *  @brief An error status code returned by NVS_lock()
 *
 *  NVS_lock() will return this value if the 'timeout' has expired
 */
#define NVS_STATUS_TIMEOUT          (-3)

/*!
 *  @brief An error status code returned by NVS_read()/NVS_write()/NVS_erase()

 *  Error status code returned if the 'offset' argument is invalid
 *  (e.g., when offset + bufferSize exceeds the size of the region).
 */
#define NVS_STATUS_INV_OFFSET       (-4)

/*!
 *  @brief An error status code
 *
 *  Error status code returned by NVS_erase() if the 'offset' argument is
 *  not aligned on a flash sector address.
 */
#define NVS_STATUS_INV_ALIGNMENT    (-5)

/*!
 *  @brief An error status code returned by NVS_erase() and NVS_write()
 *
 *  Error status code returned by NVS_erase() if the 'size' argument is
 *  not a multiple of the flash sector size, or if 'offset' + 'size'
 *  extends past the end of the region.
 */
#define NVS_STATUS_INV_SIZE         (-6)

/*!
 *  @brief An error status code returned by NVS_write()
 *
 *  NVS_write() will return this value if 'NVS_PRE_VERIFY' is
 *  requested and a flash location can not be changed to the value
 *  desired.
 */
#define NVS_STATUS_INV_WRITE        (-7)

/** @}*/

/**
 *  @defgroup NVS_CMD Command Codes
 *  NVS_CMD_* macros are general command codes for NVS_control(). Not all NVS
 *  driver implementations support these command codes.
 *  @{
 *  @ingroup NVS_CONTROL
 */

/* Add NVS_CMD_<commands> here */

/** @} end NVS commands */

/** @} end NVS_CONTROL group */


/*!
 *  @brief NVS write flags
 *
 *  The following flags can be or'd together and passed as a bit mask
 *  to NVS_write.
 *  @{
 */

/*!
 *  @brief Erase write flag.
 *
 *  If NVS_WRITE_ERASE is set in the flags passed to NVS_write(), the
 *  affected destination flash sectors will be erased prior to the
 *  start of the write operation.
 */
#define NVS_WRITE_ERASE             (0x1)

/*!
 *  @brief Validate write flag.
 *
 *  If NVS_WRITE_PRE_VERIFY is set in the flags passed to NVS_write(), the
 *  destination address range will be pre-tested to guarantee that the source
 *  data can be successfully written. If NVS_WRITE_ERASE is also requested in
 *  the write flags, then the NVS_WRITE_PRE_VERIFY modifier is ignored.
 */
#define NVS_WRITE_PRE_VERIFY        (0x2)

/*!
 *  @brief Validate write flag.
 *
 *  If NVS_WRITE_POST_VERIFY is set in the flags passed to NVS_write(), the
 *  destination address range will be tested after the write is finished to
 *  verify that the write operation was completed successfully.
 */
#define NVS_WRITE_POST_VERIFY       (0x4)

/** @} */

/*!
 *  @brief Special NVS_lock() timeout values
 *  @{
 */

 /*!
 *  @brief    NVS_lock() Wait forever define
 */
#define NVS_LOCK_WAIT_FOREVER       (~(0U))

/*!
 *  @brief    NVS_lock() No wait define
 */
#define NVS_LOCK_NO_WAIT            (0U)

/** @} */

/*!
 *  @brief Special NVS_Attrs.regionBase value
 *  @{
 */

 /*!
 *  @brief    This region is not directly addressable (e.g.,: SPI flash region)
 *
 *  The NVS_Attrs.regionBase field returned by NVS_getAttrs() is set to this
 *  value by the NVSSPI driver to indicate that the region is not directly
 *  addressable.
 */
#define NVS_REGION_NOT_ADDRESSABLE  ((void *)(~(0U)))

/** @} */

/*!
 *  @brief    NVS Parameters
 *
 *  NVS parameters are used with the NVS_open() call. Default values for
 *  these parameters are set using NVS_Params_init().
 *
 *  @sa       NVS_Params_init()
 */
typedef struct NVS_Params {
    void *custom;    /*!< Custom argument used by driver implementation */
} NVS_Params;

/*!
 *  @brief      NVS attributes
 *
 *  The address of an NVS_Attrs structure is passed to NVS_getAttrs().
 *
 *  'regionBase' is the base address of the region if directly accessible by
 *  the MCU. If the flash region is within external flash (e.g., SPI flash),
 *  this field will be set to NVS_REGION_NOT_ADDRESSABLE.
 *
 *  'regionSize' is the size, in bytes, of the NVS region that the
 *  application chooses to manage.
 *
 *  'sectorSize' is the size of the sector erase page. This attribute is
 *  device specific.
 *
 *  @sa     NVS_getAttrs()
 */
typedef struct NVS_Attrs {
    void   *regionBase;    /*! Base address of flash region to manage */
    size_t  regionSize;    /*! Region size (in bytes) */
    size_t  sectorSize;    /*! Erase sector size (in bytes) */
} NVS_Attrs;

/*!
 *  @brief      A handle that is returned from the NVS_open() call.
 */
typedef struct NVS_Config_ *NVS_Handle;

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_close().
 */
typedef void (*NVS_CloseFxn) (NVS_Handle handle);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_control().
 */
typedef int_fast16_t (*NVS_ControlFxn) (NVS_Handle handle, uint_fast16_t cmd,
                                        uintptr_t arg);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_erase().
 */
typedef int_fast16_t (*NVS_EraseFxn) (NVS_Handle handle, size_t offset,
                                      size_t size);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_getAttrs().
 */
typedef void (*NVS_GetAttrsFxn) (NVS_Handle handle, NVS_Attrs *attrs);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_init().
 */
typedef void (*NVS_InitFxn) (void);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_open().
 */
typedef NVS_Handle (*NVS_OpenFxn) (uint_least8_t index, NVS_Params *params);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_read().
 */
typedef int_fast16_t (*NVS_ReadFxn) (NVS_Handle handle, size_t offset,
                                     void *buffer, size_t bufferSize);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_write().
 */
typedef int_fast16_t (*NVS_WriteFxn) (NVS_Handle handle, size_t offset,
                                      void *buffer, size_t bufferSize,
                                      uint_fast16_t flags);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_lock().
 */
typedef int_fast16_t (*NVS_LockFxn) (NVS_Handle handle, uint32_t timeout);

/*!
 *  @brief      A function pointer to a driver specific implementation of
 *              NVS_unlock().
 */
typedef void (*NVS_UnlockFxn) (NVS_Handle handle);

/*!
 *  @brief      The definition of an NVS function table that contains the
 *              required set of functions to control a specific NVS driver
 *              implementation.
 */
typedef struct NVS_FxnTable {
    /*! Function to close the specified NVS region */
    NVS_CloseFxn        closeFxn;

    /*! Function to apply control command to the specified NVS region */
    NVS_ControlFxn      controlFxn;

    /*! Function to erase a portion of the specified NVS region */
    NVS_EraseFxn        eraseFxn;

    /*! Function to get the NVS device-specific attributes */
    NVS_GetAttrsFxn     getAttrsFxn;

    /*! Function to initialize the NVS module */
    NVS_InitFxn         initFxn;

    /*! Function to lock the specified NVS flash region */
    NVS_LockFxn         lockFxn;

    /*! Function to open an NVS region */
    NVS_OpenFxn         openFxn;

    /*! Function to read from the specified NVS region */
    NVS_ReadFxn         readFxn;

    /*! Function to unlock the specified NVS flash region */
    NVS_UnlockFxn       unlockFxn;

    /*! Function to write to the specified NVS region */
    NVS_WriteFxn        writeFxn;
} NVS_FxnTable;

/*!
 *  @brief  NVS Global configuration
 *
 *  The NVS_Config structure contains a set of pointers used to characterize
 *  the NVS driver implementation.
 *
 *  This structure needs to be defined before calling NVS_init() and it must
 *  not be changed thereafter.
 *
 *  @sa     NVS_init()
 */
typedef struct NVS_Config_ {
    /*! Pointer to a table of driver-specific implementations of NVS APIs */
    NVS_FxnTable  const *fxnTablePtr;

    /*! Pointer to a driver specific data object */
    void                *object;

    /*! Pointer to a driver specific hardware attributes structure */
    void          const *hwAttrs;
} NVS_Config;

/*!
 *  @brief  Function to close an NVS handle
 *
 *  @param  handle      A handle returned from NVS_open()
 *
 *  @sa     NVS_open()
 */
extern void NVS_close(NVS_Handle handle);

/*!
 *  @brief  Function performs implementation specific features on a given
 *          NVS_Handle.
 *
 *  @pre    NVS_open() must be called first.
 *
 *  @param  handle      An NVS handle returned from NVS_open()
 *
 *  @param  cmd         A command value defined by the driver specific
 *                      implementation
 *
 *  @param  arg         An optional R/W (read/write) argument that is
 *                      accompanied with cmd
 *
 *  @return Implementation specific return codes. Negative values indicate
 *          unsuccessful operations.
 *
 *  @sa     NVS_open()
 */
extern int_fast16_t NVS_control(NVS_Handle handle, uint_fast16_t cmd, uintptr_t arg);

/*!
 *  @brief  Erase 'size' bytes of the region beginning at 'offset' bytes
 *  from the base of the region referenced by NVS handle
 *
 *  @warning Erasing internal flash on most devices can introduce
 *  significant interrupt latencies while the erase operation is in
 *  in progress. The user may want to surround certain real-time
 *  critical code sections with NVS_lock()/NVS_unlock() calls in order
 *  to prevent uncoordinated flash erase operations from negatively
 *  impacting performance.
 *
 *  @param   handle     A handle returned from NVS_open()
 *
 *  @param   offset     The byte offset into the NVS region to start
 *                      erasing from (must be erase sector aligned)
 *
 *  @param   size       The number of bytes to erase (must be integer
 *                      multiple of sector size)
 *
 *  @return  NVS_STATUS_SUCCESS         Success.
 *  @return  NVS_STATUS_INV_ALIGNMENT   If 'offset' is not aligned on
 *                                      a sector boundary
 *  @return  NVS_STATUS_INV_OFFSET      If 'offset' exceeds region size
 *  @return  NVS_STATUS_INV_SIZE        If 'size' or 'offset + size'
 *                                      exceeds region size, or if 'size'
 *                                      is not an integer multiple of
 *                                      the flash sector size.
 *  @return  NVS_STATUS_ERROR           If an internal error occurred
 *                                      erasing the flash.
 */
extern int_fast16_t NVS_erase(NVS_Handle handle, size_t offset, size_t size);

/*!
 *  @brief  Function to get the NVS attributes
 *
 *  @param  handle      A handle returned from NVS_open()
 *
 *  @param  attrs       Location to store attributes.
 */
extern void NVS_getAttrs(NVS_Handle handle, NVS_Attrs *attrs);

/*!
 *  @brief  Function to initialize the NVS module
 *
 *  @pre    The NVS_config structure must exist and be persistent before this
 *          function can be called. This function must also be called before
 *          any other NVS APIs.
 */
extern void NVS_init(void);

/*!
 *  @brief  Function to lock the NVS driver
 *
 *  This function is provided in the event that the user needs to
 *  perform some flash related operation not provided by the NVS
 *  driver API set or if the user simply needs to block flash operations
 *  for a period of time.
 *
 *  For example, the interrupt latency introduced
 *  by an uncoordinated flash write operation could interfere with some
 *  critical operation being performed by the application.
 *
 *  NVS_lock() prevents any other thread from initiating
 *  read, write, or erase operations while the user is performing an
 *  operation which is incompatible with those functions.
 *
 *  When the application no longer needs to block flash operations by
 *  other threads, NVS_unlock() must be called to allow NVS write or erase
 *  APIs to complete.
 *
 *  @param  handle      A handle returned from NVS_open()
 *
 *  @param  timeout     Timeout (in milliseconds) to wait,
 *                      or NVS_LOCK_WAIT_FOREVER, NVS_LOCK_NO_WAIT
 *
 *  @return  NVS_STATUS_SUCCESS         Success.
 *  @return  NVS_STATUS_TIMEOUT         If 'timeout' has expired.
 */
extern int_fast16_t NVS_lock(NVS_Handle handle, uint32_t timeout);

/*!
 *  @brief  Open an NVS region for reading and writing.
 *
 *  @pre    NVS_init() was called.
 *
 *  @param  index         Index in the NVS_config table of the region
 *                        to manage.
 *
 *  @param  params        Pointer to a parameter region.  If NULL, default
 *                        parameter values will be used.
 *
 *  @return  a non-zero handle      Success.
 *  @return  NULL                   Open failed.
 */
extern NVS_Handle NVS_open(uint_least8_t index, NVS_Params *params);

/*!
 *  @brief  Function to initialize the NVS_Params struct to its defaults
 *
 *  @param  params      An pointer to NVS_Params structure for
 *                      initialization
 *
 *  Defaults values are:
 *      eraseOnOpen = false;
 */
extern void NVS_Params_init(NVS_Params *params);

/*!
 *  @brief   Read data from an NVS region.
 *
 *  @param   handle     A handle returned from NVS_open()
 *
 *  @param   offset     The byte offset into the NVS region to start
 *                      reading from.
 *
 *  @param   buffer     A buffer to copy the data to.
 *
 *  @param   bufferSize The size of the buffer (number of bytes to read).
 *
 *  @return  NVS_STATUS_SUCCESS     Success.
 *  @return  NVS_STATUS_INV_OFFSET  If 'offset + size' exceed the size
 *                                  of the region.
 */
extern int_fast16_t NVS_read(NVS_Handle handle, size_t offset, void *buffer,
                    size_t bufferSize);

/*!
 *  @brief  Function to unlock the NVS driver
 *
 *  This function allows NVS write and erase operations to proceed after being
 *  temporarily inhibited by a call to NVS_lock().
 *
 *  @param  handle      A handle returned from NVS_open()
 */
extern void NVS_unlock(NVS_Handle handle);

/*!
 *  @brief   Write data to an NVS region.
 *
 *  @warning Writing to internal flash on most devices can introduce
 *  significant interrupt latencies while the write operation is in
 *  in progress. The user may want to surround certain real-time
 *  critical code sections with NVS_lock()/NVS_unlock() calls in order
 *  to prevent uncoordinated flash write operations from negatively
 *  impacting performance.
 *
 *  @param   handle     A handle returned from NVS_open()
 *
 *  @param   offset     The byte offset into the NVS region to start
 *                      writing.
 *
 *  @param   buffer     A buffer containing data to write to
 *                      the NVS region.
 *
 *  @param   bufferSize The size of the buffer (number of bytes to write).
 *
 *  @param   flags      Write flags (NVS_WRITE_ERASE, NVS_WRITE_PRE_VERIFY,
 *                      NVS_WRITE_POST_VERIFY).
 *
 *  @return  NVS_STATUS_SUCCESS         Success.
 *  @return  NVS_STATUS_ERROR           If the internal flash write operation
 *                                      failed, or if 'NVS_WRITE_POST_VERIFY'
 *                                      was requested and the destination flash
 *                                      range does not match the source
 *                                      'buffer' data.
 *  @return  NVS_STATUS_INV_OFFSET      If 'offset + size' exceed the size
 *                                      of the region.
 *  @return  NVS_STATUS_INV_WRITE       If 'NVS_WRITE_PRE_VERIFY' is requested
 *                                      and the destination flash address range
 *                                      cannot be change to the values desired.
 *  @return  NVS_STATUS_INV_ALIGNMENT   If 'NVS_WRITE_ERASE' is requested
 *                                      and 'offset' is not aligned on
 *                                      a sector bondary
 *
 *  @remark  This call may region to ensure atomic access to the region.
 */
extern int_fast16_t NVS_write(NVS_Handle handle, size_t offset, void *buffer,
                     size_t bufferSize, uint_fast16_t flags);

#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */

/*@}*/
#endif /* ti_drivers_NVS__include */
