/*******************************************************************************
* \file cy_em_eeprom.h
* \version 2.0
*
* \brief
*  This file provides the function prototypes and constants for the Emulated
*  EEPROM middleware library.
*
********************************************************************************
* Copyright 2017, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/

/**
 * \mainpage Cypress Em_EEPROM Middleware Library
 *
 * The Emulated EEPROM provides an API that allows creating an emulated
 * EEPROM in flash that has the ability to do wear leveling and restore
 * corrupted data from a redundant copy. The Emulated EEPROM library is designed
 * to be used with the Em_EEPROM component.
 *
 * The Cy_Em_EEPROM API is described in the following sections:
 * - \ref group_em_eeprom_macros
 * - \ref group_em_eeprom_data_structures
 * - \ref group_em_eeprom_enums
 * - \ref group_em_eeprom_functions
 *
 * <b>Features:</b>
 * * EEPROM-Like Non-Volatile Storage
 * * Easy to use Read and Write API
 * * Optional Wear Leveling
 * * Optional Redundant Data storage
 *
 * \section group_em_eeprom_configuration Configuration Considerations
 *
 * The Em_EEPROM operates on the top of the flash driver. The flash driver has
 * some prerequisites for proper operation. Refer to the "Flash System 
 * Routine (Flash)" section of the PDL API Reference Manual.
 *
 * <b>Initializing Emulated EEPROM in User flash</b>
 *
 * To initialize an Emulated EEPROM in the User flash, the EEPROM storage should
 * be declared by the user. For the proper operation, the EEPROM storage should
 * be aligned to the size of the flash row. An example of the EEPROM storage
 * declaration is below (applicable for GCC and MDK compilers):
 *
 *      CY_ALIGN(CY_EM_EEPROM_FLASH_SIZEOF_ROW)
 *      const uint8 emEeprom[Em_EEPROM_PHYSICAL_SIZE] = {0u};
 *
 * The same declaration for the IAR compiler:
 *
 *      #pragma data_alignment = CY_EM_EEPROM_FLASH_SIZEOF_ROW
 *      const uint8 emEeprom[Em_EEPROM_PHYSICAL_SIZE] = {0u};
 * 
 * Note that the name "emEeprom" is shown for reference. Any other name can be
 * used instead. Also, note that the Em_EEPROM_PHYSICAL_SIZE constant is 
 * generated by the PSoC Creator Em_EEPROM component and so it is instance name
 * dependent and its prefix should be changed when the name of the component 
 * changes. If the The Cy_Em_EEPROM middleware library is used without the 
 * Em_EEPROM component, the user has to provide a proper size for the EEPROM 
 * storage instead of Em_EEPROM_PHYSICAL_SIZE. The size of the EEPROM storage 
 * can be calculated using the following equation:
 * 
 *  Physical size = EEPROM data size * 2 * wear leveling * (1 + redundant copy)
 *
 * where, 
 *   "EEPROM data size" - the size of data the user wants to store in the 
 *   EEPROM. The data size must divide evenly to the half of the flash row size.
 *   "wear leveling" - the wear leveling factor (1-10).
 *   "redundant copy" - "zero" if a redundant copy is not used, and "one" 
 *   otherwise.
 *
 * The start address of the storage should be filled to the Emulated EEPROM 
 * configuration structure and then passed to the Cy_Em_EEPROM_Init().
 * If the Em_EEPROM component is used, the config (Em_EEPROM_config) and 
 * context structures (Em_EEPROM_context) are defined by the component, so the
 * user may just use that structures otherwise both of the structures need to 
 * be provided by the user. Note that if the "Config Data in Flash"
 * option is selected in the component, then the configuration structure should
 * be copied to RAM to allow EEPROM storage start address update. The following 
 * code demonstrates utilization of "Em_EEPROM_config" and "Em_EEPROM_context"
 * Em_EEPROM component structures for Cy_Em_EEPROM middleware library 
 * initialization:
 *
 *      cy_en_em_eeprom_status_t retValue;
 *      cy_stc_eeprom_config_t config;
 *
 *      memcpy((void *)&config, 
               (void *)&Em_EEPROM_config, 
               sizeof(cy_stc_eeprom_config_t));
 *      config.userFlashStartAddr = (uint32)emEeprom;
 *      retValue = Cy_Em_EEPROM_Init(&config, &Em_EEPROM_context);
 *
 * <b>Initializing EEPROM in Emulated EEPROM flash area</b>
 * 
 * Initializing of the EEPROM storage in the Emulated EEPROM flash area is 
 * identical to initializing of the EEPROM storage in the User flash with one 
 * difference. The location of the Emulated EEPROM storage should be specified 
 * somewhere in the EmulatedEEPROM flash area. If the Em_EEPROM component is 
 * utilized in the project, then the respective storage 
 * (Em_EEPROM_em_EepromStorage[]) is automatically declared by the component 
 * if the "Use Emulated EEPROM" option is set to "Yes". The user just needs to 
 * fill the start address of the storage to the config structure. If the
 * Em_EEPROM component is not used, the user needs to declare the storage
 * in the Emulated EEPROM flash area. An example of such declaration is 
 * following (applicable for GCC and MDK compilers):
 *
 *      CY_SECTION(".cy_em_eeprom") CY_ALIGN(CY_EM_EEPROM_FLASH_SIZEOF_ROW)
 *      const uint8_t emEeprom[Em_EEPROM_PHYSICAL_SIZE] = {0u};
 *
 * The same declaration for the IAR compiler:
 *
 *      #pragma location = ".cy_em_eeprom"
 *      #pragma data_alignment = CY_EM_EEPROM_FLASH_SIZEOF_ROW
 *      const uint8 emEeprom[Em_EEPROM_PHYSICAL_SIZE] = {0u};
 *
 * where,
 *   Em_EEPROM_PHYSICAL_SIZE - is a constant that is generated by the Em_EEPROM
 *   component when the component is utilized in the project or it should be 
 *   provided by the user. The equation for the calculation of the constant is 
 *   shown above.
 *
 * Note that the size of the Emulated EEPROM flash area is limited. Refer to the
 * specific device datasheet for the value of the available EEPROM Emulation 
 * area.
 *
 * \section group_em_eeprom_more_information More Information
 * See the Em_EEPROM Component datasheet.
 *
 *
 * \section group_em_eeprom_MISRA MISRA-C Compliance
 *
 * The Cy_Em_EEPROM library has the following specific deviations:
 *
 * <table class="doxtable">
 *   <tr>
 *     <th>MISRA Rule</th>
 *     <th>Rule Class (Required/Advisory)</th>
 *     <th>Rule Description</th>
 *     <th>Description of Deviation(s)</th>
 *   </tr>
 *   <tr>
 *     <td>11.4</td>
 *     <td>A</td>
 *     <td>The cast should not be performed between a pointer to the object type
 *         and a different pointer to the object type.</td>
 *     <td>The cast from the object type and a different pointer to the object 
 *         was used intentionally because of the performance reasons.</td>
 *   </tr>
 *   <tr>
 *     <td>14.2</td>
 *     <td>R</td>
 *     <td>All non-null statements shall either have at least one side-effect,
 *         however executed, or cause control flow to change.</td>
 *     <td>To maintain common codebase, some variables, unused for a specific 
 *         device, are casted to void to prevent generation of an unused variable
 *         compiler warning.</td>
 *   </tr>
 *   <tr>
 *     <td>16.7</td>
 *     <td>A</td>
 *     <td>The object addressed by the pointer parameter is not modified and so
 *          the pointer could be of type 'pointer to const'.</td>
 *     <td>The warning is generated because of the pointer dereferencing to
 *         address which makes the MISRA checker think the data is not
 *         modified.</td>
 *   </tr>
 *   <tr>
 *     <td>17.4</td>
 *     <td>R</td>
 *     <td>The array indexing shall be the only allowed form of pointer 
 *         arithmetic.</td>
 *     <td>The pointer arithmetic used in several places on the Cy_Em_EEPROM
 *         implementation is safe and preferred because it increases the code
 *         flexibility.</td>
 *   </tr>
 *   <tr>
 *     <td>19.7</td>
 *     <td>A</td>
 *     <td>A function shall be used in preference to a function-like macro.</td>
 *     <td>Macro is used because of performance reasons.</td>
 *   </tr>
 * </table>
 *
 * \section group_em_eeprom_changelog Changelog
 * <table class="doxtable">
 *   <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
 *   <tr>
 *     <td>1.0</td>
 *     <td>Initial Version</td>
 *     <td></td>
 *   </tr>
 * </table>
 *
 * \defgroup group_em_eeprom_macros Macros
 * \brief
 * This section describes the Emulated EEPROM Macros.
 *
 * \defgroup group_em_eeprom_functions Functions
 * \brief
 * This section describes the Emulated EEPROM Function Prototypes.
 *
 * \defgroup group_em_eeprom_data_structures Data Structures
 * \brief
 * Describes the data structures defined by the Emulated EEPROM.
 *
 * \defgroup group_em_eeprom_enums Enumerated types
 * \brief
 * Describes the enumeration types defined by the Emulated EEPROM.
 *
 */


#if !defined(CY_EM_EEPROM_H)
#define CY_EM_EEPROM_H

#include "cytypes.h"
#include <stddef.h>
#if (CYDEV_CHIP_FAMILY_USED == CYDEV_CHIP_FAMILY_PSOC6)
    #include <cy_device_headers.h>
    #include "syslib/cy_syslib.h"
    #include "flash/cy_flash.h"
#else
    #include "CyFlash.h"
    #include <cyfitter.h>
#endif /* (CYDEV_CHIP_FAMILY_USED == CYDEV_CHIP_FAMILY_PSOC6) */

/* The C binding of definitions if building with the C++ compiler */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


/***************************************
* Conditional Compilation Parameters
***************************************/
#define CY_PSOC6                                    (CYDEV_CHIP_FAMILY_USED == CYDEV_CHIP_FAMILY_PSOC6)


/***************************************
* Data Structure definitions
***************************************/
/**
* \addtogroup group_em_eeprom_data_structures
* \{
*/

/** EEPROM configuration structure */
typedef struct
{
    /** The number of bytes to store in EEPROM */
    uint32 eepromSize;

    /** The amount of wear leveling from 1 to 10. 1 means no wear leveling
    * is used.
    */
    uint32 wearLevelingFactor;

    /** If not zero, a redundant copy of the Em_EEPROM is included. */
    uint8 redundantCopy;

    /** If not zero, a blocking write to flash is used. Otherwise non-blocking
    * write is used. This parameter is used only for PSoC 6.
    */
    uint8 blockingWrite;

    /** The start address for the EEPROM memory in the user's flash. */
    uint32 userFlashStartAddr;
} cy_stc_eeprom_config_t;

/** \} group_em_eeprom_data_structures */

/** The EEPROM context data structure. It is used to store the specific
* EEPROM context data.
*/
typedef struct
{
    /** The pointer to the end address of EEPROM including wear leveling overhead
    * and excluding redundant copy overhead.
    */
    uint32 wlEndAddr;

    /** The number of flash rows allocated for the EEPROM excluding the number of
    * rows allocated for wear leveling and redundant copy overhead.
    */
    uint32 numberOfRows;

    /** The address of the last written EEPROM row */
    uint32 lastWrRowAddr;

    /** The number of bytes to store in EEPROM */
    uint32 eepromSize;

    /** The amount of wear leveling from 1 to 10. 1 means no wear leveling
    * is used.
    */
    uint32 wearLevelingFactor;

    /** If not zero, a redundant copy of the Em_EEPROM is included. */
    uint8 redundantCopy;

    /** If not zero, a blocking write to flash is used. Otherwise non-blocking
    * write is used. This parameter is used only for PSoC 6.
    */
    uint8 blockingWrite;

    /** The start address for the EEPROM memory in the user's flash. */
    uint32 userFlashStartAddr;
} cy_stc_eeprom_context_t;

#if (CY_PSOC6)

    #define CY_EM_EEPROM_ID                         (CY_PDL_DRV_ID(0x1BuL))  /**< Em_EEPROM PDL ID */
    /**
    * \addtogroup group_em_eeprom_enums
    * \{
    * Specifies return values meaning.
    */
    /** A prefix for EEPROM function error return-values */
    #define CY_EM_EEPROM_ID_ERROR                   (uint32_t)(CY_EM_EEPROM_ID | CY_PDL_STATUS_ERROR)

#else

    /** A prefix for EEPROM function status codes. For non-PSoC6 devices,
    * prefix is zero.
    */
    #define CY_EM_EEPROM_ID_ERROR                       (0uL)

#endif /* (CY_PSOC6) */


/***************************************
* Enumerated Types and Parameters
***************************************/

/** EEPROM return enumeration type */
typedef enum
{
    CY_EM_EEPROM_SUCCESS      = 0x00uL,                             /**< The function executed successfully */
    CY_EM_EEPROM_BAD_PARAM    = (CY_EM_EEPROM_ID_ERROR + 1uL),      /**< The input parameter is invalid */
    CY_EM_EEPROM_BAD_CHECKSUM = (CY_EM_EEPROM_ID_ERROR + 2uL),      /**< The data in EEPROM is corrupted */
    CY_EM_EEPROM_BAD_DATA     = (CY_EM_EEPROM_ID_ERROR + 3uL),      /**< Failed to place the EEPROM in flash */
    CY_EM_EEPROM_WRITE_FAIL   = (CY_EM_EEPROM_ID_ERROR + 4uL)       /**< Write to EEPROM failed */
} cy_en_em_eeprom_status_t;

/** \} group_em_eeprom_enums */


/***************************************
*        Function Prototypes
***************************************/

/**
* \addtogroup group_em_eeprom_functions
* \{
*/
cy_en_em_eeprom_status_t Cy_Em_EEPROM_Init(cy_stc_eeprom_config_t* config, cy_stc_eeprom_context_t * context);
cy_en_em_eeprom_status_t Cy_Em_EEPROM_Read(uint32 addr,
                                        void * eepromData,
                                        uint32 size,
                                        cy_stc_eeprom_context_t * context);
cy_en_em_eeprom_status_t Cy_Em_EEPROM_Write(uint32 addr,
                                            void * eepromData,
                                            uint32 size,
                                            cy_stc_eeprom_context_t * context);
cy_en_em_eeprom_status_t Cy_Em_EEPROM_Erase(cy_stc_eeprom_context_t * context);
uint32 Cy_Em_EEPROM_NumWrites(cy_stc_eeprom_context_t * context);
/** \} group_em_eeprom_functions */


/***************************************
* API Constants
***************************************/
/**
* \addtogroup group_em_eeprom_macros
* \{
*/
/** Library major version */
#define CY_EM_EEPROM_VERSION_MAJOR                  (2)

/** Library minor version */
#define CY_EM_EEPROM_VERSION_MINOR                  (0)

/** Defines the maximum data length that can be stored in one flash row */
#define CY_EM_EEPROM_EEPROM_DATA_LEN                (CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u)

/** \} group_em_eeprom_macros */


/***************************************
* Macro definitions
***************************************/
/** \cond INTERNAL */

/* Defines the size of flash row */
#define CY_EM_EEPROM_FLASH_SIZEOF_ROW               (CY_FLASH_SIZEOF_ROW)

/* Device specific flash constants */
#if (!CY_PSOC6)
    #define CY_EM_EEPROM_FLASH_BASE_ADDR                (CYDEV_FLASH_BASE)
    #define CY_EM_EEPROM_FLASH_SIZE                     (CYDEV_FLASH_SIZE)
    #define CY_EM_EEPROM_ROWS_IN_ARRAY                  (CY_FLASH_SIZEOF_ARRAY / CY_EM_EEPROM_FLASH_SIZEOF_ROW)
    #if (CY_PSOC3)
        #define CY_EM_EEPROM_CODE_MEM_CLASS_PREFIX          (0xff0000uL)
        #define CY_EM_EEPROM_CODE_ADDR_END                  \
                        (CY_EM_EEPROM_CODE_MEM_CLASS_PREFIX + (CY_EM_EEPROM_FLASH_SIZE - 1u))
        #define CY_EM_EEPROM_CODE_ADDR_MASK                 (0xffffu)
        /* Checks if the EEPROM is in flash range */
        #define CY_EM_EEPROM_IS_IN_FLASH_RANGE(startAddr, endAddr) \
                        (((startAddr) > CY_EM_EEPROM_CODE_MEM_CLASS_PREFIX) && \
                         ((endAddr) <= CY_EM_EEPROM_CODE_ADDR_END))
    #else
        /* Checks is the EEPROM is in flash range */
        #define CY_EM_EEPROM_IS_IN_FLASH_RANGE(startAddr, endAddr) \
                        (((startAddr) > CY_EM_EEPROM_FLASH_BASE_ADDR) && ((endAddr) <= CY_EM_EEPROM_FLASH_END_ADDR))
    #endif /* (CY_PSOC3) */
#else
    #define CY_EM_EEPROM_FLASH_BASE_ADDR                (CY_FLASH_BASE)
    #define CY_EM_EEPROM_FLASH_SIZE                     (CY_FLASH_SIZE)
    #define CY_EM_EEPROM_EM_EEPROM_BASE_ADDR            (CY_EM_EEPROM_BASE)
    #define CY_EM_EEPROM_EM_EEPROM_SIZE                 (CY_EM_EEPROM_SIZE)
    #define CY_EM_EEPROM_EM_EEPROM_END_ADDR             (CY_EM_EEPROM_EM_EEPROM_BASE_ADDR + CY_EM_EEPROM_EM_EEPROM_SIZE)
    /* Checks is the EEPROM is in flash range */
    #define CY_EM_EEPROM_IS_IN_FLASH_RANGE(startAddr, endAddr) \
                    (((((startAddr) > CY_EM_EEPROM_FLASH_BASE_ADDR) && ((endAddr) <= CY_EM_EEPROM_FLASH_END_ADDR)) || \
                      (((startAddr) >= CY_EM_EEPROM_EM_EEPROM_BASE_ADDR) && \
                                                                    ((endAddr) <= CY_EM_EEPROM_EM_EEPROM_END_ADDR))))
#endif /* (!CY_PSOC6) */

#define CY_EM_EEPROM_FLASH_END_ADDR                 (CY_EM_EEPROM_FLASH_BASE_ADDR + CY_EM_EEPROM_FLASH_SIZE)

/* Defines the length of EEPROM data that can be stored in Em_EEPROM header */
#define CY_EM_EEPROM_HEADER_DATA_LEN                ((CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u) - 16u)

#define CY_EM_EEPROM_ADDR_IN_RANGE                  (1u)

/* Return CY_EM_EEPROM_ADDR_IN_RANGE if addr exceeded the upper range of
* EEPROM. The wear leveling overhead is included in the range but redundant copy
* is excluded.
*/
#define CY_EM_EEPROM_IS_ADDR_EXCEED_RANGE(addr, endEepromAddr) \
                                    (((addr) >= (endEepromAddr)) ? (0u) : (CY_EM_EEPROM_ADDR_IN_RANGE))

/* Check to see if the specified address is present in the EEPROM */
#define CY_EM_EEPROM_IS_ADDR_IN_RANGE(addr, startEepromAddr, endEepromAddr) \
                                    (((addr) > (startEepromAddr)) ? \
                                    (((addr) < (endEepromAddr)) ? (CY_EM_EEPROM_ADDR_IN_RANGE) : (0u)) : (0u))

/* Check if the EEPROM address locations from startAddr1 to endAddr1
* are crossed with EEPROM address locations from startAddr2 to endAddr2.
*/
#define CY_EM_EEPROM_IS_ADDRESES_CROSSING(startAddr1, endAddr1 , startAddr2, endAddr2) \
                                    (((startAddr1) > (startAddr2)) ? (((startAddr1) >= (endAddr2)) ? (0u) : (1u) ) : \
                                    (((startAddr2) >= (endAddr1)) ? (0u) : (1u)))

/* Return the pointer to the start of the redundant copy of the EEPROM */
#define CY_EM_EEPROM_GET_REDNT_COPY_ADDR_BASE(numRows, wearLeveling, eepromStartAddr) \
                                    ((((numRows) * CY_EM_EEPROM_FLASH_SIZEOF_ROW) * (wearLeveling)) + (eepromStartAddr))

/* Return the number of the row in EM_EEPROM which contains an address defined by
* rowAddr.
 */
#define CY_EM_EEPROM_GET_ACT_ROW_NUM_FROM_ADDR(rowAddr, maxRows, eepromStartAddr) \
                                    ((((rowAddr) - (eepromStartAddr)) / CY_EM_EEPROM_FLASH_SIZEOF_ROW) % (maxRows))


/** Returns the size allocated for the EEPROM excluding wear leveling and
* redundant copy overhead.
*/
#define CY_EM_EEPROM_GET_EEPROM_SIZE(numRows)       ((numRows) * CY_EM_EEPROM_FLASH_SIZEOF_ROW)

/* Check if the given address belongs to the EEPROM address of the row
* specified by rowNum.
*/
#define CY_EM_EEPROM_IS_ADDR_IN_ROW_RANGE(addr, rowNum) \
                                    (((addr) < ((rowNum) * (CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u))) ? (0u) : \
                                    (((addr) > ((((rowNum) + 1u) * (CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u)) - 1u)) ? \
                                    (0u) : (1u)))

/* CRC-8 constants */
#define CY_EM_EEPROM_CRC8_POLYNOM                   ((uint8)(0x31u))
#define CY_EM_EEPROM_CRC8_POLYNOM_LEN               (8u)
#define CY_EM_EEPROM_CRC8_SEED                      (0xFFu)
#define CY_EM_EEPROM_CRC8_XOR_VAL                   ((uint8) (0x80u))

#define CY_EM_EEPROM_CALCULATE_CRC8(crc)            \
                  ((CY_EM_EEPROM_CRC8_XOR_VAL == ((crc) & CY_EM_EEPROM_CRC8_XOR_VAL)) ? \
                  ((uint8)(((uint8)((uint8)((crc) << 1u))) ^ CY_EM_EEPROM_CRC8_POLYNOM)) : ((uint8)((crc) << 1u)))

#define CY_EM_EEPROM_GET_SEQ_NUM(addr)                (*(uint32*)(addr))

/** \endcond */

/**
* \addtogroup group_em_eeprom_macros
* \{
*/

/** Calculate the number of flash rows required to create an Em_EEPROM of
* dataSize.
*/
#define CY_EM_EEPROM_GET_NUM_ROWS_IN_EEPROM(dataSize) \
                                    (((dataSize) / (CY_EM_EEPROM_EEPROM_DATA_LEN)) + \
                                    ((((dataSize) % (CY_EM_EEPROM_EEPROM_DATA_LEN)) != 0u) ? 1U : 0U))

/** Returns the size of flash allocated for EEPROM including wear leveling and
* redundant copy overhead.
*/
#define CY_EM_EEPROM_GET_PHYSICAL_SIZE(dataSize, wearLeveling, redundantCopy) \
                                    (((CY_EM_EEPROM_GET_NUM_ROWS_IN_EEPROM(dataSize) * \
                                    CY_EM_EEPROM_FLASH_SIZEOF_ROW) * \
                                    (wearLeveling)) * (1uL + (redundantCopy)))

/** \} group_em_eeprom_macros */


/******************************************************************************
* Local definitions
*******************************************************************************/
/** \cond INTERNAL */

/* Offsets for 32-bit RAM buffer addressing */
#define CY_EM_EEPROM_EEPROM_DATA_OFFSET_U32         ((CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u) / 4u)
#define CY_EM_EEPROM_HEADER_SEQ_NUM_OFFSET_U32      (0u)
#define CY_EM_EEPROM_HEADER_ADDR_OFFSET_U32         (1u)
#define CY_EM_EEPROM_HEADER_LEN_OFFSET_U32          (2u)
#define CY_EM_EEPROM_HEADER_DATA_OFFSET_U32         (3u)
#define CY_EM_EEPROM_HEADER_CHECKSUM_OFFSET_U32     (CY_EM_EEPROM_EEPROM_DATA_OFFSET_U32 - 1u)

/* The same offsets as above used for direct memory addressing */
#define CY_EM_EEPROM_EEPROM_DATA_OFFSET             (CY_EM_EEPROM_FLASH_SIZEOF_ROW / 2u)
#define CY_EM_EEPROM_HEADER_ADDR_OFFSET             (4u)
#define CY_EM_EEPROM_HEADER_LEN_OFFSET              (8u)
#define CY_EM_EEPROM_HEADER_DATA_OFFSET             (12u)
#define CY_EM_EEPROM_HEADER_CHECKSUM_OFFSET         (CY_EM_EEPROM_EEPROM_DATA_OFFSET - 4u)

#define CY_EM_EEPROM_U32_DIV                        (4u)

/* Maximum wear leveling value */
#define CY_EM_EEPROM_MAX_WEAR_LEVELING_FACTOR       (10u)

/* Maximum allowed flash row write/erase operation duration */
#define CY_EM_EEPROM_MAX_WRITE_DURATION_MS          (50u)

/** \endcond */


#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CY_EM_EEPROM_H */


/* [] END OF FILE */
