/*==================================================================================================
*   Project              : RTD AUTOSAR 4.9
*   Platform             : CORTEXM
*   Peripheral           : FS26
*   Dependencies         :
*
*   Autosar Version      : 4.9.0
*   Autosar Revision     : ASR_REL_4_9_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 6.0.0
*   Build Version        : S32K3_RTD_6_0_0_D2511_ASR_REL_4_9_REV_0000_20251114
*
*   Copyright 2020 - 2025 NXP
*
*   NXP Confidential and Proprietary. 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.
==================================================================================================*/

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

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                        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 "SchM_Sbc_fs26.h"
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
    #include "Det.h"
#endif /* (STD_ON == SBC_FS26_DEV_ERROR_DETECT) */
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
#include "OsIf.h"
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#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       9
#define SBC_FS26_AR_RELEASE_REVISION_VERSION_C    0
#define SBC_FS26_SW_MAJOR_VERSION_C               6
#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

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Check if current file and SchM_Sbc_fs26 header file are of the same version */
    #if ((SBC_FS26_AR_RELEASE_MAJOR_VERSION_C != SCHM_SBC_FS26_AR_RELEASE_MAJOR_VERSION) || \
         (SBC_FS26_AR_RELEASE_MINOR_VERSION_C != SCHM_SBC_FS26_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of CDD_Sbc_fs26.c and SchM_Sbc_fs26.h are different"
    #endif
    #if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    /* Check if this source file and OsIf.h file are of the same Autosar version */
        #if ((SBC_FS26_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
            (SBC_FS26_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION))
            #error "AutoSar Version Numbers of CDD_Sbc_fs26.c and OsIf.h are different"
        #endif
    #endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
    /* Check if current file and DET header file are of the same version */
    #if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        #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 SPI register address shift.
*/
#define SBC_FS26_REG_ADDR_SHIFT_U8    ((uint8)(0x01U))

/**
* @brief Command type field mask.
*/
#define SBC_FS26_CMD_TYPE_MASK_U8     ((uint8)(0x01U))
/* CRC macros used for SPI communication. */
/**
* @brief Size of CRC table.
*/
#define SBC_FS26_CRC_TBL_SIZE_U16     ((uint16)(256U))
/**
* @brief CRC initial value.
*/
#define SBC_FS26_COM_CRC_INIT_U8      ((uint8)(0xFFU))

/**
* @brief Time wait to check Abist 2 done.
*/
#define SBC_FS26_WAIT_ABIST2_U16      ((uint16)(10000U))

/**
* @brief Time wait device to Init FS state.
*/
#define SBC_FS26_WAIT_INITFS_U16      ((uint16)(10000U))

/**
* @brief Maximum register address.
*/
#define SBC_FS26_MAX_REG_ADD_U8       ((uint8)(0x3CU))

/**
* @brief MISO general device status bits mask.
*/
#define SBC_FS26_DEVICE_STATUS_MASK_U8  ((uint8)(0x37U))

/*==================================================================================================
*                                      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 au8CrcTable[SBC_FS26_CRC_TBL_SIZE_U16] = {
    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
==================================================================================================*/
#ifdef SBC_FS26_ASYNC_TRANSMIT
    #define SBC_FS26_START_SEC_VAR_CLEARED_8_NO_CACHEABLE
    #include "Sbc_fs26_MemMap.h"
    /**
    * @brief Transmit queue
    */
    static uint8 Sbc_fs26_apxTxQueueBuffer[SBC_FS26_QUEUE_LEN][SBC_FS26_COMM_FRAME_SIZE_U8];
    #define SBC_FS26_STOP_SEC_VAR_CLEARED_8_NO_CACHEABLE
    #include "Sbc_fs26_MemMap.h"

    #define SBC_FS26_START_SEC_VAR_CLEARED_UNSPECIFIED
    #include "Sbc_fs26_MemMap.h"
    /**
    * @brief Receive shadow buffer
    */
    static Sbc_fs26_RxFrameType * Sbc_fs26_apxRxShadowBuffer[SBC_FS26_QUEUE_LEN];
    /**
     * @brief Local Queue Handle
     *
     */
    static Sbc_fs26_BufferRingType Sbc_fs26_apxTxBufferRing;
    static Sbc_fs26_DataRingType Sbc_fs26_apxRxDataRing;
    #define SBC_FS26_STOP_SEC_VAR_CLEARED_UNSPECIFIED
    #include "Sbc_fs26_MemMap.h"

    #define SBC_FS26_START_SEC_VAR_INIT_UNSPECIFIED
    #include "Sbc_fs26_MemMap.h"
    /**
     * @brief Internal Transmission status
     *
     */
    static volatile Sbc_fs26_SpiAsyncStatusType Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_DONE;
    #define SBC_FS26_STOP_SEC_VAR_INIT_UNSPECIFIED
    #include "Sbc_fs26_MemMap.h"
#endif /*SBC_FS26_ASYNC_TRANSMIT*/

#define SBC_FS26_START_SEC_VAR_CLEARED_8_NO_CACHEABLE
#include "Sbc_fs26_MemMap.h"
/**
* @brief Receive buffer
*/
static uint8 Sbc_fs26_au8RxBuffer[SBC_FS26_COMM_FRAME_SIZE_U8];
/**
* @brief Transmit buffer
*/
static uint8 Sbc_fs26_au8TxBuffer[SBC_FS26_COMM_FRAME_SIZE_U8];
#define SBC_FS26_STOP_SEC_VAR_CLEARED_8_NO_CACHEABLE
#include "Sbc_fs26_MemMap.h"

#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 const Sbc_fs26_ConfigType* pSbcFs26ConfigPtr;

/**
* @brief Local info of Spi in used.
*/
static Sbc_fs26_SpiSetupType xSpiSetup;

#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 bIsInitialized;

/**
* @brief Allow or prevent watchdog trigger.
*/
static boolean bGateWdgTrigger;

/**
* @brief Indicate watchdog trigger in progress or not.
*/
static boolean bIsWdgTrigger;

#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_UNSPECIFIED
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
/**
* @brief Global copy of the wdg token.
*/
static Sbc_fs26_RxFrameType xWdwToken;

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

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

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
#define SBC_FS26_START_SEC_CODE
/**
* @brief Include Memory mapping specification
*/
#include "Sbc_fs26_MemMap.h"
#ifdef SBC_FS26_ASYNC_TRANSMIT
    static inline void Sbc_fs26_MemCopy(const uint8 *pSrc,
                                        uint8 *pDes);

    static inline void Sbc_fs26_DataBufferQueuePush(Sbc_fs26_DataRingType* pRing,
                                                    Sbc_fs26_RxFrameType * pDataDes);

    static void Sbc_fs26_DataBufferQueueParse(Sbc_fs26_DataRingType* pRing,
                                              const uint8* u8Data);

    static Std_ReturnType Sbc_fs26_TxQueuePush(Sbc_fs26_BufferRingType* pRing,
                                             const uint8* u8Data);

    static Std_ReturnType Sbc_fs26_TxQueuePop(Sbc_fs26_BufferRingType* pRing,
                                              uint8** pData);

    static Std_ReturnType Sbc_fs26_WaitTransmissionDone(void);

    static Std_ReturnType Sbc_fs26_TransferDataAsync(const Sbc_fs26_TxFrameType* pxTxData);
#else
/**
* @brief        Performs SPI transfer.
*
* @param[in]    pTxData          TX data.
* @param[out]   pRxData          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);
#endif /*SBC_FS26_ASYNC_TRANSMIT*/

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


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

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

#if (STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)
/**
* @brief        Computes Challenger Watchdog answer.
*
* @param[in]    u16Token           Challenge token.
*
* @return       uint16          Result of calculation.
*/
static uint16 Sbc_fs26_WdComputeAnswer(uint16 u16Token);

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

/**
* @brief        The procedure to compute the RELEASE_FS0B_FS1B [15:0] value to release the safety outputs
*
* @param[in]    eFsOutput       FS output to release.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_ComputeReleaseFsxbValue(Sbc_fs26_FsOutputType eFsOutput);

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

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

#if (STD_ON == SBC_FS26_LDT_FUNCTION_API)
/**
* @brief        Check parameters for set LDT function.
*
* @param[in]    eLdtFunction      LDT function.
* @param[in]    eLdtMode          LDT mode.
* @param[in]    eLdtLp            LDT low power.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckParametersSetLDT(Sbc_fs26_LdtFuncType eLdtFunction,
                                                     Sbc_fs26_LdtModeType eLdtMode,
                                                     Sbc_fs26_LdtLpType eLdtLp);
#endif /* (STD_ON == SBC_FS26_LDT_FUNCTION_API) */

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

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

/**
* @brief        Check Register and Otp Error
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckRegAndOTPCorrupt(void);

/**
* @brief        Initialize SBC register
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_InitFSConfigure(void);

/**
* @brief        Check mandatory conditions and initialize register
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_DoInitRegister(void);
#if (STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED)
/**
* @brief        Leave debug mode state
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_ExitDebugMode(void);
#endif /*STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED*/
/**
* @brief        Time wait need to clear fault error counter
*
* @param[in]    u32TimeValueUs            Time wait.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_TimeWaitClearFault(const uint32 u32TimeValueUs);
/**
* @brief        Decrease fault error counter to zero
*
* @param[in]    u8FaultErrorValue         Number of fault error counter.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_ClearFaultErrorCounter(void);

#if (STD_ON == SBC_FS26_ABIST2_CHECK_API)
/**
* @brief        Wait for Abist 2 check done and check pass then
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_WaitAbist2DoneAndPass(void);
#endif /* (STD_ON == SBC_FS26_ABIST2_CHECK_API) */

#if (STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)
/**
* @brief        Implement Watchdog trigger process
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_DoWatchdogTriggerProcess(void);
#endif /*(STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)*/

/**
* @brief        Check state and switch device to Init FS state
*
* @param[in]    u16DeviceFSState         Current State of Fail Safe state machine.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_CheckDeviceStateAndGotoInitFS(void);
#if (STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED)
/**
* @brief        Wait until InitFS is closed
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_WaitInitFSClosed(void);
#endif /*STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED*/
/**
* @brief        Wait until Fail-safe pins are released
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_WaitFailsafeRelease(Sbc_fs26_FsOutputType FsOutput);

/**
* @brief        Switch device to Normal FS state
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_NormalFSSequence(Sbc_fs26_DeviceState eDeviceState);

/**
* @brief        Release FSxB pins sequence
*
* @param[in]    eFsOutput         Fs release output option.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_ReleaseSequence(Sbc_fs26_FsOutputType eFsOutput);

#if (STD_ON == SBC_FS26_WAKEUP_API)
/**
* @brief        Validate device's wake-up reasons
*
* @param[in]    u16WuEvent      Data retrieved from M_WIO_FLG register.
*
* @return       Std_ReturnType  Return code
*/
static Std_ReturnType Sbc_fs26_ValidateWakeup(uint16 u16WuEvent);
#endif/*STD_ON == SBC_FS26_WAKEUP_API*/
/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/
#ifdef SBC_FS26_ASYNC_TRANSMIT
static inline void Sbc_fs26_MemCopy(const uint8 *pSrc,
                                    uint8 *pDes)
{
    /*Copy data from Src to Dest address*/
    uint8 u8Index = 0U;

    if (NULL_PTR == pSrc)
    {
        /* Clear destination buffer*/
        for (u8Index = 0U; u8Index < SBC_FS26_COMM_FRAME_SIZE_U8; u8Index++)
        {
            pDes[u8Index] = 0U;
        }
    }
    else
    {
        /*Copy from source to destination buffer*/
        for (u8Index = 0; u8Index < SBC_FS26_COMM_FRAME_SIZE_U8; u8Index++)
        {
            pDes[u8Index] = pSrc[u8Index];
        }
    }
}

static inline void Sbc_fs26_DataBufferQueuePush(Sbc_fs26_DataRingType* pRing,
                                                Sbc_fs26_RxFrameType * pDataDes)
{
    if (pRing->u32Head >= pRing->u32Maxlen)
    {
        /*Roll-over*/
        pRing->u32Head = 0U;
    }

    /* Map to destination*/
    pRing->pData[pRing->u32Head] = pDataDes;
    pRing->u32Head+=1U;
}

static void Sbc_fs26_DataBufferQueueParse(Sbc_fs26_DataRingType* pRing,
                                          const uint8* u8Data)
{
    Sbc_fs26_RxFrameType * pRxData;

    /* Pop buffer address out of queue*/
    if (pRing->u32Tail >= pRing->u32Maxlen)
    {
        pRing->u32Tail = 0U;
    }
    pRxData = pRing->pData[pRing->u32Tail];
    /* Parse data*/
    if (pRxData != NULL_PTR)
    {
        pRxData->u8DeviceStatus = u8Data[0U];
        pRxData->u16ReadData = (((uint16)u8Data[1U] << 8U) | (uint16)u8Data[2U]) & (uint16)0xFFFFU;
    }
    pRing->u32Tail +=1U;
}

/* Push one element to the Tx queue. */
static Std_ReturnType Sbc_fs26_TxQueuePush(Sbc_fs26_BufferRingType* pRing,
                                           const uint8* u8Data)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */
    /* next is where head will point to after this write.*/
    uint32 u32Next = pRing->u32Head + 1U;

    if (u32Next >= pRing->u32Maxlen)
    {
        /*Roll-over*/
        u32Next = 0U;
    }
    /* if the head + 1 == tail, circular buffer is full */
    if (u32Next != pRing->u32Tail)
    {
        Sbc_fs26_MemCopy(u8Data, pRing->paBuffer[pRing->u32Head]);
        /* head to next data offset. */
        pRing->u32Head = u32Next;
        eReturnValue = (Std_ReturnType)E_OK;
    }

    return eReturnValue;        /* return success to indicate successful push */
}

/* Remove one element from the Tx queue. */
static Std_ReturnType Sbc_fs26_TxQueuePop(Sbc_fs26_BufferRingType* pRing,
                                          uint8** pData)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK;
    uint32 u32Next;

    /* if the head == tail, we don't have any data */
    if (pRing->u32Head != pRing->u32Tail)
    {
        /* next is where tail will point to after this read */
        u32Next = pRing->u32Tail + 1U;
        if (u32Next >= pRing->u32Maxlen)
        {
            u32Next = 0U;
        }

        *pData = (pRing->paBuffer[pRing->u32Tail]);

        pRing->u32Tail = u32Next;
        /* tail to next offset. */
        eReturnValue = (Std_ReturnType)E_OK;
    }

    return eReturnValue;
}

static Std_ReturnType Sbc_fs26_WaitTransmissionDone(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    volatile uint32 u32TimeOut = 0U;

#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;

    u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_TIMEOUT_DURATION_U32, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
#else
    u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
    /* Wait until InitFS being closed */
    do
    {
        if (SBC_FS26_TRANS_FAILED == Sbc_fs26_Transmission_Status)
        {
            /* Fail state catches */
            eReturnValue = (Std_ReturnType)E_NOT_OK;
            break;
        }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
        u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    } while ((u32ElapsedTicks <= u32TimeOut) && (SBC_FS26_TRANS_ON_GOING == Sbc_fs26_Transmission_Status));
    if (u32ElapsedTicks > u32TimeOut)
    {
#else
        u32TimeOut--;
    } while (((uint32)0U < u32TimeOut) && (SBC_FS26_TRANS_ON_GOING == Sbc_fs26_Transmission_Status));
    if ((uint32)0U == u32TimeOut)
    {
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
        eReturnValue = (Std_ReturnType)E_NOT_OK;
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
        if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
        }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
    }

    return eReturnValue;
}

static Std_ReturnType Sbc_fs26_TransferDataAsync(const Sbc_fs26_TxFrameType* pxTxData)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    uint8 *pTxBuffer = NULL_PTR;
    Sbc_fs26_SpiStatusType SpiStatus = SPI_TRANS_OK;

    /* Create the SPI tx frame */
    Sbc_fs26_CreateSendFrame(pxTxData, Sbc_fs26_au8TxBuffer);
    SpiStatus = Sbc_fs26_GetTransmissionStatus(&xSpiSetup);
    if (SPI_TRANS_FAILED == SpiStatus)
    {
        /* Unexpected behaviour from SPI*/
        Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_FAILED;
        eReturnValue = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* Push into TxQueue*/
        eReturnValue = Sbc_fs26_TxQueuePush(&Sbc_fs26_apxTxBufferRing, Sbc_fs26_au8TxBuffer);
        /* Trigger the SPI transfer if Spi status is idle*/
        if (((Std_ReturnType)E_OK == eReturnValue) && (SPI_TRANS_OK == SpiStatus))
        {
            (void)Sbc_fs26_TxQueuePop(&Sbc_fs26_apxTxBufferRing, &pTxBuffer);
            /*Deque TxQueue and send the data*/
            Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_ON_GOING;
            eReturnValue = Sbc_fs26_SpiPrepareBuffer(&xSpiSetup, pTxBuffer, Sbc_fs26_au8RxBuffer);
            eReturnValue |= Sbc_fs26_SpiTransferExternal(&xSpiSetup,pTxBuffer,Sbc_fs26_au8RxBuffer);
        }
    }

    return eReturnValue;
}
#else
/* Performs SPI transfer. */
static Std_ReturnType Sbc_fs26_TransferData(const Sbc_fs26_TxFrameType* pTxData,
                                            Sbc_fs26_RxFrameType* pRxData)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

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

    /* Trigger the SPI transfer */
    /* Enter critical section. */
    SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_00();
    eReturnValue = Sbc_fs26_SpiTransferExternal(&xSpiSetup, Sbc_fs26_au8TxBuffer, Sbc_fs26_au8RxBuffer);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* Check the CRC of the retrieved frame */
        eReturnValue = (Sbc_fs26_au8RxBuffer[3] == Sbc_fs26_CalcCrc(Sbc_fs26_au8RxBuffer)) ? (Std_ReturnType)E_OK : (Std_ReturnType)E_NOT_OK;

        if (((Std_ReturnType)E_OK == eReturnValue) && (NULL_PTR != pRxData))
        {
            /* Copy the retrieved data into the user provided buffer */
            pRxData->u8DeviceStatus = Sbc_fs26_au8RxBuffer[0];
            pRxData->u16ReadData = (((uint16)Sbc_fs26_au8RxBuffer[1U] << 8U) | (uint16)Sbc_fs26_au8RxBuffer[2U]) & (uint16)0xFFFFU;

#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
            /* Check the device's responded status */
            if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.state)
            {
                if (0U == (pRxData->u8DeviceStatus & SBC_FS26_DEVICE_STATUS_MASK_U8))
                {
                    (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.id, DEM_EVENT_STATUS_PASSED);
                }
                else
                {
                    (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.id, DEM_EVENT_STATUS_FAILED);
                }
            }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
        }
    }
    SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_00();

    return eReturnValue;
}

#endif /*SBC_FS26_ASYNC_TRANSMIT*/
/* This function calculates CRC value of passed data array. */
static uint8 Sbc_fs26_CalcCrc(const uint8* pu8Data)
{
    uint8 u8Crc = SBC_FS26_COM_CRC_INIT_U8;      /* Result. */
    uint8 u8TableIdx = 0U; /* Index to the CRC table. */
    uint8 u8DataIdx = 0U;  /* Index to the data array (memory). */

    /* Calculate CRC. */
    for (u8DataIdx = 0U; u8DataIdx < (SBC_FS26_COMM_FRAME_SIZE_U8 - 1U); u8DataIdx++)
    {
        u8TableIdx = u8Crc ^ pu8Data[u8DataIdx];
        u8Crc = au8CrcTable[u8TableIdx];
    }

    return u8Crc;
}

/* Creates a raw frame for SPI transfer. */
static void Sbc_fs26_CreateSendFrame(const Sbc_fs26_TxFrameType* pTxData,
                                     uint8* pu8TxFrame)
{
    /* Selects register set (main x fail-safe). */
    pu8TxFrame[0U] = pTxData->bIsFailSafe ? 0x80U : 0x00U;
    /* Sets address of the register. */
    pu8TxFrame[0U] |= pTxData->u8RegisterAddress << SBC_FS26_REG_ADDR_SHIFT_U8;

    /* check if register is r or w */
    if (SBC_FS26_COM_READ == pTxData->commandType)
    {
        /* Creates read command. */
        pu8TxFrame[0U] = pu8TxFrame[0U] & (~SBC_FS26_CMD_TYPE_MASK_U8);
        /* No data to be sent. */
        pu8TxFrame[1U] = 0x00;
        pu8TxFrame[2U] = 0x00;
    }
    else
    {
        /* Creates write command. */
        pu8TxFrame[0U] |= SBC_FS26_CMD_TYPE_MASK_U8;
        /* Sets data - MSB first. */
        pu8TxFrame[1U] = (uint8)(pTxData->u16WriteData >> 8U);
        pu8TxFrame[2U] = (uint8)(pTxData->u16WriteData & 0x00FFU);
    }

    /* Sets CRC. */
    pu8TxFrame[3U] = Sbc_fs26_CalcCrc(pu8TxFrame);
}

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

    /* Enter critical section. */
    SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_01();
    eReturnValue = Sbc_fs26_WriteRegister(TRUE, u8Address, u16WriteData);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* _NOT_ registers have address +1 from normal register. */
        u8AddressNot = (uint8)(u8Address + 1U);
        /* Inverted value should be written to _NOT_ register. */
        u16WriteDataInv = (uint16)~u16WriteData;
        eReturnValue = Sbc_fs26_WriteRegister(TRUE, u8AddressNot, u16WriteDataInv);
    }
    /* Exit critical section. */
    SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_01();

    return eReturnValue;
}


#if (STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)
/* Computes Challenger Watchdog answer. */
static uint16 Sbc_fs26_WdComputeAnswer(uint16 u16Token)
{
    uint32 u32Mr = (uint32)u16Token; /* Monitoring result. */

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

    return (uint16)u32Mr;
}

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

#ifndef SBC_FS26_ASYNC_TRANSMIT
    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_GRL_FLAGS_ADDR, &xRxData);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if (NULL_PTR != pSbcFs26ConfigPtr->pfWdRefreshFaultNotification)
        {
            pSbcFs26ConfigPtr->pfWdRefreshFaultNotification(xRxData.u16ReadData);
        }
#ifndef SBC_FS26_ASYNC_TRANSMIT
        if (SBC_FS26_FS_FS_WD_G_BAD_REFRESH == (xRxData.u16ReadData & SBC_FS26_FS_FS_WD_G_MASK))
        {
            eReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    }
#endif /*SBC_FS26_ASYNC_TRANSMIT*/

    return eReturnValue;
}
#endif /*(STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)*/

static Std_ReturnType Sbc_fs26_ComputeReleaseFsxbValue(Sbc_fs26_FsOutputType eFsOutput)
{
    uint8 u8Index = 0U;                      /* Counter. */
    uint16 u16ReleaseWrite = 0U;             /* Value to be written to the FS_RELEASE_FS0B_FS1B register. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    /* Enter critical section. */
    SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_05();
    for (u8Index = 0U; u8Index < 16U; u8Index++)
    {
        u16ReleaseWrite |= (uint16)((((xWdwToken.u16ReadData >> (15U - u8Index)) & (uint16)1U) << u8Index) & (uint16)0xFFFFU);
    }

    u16ReleaseWrite = ~u16ReleaseWrite;
    /* Replace bits 15 to 13 with FS outputs code. */
    u16ReleaseWrite = ((uint16)eFsOutput & 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);

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

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_WAKEUP_API)
/* Create wake up source payload for configuring wake up from low-power mode */
static uint16 Sbc_fs26_CreateWakeupSrcPayload(Sbc_fs26_WuSrcType xWakeupSrc)
{
    uint16 u16WriteData = 0U;                /* Register value to write. */

    u16WriteData = (((TRUE == xWakeupSrc.bWk1WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WK1WUEN_SHIFT) |
                (((TRUE == xWakeupSrc.bWk2WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_WK2WUEN_SHIFT) |
                (((TRUE == xWakeupSrc.bGpio1WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO1WUEN_SHIFT) |
                (((TRUE == xWakeupSrc.bGpio2WuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_GPIO2WUEN_SHIFT) |
                (((TRUE == xWakeupSrc.bLdtWuEnabled) ? (uint16)1U : (uint16)0U) << SBC_FS26_M_LDTWUEN_SHIFT) |
                (((TRUE == xWakeupSrc.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 xWakeupPol)
{
    uint16 u16WriteData = 0U;                /* Register value to write. */

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

    return u16WriteData;
}
#endif /* (STD_ON == SBC_FS26_WAKEUP_API) */

#if (STD_ON == SBC_FS26_LDT_FUNCTION_API)
/* Check paramters for setting LDT*/
static Std_ReturnType Sbc_fs26_CheckParametersSetLDT(Sbc_fs26_LdtFuncType eLdtFunction,
                                                     Sbc_fs26_LdtModeType eLdtMode,
                                                     Sbc_fs26_LdtLpType eLdtLp)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    if ((SBC_FS26_LDTFUNC_FUNC5 < eLdtFunction) || ((SBC_FS26_LDTMODE_LONG != eLdtMode) &&
            (SBC_FS26_LDTMODE_SHORT != eLdtMode)) || ((SBC_FS26_LDTLP_LPOFF != eLdtLp) && (SBC_FS26_LDTLP_STANDBY != eLdtLp)))
    {
        eReturnValue = (Std_ReturnType)E_NOT_OK;
    }

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_LDT_FUNCTION_API) */

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

    if ((SBC_FS26_FS_FS0B != eFsOutput) && (SBC_FS26_FS_FS1B != eFsOutput) && (SBC_FS26_FS_BOTH != eFsOutput))
    {
        eReturnValue = (Std_ReturnType)E_NOT_OK;
    }

    return eReturnValue;
}

/* Perform LBIST and ABIST tests. */
static Std_ReturnType Sbc_fs26_CheckLBistABist1(void)
{
    Sbc_fs26_RxFrameType xRxData = {0};       /* Response to the command. */
    uint16 u16CheckMask = 0U;                /* Mask for reading of value. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
    eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
    u16CheckMask = xRxData.u16ReadData & SBC_FS26_FS_ABIST1_PASS_MASK;
    if (u16CheckMask == SBC_FS26_FS_ABIST1_PASS_FAIL)
    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
    }

    if ((TRUE == pSbcFs26ConfigPtr->bAsilDLevel))
    {
        u16CheckMask = xRxData.u16ReadData & SBC_FS26_FS_LBIST_STATUS_MASK;
        if ((u16CheckMask == SBC_FS26_FS_LBIST_STATUS_FAIL) || (u16CheckMask == SBC_FS26_FS_LBIST_STATUS_RESERVED))
        {
            eReturnValue |= (Std_ReturnType)E_NOT_OK;
        }
    }

    return eReturnValue;
}

/* Perform check if Reg corrupt or OTP corrupt  */
static Std_ReturnType Sbc_fs26_CheckRegAndOTPCorrupt(void)
{
    Sbc_fs26_RxFrameType xRxData = {0};        /* Response to the command. */
    uint16 u16CheckMask = 0U;                 /* Mask for reading of value. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_STATES_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
    eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
    u16CheckMask = xRxData.u16ReadData & SBC_FS26_FS_OTP_CORRUPT_MASK;
    if (u16CheckMask == SBC_FS26_FS_OTP_CORRUPT_ERROR)
    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
    }

    u16CheckMask = xRxData.u16ReadData & SBC_FS26_FS_REG_CORRUPT_MASK;
    if (u16CheckMask == SBC_FS26_FS_REG_CORRUPT_ERROR)
    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
    }

    return eReturnValue;
}

/* Writes all the INIT_FS registers of SBC device. */
static Std_ReturnType Sbc_fs26_InitFSConfigure(void)
{
    uint16 u16WriteData = 0U;                /* Register value to write. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    /* Write INIT_FS registers. */
    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonPreOvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonPreUvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonCoreOvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonCoreUvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonLdo1OvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonLdo1UvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonLdo2OvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe1Reg.u16VmonLdo2UvFs);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_OVUV_SAFE_REACTION1_ADDR, u16WriteData);

    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonExtOvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonExtUvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonRefOvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonRefUvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonTrk2OvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonTrk2UvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonTrk1OvFs |
            pSbcFs26ConfigPtr->pInitConfig->xOvuvSafe2Reg.u16VmonTrk1UvFs);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_OVUV_SAFE_REACTION2_ADDR, u16WriteData);

    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16FccuCfg |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu12FltPol |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu1FltPol |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu2FltPol |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu12Fs |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu1Fs |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu2Fs |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Wake2LpPol |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16ErrmonFaultPol |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16ErrmonAckTime |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16ErrmonFs |
            pSbcFs26ConfigPtr->pInitConfig->xSafeInputsReg.u16Fccu12Filt);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_SAFE_INPUTS_ADDR, u16WriteData);

    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16FltErrCntLimit |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16FltErrFs |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16RstbDur |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16BackupFs0b |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16BackupFs1b |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16ClkMonDis |
            pSbcFs26ConfigPtr->pInitConfig->xFssmReg.u16Dis8s);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_FSSM_ADDR, u16WriteData);

    /* Configure INTB events */
    eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_INTB_MASK_ADDR,pSbcFs26ConfigPtr->pInitConfig->u16IntbMaskValue);

    /* Configure Abist source to be checked */
    eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_ABIST_ON_DEMAND_ADDR,pSbcFs26ConfigPtr->pInitConfig->u16Abist2Value);

#if (STD_OFF == SBC_FS26_EXTERNAL_WDG_USED)
    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xWdCfgReg.u16WdErrLimit |
            pSbcFs26ConfigPtr->pInitConfig->xWdCfgReg.u16WdRfrLimit |
            pSbcFs26ConfigPtr->pInitConfig->xWdCfgReg.u16WdFs);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_I_WD_CFG_ADDR, u16WriteData);

    u16WriteData = (uint16) (pSbcFs26ConfigPtr->pInitConfig->xWdwDurationReg.u16WdwPeriod |
            pSbcFs26ConfigPtr->pInitConfig->xWdwDurationReg.u16WdwDc |
            pSbcFs26ConfigPtr->pInitConfig->xWdwDurationReg.u16WdwRecovery);
    eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_WDW_DURATION_ADDR, u16WriteData);

    /* Change to new watchdog token configuration */
    eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, pSbcFs26ConfigPtr->u16WatchdogToken);
    xWdwToken.u16ReadData = pSbcFs26ConfigPtr->u16WatchdogToken;
#endif /* (STD_OFF == SBC_FS26_EXTERNAL_WDG_USED) */

    return eReturnValue;
}

static Std_ReturnType Sbc_fs26_DoInitRegister(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */

    /* Perform LBIST & ABIST1 check. */
    eReturnValue = Sbc_fs26_CheckLBistABist1();

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* Perform initialization of Init register  */
        eReturnValue = Sbc_fs26_InitFSConfigure();
    }

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED)
static Std_ReturnType Sbc_fs26_ExitDebugMode(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData = {0};

    eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_STATES_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
    eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
    /* Check if device is in Debug Mode */
    if (SBC_FS26_FS_DBG_MODE_DEBUG == (xRxData.u16ReadData & SBC_FS26_FS_DBG_MODE_MASK))
    {
        /* EXIT_DBG_MODE = 1 */
        eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_STATES_ADDR, SBC_FS26_FS_EXIT_DBG_MODE_MASK);
    }

    return eReturnValue;
}
#endif /*STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED*/
static Std_ReturnType Sbc_fs26_TimeWaitClearFault(const uint32 u32TimeValueUs)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    volatile uint32 u32TimeOut = 0U;
    uint8 u8ErrorCounter = 0U;

#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;
    volatile OsIf_CounterType eOsIfType = (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE;

    if (OSIF_COUNTER_DUMMY == eOsIfType)
    {
        (void)u32TimeValueUs;
        u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_TIMEOUT_DURATION_U32, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    }
    else
    {
        u32TimeOut = OsIf_MicrosToTicks(u32TimeValueUs, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    }

    u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);

    /* Wait for the Fault Error Counter is decremented to 0 */
    do
    {
        u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    } while (u32ElapsedTicks <= u32TimeOut);
#else

    (void)u32TimeValueUs;
    u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
    /* Dummy Wait for the Fault Error Counter is decremented to 0 */
    do
    {
        u32TimeOut--;
    } while ((uint32)0U < u32TimeOut);
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
    eReturnValue = Sbc_fs26_GetFaultErrorCounterValue(&u8ErrorCounter);

    if (u8ErrorCounter > 0U)
    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
    }

#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
    if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
    {
        if ((Std_ReturnType)E_NOT_OK == eReturnValue)
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
        }
        else
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_PASSED);
        }
    }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */

    return eReturnValue;
}

static Std_ReturnType Sbc_fs26_ClearFaultErrorCounter(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData1 = {0};            /* FS_I_WD_CFG register value */
    Sbc_fs26_RxFrameType xRxData2 = {0};            /* FS_WDW_DURATION register value */
    uint16 u16WdgRfrRequest = 0U;                   /* Expect number wdg refresh for decreasing fault error */
    uint16 u16WriteData = 0U;
    uint8 u8WdgRfrLimit = 0U;                       /* Number of wdg refresh limit */
    uint8 u8FaultErrorValue = 0U;
    const uint8 au8ArrayRfrLimitValue[4U] = {6U, 4U, 2U, 1U};
    const uint32 au32ArrayWindowPeriodToUs[16U] =
    {
        0U,
        1000U,
        2000U,
        3000U,
        4000U,
        6000U,
        8000U,
        12000U,
        16000U,
        24000U,
        32000U,
        64000U,
        128000U,
        256000U,
        512000U,
        1024000U
    };

    /* Remove OVUV error */
    u16WriteData = (uint16)0xFFFFU;
    eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_OVUV_REG_STATUS_ADDR, u16WriteData);
    /* Remove FCCUx and ERRMON error */
    u16WriteData = SBC_FS26_FS_ERRMON_ERROR | SBC_FS26_FS_FCCU1_ERROR | SBC_FS26_FS_FCCU2_ERROR | SBC_FS26_FS_FCCU12_ERROR;
    eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY2_ADDR, u16WriteData);
    /* Clear Spi fault and Fail-safe oscillator drift flag */
    u16WriteData = SBC_FS26_FS_SPI_FS_CRC_ERROR | SBC_FS26_FS_SPI_FS_REQ_ERROR | SBC_FS26_FS_SPI_FS_CLK_ERROR | SBC_FS26_FS_FS_OSC_DRIFT_DRIFT;
    eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, u16WriteData);
    /* Decrease fault error counter to zero */
    eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_I_WD_CFG_ADDR, &xRxData1);
    eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WDW_DURATION_ADDR, &xRxData2);
    eReturnValue |= Sbc_fs26_GetFaultErrorCounterValue(&u8FaultErrorValue);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        u8WdgRfrLimit = au8ArrayRfrLimitValue[(xRxData1.u16ReadData & SBC_FS26_FS_WD_RFR_LIMIT_MASK) >> SBC_FS26_FS_WD_RFR_LIMIT_SHIFT];
        u16WdgRfrRequest = (uint16)u8FaultErrorValue * ((uint16)u8WdgRfrLimit + 1U);

        if (SBC_FS26_FS_WDW_PERIOD_INFINITE == (xRxData2.u16ReadData & SBC_FS26_FS_WDW_PERIOD_MASK))
        {
            while ((u16WdgRfrRequest > 0U) && ((Std_ReturnType)E_OK == eReturnValue))
            {
                eReturnValue = Sbc_fs26_WdRefresh();
#ifdef SBC_FS26_ASYNC_TRANSMIT
                eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
                u16WdgRfrRequest--;
            }
        }
        else
        {
            eReturnValue = Sbc_fs26_TimeWaitClearFault(u16WdgRfrRequest * au32ArrayWindowPeriodToUs[(xRxData2.u16ReadData & SBC_FS26_FS_WDW_PERIOD_MASK) >> SBC_FS26_FS_WDW_PERIOD_SHIFT]);
        }
    }

    return eReturnValue;
}

/* Wait until Abist 2 done and pass*/
static Std_ReturnType Sbc_fs26_WaitAbist2DoneAndPass(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData = {0};
    volatile uint32 u32TimeOut = 0U;

#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;

    u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_WAIT_ABIST2_U16, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
#else
    u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */

    /* Wait for the test sequence DONE first */
    do
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if (SBC_FS26_FS_ABIST2_DONE_PASS == (xRxData.u16ReadData & SBC_FS26_FS_ABIST2_DONE_MASK))
        {
            break;
        }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
        u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    } while (u32ElapsedTicks <= u32TimeOut);

    if ((u32ElapsedTicks > u32TimeOut) || (SBC_FS26_FS_ABIST2_PASS_FAIL == (xRxData.u16ReadData & SBC_FS26_FS_ABIST2_PASS_MASK)))
#else
        u32TimeOut--;
    } while ((uint32)0U < u32TimeOut);

    if (((uint32)0U == u32TimeOut) || (SBC_FS26_FS_ABIST2_PASS_FAIL == (xRxData.u16ReadData & SBC_FS26_FS_ABIST2_PASS_MASK)))
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */

    /* Return E_NOT_OK if timeout or the Abist2 is not PASS */
    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
        if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
        }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
    }

    return eReturnValue;
}

#if (STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)
static Std_ReturnType Sbc_fs26_DoWatchdogTriggerProcess(void)
{
    uint16 u16Answer = 0U;                   /* Calculated monitoring result. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;

    /* Clear both (Data and Timing) Bad WD diagnostic bits before checking status */
    eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, SBC_FS26_FS_BAD_WD_TIMING_MASK | SBC_FS26_FS_BAD_WD_DATA_MASK);

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        bIsWdgTrigger = TRUE;

        switch (pSbcFs26ConfigPtr->eWatchdogType)
        {
            case SBC_FS26_WD_SIMPLE:
                eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_ANSWER_ADDR, xWdwToken.u16ReadData);
                break;
            case SBC_FS26_WD_CHALLENGER:
                u16Answer = Sbc_fs26_WdComputeAnswer(xWdwToken.u16ReadData);
                eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_ANSWER_ADDR, u16Answer);
                /* Synchronize with LFSR generator on the device. */
                /* Store WdToken for the next service */
                eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, &xWdwToken);
                break;
            default:
                eReturnValue = (Std_ReturnType)E_NOT_OK;
                break;
        }

        bIsWdgTrigger = FALSE;
    }

    return eReturnValue;
}
#endif /*(STD_OFF == SBC_FS26_DISABLE_WDG_TIMER)*/

static Std_ReturnType Sbc_fs26_CheckDeviceStateAndGotoInitFS(void)
{
    Sbc_fs26_RxFrameType xRxData = {0};
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_DeviceState eDeviceFSState;
    volatile uint32 u32TimeOut = 0U;
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */

    eDeviceFSState = Sbc_fs26_GetDeviceState();
    if (FS_STATES_INIT_FS == eDeviceFSState)
    {
        /* Currently in INIT_FS state */
        eReturnValue = (Std_ReturnType)E_OK;
    }
    else
    {
        if ((FS_STATES_FS0B_ASSERT == eDeviceFSState) || (FS_STATES_NORMAL_FS == eDeviceFSState))
        {
            /* Prevent Watchdog trigger in order to prevent exiting InitFS state */
            bGateWdgTrigger = TRUE;
            /* GoTo_INIT = 1 */
            eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_SAFE_IOS_1_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
            eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_SAFE_IOS_1_ADDR, xRxData.u16ReadData | SBC_FS26_FS_GOTO_INIT_INIT);
        }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
        u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_WAIT_INITFS_U16, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
        u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
#else
        u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
        /* Wait until device in Init FS state */
        do
        {
            eDeviceFSState = Sbc_fs26_GetDeviceState();
            if (FS_STATES_INIT_FS == eDeviceFSState)
            {
                break;
            }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
            u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
        } while (u32ElapsedTicks <= u32TimeOut);

        if (u32ElapsedTicks > u32TimeOut)
#else
            u32TimeOut--;
        } while ((uint32)0U < u32TimeOut);

        if ((uint32)0U == u32TimeOut)
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
        {
            eReturnValue |= (Std_ReturnType)E_NOT_OK;
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
            if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
            {
                (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
            }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
        }
    }

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED)
static Std_ReturnType Sbc_fs26_WaitInitFSClosed(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    volatile uint32 u32TimeOut = 0U;

#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;

    u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_TIMEOUT_DURATION_U32, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
#else
    u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
    /* Wait until InitFS being closed */
    do
    {
        if (FS_STATES_FS0B_ASSERT == Sbc_fs26_GetDeviceState())
        {
            /* Expectation state catches */
            break;
        }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
        u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    } while (u32ElapsedTicks <= u32TimeOut);
    /*If Timeout expired*/
    if (u32ElapsedTicks >u32TimeOut)
    {
#else
        u32TimeOut--;
    } while ((uint32)0U < u32TimeOut);
    /*If Timeout expired*/
    if (0U == u32TimeOut)
    {
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */

        eReturnValue |= (Std_ReturnType)E_NOT_OK;
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
        if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
        }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
    }

    return eReturnValue;
}
#endif /*STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED*/

static Std_ReturnType Sbc_fs26_NormalFSSequence(Sbc_fs26_DeviceState eDeviceState)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData = {0};

    if (FS_STATES_INVALID <= eDeviceState)
    {
        eReturnValue = (Std_ReturnType)E_NOT_OK;
    }
    else if (FS_STATES_INIT_FS == eDeviceState)
    {
        /* Allow triggering watchdog */
        bGateWdgTrigger = FALSE;
        /* Read current FS_WDW_DURATION register setting */
        eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WDW_DURATION_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
#if (STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED)
        if ((SBC_FS26_FS_WDW_PERIOD_INFINITE == (xRxData.u16ReadData & SBC_FS26_FS_WDW_PERIOD_MASK)) && ((Std_ReturnType)E_OK == eReturnValue))
        {
            /* Close initialization phase by sending first watchdog refresh. */
            eReturnValue = Sbc_fs26_WdRefresh();
        }
        else if (((Std_ReturnType)E_OK == eReturnValue) && (NULL_PTR != pSbcFs26ConfigPtr->pfWdgNotification))
        {
#else
        if (((Std_ReturnType)E_OK == eReturnValue) && (NULL_PTR != pSbcFs26ConfigPtr->pfWdgNotification))
        {
#endif /*STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED*/
            /* Notify upper layer to start wdg synchronization*/
            pSbcFs26ConfigPtr->pfWdgNotification((xRxData.u16ReadData & SBC_FS26_FS_WDW_PERIOD_MASK) >> SBC_FS26_FS_WDW_PERIOD_SHIFT, (xRxData.u16ReadData & SBC_FS26_FS_WDW_DC_MASK) >> SBC_FS26_FS_WDW_DC_SHIFT);
        }
#if (STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED)
        else
        {
            /*Avoid Misra violation*/
        }
        /* Wait InitFS State transition*/
        eReturnValue |= Sbc_fs26_WaitInitFSClosed();
#endif /*STD_ON == SBC_FS26_CLOSE_INITFS_ENABLED*/
    }
    else
    {
        /* Allow triggering watchdog */
        bGateWdgTrigger = FALSE;
        if (NULL_PTR != pSbcFs26ConfigPtr->pfWdgNotification)
        {
            /* Notify upper layer to start wdg synchronization*/
            pSbcFs26ConfigPtr->pfWdgNotification((xRxData.u16ReadData & SBC_FS26_FS_WDW_PERIOD_MASK) >> SBC_FS26_FS_WDW_PERIOD_SHIFT, (xRxData.u16ReadData & SBC_FS26_FS_WDW_DC_MASK) >> SBC_FS26_FS_WDW_DC_SHIFT);
        }
    }
    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* Perform check REG_CORRUPT and OTP_CORRUPT */
        eReturnValue |= Sbc_fs26_CheckRegAndOTPCorrupt();
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
#if (STD_ON == SBC_FS26_CLEAR_FAULT_ENABLED)
            /* Read Fault Error Counter and decrease to 0 */
            eReturnValue |= Sbc_fs26_ClearFaultErrorCounter();
#endif /*STD_ON == SBC_FS26_CLEAR_FAULT_ENABLED*/
            /* Notify upper layer to perform RSTB path check */
            if (NULL_PTR != pSbcFs26ConfigPtr->pRstbCheckNotification)
            {
                pSbcFs26ConfigPtr->pRstbCheckNotification();
            }
#if (STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED)
            /* Exit Debug mode if device in Debug mode */
            eReturnValue |= Sbc_fs26_ExitDebugMode();
#endif /*STD_ON == SBC_FS26_EXIT_DBG_MODE_ENABLED*/
#if (STD_ON == SBC_FS26_RELEASE_SAFETY_OUTPUTS_ENABLED)
            /* Release Fail-safe pins*/
            eReturnValue |= Sbc_fs26_ReleaseSequence((Sbc_fs26_FsOutputType)pSbcFs26ConfigPtr->eSafetyOutput);
#endif /*(STD_ON == SBC_FS26_RELEASE_SAFETY_OUTPUTS_ENABLED*/
        }
    }

    return eReturnValue;
}

/* Wait for fail-safe pin to be released */
static Std_ReturnType Sbc_fs26_WaitFailsafeRelease(Sbc_fs26_FsOutputType FsOutput)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData = {0};
    uint16 u16MaskedData = 0U;
    volatile uint32 u32TimeOut;

    switch (FsOutput)
    {
    case SBC_FS26_FS_FS0B:
        u16MaskedData = SBC_FS26_FS_FS0B_SNS_MASK;
        break;
    case SBC_FS26_FS_FS1B:
        u16MaskedData = SBC_FS26_FS_FS1B_SNS_MASK;
        break;
    default:
        u16MaskedData = SBC_FS26_FS_FS0B_SNS_MASK|SBC_FS26_FS_FS1B_SNS_MASK;
        break;
    }

#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
    uint32 u32ElapsedTicks = 0U;
    uint32 u32CurrentTicks = 0U;

    u32TimeOut = OsIf_MicrosToTicks(SBC_FS26_TIMEOUT_DURATION_U32, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    u32CurrentTicks = OsIf_GetCounter((OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
#else
    u32TimeOut = SBC_FS26_TIMEOUT_DURATION_U32;
#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */
    /* Wait until InitFS being closed */
    do
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE,SBC_FS26_FS_SAFE_IOS_1_ADDR,&xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if  (u16MaskedData == (xRxData.u16ReadData & u16MaskedData))
        {
            break;
        }
#if (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS)
        u32ElapsedTicks += OsIf_GetElapsed(&u32CurrentTicks, (OsIf_CounterType)SBC_FS26_TIMEOUT_OSIF_COUNTER_TYPE);
    } while ((u32ElapsedTicks <= u32TimeOut));
    if (u32ElapsedTicks > u32TimeOut)
#else
        u32TimeOut--;
    } while ((uint32)0U < u32TimeOut);
    if ((uint32)0U == u32TimeOut)

#endif /* (STD_OFF == SBC_FS26_TIMEOUT_MECHANISM_LOOPS) */

    {
        eReturnValue |= (Std_ReturnType)E_NOT_OK;
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
        if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xTimeError.state)
        {
            (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xTimeError.id, DEM_EVENT_STATUS_FAILED);
        }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
    }
    return eReturnValue;
}

static Std_ReturnType Sbc_fs26_ReleaseSequence(Sbc_fs26_FsOutputType eFsOutput)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    Sbc_fs26_RxFrameType xRxData = {0};

    if (SBC_FS26_FS_FS1B == eFsOutput)
    {
        /* No need to check ABIST, LBIST if only release FS1B pin */
    }
    else
    {
        /* Check LBIST_OK = ABIST1_OK = 1 */
        eReturnValue = Sbc_fs26_CheckLBistABist1();
    }

    /* Launch and check Abist On Demand if at least one regulator is set to launch */
    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE,SBC_FS26_FS_ABIST_ON_DEMAND_ADDR,&xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if ((uint16)0U == xRxData.u16ReadData)
        {
            /* No ABIST2 requested, do nothing */
        }
        else
        {
            /* Clear Abist On Demand status */
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, SBC_FS26_FS_ABIST2_DONE_PASS | SBC_FS26_FS_ABIST2_PASS_PASS);
            /* Launch Abist On Demand */
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_ABIST_ON_DEMAND_ADDR, SBC_FS26_FS_LAUNCH_ABIST2_ABIST | xRxData.u16ReadData);
            eReturnValue |= Sbc_fs26_WaitAbist2DoneAndPass();
        }
    }

    if ((Std_ReturnType)E_OK == eReturnValue)
    {
        /* RELEASE_FS0B_FS1B register filled with ongoing WD_TOKEN reversed and complemented */
        eReturnValue = Sbc_fs26_ComputeReleaseFsxbValue(eFsOutput);
    }

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_WAKEUP_API)
static Std_ReturnType Sbc_fs26_ValidateWakeup(uint16 u16WuEvent)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;

    /* Check if the return WuEvent is out of valid range*/
    if (((u16WuEvent & SBC_FS26_M_WUEVENT_MASK) > SBC_FS26_M_WUEVENT_SPI_ACTIVE) && ((u16WuEvent & SBC_FS26_M_WUEVENT_MASK) != SBC_FS26_M_WUEVENT_DFS_REC)
        && ((u16WuEvent & SBC_FS26_M_WUEVENT_MASK) != SBC_FS26_M_WUEVENT_BATT_FAIL))
    {
        eReturnValue = (Std_ReturnType)E_NOT_OK;
    }

    return eReturnValue;
}
#endif /*STD_ON == SBC_FS26_WAKEUP_API*/
/*==================================================================================================
*                                       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. The argument cannot be NULL_PTR in case SBC_FS26_PRECOMPILE_SUPPORT = STD_OFF.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_Init_Activity */
Std_ReturnType Sbc_fs26_Init(const Sbc_fs26_ConfigType* pConfig)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    /* Check if already initialized. */
    if (TRUE == bIsInitialized)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INIT, (uint8)SBC_FS26_E_MULTIPLE_INIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Get a local copy of the driver initalization structure. */
#if (STD_ON == SBC_FS26_PRECOMPILE_SUPPORT)
        if (NULL_PTR == pConfig)
        {
            pSbcFs26ConfigPtr = &Sbc_fs26_xConfigPredefined;
#else
        if (NULL_PTR != pConfig)
        {
            pSbcFs26ConfigPtr = pConfig;
#endif /* STD_ON == SBC_FS26_PRECOMPILE_SUPPORT */
            xWdwToken.u16ReadData = pSbcFs26ConfigPtr->u16WatchdogToken;
            eReturnValue = (Std_ReturnType)E_OK;
        }
        else
        {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
            (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INIT, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
        }

        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Device initialized. */
            bIsInitialized = TRUE;
            bIsWdgTrigger = FALSE;
            bGateWdgTrigger = TRUE;
            /* Spi initialized*/
            xSpiSetup.Extension = pSbcFs26ConfigPtr->pSpi->pExt;
            xSpiSetup.NumberOfBytes =  SBC_FS26_COMM_FRAME_SIZE_U8;
#if !(defined(SBC_FS26_USE_IPV_DSPI) || defined(SBC_FS26_USE_IPV_LPSPI) || defined(SBC_FS26_USE_IPV_FLEXIO_SPI))
            xSpiSetup.Spi = pSbcFs26ConfigPtr->pSpi->uSpiChannel;
#else
            xSpiSetup.Callback = pSbcFs26ConfigPtr->pSpi->Callback;
#endif
#ifdef SBC_FS26_ASYNC_TRANSMIT
            xSpiSetup.SyncTransmit = FALSE;
            Sbc_fs26_apxTxBufferRing.paBuffer = Sbc_fs26_apxTxQueueBuffer;
            Sbc_fs26_apxTxBufferRing.u32Maxlen = SBC_FS26_QUEUE_LEN;
            Sbc_fs26_apxRxDataRing.pData = Sbc_fs26_apxRxShadowBuffer;
            Sbc_fs26_apxRxDataRing.u32Maxlen = SBC_FS26_QUEUE_LEN;
#else
            xSpiSetup.SyncTransmit = TRUE;
            xSpiSetup.Timeout = 10000U;
#if !(defined(SBC_FS26_USE_IPV_DSPI) || defined(SBC_FS26_USE_IPV_LPSPI) || defined(SBC_FS26_USE_IPV_FLEXIO_SPI))
            eReturnValue = Sbc_fs26_SpiPrepareBuffer(&xSpiSetup, Sbc_fs26_au8TxBuffer, Sbc_fs26_au8RxBuffer);
#endif
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Configures the device. SID is 0x10.
* @details      Performs initialization checks (in INIT_FS or not, LBIST, ABIST1 are pass)
*               and writes all INIT_FS registers and watchdog configuration.
*               Closes initialization phase by sending first watchdog refresh.
*               Exit Debug mode (if available) and release Fsxb pin.
*               The device shall go to NORMAL state after executing this function.
*
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_InitDevice_Activity */
Std_ReturnType Sbc_fs26_InitDevice(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */
    Sbc_fs26_DeviceState eDeviceFSState;

    /* Check if initialized. */
    if (TRUE == bIsInitialized)
    {
        eDeviceFSState = Sbc_fs26_GetDeviceState();
        /* If the device already leaves INITFS, skip I_FS register configuration */
        if (FS_STATES_INIT_FS >= eDeviceFSState)
        {
            eReturnValue |= Sbc_fs26_CheckDeviceStateAndGotoInitFS();

            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                eReturnValue = Sbc_fs26_DoInitRegister();
                if ((Std_ReturnType)E_OK == eReturnValue)
                {
                    /* Exit INITFS and Go to Normal Fail-safe state */
                    eReturnValue = Sbc_fs26_NormalFSSequence(FS_STATES_INIT_FS);
                }
            }
        }
        else
        {
            /* Go to Normal Fail-safe state */
            eReturnValue = Sbc_fs26_NormalFSSequence(eDeviceFSState);
        }
    }
    else
    {
        eReturnValue = (Std_ReturnType)E_NOT_OK;
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_INITDEVICE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }

    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]    bIsFailSafe      TRUE if the register is Fail Safe.
* @param[in]    u8Address        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 bIsFailSafe,
                                     uint8 u8Address,
                                     Sbc_fs26_RxFrameType* pRxData)
{
    Sbc_fs26_TxFrameType txData =
    {
        bIsFailSafe,
        u8Address,
        SBC_FS26_COM_READ,
        0U
    };
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (NULL_PTR == pRxData)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (SBC_FS26_MAX_REG_ADD_U8 < u8Address)
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_READREGISTER, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
#ifdef SBC_FS26_ASYNC_TRANSMIT
        SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_06();
        eReturnValue = Sbc_fs26_TransferDataAsync(&txData);
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            Sbc_fs26_DataBufferQueuePush(&Sbc_fs26_apxRxDataRing, pRxData);
        }
        SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_06();
#else
       eReturnValue = Sbc_fs26_TransferData(&txData, pRxData);
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Sends write command to the FS26. SID is 0x02.
*
* @param[in]    bIsFailSafe        TRUE: Reading from FS register, FALSE: Reading from Main register.
* @param[in]    u8Address          Register address. Valid range for address is less than SBC_FS26_MAX_REG_ADD_U8.
* @param[in]    u16WriteData       Register write value. The whole 16 bit range is valid.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_WriteRegister_Activity */
Std_ReturnType Sbc_fs26_WriteRegister(boolean bIsFailSafe,
                                      uint8 u8Address,
                                      uint16 u16WriteData)
{
    Sbc_fs26_TxFrameType txData =
    {
        bIsFailSafe,
        u8Address,
        SBC_FS26_COM_WRITE,
        u16WriteData
    };
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WRITEREGISTER, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (SBC_FS26_MAX_REG_ADD_U8 < u8Address)
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WRITEREGISTER, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
#ifdef SBC_FS26_ASYNC_TRANSMIT
        SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_04();
        eReturnValue = Sbc_fs26_TransferDataAsync(&txData);
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            Sbc_fs26_DataBufferQueuePush(&Sbc_fs26_apxRxDataRing, NULL_PTR);
        }
        SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_04();
#else
        eReturnValue = Sbc_fs26_TransferData(&txData, NULL_PTR);
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
    }

    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.
*               The FS26 only supports switching from Normal mode to Low power mode as follow:
*               - 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]    eOpMode          Device operating mode. Valid value is SBC_FS26_OPMODE_STANDBY or SBC_FS26_OPMODE_LPOFF.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetOperatingMode_Activity */
Std_ReturnType Sbc_fs26_SetOperatingMode(Sbc_fs26_OpModeType eOpMode)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETOPERATINGMODE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if ((SBC_FS26_OPMODE_STANDBY != eOpMode) && (SBC_FS26_OPMODE_LPOFF != eOpMode))
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETOPERATINGMODE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Enter critical section. */
        SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_02();
        /* Go to pre standby, or pre LPOFF. */
        eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, (uint16)eOpMode);

        if (SBC_FS26_OPMODE_STANDBY == eOpMode)
        {
            /* Go to standby from pre standby. */
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, SBC_FS26_FS_FS_LP_REQ_STANDBY);
        }
        else
        {
            /* Go to LPOFF from pre LPOFF. */
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_LP_REQ_ADDR, SBC_FS26_FS_FS_LP_REQ_LPOFF);
        }

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

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_LDT_FUNCTION_API)
/*================================================================================================*/
/**
* @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]    eLdtFunction       LDT function. Valid value is between the range (including) of SBC_FS26_LDTFUNC_FUNC1 and SBC_FS26_LDTFUNC_FUNC5.
* @param[in]    eLdtMode           LDT operation mode. Valid value is SBC_FS26_LDTMODE_LONG or SBC_FS26_LDTMODE_SHORT.
* @param[in]    u16AfterRun        LDT after run value (16 bits). Valid value is the whole 16 bit range.
* @param[in]    u32WakeUp          LDT wake-up value (24 bits). Valid value is only the last 24 bits. Value must be less than 0x00FFFFFFU.
* @param[in]    eLdtLp             Low-power mode to go to for functions 2-3. Valid value is SBC_FS26_LDTLP_LPOFF or SBC_FS26_LDTLP_STANDBY.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetLDT_Activity */
Std_ReturnType Sbc_fs26_SetLDT(Sbc_fs26_LdtFuncType eLdtFunction,
                               Sbc_fs26_LdtModeType eLdtMode,
                               uint16 u16AfterRun,
                               uint32 u32WakeUp,
                               Sbc_fs26_LdtLpType eLdtLp)
{
    uint16 u16WriteData = (uint16)eLdtFunction | (uint16)eLdtMode; /* Register value to write. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK;          /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETLDT, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (((Std_ReturnType)E_NOT_OK == Sbc_fs26_CheckParametersSetLDT(eLdtFunction,eLdtMode, eLdtLp)) || (0x00FFFFFFU < u32WakeUp))
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETLDT, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Write LDT configuration. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, u16WriteData);

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

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

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

        /* Enable the counter. */
        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);
        }
    }

    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]   pu32LdtValue       Pointer to Long Duration Timer value storage. Value cannot be NULL_PTR.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GetLDTValue_Activity */
Std_ReturnType Sbc_fs26_GetLDTValue(uint32* pu32LdtValue)
{
    Sbc_fs26_RxFrameType rxData1 = {0};       /* Register received data. */
    Sbc_fs26_RxFrameType rxData2 = {0};       /* Register received data. */
    uint16 u16WriteData = 0U;                /* Register value to write. */
    uint32 u32TempValue = 0U;                /* LDT value. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (NULL_PTR == pu32LdtValue)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETLDTVALUE, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETLDTVALUE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Read LDT configuration and status. */
        eReturnValue = Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_LDT_CTRL_ADDR, &rxData1);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/

        /* Check if the Sbc_fs26_ReadRegister is valid. */
        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            /* Enter critical section. */
            SchM_Enter_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_03();
            /* 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);
            /* 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);
            /* Exit critical section. */
            SchM_Exit_Sbc_fs26_SBC_FS26_EXCLUSIVE_AREA_03();
#ifdef SBC_FS26_ASYNC_TRANSMIT
            eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        }

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

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_LDT_FUNCTION_API) */

/*================================================================================================*/
/**
* @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]    u16Token         New watchdog token, stored to run-time configuration if change was successful.
*                                The Watchdog token shall be different from 0x0000U for both SIMPLE and CHALLENGER watchdog. And the value shall be different from 0xFFFFU for SIMPLE watchdog.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_WdChangeToken_Activity */
Std_ReturnType Sbc_fs26_WdChangeToken(uint16 u16Token)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDCHANGETOKEN, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    /* Token 0x0000U not allowed, for simple watchdog also 0xFFFFU. */
    else if (((SBC_FS26_WD_SIMPLE == pSbcFs26ConfigPtr->eWatchdogType) && (0xFFFFU == u16Token)) || (0x0000U == u16Token))
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDCHANGETOKEN, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Write new watchdog token. */
        eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_WD_TOKEN_ADDR, u16Token);

        /* Store watchdog token after written correctly. */
        xWdwToken.u16ReadData = u16Token;
    }

    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)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_WDREFRESH, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        if ((FALSE == bGateWdgTrigger) && (FALSE == bIsWdgTrigger))
        {
#if (STD_ON == SBC_FS26_DISABLE_WDG_TIMER)
            eReturnValue = (Std_ReturnType)E_NOT_OK;
#else
            eReturnValue = Sbc_fs26_DoWatchdogTriggerProcess();
            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                /* Check if watchdog refresh was successful. */
                eReturnValue = Sbc_fs26_CheckWdgRefresh();
            }
#endif /* (STD_ON == SBC_FS26_DISABLE_WDG_TIMER) */
        }
    }

    return eReturnValue;
}

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

    if (NULL_PTR == pu8FaultErrorCounterValue)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETFAULTERRORCOUNTERVALUE, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETFAULTERRORCOUNTERVALUE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_I_FSSM_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if (((Std_ReturnType)E_OK == eReturnValue) && ((xRxData.u16ReadData & SBC_FS26_FS_FLT_ERR_CNT_MASK) <= SBC_FS26_FS_FLT_ERR_CNT_12))
        {
            *pu8FaultErrorCounterValue = (uint8)((xRxData.u16ReadData & SBC_FS26_FS_FLT_ERR_CNT_MASK) >> SBC_FS26_FS_FLT_ERR_CNT_SHIFT);
        }
        else
        {
            eReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        FSxB release routine. SID is 0x09.
*
* @details      This function allow release FS0B pin or FS1B pin or both pins when these pins were asserted by the device before.
*               This function also checks all preconditions before it sends the register write command (LBIST_OK = ABIST1_OK = 1, launch ABIST2, remove fault and clear Fault Error Counter).
*               If any precondition is not met, the function returns E_NOT_OK.
*
* @param[in]    eFsOutput        FS output to release. Valid value is SBC_FS26_FS_FS0B, SBC_FS26_FS_FS1B or SBC_FS26_FS_BOTH.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_FsxbRelease_Activity */
Std_ReturnType Sbc_fs26_FsxbRelease(Sbc_fs26_FsOutputType eFsOutput)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_FSXBRELEASE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if ((Std_ReturnType)E_NOT_OK == Sbc_fs26_CheckParameterFsxbRelease(eFsOutput))
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_FSXBRELEASE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Read Fault Error Counter and decrease to 0 */
        eReturnValue = Sbc_fs26_ClearFaultErrorCounter();
        /* Release fail-safe pins*/
        eReturnValue |= Sbc_fs26_ReleaseSequence(eFsOutput);
        eReturnValue |= Sbc_fs26_WaitFailsafeRelease(eFsOutput);
    }

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_SET_REGULATOR_API)
/*================================================================================================*/
/**
* @brief        Sets state (enable/disable) of the selected voltage regulator. SID is 0x0A.
*
* @param[in]    eVreg            Voltage regulator. Vaid value is between (including) the range of SBC_FS26_REG_LDO1 and SBC_FS26_REG_VREF.
* @param[in]    bEnable          State (enable = TRUE / disable = FALSE).
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetRegulatorState_Activity */
Std_ReturnType Sbc_fs26_SetRegulatorState(Sbc_fs26_RegOutputType eVreg,
                                          boolean bEnable)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK;            /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETREGULATORSTATE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (SBC_FS26_REG_VREF < eVreg)
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETREGULATORSTATE, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, bEnable ? SBC_FS26_M_REG_CTRL1_ADDR : SBC_FS26_M_REG_CTRL2_ADDR, ((uint16)1U << (uint16)eVreg) & (uint16)0xFFFFU);
    }

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_SET_REGULATOR_API) */

#if (STD_ON == SBC_FS26_AMUX_CHANNEL_API)
/*================================================================================================*/
/**
* @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]    eAmuxChannel     AMUX channel selection. Valid value is equal or less than SBC_FS26_AMUXCHAN_GPIO1_TEMP.
* @param[in]    eAmuxDiv         AMUX divider. Valid value is SBC_FS26_AMUXDIV_LOW or SBC_FS26_AMUXDIV_HIGH.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_SetAmux_Activity */
Std_ReturnType Sbc_fs26_SetAmux(Sbc_fs26_AmuxChanType eAmuxChannel,
                                Sbc_fs26_AmuxDivType eAmuxDiv)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETAMUX, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if ((SBC_FS26_AMUXCHAN_GPIO1_TEMP < eAmuxChannel) || ((SBC_FS26_AMUXDIV_LOW != eAmuxDiv) && (SBC_FS26_AMUXDIV_HIGH != eAmuxDiv)))
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETAMUX, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Configure AMUX. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_AMUX_CTRL_ADDR, (uint16)eAmuxChannel | (uint16)eAmuxDiv | SBC_FS26_M_AMUX_EN_ENABLED);
    }

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_AMUX_CHANNEL_API) */

#if (STD_ON == SBC_FS26_WAKEUP_API)
/*================================================================================================*/
/**
* @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]    xWakeupSrc       Wake up source (when source is TRUE = enabled).
* @param[in]    xWakeupPol       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 xWakeupSrc,
                                  Sbc_fs26_WuPolType xWakeupPol)
{
    uint16 u16WriteData = 0U;                /* Register value to write. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_SETWAKEUP, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        u16WriteData = Sbc_fs26_CreateWakeupSrcPayload(xWakeupSrc);
        u16WriteData |= Sbc_fs26_CreateWakeupPolPayload(xWakeupPol);
        /* Configure Wake up. */
        eReturnValue = Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_WIO_CFG_ADDR, u16WriteData);
    }

    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]    bClearFlags     TRUE = clear wake up flags after reading.
* @param[out]   pWakeupReason   Status of wake up flags. Value cannot be NULL_PTR.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GetWakeup_Activity */
Std_ReturnType Sbc_fs26_GetWakeup(boolean bClearFlags,
                                  Sbc_fs26_WuReasonType* pWakeupReason)
{
    Sbc_fs26_RxFrameType xRxData = {0};        /* Register received data. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (NULL_PTR == pWakeupReason)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETWAKEUP, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETWAKEUP, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        eReturnValue = Sbc_fs26_ReadRegister(FALSE, SBC_FS26_M_WIO_FLG_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if ((Std_ReturnType)E_OK == Sbc_fs26_ValidateWakeup(xRxData.u16ReadData))
        {
            pWakeupReason->bWk1Flag = (SBC_FS26_M_WK1_I_EVENT == (xRxData.u16ReadData & SBC_FS26_M_WK1_I_MASK)) ? TRUE : FALSE;
            pWakeupReason->bWk2Flag = (SBC_FS26_M_WK2_I_EVENT == (xRxData.u16ReadData & SBC_FS26_M_WK2_I_MASK)) ? TRUE : FALSE;
            pWakeupReason->bGpio1Flag = (SBC_FS26_M_GPIO1_I_EVENT == (xRxData.u16ReadData & SBC_FS26_M_GPIO1_I_MASK)) ? TRUE : FALSE;
            pWakeupReason->bGpio2Flag = (SBC_FS26_M_GPIO2_I_EVENT == (xRxData.u16ReadData & SBC_FS26_M_GPIO2_I_MASK)) ? TRUE : FALSE;
            pWakeupReason->bLdtFlag = (SBC_FS26_M_LDT_I_EVENT == (xRxData.u16ReadData & SBC_FS26_M_LDT_I_MASK)) ? TRUE : FALSE;
            pWakeupReason->u8WuEvent = (uint8)((xRxData.u16ReadData & SBC_FS26_M_WUEVENT_MASK) >> SBC_FS26_M_WUEVENT_SHIFT);

            if (TRUE == bClearFlags)
            {
                eReturnValue |= Sbc_fs26_WriteRegister(FALSE, SBC_FS26_M_WIO_FLG_ADDR, SBC_FS26_M_WU_CLR_CLEAR_ALL);
            }
        }
        else
        {
            eReturnValue |= (Std_ReturnType)E_NOT_OK;
        }
    }

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_WAKEUP_API) */

/*================================================================================================*/
/**
* @brief        Switch SBC device back to Init mode. SID is 0x11.
* @details      This function is used to switch device back to Init state and then users can re-configure
*               the Fail-safe register. To make sure every register is set before closing the Init phase,
*               the requesting watchdog refresh must be ignored. In order to trigger watchdog again, the user
*               must use Sbc_fs26_InitDevice() function after executing this function.
*
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_GotoInitFS_Activity */
Std_ReturnType Sbc_fs26_GotoInitFS(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */;
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GOTOINITFS, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /*If device is not in INITFS - Goto INITFS */
        eReturnValue = Sbc_fs26_CheckDeviceStateAndGotoInitFS();
    }

    return eReturnValue;
}

/*================================================================================================*/
/**
* @brief        Disable Watchdog during runtime. SID is 0x12.
* @details      This function is used to set Window Period Infinity which only be set in InitFS state.
*               The device will go to InitFS to set Window Period Infinity then switch back to Normal state at the end of function.
*
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_DisableWatchdog_Activity */
Std_ReturnType Sbc_fs26_DisableWatchdog(void)
{
    Sbc_fs26_RxFrameType xRxData = {0};        /* Register received data. */
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */
    uint16 u16WriteData = 0U;

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_DISABLEWATCHDOG, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Infinite open window can be set during INIT_FS only */
        eReturnValue = Sbc_fs26_CheckDeviceStateAndGotoInitFS();

        if ((Std_ReturnType)E_OK == eReturnValue)
        {
            eReturnValue |= Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_WDW_DURATION_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
            eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
            u16WriteData = xRxData.u16ReadData & (~SBC_FS26_FS_WDW_PERIOD_MASK);
            eReturnValue |= Sbc_fs26_WriteRegisterInit(SBC_FS26_FS_WDW_DURATION_ADDR, u16WriteData);

            if ((Std_ReturnType)E_OK == eReturnValue)
            {
                eReturnValue = Sbc_fs26_NormalFSSequence(FS_STATES_INIT_FS);
            }
        }
    }

    return eReturnValue;
}

#if (STD_ON == SBC_FS26_ABIST2_CHECK_API)
/*================================================================================================*/
/**
* @brief        Perform Abist on demand (Abist2) check. SID is 0x13.
* @details      This check can be launched as soon as device is in Normal mode.
*               This feature is available for specific part numbers. To launch this
*               check, the user must select which monitoring has to be checked. It will return OK
*               only when the diagnostic on Abist2 is DONE and report PASS then.
*
* @param[in]    eVmonitor            Voltage to be checked. Valid value is equal or less than SBC_FS26_MOR_VEXT.
*
* @return       Std_ReturnType  Return code.
*
* @api
*/
/** @implements   Sbc_fs26_PerformAbist2Check_Activity */
Std_ReturnType Sbc_fs26_PerformAbist2Check(Sbc_fs26_VoltageSupervisionType eVmonitor)
{
    uint16 u16WriteData = 0U;                     /* Data to write */
    Sbc_fs26_DeviceState eDeviceFSState;
    Std_ReturnType eReturnValue = (Std_ReturnType)E_NOT_OK; /* Status. */

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_PERFORMABIST2CHECK, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else if (SBC_FS26_MOR_VEXT < eVmonitor)
    {
        /* Parameter out of range. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_PERFORMABIST2CHECK, (uint8)SBC_FS26_E_PARAM_RANGE);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        eDeviceFSState = Sbc_fs26_GetDeviceState();
        if ((FS_STATES_INIT_FS < eDeviceFSState) && (FS_STATES_INVALID > eDeviceFSState))
        {
            /* Clear Abist2 status */
            u16WriteData = SBC_FS26_FS_ABIST2_DONE_PASS | SBC_FS26_FS_ABIST2_PASS_PASS;
            eReturnValue = Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_DIAG_SAFETY1_ADDR, u16WriteData);

            /* Select voltage to monitor and launch Abist2 check */
            u16WriteData = ((uint16)1U << (uint16)eVmonitor) | SBC_FS26_FS_LAUNCH_ABIST2_MASK;
            eReturnValue |= Sbc_fs26_WriteRegister(TRUE, SBC_FS26_FS_ABIST_ON_DEMAND_ADDR, u16WriteData);

            /* Wait until ABIST2 DONE and PASS */
            eReturnValue |= Sbc_fs26_WaitAbist2DoneAndPass();
        }
        else
        {
            eReturnValue = (Std_ReturnType)E_NOT_OK;
        }
    }

    return eReturnValue;
}
#endif /* (STD_ON == SBC_FS26_ABIST2_CHECK_API) */

#ifdef SBC_FS26_ASYNC_TRANSMIT
/*================================================================================================*/
/**
* @brief        Get Asynchronous Transmision  status.
* @details      This function return status for Asynchronous Transmision.
*
* @return       Sbc_fs26_SpiAsyncStatusType
*               SBC_FS26_TRANS_DONE: Successful Spi transmission
*               SBC_FS26_TRANS_ON_GOING: Spi transmission is on-going
*               SBC_FS26_TRANS_FAILED: Spi transmission failed or service request failed due to development errors
*
* @api
*/
/** @implements   Sbc_fs26_GetAsyncTransmissionStatus_Activity */
Sbc_fs26_SpiAsyncStatusType Sbc_fs26_GetAsyncTransmissionStatus(void)
{
    Sbc_fs26_SpiAsyncStatusType eTransmissionStatus;
    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETASYNCSTATUS, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
        eTransmissionStatus = SBC_FS26_TRANS_FAILED;
    }
    else
    {
        eTransmissionStatus = Sbc_fs26_Transmission_Status;
    }

    return eTransmissionStatus;
}

/*================================================================================================*/
/**
* @brief        Hook-up function is called by Spi callback in case Asynchronous is used.
* @details      When Spi hardware transmission is completed, the function must be called in order to handle queue activities.
*
*
* @return       void
*
* @api
*/
/** @implements   Sbc_fs26_SpiNotification_Activity */
void Sbc_fs26_SpiNotification(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK;
    uint8 *pTxBuffer;
    Sbc_fs26_SpiStatusType SpiStatus = SPI_TRANS_OK;
    /*Check if driver has been initialized*/
    if (TRUE == bIsInitialized)
    {
        SpiStatus = Sbc_fs26_GetTransmissionStatus(&xSpiSetup);
        if (SPI_TRANS_OK == SpiStatus)
        {
            /* Check the CRC of the retrieved frame */
            eReturnValue = (Sbc_fs26_au8RxBuffer[3] == Sbc_fs26_CalcCrc(Sbc_fs26_au8RxBuffer)) ? (Std_ReturnType)E_OK : (Std_ReturnType)E_NOT_OK;
            if ((Std_ReturnType)E_OK == eReturnValue)
            {
#if (STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT)
                /* Check the device's responded status */
                if ((uint32)STD_ON == pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.state)
                {
                    if (0U == (Sbc_fs26_au8RxBuffer[0U] & SBC_FS26_DEVICE_STATUS_MASK_U8))
                    {
                        (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.id, DEM_EVENT_STATUS_PASSED);
                    }
                    else
                    {
                        (void)Dem_SetEventStatus((Dem_EventIdType)pSbcFs26ConfigPtr->pDemConfig->xDeviceStatusError.id, DEM_EVENT_STATUS_FAILED);
                    }
                }
#endif /* STD_OFF == SBC_FS26_DISABLE_DEM_ERROR_REPORT */
                /*CRC check passed */
                Sbc_fs26_DataBufferQueueParse(&Sbc_fs26_apxRxDataRing, Sbc_fs26_au8RxBuffer);
                if ((Std_ReturnType)E_OK == Sbc_fs26_TxQueuePop(&Sbc_fs26_apxTxBufferRing, &pTxBuffer))
                {
                    /*Deque TxQueue and send the data*/
                    (void)Sbc_fs26_SpiPrepareBuffer(&xSpiSetup, pTxBuffer, Sbc_fs26_au8RxBuffer);
                    (void)Sbc_fs26_SpiTransferExternal(&xSpiSetup,pTxBuffer,Sbc_fs26_au8RxBuffer);
                }
                else
                {
                    /*If TxQueue is empty, transmission done*/
                    Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_DONE;
                }
                /* Clear RxBuffer to prevent CRC false positive in the next cycle*/
                Sbc_fs26_MemCopy(NULL_PTR, Sbc_fs26_au8RxBuffer);
            }
            else
            {
                /*CRC check failed*/
                Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_FAILED;
                /*Reset Queue indexing*/
                Sbc_fs26_apxTxBufferRing.u32Tail = Sbc_fs26_apxTxBufferRing.u32Head;
                Sbc_fs26_apxRxDataRing.u32Tail = Sbc_fs26_apxRxDataRing.u32Head;
            }
        }
        else if (SPI_TRANS_PENDING == SpiStatus)
        {
            /*Transmission is on-going due to SPI errors*/
            Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_ON_GOING;
        }
        else
        {
            /*Transmission failed due to SPI errors*/
            Sbc_fs26_Transmission_Status = SBC_FS26_TRANS_FAILED;
            /*Reset Queue indexing*/
            Sbc_fs26_apxTxBufferRing.u32Tail = Sbc_fs26_apxTxBufferRing.u32Head;
            Sbc_fs26_apxRxDataRing.u32Tail = Sbc_fs26_apxRxDataRing.u32Head;
        }
    }
}
#endif /*SBC_FS26_ASYNC_TRANSMIT*/

#if (STD_ON == SBC_FS26_VERSION_INFO_API)
/*================================================================================================*/
/**
* @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. Value cannot be NULL_PTR.
*
* @return       void
*
* @api
*/
/** @implements   Sbc_fs26_GetVersionInfo_Activity */
void Sbc_fs26_GetVersionInfo(Std_VersionInfoType* pVersionInfo)
{
    if (NULL_PTR == pVersionInfo)
    {
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETVERSIONINFO, (uint8)SBC_FS26_E_PARAM_POINTER);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        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;
    }
}
#endif /* STD_ON == SBC_FS26_VERSION_INFO_API */

/*================================================================================================*/
/**
*   @brief          This function indicate the current Sbc's state
*
*   @param[in]      void
*
*
*   @return         Sbc_fs26_DeviceState    Device State
*/
Sbc_fs26_DeviceState Sbc_fs26_GetDeviceState(void)
{
    Std_ReturnType eReturnValue = (Std_ReturnType)E_OK; /* Status. */
    Sbc_fs26_RxFrameType xRxData = {0};        /* Response to the command. */
    uint8 u8MaskedValue = 0U;
    Sbc_fs26_DeviceState eCurrentState = FS_STATES_INVALID;

    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_GETDEVICESTATE, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        eReturnValue = Sbc_fs26_ReadRegister(TRUE, SBC_FS26_FS_STATES_ADDR, &xRxData);
#ifdef SBC_FS26_ASYNC_TRANSMIT
        eReturnValue |= Sbc_fs26_WaitTransmissionDone();
#endif /*SBC_FS26_ASYNC_TRANSMIT*/
        if ((Std_ReturnType)E_OK != eReturnValue)
        {
            eCurrentState = FS_STATES_INVALID;
        }
        else
        {
            u8MaskedValue = (uint8)(xRxData.u16ReadData & SBC_FS26_FS_FS_STATES_MASK);

            /* Check the value from FS_STATES register */
            switch (u8MaskedValue)
            {
                case 0x04U:
                    /* DEBUG ENTRY */
                    eCurrentState = FS_STATES_DEBUG_ENTRY;
                    break;
                case 0x06U:
                    /* ENABLE MONITORING */
                    eCurrentState = FS_STATES_MONITORING;
                    break;
                case 0x08U:
                    /* RSTB RELEASE */
                    eCurrentState = FS_STATES_RSTB_RELEASE;
                    break;
                case 0x09U:
                    /* FS_INIT */
                    eCurrentState = FS_STATES_INIT_FS;
                    break;
                case 0x0AU:
                    /* FS0B NOT RELEASED */
                    eCurrentState = FS_STATES_FS0B_ASSERT;
                    break;
                case 0x0BU:
                    /* NORMAL_FS */
                    eCurrentState = FS_STATES_NORMAL_FS;
                    break;
                default:
                    /* State not valid. */
                    eCurrentState = FS_STATES_INVALID;
                    break;
            }
        }
    }

    return (Sbc_fs26_DeviceState)eCurrentState;
}

/*================================================================================================*/
/**
* @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)
{
    if (FALSE == bIsInitialized)
    {
        /* Driver not initialized. */;
#if (STD_ON == SBC_FS26_DEV_ERROR_DETECT)
        (void)Det_ReportError((uint16)SBC_FS26_MODULE_ID, (uint8)0, (uint8)SBC_FS26_SID_DEINIT, (uint8)SBC_FS26_E_UNINIT);
#endif /* STD_ON == SBC_FS26_DEV_ERROR_DETECT */
    }
    else
    {
        /* Clear the local copy of the driver initialization structure. */
        pSbcFs26ConfigPtr = NULL_PTR;
#ifdef SBC_FS26_ASYNC_TRANSMIT
        Sbc_fs26_apxTxBufferRing.u32Head = 0U;
        Sbc_fs26_apxTxBufferRing.u32Tail = 0U;
        Sbc_fs26_apxRxDataRing.u32Head = 0U;
        Sbc_fs26_apxRxDataRing.u32Tail = 0U;
#endif
        /* Driver not initialized. */
        bIsInitialized = FALSE;
    }
}

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

#ifdef __cplusplus
}
#endif

/** @} */
