/**
* @file         CDD_Sbc_fs26.c
* @version      1.0.0
*
* @brief        AUTOSAR Sbc_fs26 - module interface
* @details      API implementation for FS26 driver.
*
* @addtogroup   CDD_SBC_FS26_DRIVER
* @{
*/

/*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : 
*   Dependencies         : 
*
*   Autosar Version      : 4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : S32K3_RTD_1_0_0_D2209_ASR_REL_4_4_REV_0000_20220916
*
*   (c) Copyright 2020 - 2022 NXP Semiconductors
*   All Rights Reserved.
*
*   NXP Confidential. This software is owned or controlled by NXP and may only be
*   used strictly in accordance with the applicable license terms. By expressly
*   accepting such terms or by downloading, installing, activating and/or otherwise
*   using the software, you are agreeing that you have read, and that you agree to
*   comply with and are bound by, such license terms. If you do not agree to be
*   bound by the applicable license terms, then you may not retain, install,
*   activate or otherwise use the software.
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/**
* @page misra_violations MISRA-C:2012 violations
*
* @section [global]
* Violates MISRA 2012 Required Rule 1.3, Taking address of near auto variable
* The code is not dynamically linked. An absolute stack address is obtained when
* taking the address of the near auto variable. A source of error in writing
* dynamic code is that the stack segment may be different from the data segment.
*
* @section [global]
* Violates MISRA 2012 Advisory Rule 8.7, External could be made static.
* The function is defined for use by application code.
*
* @section [global]
* Violates MISRA 2012 Required Rule 8.10, external ... could be made static
* The respective code could not be made static because of layers architecture design of the driver.
*
* @section [global]
* Violates MISRA 2012 Required Rule 1.4, The compiler/linker shall be checked to ensure that 31 character
* signifiance and case sensitivity are supported for external identifiers.
* The used compilers use more than 31 chars for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.1, Identifiers (internal and external) shall not rely
* on the significance of more than 31 characters. The used compilers use more than 31 chars for
* identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.1, identifier clash
* The supported compilers use more than 31 significant characters for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.2, identifier clash
* The supported compilers use more than 31 significant characters for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.4, identifier clash
* The supported compilers use more than 31 significant characters for identifiers.
*
* @section [global]
* Violates MISRA 2012 Required Rule 5.5, identifier clash
* The supported compilers use more than 31 significant characters for identifiers.
*
*/

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "CDD_Sbc_fs26.h"
#include "sbc_spi_external_access.h"
#include "SchM_Sbc_fs26.h"
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    #include "Det.h"
#endif /* (SBC_FS26_DEV_ERROR_DETECT == STD_ON) */
/*
#include "Mcal.h"
#include "Siul2_Dio_Ip.h"
#include "retarget.h"
#include "stdio.h"
*/

/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
/*
    Internal micro-dependent versioning. Check of AUTOSAR & Vendor specification version.
*/
#define SBC_FS26_VENDOR_ID_C                      43
#define SBC_FS26_MODULE_ID_C                      255
#define SBC_FS26_AR_RELEASE_MAJOR_VERSION_C       4
#define SBC_FS26_AR_RELEASE_MINOR_VERSION_C       4
#define SBC_FS26_AR_RELEASE_REVISION_VERSION_C    0
#define SBC_FS26_SW_MAJOR_VERSION_C               1
#define SBC_FS26_SW_MINOR_VERSION_C               0
#define SBC_FS26_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and CDD_Sbc_fs26 header file are of the same vendor */
#if (SBC_FS26_VENDOR_ID_C != SBC_FS26_VENDOR_ID)
    #error "CDD_Sbc_fs26.c and CDD_Sbc_fs26.h have different vendor ids"
#endif
/* Check if current file and CDD_Sbc_fs26 header file are of the same module */
#if (SBC_FS26_MODULE_ID_C != SBC_FS26_MODULE_ID)
    #error "CDD_Sbc_fs26.c and CDD_Sbc_fs26.h have different module ids"
#endif
/* Check if current file and CDD_Sbc_fs26 header file are of the same Autosar version */
#if ((SBC_FS26_AR_RELEASE_MAJOR_VERSION_C    != SBC_FS26_AR_RELEASE_MAJOR_VERSION) || \
     (SBC_FS26_AR_RELEASE_MINOR_VERSION_C    != SBC_FS26_AR_RELEASE_MINOR_VERSION) || \
     (SBC_FS26_AR_RELEASE_REVISION_VERSION_C != SBC_FS26_AR_RELEASE_REVISION_VERSION))
    #error "AutoSar Version Numbers of CDD_Sbc_fs26.c and CDD_Sbc_fs26.h are different"
#endif
/* Check if current file and CDD_Sbc_fs26 header file are of the same Software version */
#if ((SBC_FS26_SW_MAJOR_VERSION_C != SBC_FS26_SW_MAJOR_VERSION) || \
     (SBC_FS26_SW_MINOR_VERSION_C != SBC_FS26_SW_MINOR_VERSION) || \
     (SBC_FS26_SW_PATCH_VERSION_C != SBC_FS26_SW_PATCH_VERSION))
    #error "Software Version Numbers of CDD_Sbc_fs26.c and CDD_Sbc_fs26.h are different"
#endif

/* Check if current file and spi external access header file are of the same version */
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
  #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    #if ((SBC_FS26_AR_RELEASE_MAJOR_VERSION_C != SPI_EXTERNAL_ACCESS_AR_RELEASE_MAJOR_VERSION) || \
         (SBC_FS26_AR_RELEASE_MINOR_VERSION_C != SPI_EXTERNAL_ACCESS_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of CDD_Sbc_fs26.c and sbc_spi_external_access.h are different"
    #endif
  #endif
#endif

/* Check if current file and DET header file are of the same version */
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
  #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    #if ((SBC_FS26_AR_RELEASE_MAJOR_VERSION_C != DET_AR_RELEASE_MAJOR_VERSION) || \
         (SBC_FS26_AR_RELEASE_MINOR_VERSION_C != DET_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of CDD_Sbc_fs26.c and Det.h are different"
    #endif
  #endif
#endif

/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/
/**
* @brief Command type.
*/
typedef enum
{
    SBC_FS26_COM_READ, /**< Register Read */
    SBC_FS26_COM_WRITE /**< Register Write */
} Sbc_fs26_CommandType;

/**
* @brief Structure representing transmit data frame.
*/
typedef struct
{
    /** @brief Main/Fail Safe register selection. */
    boolean bIsFailSafe;
    /** @brief Register address. */
    uint8 u8RegisterAddress;
    /** @brief Command type (R/W). */
    Sbc_fs26_CommandType commandType;
    /** @brief Data to be written to the register.
    *   If commandType is "read", this value will be ignored. */
    uint16 u16WriteData;
} Sbc_fs26_TxFrameType;

/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/
/**
* @brief This macro updates value of bits specified by the mask. It is assumed that
* value is already shifted.
*/
#define SBC_FS26_BO_SETVAL(data, val, mask)  (((data) & ~(mask)) | (val))

/**
* @brief This macro updates value of bits specified by the mask. Additionally range
* check on the value is performed. It is assumed that value is not shifted.
*/
#define SBC_FS26_BO_SETVAL_EXT(data, value, mask, shift) \
    (((data) & ~(mask << shift)) | (((value) & (mask)) << (shift)))

/* Data frame macros. */
/**
* @brief Length of the communication frame.
*/
#define SBC_FS26_COMM_FRAME_SIZE  (0x04U)
/**
* @brief Register address mask.
*/
#define SBC_FS26_REG_ADDR_MASK    (0x3FU)
/**
* @brief SPI register address shift.
*/
#define SBC_FS26_REG_ADDR_SHIFT   (0x01U)

/* CRC macros used for SPI communication. */
/**
* @brief Size of CRC table.
*/
#define SBC_FS26_CRC_TBL_SIZE     (256U)
/**
* @brief CRC initial value.
*/
#define SBC_FS26_COM_CRC_INIT     (0xFFU)

/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/
#define SBC_FS26_START_SEC_CONST_8
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

/**
* @brief CRC lookup table.
*/
static const uint8 SBC_FS26_CRC_TABLE[SBC_FS26_CRC_TBL_SIZE] = {
    0x00U, 0x1DU, 0x3AU, 0x27U, 0x74U, 0x69U, 0x4EU, 0x53U, 0xE8U, 0xF5U, 0xD2U, 0xCFU, 0x9CU,
    0x81U, 0xA6U, 0xBBU, 0xCDU, 0xD0U, 0xF7U, 0xEAU, 0xB9U, 0xA4U, 0x83U, 0x9EU, 0x25U, 0x38U,
    0x1FU, 0x02U, 0x51U, 0x4CU, 0x6BU, 0x76U, 0x87U, 0x9AU, 0xBDU, 0xA0U, 0xF3U, 0xEEU, 0xC9U,
    0xD4U, 0x6FU, 0x72U, 0x55U, 0x48U, 0x1BU, 0x06U, 0x21U, 0x3CU, 0x4AU, 0x57U, 0x70U, 0x6DU,
    0x3EU, 0x23U, 0x04U, 0x19U, 0xA2U, 0xBFU, 0x98U, 0x85U, 0xD6U, 0xCBU, 0xECU, 0xF1U, 0x13U,
    0x0EU, 0x29U, 0x34U, 0x67U, 0x7AU, 0x5DU, 0x40U, 0xFBU, 0xE6U, 0xC1U, 0xDCU, 0x8FU, 0x92U,
    0xB5U, 0xA8U, 0xDEU, 0xC3U, 0xE4U, 0xF9U, 0xAAU, 0xB7U, 0x90U, 0x8DU, 0x36U, 0x2BU, 0x0CU,
    0x11U, 0x42U, 0x5FU, 0x78U, 0x65U, 0x94U, 0x89U, 0xAEU, 0xB3U, 0xE0U, 0xFDU, 0xDAU, 0xC7U,
    0x7CU, 0x61U, 0x46U, 0x5BU, 0x08U, 0x15U, 0x32U, 0x2FU, 0x59U, 0x44U, 0x63U, 0x7EU, 0x2DU,
    0x30U, 0x17U, 0x0AU, 0xB1U, 0xACU, 0x8BU, 0x96U, 0xC5U, 0xD8U, 0xFFU, 0xE2U, 0x26U, 0x3BU,
    0x1CU, 0x01U, 0x52U, 0x4FU, 0x68U, 0x75U, 0xCEU, 0xD3U, 0xF4U, 0xE9U, 0xBAU, 0xA7U, 0x80U,
    0x9DU, 0xEBU, 0xF6U, 0xD1U, 0xCCU, 0x9FU, 0x82U, 0xA5U, 0xB8U, 0x03U, 0x1EU, 0x39U, 0x24U,
    0x77U, 0x6AU, 0x4DU, 0x50U, 0xA1U, 0xBCU, 0x9BU, 0x86U, 0xD5U, 0xC8U, 0xEFU, 0xF2U, 0x49U,
    0x54U, 0x73U, 0x6EU, 0x3DU, 0x20U, 0x07U, 0x1AU, 0x6CU, 0x71U, 0x56U, 0x4BU, 0x18U, 0x05U,
    0x22U, 0x3FU, 0x84U, 0x99U, 0xBEU, 0xA3U, 0xF0U, 0xEDU, 0xCAU, 0xD7U, 0x35U, 0x28U, 0x0FU,
    0x12U, 0x41U, 0x5CU, 0x7BU, 0x66U, 0xDDU, 0xC0U, 0xE7U, 0xFAU, 0xA9U, 0xB4U, 0x93U, 0x8EU,
    0xF8U, 0xE5U, 0xC2U, 0xDFU, 0x8CU, 0x91U, 0xB6U, 0xABU, 0x10U, 0x0DU, 0x2AU, 0x37U, 0x64U,
    0x79U, 0x5EU, 0x43U, 0xB2U, 0xAFU, 0x88U, 0x95U, 0xC6U, 0xDBU, 0xFCU, 0xE1U, 0x5AU, 0x47U,
    0x60U, 0x7DU, 0x2EU, 0x33U, 0x14U, 0x09U, 0x7FU, 0x62U, 0x45U, 0x58U, 0x0BU, 0x16U, 0x31U,
    0x2CU, 0x97U, 0x8AU, 0xADU, 0xB0U, 0xE3U, 0xFEU, 0xD9U, 0xC4U
};

#define SBC_FS26_STOP_SEC_CONST_8
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/
#define SBC_FS26_START_SEC_VAR_CLEARED_UNSPECIFIED
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

/**
* @brief Local copy of the pointer to the configuration data.
*/
static Sbc_fs26_ConfigType* Sbc_fs26_pConfigPtr;

#define SBC_FS26_STOP_SEC_VAR_CLEARED_UNSPECIFIED
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

#define SBC_FS26_START_SEC_VAR_CLEARED_BOOLEAN
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
/**
* @brief Initialization flag, FALSE = Sbc_fs26_Init function was not called yet.
*/
static boolean Sbc_fs26_IsInitialized;
/**
* @brief Microcontroller endianness, TRUE = big-endian architecture (MSB at lowest address).
*/
static boolean Sbc_fs26_IsBigEndian;

#define SBC_FS26_STOP_SEC_VAR_CLEARED_BOOLEAN
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

#define  SBC_FS26_START_SEC_VAR_CLEARED_16
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
/**
* @brief Global copy of the wdg token.
*/
static uint16 watchDogToken;

#define SBC_FS26_STOP_SEC_VAR_CLEARED_16
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/
#if (SBC_FS26_PRECOMPILE_SUPPORT == STD_ON)
#define SBC_FS26_START_SEC_CONFIG_DATA_UNSPECIFIED
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

/**
* @brief Predefined FS26 driver configuration set.
*/
extern Sbc_fs26_ConfigType Sbc_fs26_PBCfgVariantPredefined;

#define SBC_FS26_STOP_SEC_CONFIG_DATA_UNSPECIFIED
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
#endif

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
#define SBC_FS26_START_SEC_CODE
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

/**
* @brief        This function will return TRUE if the platform is big-endian.
*
* @return       boolean         TRUE = big-endian.
*/
static boolean Sbc_fs26_GetEndian(void);

/**
* @brief        This function will switch the endianness of the input buffer.
*
* @param[in]    SpiFrameSize    SPI frame size.
* @param[in]    pData           Data array.
*
* @return       void
*/
static void Sbc_fs26_ChangeEndianness(uint8 SpiFrameSize, uint8 *pData);

/**
* @brief        This function calculates CRC value of passed data array.
*               Takes bytes in inverted order due to frame format.
*
* @param[in]    pData           Data array.
* @param[in]    DataLen         Length of the data array.
*
* @return       uint8           Result of CRC calculation.
*/
static uint8 Sbc_fs26_CalcCrc(const uint8* pData, uint8 DataLen);

/**
* @brief        Performs CRC check of the data array.
*               CRC is expected in the first array item (index 0).
*
* @param[in]    pData           Data array.
* @param[in]    DataLen         Length of the data array.
*
* @return       Std_ReturnType  Return code.
*/
static Std_ReturnType Sbc_fs26_CheckCrc(const uint8* pData, uint8 DataLen);

/**
* @brief        Creates a raw frame for SPI transfer.
*
* @param[in]    txData          TX data.
* @param[out]   txFrame         TX frame for SPI transfer.
*
* @return       void
*/
static void Sbc_fs26_CreateSendFrame(const Sbc_fs26_TxFrameType* pTxData, uint8* pTxFrame);

/**
* @brief        Performs SPI transfer.
*
* @param[in]    txData          TX data.
* @param[out]   rxData          RX data. Can be NULL_PTR in case of write-only command.
*
* @return       Std_ReturnType  Return code.
*/
static Std_ReturnType Sbc_fs26_TransferData(const Sbc_fs26_TxFrameType* pTxData, Sbc_fs26_RxFrameType* pRxData);

/**
* @brief        Performs a write to a single FS26 FS init register (during the INIT_FS phase only).
*
* @param[in]    Address         Register address.
* @param[in]    WriteData       Register write value.
*
* @return       Std_ReturnType  Return code.
*/
static Std_ReturnType Sbc_fs26_WriteRegisterInit(uint8 Address, uint16 WriteData);

/**
* @brief        Reads challenge token (next generated LFSR state) from the SBC.
*
* @param[out]   pWdToken        Pointer to challenge token storage.
*
* @return       Std_ReturnType  Return code.
*/
static Std_ReturnType Sbc_fs26_WdReadChallengeToken(uint16* pWdToken);

/**
* @brief        Computes Challenger Watchdog answer.
*
* @param[in]    Token           Challenge token.
*
* @return       uint16          Result of calculation.
*/
static uint16 Sbc_fs26_WdComputeAnswer(uint16 Token);

/**
* @brief        Check if watchdog refresh was successful.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckWdgRefresh(void);

/**
* @brief        Create wake up source payload for configuring wake up from low-power mode
*
* @param[in]    WakeupSrc       Wake up source configuration
*
* @return       uint16          Return payload
*/
static uint16 Sbc_fs26_CreateWakeupSrcPayload(Sbc_fs26_WuSrcType WakeupSrc);

/**
* @brief        Create wake up polarity payload for configuring wake up from low-power mode
*
* @param[in]    WakeupPol        Wake up polarity configuration.
*
* @return       uint16           Return payload
*/
static uint16 Sbc_fs26_CreateWakeupPolPayload(Sbc_fs26_WuPolType WakeupPol);

/**
* @brief        Check parameters for set LDT function.
*
* @param[in]    LdtFunction      LDT function.
* @param[in]    LdtMode          LDT mode.
* @param[in]    LdtLp            LDT low power.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckParametersSetLDT(Sbc_fs26_LdtFuncType LdtFunction, Sbc_fs26_LdtModeType LdtMode, Sbc_fs26_LdtLpType LdtLp);


/**
* @brief        Check parameter for set FsxbRelease.
*
* @param[in]    FsOutput      Fs release output option.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckParameterFsxbRelease(Sbc_fs26_FsOutputType FsOutput);

/**
* @brief        Check LBIST and ABIST1 pass.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckLBistABist1(void);

/**
* @brief        Check INIT_FS state, Debug mode and OTP error
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckInitFsDebugAndOTPError(void);

/**
* @brief        Initialize OVUV register
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_InitOVUV(void);

/**
* @brief        Initialize Wdg and FSSM register
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_InitWdgAndFSSM(void);
/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/
/* This function will return TRUE if the platform is big-endian. */
static boolean Sbc_fs26_GetEndian(void)
{
    boolean bIsBigEndian = FALSE;
    uint32 u32TestValue = 0x11223344UL;

    if ((*(uint8*)&u32TestValue) == (uint8)0x11U)
    {
        bIsBigEndian = TRUE;
    }

    return bIsBigEndian;
}

/* This function will switch the endianness of the input buffer. */
static void Sbc_fs26_ChangeEndianness(uint8 SpiFrameSize, uint8 *pData)
{
    uint8 u32TempData[SBC_FS26_COMM_FRAME_SIZE] = {0};

    /* Reorder bytes for 4 byte frames */
    if (4U == SpiFrameSize)
    {
        u32TempData[0] = pData[3];
        u32TempData[1] = pData[2];
        u32TempData[2] = pData[1];
        u32TempData[3] = pData[0];
    }

    /* Reorder bytes for 2 byte frames */
    if (2U == SpiFrameSize)
    {
        u32TempData[0] = pData[2];
        u32TempData[1] = pData[3];
        u32TempData[2] = pData[0];
        u32TempData[3] = pData[1];
    }

    /* Copy data. */
    if ((4U == SpiFrameSize) || (2U == SpiFrameSize))
    {
        pData[0] = u32TempData[0];
        pData[1] = u32TempData[1];
        pData[2] = u32TempData[2];
        pData[3] = u32TempData[3];
    }
}

/* This function calculates CRC value of passed data array. */
static uint8 Sbc_fs26_CalcCrc(const uint8* pData, uint8 DataLen)
{
    uint8 u8Crc;      /* Result. */
    uint8 u8TableIdx; /* Index to the CRC table. */
    uint8 u8DataIdx;  /* Index to the data array (memory). */

    /* Set CRC token value. */
    u8Crc = SBC_FS26_COM_CRC_INIT;

    /* Calculate CRC. */
    for (u8DataIdx = DataLen - 1U; u8DataIdx > 0U; u8DataIdx--)
    {
        u8TableIdx = u8Crc ^ pData[u8DataIdx];
        u8Crc = SBC_FS26_CRC_TABLE[u8TableIdx];
    }

    return u8Crc;
}

/* Performs CRC check of the data array. */
static Std_ReturnType Sbc_fs26_CheckCrc(const uint8* pData, uint8 DataLen)
{
    uint8 u8FrameCrc; /* CRC value from resp. */
    uint8 u8CompCrc;  /* Computed CRC value. */

    /* Check CRC. */
    u8FrameCrc = pData[0];
    u8CompCrc = Sbc_fs26_CalcCrc(pData, DataLen);

    return (u8CompCrc != u8FrameCrc) ? (Std_ReturnType)E_NOT_OK : (Std_ReturnType)E_OK;
}

/* Creates a raw frame for SPI transfer. */
static void Sbc_fs26_CreateSendFrame(const Sbc_fs26_TxFrameType* pTxData, uint8* pTxFrame)
{
    /* Selects register set (main x fail-safe). */
    pTxFrame[3] |= pTxData->bIsFailSafe ? 0x80U : 0x00U;

    /* Sets address of the register. */
    pTxFrame[3] |= (uint8)SBC_FS26_BO_SETVAL_EXT(pTxFrame[3], pTxData->u8RegisterAddress, SBC_FS26_REG_ADDR_MASK, SBC_FS26_REG_ADDR_SHIFT);

    /* check if register is r or w */
    switch (pTxData->commandType)
    {
        case SBC_FS26_COM_READ:
            /* Creates read command. */
            pTxFrame[3] = (uint8)SBC_FS26_BO_SETVAL(pTxFrame[3], 0x00U, 0x01U);
            /* No data to be sent. */
            pTxFrame[2] = 0x00;
            pTxFrame[1] = 0x00;
            break;

        case SBC_FS26_COM_WRITE:
            /* Creates write command. */
            pTxFrame[3] = (uint8)SBC_FS26_BO_SETVAL(pTxFrame[3], 0x01U, 0x01U);
            /* Sets data - MSB first. */
            pTxFrame[2] = (uint8)(pTxData->u16WriteData >> 8);
            pTxFrame[1] = (uint8)(pTxData->u16WriteData);
            break;
        default:
            /* Command not valid. */
            break;
    }

    /* Sets CRC. */
    pTxFrame[0] = Sbc_fs26_CalcCrc(pTxFrame, SBC_FS26_COMM_FRAME_SIZE);
}

/* Performs SPI transfer. */
static Std_ReturnType Sbc_fs26_TransferData(const Sbc_fs26_TxFrameType* pTxData, Sbc_fs26_RxFrameType* pRxData)
{
    uint8 spiTxFrame[SBC_FS26_COMM_FRAME_SIZE] = {0};
    uint8 spiRxFrame[SBC_FS26_COMM_FRAME_SIZE] = {0};
    Std_ReturnType eReturnValue = E_OK; /* Status. */
    Sbc_Ip_SpiSetupType spiSetup;

    /* Create the SPI tx frame */
    Sbc_fs26_CreateSendFrame(pTxData, spiTxFrame);

    /* Convert the frame to SPI compatible endianess */
    if (FALSE == Sbc_fs26_IsBigEndian)
    {
        Sbc_fs26_ChangeEndianness(Sbc_fs26_pConfigPtr->pcSpi->u8FrameSize, spiTxFrame);
    }
    /* Set spiSetup param */
    spiSetup.spi = Sbc_fs26_pConfigPtr->pcSpi->u32Spi;
    spiSetup.syncTransmit = TRUE;
    spiSetup.extension = Sbc_fs26_pConfigPtr->pcSpi->ext;
    spiSetup.numberOfBytes =  SBC_FS26_COMM_FRAME_SIZE;
    spiSetup.timeout = 10000U;

    /* Trigger the SPI transfer */
    eReturnValue = Sbc_Ip_SpiTransferExternal(&spiSetup,(uint32*)(&spiTxFrame[0]), (uint32*)(&spiRxFrame[0]));

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* Convert the retrieved frame to MCU compatible endianess */
        if (FALSE == Sbc_fs26_IsBigEndian)
        {
            Sbc_fs26_ChangeEndianness(Sbc_fs26_pConfigPtr->pcSpi->u8FrameSize, spiRxFrame);
        }

        /* Check the CRC of the retrieved frame */
        eReturnValue = Sbc_fs26_CheckCrc(spiRxFrame, SBC_FS26_COMM_FRAME_SIZE);
        if (((Std_ReturnType)E_OK == eReturnValue) && (NULL_PTR != pRxData))
        {
            /* Copy the retrieved data into the user provided buffer */
            pRxData->u8DeviceStatus = spiRxFrame[3];
            pRxData->u16ReadData = ((uint16)spiRxFrame[2] << 8U) | (uint16)spiRxFrame[1];
        }
    }

    return eReturnValue;
}

/* Performs a write to a single FS26 FS init register (during the INIT_FS phase only). */
static Std_ReturnType Sbc_fs26_WriteRegisterInit(uint8 Address, uint16 WriteData)
{
    uint16 u16WriteDataInv;             /* Inverted register data. */
    uint8 u8AddressNot;                 /* Address of _NOT_ register. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */


    /* Enter critical section. */
    SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_01();

    if ((Std_ReturnType)E_OK != Sbc_fs26_WriteRegister(TRUE, Address, WriteData, NULL_PTR))
    {
        eReturnValue = E_NOT_OK;
    }
    else
    {
        /* _NOT_ registers have address +1 from normal register. */
        u8AddressNot = (uint8)(Address + 1U);
        /* Inverted value should be written to _NOT_ register. */
        u16WriteDataInv = (uint16)~WriteData;

        eReturnValue = Sbc_fs26_WriteRegister(TRUE, u8AddressNot, u16WriteDataInv, NULL_PTR);
    }

    /* Exit critical section. */
    SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_01();


    return eReturnValue;
}

/* Reads challenge token (next generated LFSR state) from the SBC. */
static Std_ReturnType Sbc_fs26_WdReadChallengeToken(uint16* pWdToken)
{
    Sbc_fs26_RxFrameType rxData;        /* Response to the command. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, &rxData);
    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* Store the watchdog token from the SBC device. */
        *pWdToken = rxData.u16ReadData;
    }

    return eReturnValue;
}

/* Computes Challenger Watchdog answer. */
static uint16 Sbc_fs26_WdComputeAnswer(uint16 Token)
{
    uint32 u32Mr = Token; /* Monitoring result. */

    /* Simulates ALU Checker on the MCU side. */
    u32Mr *= 4U;
    u32Mr += 6U;
    u32Mr -= 4U;
    u32Mr = ~u32Mr;
    u32Mr /= 4U;

    return (uint16)u32Mr;
}

/* Check if watchdog refresh was successful. */
static Std_ReturnType Sbc_fs26_CheckWdgRefresh(void)
{
    Sbc_fs26_RxFrameType rxData;        /* Response to the command. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if ((SBC_FS26_WD_SIMPLE == Sbc_fs26_pConfigPtr->WatchdogType) || (SBC_FS26_WD_CHALLENGER == Sbc_fs26_pConfigPtr->WatchdogType))
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_GRL_FLAGS_ADDR, &rxData);
        if (((Std_ReturnType)E_OK == eReturnValue) && (SBC_FS26_FS_FS_WD_G_BAD_REFRESH == (rxData.u16ReadData & SBC_FS26_FS_FS_WD_G_MASK)) )
        {
            eReturnValue = E_NOT_OK;
        }
    }
    return eReturnValue;
}

/* Create wake up source payload for configuring wake up from low-power mode */
static uint16 Sbc_fs26_CreateWakeupSrcPayload(Sbc_fs26_WuSrcType WakeupSrc)
{
    uint16 u16WriteData;                /* Register value to write. */

    u16WriteData = (((TRUE == WakeupSrc.bWk1WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WK1WUEN_SHIFT) | \
                (((TRUE == WakeupSrc.bWk2WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WK2WUEN_SHIFT) | \
                (((TRUE == WakeupSrc.bGpio1WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO1WUEN_SHIFT) | \
                (((TRUE == WakeupSrc.bGpio2WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO2WUEN_SHIFT) | \
                (((TRUE == WakeupSrc.bLdtWuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_LDTWUEN_SHIFT) | \
                (((TRUE == WakeupSrc.bCsbWuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_CSBWUEN_SHIFT);

    return u16WriteData;
}

/* Create wake up polarity payload for configuring wake up from low-power mode */
static uint16 Sbc_fs26_CreateWakeupPolPayload(Sbc_fs26_WuPolType WakeupPol)
{
    uint16 u16WriteData;                /* Register value to write. */

    u16WriteData = (((TRUE == WakeupPol.bWk1Polarity) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WAKE1POL_SHIFT) | \
                (((TRUE == WakeupPol.bWk2Polarity) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WAKE2POL_SHIFT) | \
                (((TRUE == WakeupPol.bGpio1Polarity) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO1WUPOL_SHIFT) | \
                (((TRUE == WakeupPol.bGpio2Polarity) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO2WUPOL_SHIFT);

    return u16WriteData;
}

/* Check paramters for setting LDT*/
static Std_ReturnType Sbc_fs26_CheckParametersSetLDT(Sbc_fs26_LdtFuncType LdtFunction, Sbc_fs26_LdtModeType LdtMode, Sbc_fs26_LdtLpType LdtLp)
{
    Std_ReturnType eReturnValue = E_OK; /* Status. */
    if (((SBC_FS26_LDTFUNC_FUNC1 != LdtFunction) && (SBC_FS26_LDTFUNC_FUNC2 != LdtFunction) && (SBC_FS26_LDTFUNC_FUNC3 != LdtFunction) && \
            (SBC_FS26_LDTFUNC_FUNC4 != LdtFunction) && (SBC_FS26_LDTFUNC_FUNC5 != LdtFunction)) || ((SBC_FS26_LDTMODE_LONG != LdtMode) && \
            (SBC_FS26_LDTMODE_SHORT != LdtMode)) || ((SBC_FS26_LDTLP_LPOFF != LdtLp) && (SBC_FS26_LDTLP_STANDBY != LdtLp)))
    {
        eReturnValue = E_NOT_OK;
    }

    return eReturnValue;
}

/* Check parameter for FsxbRelease*/
static Std_ReturnType Sbc_fs26_CheckParameterFsxbRelease(Sbc_fs26_FsOutputType FsOutput)
{
    Std_ReturnType eReturnValue = E_OK;

    if ((SBC_FS26_FS_FS0B != FsOutput) && (SBC_FS26_FS_FS1B != FsOutput) && (SBC_FS26_FS_BOTH != FsOutput))
    {
        eReturnValue = E_NOT_OK;
    }
    return eReturnValue;
}

/* Perform LBIST and ABIST tests. */
static Std_ReturnType Sbc_fs26_CheckLBistABist1(void)
{
    Sbc_fs26_RxFrameType rxData;        /* Response to the command. */
    uint16 u16CheckMask;                /* Mask for reading of value. */
    uint16 u16CheckValue;               /* Expected value of the masked bits. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, &rxData);
    if (TRUE == Sbc_fs26_pConfigPtr->bAsilDLevel)
    {
        u16CheckMask = (SBC_FS26_FS_LBIST_STATUS_MASK | SBC_FS26_FS_ABIST1_PASS_MASK);
        u16CheckValue = (SBC_FS26_FS_LBIST_STATUS_OK | SBC_FS26_FS_ABIST1_PASS_PASS);
    }
    else
    {
        u16CheckMask = SBC_FS26_FS_ABIST1_PASS_MASK;
        u16CheckValue = SBC_FS26_FS_ABIST1_PASS_PASS;
    }

    if (((Std_ReturnType)E_OK != eReturnValue) || (u16CheckValue != (rxData.u16ReadData & u16CheckMask)) )
    {
    	eReturnValue = rxData.u16ReadData;
    	//eReturnValue = E_NOT_OK;
        //printf("BIST status 0x%04X, device status 0x%02X.\r\n", (unsigned int)(rxData.u16ReadData), (unsigned int)(rxData.u8DeviceStatus));
    }

    return eReturnValue;
}
/* Perform check if not in INIT_FS state, debug mode or no Otp error. */
static Std_ReturnType Sbc_fs26_CheckInitFsDebugAndOTPError(void)
{
    Sbc_fs26_RxFrameType rxData;        /* Response to the command. */
    uint16 u16CheckMask;                /* Mask for reading of value. */
    uint16 u16CheckValue;               /* Expected value of the masked bits. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_STATES_ADDR, &rxData);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        u16CheckMask = (SBC_FS26_FS_DBG_MODE_MASK | SBC_FS26_FS_OTP_CORRUPT_MASK | SBC_FS26_FS_FS_STATES_MASK);
        
        if (FALSE == Sbc_fs26_pConfigPtr->bDebugMode)
        {
            //u16CheckValue = (SBC_FS26_FS_DBG_MODE_NOT | SBC_FS26_FS_OTP_CORRUPT_NO_ERROR | SBC_FS26_FS_FS_STATES_INIT_FS);
        	/* Change this line so that Debug mode is not checked by the RTD driver. */
        	u16CheckValue = (SBC_FS26_FS_DBG_MODE_DEBUG | SBC_FS26_FS_OTP_CORRUPT_NO_ERROR | SBC_FS26_FS_FS_STATES_INIT_FS);
        }
        else
        {
            u16CheckValue = (SBC_FS26_FS_DBG_MODE_DEBUG | SBC_FS26_FS_OTP_CORRUPT_NO_ERROR | SBC_FS26_FS_FS_STATES_INIT_FS);
        }
        
        if (u16CheckValue != (rxData.u16ReadData & u16CheckMask))
        {
            eReturnValue = E_NOT_OK;
        }
        //printf("CheckValue 0x%04X, ReadData 0x%04X.\r\n", (unsigned int)u16CheckValue, (unsigned int)(rxData.u16ReadData));
    }

    return eReturnValue;
}

/* Initialize OVUV register. */
static Std_ReturnType Sbc_fs26_InitOVUV(void)
{
    uint16 u16WriteData;                /* Register value to write. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    /* Write INIT_FS registers. */
    u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonPreOvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonPreUvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonCoreOvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonCoreUvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonLdo1OvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonLdo1UvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonLdo2OvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe1Reg.u16VmonLdo2UvFs);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_OVUV_SAFE_REACTION1_ADDR, u16WriteData);


    u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonExtOvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonExtUvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonRefOvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonRefUvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonTrk2OvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonTrk2UvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonTrk1OvFs | \
            Sbc_fs26_pConfigPtr->pcInitConfig->ovuvSafe2Reg.u16VmonTrk1UvFs);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_OVUV_SAFE_REACTION2_ADDR, u16WriteData);

    return eReturnValue;
}
/* Initialize wdg and FSSM. */
static Std_ReturnType Sbc_fs26_InitWdgAndFSSM(void)
{
    uint16 u16WriteData;                /* Register value to write. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

#if (SBC_FS26_EXTERNAL_WDG_USED == FALSE)
        u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->wdCfgReg.u16WdErrLimit | \
                Sbc_fs26_pConfigPtr->pcInitConfig->wdCfgReg.u16WdRfrLimit | \
                Sbc_fs26_pConfigPtr->pcInitConfig->wdCfgReg.u16WdFs);
        eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_WD_CFG_ADDR, u16WriteData);
#endif
        u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16FccuCfg | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu12FltPol | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu1FltPol | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu2FltPol | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu12Fs | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu1Fs | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu2Fs | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Wake2LpPol | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16ErrmonFaultPol | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16ErrmonAckTime | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16ErrmonFs | \
                Sbc_fs26_pConfigPtr->pcInitConfig->safeInputsReg.u16Fccu12Filt);
        eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_SAFE_INPUTS_ADDR, u16WriteData);

        u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16FltErrCntLimit | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16FltErrFs | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16RstbDur | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16BackupFs0b | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16BackupFs1b | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16ClkMonDis | \
                Sbc_fs26_pConfigPtr->pcInitConfig->fssmReg.u16Dis8s);
        eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_FSSM_ADDR, u16WriteData);

#if (SBC_FS26_EXTERNAL_WDG_USED == FALSE)
        u16WriteData = (uint16) (Sbc_fs26_pConfigPtr->pcInitConfig->wdwDurationReg.u16WdwPeriod | \
                Sbc_fs26_pConfigPtr->pcInitConfig->wdwDurationReg.u16WdwDc | \
                Sbc_fs26_pConfigPtr->pcInitConfig->wdwDurationReg.u16WdwRecovery);
        eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_WDW_DURATION_ADDR, u16WriteData);
#endif

        /* Change watchdog token if requested (during INIT_FS phase for challenger,
         * during open window for simple). */
        if (TRUE == Sbc_fs26_pConfigPtr->bChangeToken)
        {
            eReturnValue |= Sbc_fs26_WdChangeToken(watchDogToken);
        }

        if (eReturnValue != (Std_ReturnType)E_OK)
        {
            eReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    return eReturnValue;
}
/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
/*================================================================================================*/
/**
* @brief        Initializes the FS26 driver. SID is 0x00.
* @details      Internally stores the run-time configuration.
*
* @param[in]    pConfig         Pointer to FS26 driver configuration set.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_Init_Activity */
Std_ReturnType Sbc_fs26_Init(Sbc_fs26_ConfigType* pConfig)
{
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    /* Check if already initialized. */
    if (TRUE == Sbc_fs26_IsInitialized)
    {
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INIT, (uint8)SBC_FS26_E_MULTIPLE_INIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
        eReturnValue = E_NOT_OK;
    }
    else
    {
        /* Get a local copy of the driver initalization structure. */
#if (SBC_FS26_PRECOMPILE_SUPPORT == STD_ON)
        if (NULL_PTR == pConfig)
        {
            Sbc_fs26_pConfigPtr = &Sbc_fs26_PBCfgVariantPredefined;
            watchDogToken = Sbc_fs26_pConfigPtr->u16WatchdogToken;
        }
        else
        {
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
            (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INIT, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
            eReturnValue = E_NOT_OK;
        }
#else

        if (NULL_PTR == pConfig)
        {
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
            (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INIT, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
            eReturnValue = E_NOT_OK;
        }
        else
        {
            Sbc_fs26_pConfigPtr = pConfig;
            watchDogToken = Sbc_fs26_pConfigPtr->u16WatchdogToken;
        }
#endif
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Get microcontroller endianness. */
            Sbc_fs26_IsBigEndian = Sbc_fs26_GetEndian();
            /* Device initialized. */
            Sbc_fs26_IsInitialized = TRUE;
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Configures the device. SID is 0x10.
* @details      Performs initialization checks (LBIST, ABIST1 are pass)
*               and writes all INIT_FS registers and watchdog configuration.
*               Closes initialization phase by sending first watchdog refresh.
*
*               NOTE: If external watchdog is used (SBC_FS26_EXTERNAL_WDG_USED = TRUE) writing
*               watchdog related registers and first watchdog refresh (closing INIT_FS phase)
*               is skipped in order to allow watchdog configuration by the external watchdog.
*               The function leaves the device in INIT_FS phase, which needs to be properly
*               closed by the external watchdog within 256 ms from FS26 start-up.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_InitDevice_Activity */
Std_ReturnType Sbc_fs26_InitDevice(void)
{
    //Std_ReturnType eReturnValue = E_OK; /* Status. */
	uint16_t eReturnValue = E_OK;

    /* Check if initialized. */
    if (TRUE == Sbc_fs26_IsInitialized)
    {
        /* Perform check INIT_FS state, debug mode and OTP error. */
        eReturnValue |= Sbc_fs26_CheckInitFsDebugAndOTPError();
        /* Perform LBIST & ABIST1 check. */
        eReturnValue |= Sbc_fs26_CheckLBistABist1();
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Perform initialization of OVUV. */
            eReturnValue = Sbc_fs26_InitOVUV();
            /* Perform intialization of Wdg and FSSM */
            eReturnValue |= Sbc_fs26_InitWdgAndFSSM();
        }
        
#if (SBC_FS26_EXTERNAL_WDG_USED == FALSE)
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Close initialization phase by sending first watchdog refresh. */
            eReturnValue = Sbc_fs26_WdRefresh();
        }
#endif
    }
    else
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INITDEVICE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Performs a read from a single FS26 register. SID is 0x01.
* @details      Performs a single read register based on provided address.
*               The response is returned in Sbc_fs26_RxFrameType structure.
*
* @param[in]    IsFailSafe      TRUE if the register is Fail Safe.
* @param[in]    Address         Register address.
* @param[out]   pRxData         Pointer to structure holding the response from SBC.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_ReadRegister_Activity */
Std_ReturnType Sbc_fs26_ReadRegister(boolean IsFailSafe, uint8 Address, Sbc_fs26_RxFrameType* pRxData)
{
    Sbc_fs26_TxFrameType txData =
    {
        IsFailSafe,
        Address,
        SBC_FS26_COM_READ,
        0U
    };
    Std_ReturnType eReturnValue = E_OK; /* Status. */

#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == pRxData)
    {
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_PARAM_POINTER);
        eReturnValue = E_NOT_OK;
    }
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */

    if (((Std_ReturnType)E_OK == eReturnValue) && (FALSE == Sbc_fs26_IsInitialized))
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if (((Std_ReturnType)E_OK == eReturnValue) && (0x3FU < Address))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            eReturnValue = Sbc_fs26_TransferData(&txData, pRxData);
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Sends write command to the FS26. SID is 0x02.
*
* @param[in]    IsFailSafe      TRUE if the register is Fail Safe.
* @param[in]    Address         Register address.
* @param[in]    WriteData       Register write value.
* @param[out]   pRxData         Response for write command.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_WriteRegister_Activity */
Std_ReturnType Sbc_fs26_WriteRegister(boolean IsFailSafe, uint8 Address, uint16 WriteData, Sbc_fs26_RxFrameType* pRxData)
{
    Sbc_fs26_TxFrameType txData =
    {
        IsFailSafe,
        Address,
        SBC_FS26_COM_WRITE,
        WriteData
    };
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WRITEREGISTER, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if (0x3FU < Address)
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WRITEREGISTER, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        eReturnValue = Sbc_fs26_TransferData(&txData, pRxData);
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Sets device operating mode. SID is 0x03.
* @details      The FS26 provides three main operating modes:
*               - NORMAL mode: The system is fully functional with all power supplies enabled
*                 as required by the system as well as all the system functionality provided
*                 by the FS26 device is available. During the normal mode, the Fail Safe state machine
*                 is available and providing full monitoring and operation of all the safety features
*                 in the device.
*               - STANDBY mode: This is intended to be a low power ON mode, providing support
*                 to the minimum system requirements with low current consumption from the battery.
*                 During the standby mode, only the VPRE remain enabled to supply the microcontroller
*                 I/O rail. LDO1 and LDO2 can be enabled in this mode depending on OTP configuration.
*                 This mode is assumed to be a safe state with no critical activity and therefore
*                 the Fail-safe state machine is disabled to allow minimum current consumption of the system.
*               - LPOFF mode: this mode is intended to place the system in a fully OFF state with no
*                 system supplies active. Logic circuitry is supplied internally to allow proper wake up
*                 from any of the available wake-up mechanism, with the minimum current consumption possible.
*               Switching between the modes is done as follows:
*               - Switch to normal mode (via SPI) can be done from standby mode only. SPI CSB transition
*                 wake-up must be previously enabled in M_WIO_CFG register (using Sbc_fs26_SetWakeup).
*               - Switching to standby mode is done from normal mode through pre standby mode.
*               - Switching to LPOFF mode is done from normal mode through pre LPOFF mode.
*
*               NOTE: Before entering any low-power mode make sure some wake-up source is enabled
*               (using Sbc_fs26_SetWakeup).
*
* @param[in]    OpMode          Device operating mode.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetOperatingMode_Activity */
Std_ReturnType Sbc_fs26_SetOperatingMode(Sbc_fs26_OpModeType OpMode)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETOPERATINGMODE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if ((SBC_FS26_OPMODE_NORMAL != OpMode) && (SBC_FS26_OPMODE_STANDBY != OpMode) && (SBC_FS26_OPMODE_LPOFF != OpMode))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETOPERATINGMODE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        /* Enter critical section. */
        SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_02();

        /* Go to normal mode, pre standby, or pre LPOFF. */
        eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, (uint16)OpMode, NULL_PTR);

        if(((Std_ReturnType)E_OK == eReturnValue) && (SBC_FS26_OPMODE_STANDBY == OpMode))
        {
            /* Go to standby from pre standby. */
            eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, SBC_FS26_FS_FS_LP_REQ_STANDBY, NULL_PTR);
        }
        else if(((Std_ReturnType)E_OK == eReturnValue) && (SBC_FS26_OPMODE_LPOFF == OpMode))
        {
            /* Go to LPOFF from pre LPOFF. */
            eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, SBC_FS26_FS_FS_LP_REQ_LPOFF, NULL_PTR);
        }
        else
        {
            /* Do nothing - final else branch needed by MISRA */
        }

        /* Exit critical section. */
        SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_02();
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Sets long duration timer function. SID is 0x04.
* @details      FS26 features a long duration timer, with an integrated oscillator. The timer is
*               configurable by SPI and can operate in NORMAL and in Low Power modes. The timer is
*               based on a 24-bit counter, with a 32768Hz oscillator allowing a 1.0 second time base.
*               In normal operation, the timer can count up to 194 days, with 1 second resolution.
*               The timer functions are:
*               - Function 1: In normal mode, count and generate a flag or an Interrupt when
*                 the counter reaches the after run value.
*               - Function 2: In normal mode, count until the counter reaches the after run value
*                 and enters into low-power mode.
*               - Function 3: In normal mode, count until the counter reaches the after run value
*                 and enters into low-power mode. Once in low-power mode, count until the counter
*                 reaches the wake-up value and wakes up.
*               - Function 4: In low-power mode, count until the counter reaches the wake-up
*                 value and wakes up.
*               - Function 5: In low-power mode, count and do not wake-up unless the counter overflow
*                 occurs, or if the device wakes up by wake up input source.
*
*               NOTE: For functions 1-3 the timer is started automatically, for functions 4-5 the timer
*               starts as soon as the application enters low-power mode (using Sbc_fs26_SetOperatingMode).
*
*               NOTE: For functions 3-5 make sure LDT wake up is enabled (using Sbc_fs26_SetWakeup).
*
* @param[in]    LdtFunction     LDT function.
* @param[in]    LdtMode         LDT operation mode.
* @param[in]    AfterRun        LDT after run value (16 bits).
* @param[in]    WakeUp          LDT wake-up value (24 bits).
* @param[in]    LdtLp           Low-power mode to go to for functions 2-3.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetLDT_Activity */
Std_ReturnType Sbc_fs26_SetLDT(Sbc_fs26_LdtFuncType LdtFunction, Sbc_fs26_LdtModeType LdtMode, uint16 AfterRun, uint32 WakeUp, Sbc_fs26_LdtLpType LdtLp)
{

    uint16 u16WriteData = (uint16)LdtFunction | (uint16)LdtMode; /* Register value to write. */
    Std_ReturnType eReturnValue = E_OK;          /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETLDT, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if (((Std_ReturnType)E_OK != Sbc_fs26_CheckParametersSetLDT(LdtFunction,LdtMode, LdtLp)) || (0x00FFFFFFU < WakeUp))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETLDT, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        /* Write LDT configuration. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, u16WriteData, NULL_PTR);

        /* Set low-power mode to go to for functions 2 to 3. */
        if((SBC_FS26_LDTFUNC_FUNC2 == LdtFunction) || (SBC_FS26_LDTFUNC_FUNC3 == LdtFunction))
        {
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LDT_LPSEL_ADDR, (uint16)LdtLp, NULL_PTR);
        }

        /* Set after run value for functions 1 to 3. */
        if (SBC_FS26_LDTFUNC_FUNC3 >= LdtFunction)
        {
            eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CFG1_ADDR, AfterRun, NULL_PTR);
        }

        /* Set wake-up value for functions 3 and 4. */
        if((SBC_FS26_LDTFUNC_FUNC3 == LdtFunction) || (SBC_FS26_LDTFUNC_FUNC4 == LdtFunction))
        {
            eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CFG2_ADDR, (uint16)(WakeUp & 0x0000FFFFU), NULL_PTR);
            eReturnValue |= Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CFG3_ADDR, (uint16)((WakeUp & 0x00FF0000U) >> 16), NULL_PTR);
        }

        if((Std_ReturnType)E_OK == eReturnValue)
        {
            u16WriteData |= SBC_FS26_M_LDT_EN_ENABLED;
            eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, u16WriteData, NULL_PTR);
        }
        /* Enable the counter. */
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Reads actual Long Duration Timer value. SID is 0x05.
* @details      This function checks if the Long Duration Timer is running and reads the real-time value.
*
* @param[out]   pLdtValue       Pointer to Long Duration Timer value storage.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GetLDTValue_Activity */
Std_ReturnType Sbc_fs26_GetLDTValue(uint32* pLdtValue)
{
    Sbc_fs26_RxFrameType rxData1;       /* Register received data. */
    Sbc_fs26_RxFrameType rxData2;       /* Register received data. */
    uint16 u16WriteData;                /* Register value to write. */
    uint32 u32TempValue;                /* LDT value. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == pLdtValue)
    {
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETLDTVALUE, (uint8)SBC_FS26_E_PARAM_POINTER);
        eReturnValue = E_NOT_OK;
    }
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */

    if (((Std_ReturnType)E_OK == eReturnValue) && (FALSE == Sbc_fs26_IsInitialized))
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETLDTVALUE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Enter critical section. */
            SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_03();

            /* Read LDT configuration and status. */
            eReturnValue = Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, &rxData1);

            /* Check if the Long Duration Timer is running. */
            if(((Std_ReturnType)E_OK == eReturnValue) && (SBC_FS26_M_LDT_RUN_ENABLED != ((rxData1.u16ReadData & SBC_FS26_M_LDT_RUN_MASK) >> SBC_FS26_M_LDT_RUN_SHIFT)))
            {
                eReturnValue = E_NOT_OK;
            }

            if((Std_ReturnType)E_OK == eReturnValue)
            {
                /* Write LDT configuration for reading timer value. */
                u16WriteData = rxData1.u16ReadData | SBC_FS26_M_LDT_SEL_REALTIME;
                eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, u16WriteData, NULL_PTR);
            }

            if((Std_ReturnType)E_OK == eReturnValue)
            {
                /* Read timer value - CFG2 = 16 low bits, CFG3 = 8 high bits of the 24-bit value. */
                eReturnValue = Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_LDT_CFG2_ADDR, &rxData1);
                eReturnValue |= Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_LDT_CFG3_ADDR, &rxData2);
            }

            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                u32TempValue = ((uint32)rxData2.u16ReadData) << 16;
                u32TempValue = (u32TempValue & 0xFFFF0000U) | rxData1.u16ReadData;
                *pLdtValue = u32TempValue;
            }

            /* Exit critical section. */
            SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_03();
        }

    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Changes token of LFSR used for watchdog. SID is 0x06.
* @details      The watchdog token can be changed just during the INIT_FS phase (for challenger WD)
*               or during the OPEN watchdog window (for simple WD). Timing is up to the application!
*
* @param[in]    WdToken         New watchdog token, stored to run-time configuration if change was successful.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_WdChangeToken_Activity */
Std_ReturnType Sbc_fs26_WdChangeToken(uint16 WdToken)
{
    Sbc_fs26_RxFrameType rxData;
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDCHANGETOKEN, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    /* Token 0x0000U not allowed, for simple watchdog also 0xFFFFU. */
    else if (((SBC_FS26_WD_SIMPLE == Sbc_fs26_pConfigPtr->WatchdogType) && (0xFFFFU == WdToken)) || (0x0000U == WdToken))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDCHANGETOKEN, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        /* Write new watchdog token and check it was written correctly. */
        eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, WdToken, NULL_PTR);
        eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, &rxData);
        if (((Std_ReturnType)E_OK == eReturnValue) && (WdToken == rxData.u16ReadData))
        {
           /* Store watchdog token after written correctly. */
           watchDogToken = WdToken;

        }

    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Performs the watchdog refresh. SID is 0x07.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_WdRefresh_Activity */
Std_ReturnType Sbc_fs26_WdRefresh(void)
{
    uint16 u16Answer;                   /* Calculated monitoring result. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDREFRESH, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        switch (Sbc_fs26_pConfigPtr->WatchdogType)
        {
            case SBC_FS26_WD_DISABLED:
                eReturnValue = E_OK;
                break;
            case SBC_FS26_WD_SIMPLE:
                eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_ANSWER_ADDR,watchDogToken, NULL_PTR);
                break;
            case SBC_FS26_WD_CHALLENGER:
                /* Enter critical section. */
                SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_04();

                /* Synchronize with LFSR generator on the device. */
                eReturnValue |= Sbc_fs26_WdReadChallengeToken(&watchDogToken);
                if ((Std_ReturnType)E_OK == eReturnValue)
                {
                    u16Answer = Sbc_fs26_WdComputeAnswer(watchDogToken);
                    eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_ANSWER_ADDR, u16Answer, NULL_PTR);
                }

                /* Exit critical section. */
                SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_04();

                break;
            default:
                eReturnValue = E_NOT_OK;
                break;
        }

        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Check if watchdog refresh was successful. */
            eReturnValue = Sbc_fs26_CheckWdgRefresh();
        }

    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Reads actual Fault Error Counter value. SID is 0x08.
*
* @param[out]   pFaultErrorCounterValue  Pointer to Fault Error counter value storage.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GetFaultErrorCounterValue_Activity */
Std_ReturnType Sbc_fs26_GetFaultErrorCounterValue(uint8* pFaultErrorCounterValue)
{
    Sbc_fs26_RxFrameType rxData;        /* Register received data. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == pFaultErrorCounterValue)
    {
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETFAULTERRORCOUNTERVALUE, (uint8)SBC_FS26_E_PARAM_POINTER);
        eReturnValue = E_NOT_OK;
    }
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */

    if (((Std_ReturnType)E_OK == eReturnValue) && (FALSE == Sbc_fs26_IsInitialized))
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETFAULTERRORCOUNTERVALUE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_I_FSSM_ADDR, &rxData);
            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                *pFaultErrorCounterValue = (uint8)((rxData.u16ReadData & SBC_FS26_FS_FLT_ERR_CNT_MASK) >> SBC_FS26_FS_FLT_ERR_CNT_SHIFT);
            }
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        FSxB release routine. SID is 0x09.
*
* @details      This function also checks all preconditions before it sends the register write
*               command (LBIST_OK = ABIST1_OK = 1, Fault Error Counter = 0).
*               If any precondition is not met, the function returns E_NOT_OK.
*
* @param[in]    FsOutput        FS output to release.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_FsxbRelease_Activity */
Std_ReturnType Sbc_fs26_FsxbRelease(Sbc_fs26_FsOutputType FsOutput)
{
    Sbc_fs26_RxFrameType rxData;        /* Response to the command. */
    uint16 u16ReleaseWrite = 0;         /* Value to be written to the FS_RELEASE_FS0B_FS1B register. */
    uint16 u16DiagSafetyMask;           /* Mask for reading of value from the FS_DIAG_SAFETY register. */
    uint16 u16DiagSafetyValue;          /* FS_DIAG_SAFETY bits defined by the former mask should have this value. */
    uint8 u8ErrorCounter;               /* Fault Error Counter value. */
    uint8 i;                            /* Counter. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_FSXBRELEASE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if ((Std_ReturnType)E_OK != Sbc_fs26_CheckParameterFsxbRelease(FsOutput))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_FSXBRELEASE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        /* Fault Error Counter = 0 */
        eReturnValue = Sbc_fs26_GetFaultErrorCounterValue(&u8ErrorCounter);

        /* LBIST_OK = ABIST1_OK = 1 */
        eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, &rxData);

        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            if (TRUE == Sbc_fs26_pConfigPtr->bAsilDLevel)
            {
                /* Extract LBIST and ABIST status. */
                u16DiagSafetyMask = (SBC_FS26_FS_LBIST_STATUS_MASK | SBC_FS26_FS_ABIST1_PASS_MASK);
                u16DiagSafetyValue = (SBC_FS26_FS_LBIST_STATUS_OK | SBC_FS26_FS_ABIST1_PASS_PASS);
            }
            else
            {
                /* Extract ABIST status. */
                u16DiagSafetyMask = SBC_FS26_FS_ABIST1_PASS_MASK;
                u16DiagSafetyValue = SBC_FS26_FS_ABIST1_PASS_PASS;
            }
            
            if (u16DiagSafetyValue != (rxData.u16ReadData & u16DiagSafetyMask))
            {
                eReturnValue = E_NOT_OK;
            }
        }

        if (((Std_ReturnType)E_OK == eReturnValue) && (u8ErrorCounter == (uint8)0U))
        {
            /* Enter critical section. */
            SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_05();

            /* RELEASE_FS0B_FS1B register filled with ongoing WD_TOKEN reversed and complemented */
            eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, &rxData);

            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                for (i = 0U; i < 16U; i++)
                {
                    u16ReleaseWrite |= (uint16)(((rxData.u16ReadData >> (15U - i)) & 1U) << i);
                }
                u16ReleaseWrite = ~u16ReleaseWrite;

                /* Replace bits 15 to 13 with FS outputs code. */
                u16ReleaseWrite = ((uint16)FsOutput & SBC_FS26_FS_RELEASE_FS_OUTPUT_MASK) | (u16ReleaseWrite & SBC_FS26_FS_RELEASE_WD_TOKEN_MASK);

                eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_RELEASE_FS0B_FS1B_ADDR, u16ReleaseWrite, NULL_PTR);
            }

            /* Exit critical section. */
            SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_05();
        }
        else
        {
            eReturnValue = E_NOT_OK;
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Sets state (enable/disable) of the selected voltage regulator. SID is 0x0A.
*
* @param[in]    Vreg            Voltage regulator.
* @param[in]    Enable          State (enable = TRUE / disable = FALSE).
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetRegulatorState_Activity */
Std_ReturnType Sbc_fs26_SetRegulatorState(Sbc_fs26_RegOutputType Vreg, boolean Enable)
{
    uint16 u16Shift = (uint16)Vreg;                /* Shift of the mask for disable value. */
    uint8 u8Address = SBC_FS26_M_REG_CTRL1_ADDR; /* M_REG_CTRL1 register address. */
    Std_ReturnType eReturnValue = E_OK;            /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETREGULATORSTATE, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if ((SBC_FS26_REG_LDO1 != Vreg) && (SBC_FS26_REG_LDO2 != Vreg) && (SBC_FS26_REG_VCORE != Vreg) && (SBC_FS26_REG_TRK1 != Vreg) && \
            (SBC_FS26_REG_TRK2 != Vreg) && (SBC_FS26_REG_VBST != Vreg) && (SBC_FS26_REG_VREF != Vreg))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETREGULATORSTATE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        if (FALSE == Enable)
        {
            u8Address++; /* Disable value is in M_REG_CTRL2 register. */
        }

        /* Register read is not necessary here as a bit value of 0 is ignored anyway. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, u8Address, (uint16)1U << u16Shift, NULL_PTR);
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Configures analog multiplexer. SID is 0x0B.
* @details      The AMUX pin delivers internal voltage channels to the AMUX pin. Maximum AMUX output
*               voltage range is VDDIO. The analog multiplexer can be used in the system to monitor
*               critical parameters of the FS26 and the application.
*               AMUX divider selection is used only for VBST, VSUP, WAKE1, WAKE2, GPIO1, GPIO2
*               and BATSENSE pin voltages (see datasheet or Sbc_fs26_AmuxDivType type for details).
*
* @param[in]    AmuxChannel     AMUX channel selection.
* @param[in]    AmuxDiv         AMUX divider.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetAmux_Activity */
Std_ReturnType Sbc_fs26_SetAmux(Sbc_fs26_AmuxChanType AmuxChannel, Sbc_fs26_AmuxDivType AmuxDiv)
{
    uint16 u16WriteData = (uint16)AmuxChannel;  /* Register value to write. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETAMUX, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else if ((SBC_FS26_AMUXCHAN_GPIO1_TEMP < AmuxChannel) || ((SBC_FS26_AMUXDIV_LOW != AmuxDiv) && (SBC_FS26_AMUXDIV_HIGH != AmuxDiv)))
    {
        /* Parameter out of range. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETAMUX, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        /* Enable AMUX block. */
        if(SBC_FS26_AMUXCHAN_DISABLED != AmuxChannel)
        {
            u16WriteData |= SBC_FS26_M_AMUX_EN_ENABLED;
        }
        /* Select divider ratio. */
        if((SBC_FS26_AMUXCHAN_VBST <= AmuxChannel) && (SBC_FS26_AMUXCHAN_BATSENSE >= AmuxChannel))
        {
            u16WriteData |= (uint16)AmuxDiv;
        }

        /* Configure AMUX. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_AMUX_CTRL_ADDR, u16WriteData, NULL_PTR);
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Configures wake up from low-power mode. SID is 0x0C.
* @details      The system can Wake up from any of the Low Power modes via any of the selectable
*               wake up mechanism available in the device:
*               - WAKE1 and WAKE2 pins,
*               - GPIO1 and GPIO2 pins,
*               - Long Duration Timer (LDT) expiration (needed for proper Sbc_fs26_SetLDT functionality),
*               - SPI CS pin edge detection (needed for proper Sbc_fs26_SetOperatingMode functionality).
*               This function enables/disables all of the wake up sources and sets wake up polarity
*               for WAKE1/2 and GPIO1/2 wake up.
*
* @param[in]    WakeupSrc       Wake up source (when source is TRUE = enabled).
* @param[in]    WakeupPol       Wake up polarity (when source polarity is TRUE = low).
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetWakeup_Activity */
Std_ReturnType Sbc_fs26_SetWakeup(Sbc_fs26_WuSrcType WakeupSrc, Sbc_fs26_WuPolType WakeupPol)
{
    uint16 u16WriteData;                /* Register value to write. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETWAKEUP, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        u16WriteData = Sbc_fs26_CreateWakeupSrcPayload(WakeupSrc);
        u16WriteData |= Sbc_fs26_CreateWakeupPolPayload(WakeupPol);
        /* Configure AMUX. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_WIO_CFG_ADDR, u16WriteData, NULL_PTR);
    }

    return eReturnValue;
}

/**
* @brief        Reads device wake up flags. SID is 0x0D.
* @details      This function reads device wake up flags and clears them if requested.
*               The device has dedicated wake up flags for WAKE1/2, GPIO1/2 and LDT sources,
*               but also reports general wake up status, which contains also sources such as
*               deep fail safe recovery, battery fail or SPI wake up (see datasheet).
*
* @param[in]    ClearFlags      TRUE = clear wake up flags after reading.
* @param[out]   pWakeupReason   Status of wake up flags.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GetWakeup_Activity */
Std_ReturnType Sbc_fs26_GetWakeup(boolean ClearFlags, Sbc_fs26_WuReasonType* pWakeupReason)
{
    Sbc_fs26_RxFrameType rxData;        /* Register received data. */
    Std_ReturnType eReturnValue = E_OK; /* Status. */

#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == pWakeupReason)
    {
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETWAKEUP, (uint8)SBC_FS26_E_PARAM_POINTER);
        eReturnValue = E_NOT_OK;
    }
    else
    {
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */

    if (FALSE == Sbc_fs26_IsInitialized)
    {
        /* Driver not initialized. */
        eReturnValue = E_NOT_OK;
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETWAKEUP, (uint8)SBC_FS26_E_UNINIT);
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    }
    else
    {
        eReturnValue = Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_WIO_FLG_ADDR, &rxData);
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            pWakeupReason->bWk1Flag = (1U == ((rxData.u16ReadData & SBC_FS26_M_WK1_I_MASK) >> SBC_FS26_M_WK1_I_SHIFT)) ? TRUE : FALSE;
            pWakeupReason->bWk2Flag = (1U == ((rxData.u16ReadData & SBC_FS26_M_WK2_I_MASK) >> SBC_FS26_M_WK2_I_SHIFT)) ? TRUE : FALSE;
            pWakeupReason->bGpio1Flag = (1U == ((rxData.u16ReadData & SBC_FS26_M_GPIO1_I_MASK) >> SBC_FS26_M_GPIO1_I_SHIFT)) ? TRUE : FALSE;
            pWakeupReason->bGpio2Flag = (1U == ((rxData.u16ReadData & SBC_FS26_M_GPIO2_I_MASK) >> SBC_FS26_M_GPIO2_I_SHIFT)) ? TRUE : FALSE;
            pWakeupReason->bLdtFlag = (1U == ((rxData.u16ReadData & SBC_FS26_M_LDT_I_MASK) >> SBC_FS26_M_LDT_I_SHIFT)) ? TRUE : FALSE;
            pWakeupReason->u8WuEvent = (uint8)((rxData.u16ReadData & SBC_FS26_M_WUEVENT_MASK) >> SBC_FS26_M_WUEVENT_SHIFT);

            if(TRUE == ClearFlags)
            {
                eReturnValue |= Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_WIO_FLG_ADDR, SBC_FS26_M_WU_CLR_CLEAR_ALL, NULL_PTR);
            }
        }
    }
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    }
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    return eReturnValue;
}

#if (SBC_FS26_VERSION_INFO_API == STD_ON)
/*================================================================================================*/
/**
* @brief        FS26 driver get version info function. SID is 0x0E.
* @details      Returns the version information of this module.
*
* @param[out]   pVersionInfo    Pointer to where to store the version information of this module.
*
* @return       void
*
* @api
*/
/** @implements   Sbc_fs26_GetVersionInfo_Activity */
void Sbc_fs26_GetVersionInfo(Std_VersionInfoType* pVersionInfo)
{
#if (SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == pVersionInfo)
    {
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETVERSIONINFO, (uint8)SBC_FS26_E_PARAM_POINTER);
    }
    else
    {
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
    pVersionInfo->vendorID = (uint16)SBC_FS26_VENDOR_ID;
    pVersionInfo->moduleID = (uint8)SBC_FS26_MODULE_ID;
    pVersionInfo->sw_major_version = (uint8)SBC_FS26_SW_MAJOR_VERSION;
    pVersionInfo->sw_minor_version = (uint8)SBC_FS26_SW_MINOR_VERSION;
    pVersionInfo->sw_patch_version = (uint8)SBC_FS26_SW_PATCH_VERSION;
#if(SBC_FS26_DEV_ERROR_DETECT == STD_ON)
    }
#endif /* SBC_FS26_DEV_ERROR_DETECT == STD_ON */
}
#endif /* SBC_FS26_VERSION_INFO_API == STD_ON */

/*================================================================================================*/
/**
* @brief        Deinitializes the FS26 driver. SID is 0x0F.
* @details      Clears the internal run-time configuration.
*
* @return       void
*
* @api
*/
/** @implements   Sbc_fs26_Deinit_Activity */
void Sbc_fs26_Deinit(void)
{
    /* Clear the local copy of the driver initialization structure. */
    Sbc_fs26_pConfigPtr = NULL_PTR;

    /* Driver not initialized. */
    Sbc_fs26_IsInitialized = FALSE;
}

#define SBC_FS26_STOP_SEC_CODE
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */
