/**
* @file    CddI2c_Lld.c
*==================================================================================================
*   Project              : YTMicro AUTOSAR 4.4.0 MCAL
*   Platform             : ARM
*   Peripheral           : CddI2c_Lld
*   Dependencies         : none
*
*   Autosar Version      : V4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   SW Version           : V1.3.2
*
*   (c) Copyright 2020-2023 Yuntu Microelectronics co.,ltd.
*   All Rights Reserved.
==================================================================================================*/

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @page misra_violations MISRA-C:2012 violations list
 * PRQA S 3678 Rule 8.13: A pointer should point to a const-qualified type whenever possible.
 * PRQA S 3673 Rule 8.13: A pointer should point to a const-qualified type whenever possible.
 * PRQA S 2985 Rule 2.2:  The operation here is redundant as the result's Value is always that of the left-hand operand.
 * PRQA S 1505 Rule 3.4:  The function is only referenced in the translation unit where it is defined.
 */

/*==================================================================================================
                                              INCLUDE FILES
==================================================================================================*/
#include "Mcal.h"
#include "CddI2c.h"
#include "CddI2c_Lld_Reg.h"
#include "CddI2c_Lld.h"
#include "SchM_CddI2c.h"
#include "OsIf.h"

#if (I2C_DMA_USED == STD_ON)
#include "CddDma.h"
#endif

/*==================================================================================================
                                      SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define CDDI2C_LLD_VENDOR_ID_C                      (180)
#define CDDI2C_LLD_AR_RELEASE_MAJOR_VERSION_C       (4)
#define CDDI2C_LLD_AR_RELEASE_MINOR_VERSION_C       (4)
#define CDDI2C_LLD_AR_RELEASE_REVISION_VERSION_C    (0)
#define CDDI2C_LLD_SW_MAJOR_VERSION_C               (1)
#define CDDI2C_LLD_SW_MINOR_VERSION_C               (3)
#define CDDI2C_LLD_SW_PATCH_VERSION_C               (2)
/*==================================================================================================
                                            FILE VERSION CHECKS
==================================================================================================*/
/* Check if source file and CDDI2C_LLD header file are of the same vendor */
#if (CDDI2C_LLD_VENDOR_ID_C != CDDI2C_LLD_VENDOR_ID)
#error "CddI2c_Lld.c and CddI2c_Lld.h have different vendor ids"
#endif

/* Check if source file and CDDI2C_LLD header file are of the same Autosar version */
#if ((CDDI2C_LLD_AR_RELEASE_MAJOR_VERSION_C != CDDI2C_LLD_AR_RELEASE_MAJOR_VERSION) || \
     (CDDI2C_LLD_AR_RELEASE_MINOR_VERSION_C != CDDI2C_LLD_AR_RELEASE_MINOR_VERSION) || \
     (CDDI2C_LLD_AR_RELEASE_REVISION_VERSION_C != CDDI2C_LLD_AR_RELEASE_REVISION_VERSION))
#error "AutoSar Version Numbers of CddI2c_Lld.c and CddI2c_Lld.h are different"
#endif

/* Check if source file and CDDI2C_LLD header file are of the same Software version */
#if ((CDDI2C_LLD_SW_MAJOR_VERSION_C != CDDI2C_LLD_SW_MAJOR_VERSION) || \
     (CDDI2C_LLD_SW_MINOR_VERSION_C != CDDI2C_LLD_SW_MINOR_VERSION) || \
     (CDDI2C_LLD_SW_PATCH_VERSION_C != CDDI2C_LLD_SW_PATCH_VERSION))
#error "Software Version Numbers of CddI2c_Lld.c and CddI2c_Lld.h are different"
#endif

/* Check if source file and CDDI2C_Lld_Reg header file are of the same vendor */
#if (CDDI2C_LLD_VENDOR_ID_C != CDDI2C_LLD_REG_VENDOR_ID)
#error "CddI2c_Lld.c and CddI2c_Lld_Reg.h have different vendor ids"
#endif

/* Check if source file and CDDI2C_Lld_Reg header file are of the same Autosar version */
#if ((CDDI2C_LLD_AR_RELEASE_MAJOR_VERSION_C != CDDI2C_LLD_REG_AR_RELEASE_MAJOR_VERSION) || \
     (CDDI2C_LLD_AR_RELEASE_MINOR_VERSION_C != CDDI2C_LLD_REG_AR_RELEASE_MINOR_VERSION) || \
     (CDDI2C_LLD_AR_RELEASE_REVISION_VERSION_C != CDDI2C_LLD_REG_AR_RELEASE_REVISION_VERSION))
#error "AutoSar Version Numbers of CddI2c_Lld.c and CddI2c_Lld_Reg.h are different"
#endif

/* Check if source file and CDDI2C_Lld_Reg header file are of the same Software version */
#if ((CDDI2C_LLD_SW_MAJOR_VERSION_C != CDDI2C_LLD_REG_SW_MAJOR_VERSION) || \
     (CDDI2C_LLD_SW_MINOR_VERSION_C != CDDI2C_LLD_REG_SW_MINOR_VERSION) || \
     (CDDI2C_LLD_SW_PATCH_VERSION_C != CDDI2C_LLD_REG_SW_PATCH_VERSION))
#error "Software Version Numbers of CddI2c_Lld.c and CddI2c_Lld_Reg.h are different"
#endif

/*==================================================================================================
                                                GLOBAL VARIABLES
==================================================================================================*/
#define CDDI2C_START_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"

CDDI2C_VAR static I2C_MasterStateType I2c_MasterStatus[I2C_INSTANCE_COUNT];
CDDI2C_VAR static I2C_SlaveStateType I2c_SlaveStatus[I2C_INSTANCE_COUNT];

#define CDDI2C_STOP_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"

#if (I2C_DMA_USED == STD_ON)
extern const CddDma_TransferConfigType *DmaChannelTransferConfigArray[CDDDMA_TRANSFER_CONFIG_COUNT];
#endif
/*==================================================================================================
                                                LOCAL VARIABLES
==================================================================================================*/
#define CDDI2C_START_SEC_VAR_INIT_UNSPECIFIED
#include "CddI2c_MemMap.h"

/* MR12 RULE 8.13 VIOLATION: A pointer should point to a const-qualified type whenever possible.
 * Tessy comp test need volatile Value define, thus, couldn't adhere to M3CM Rule-8.13
 */
CDDI2C_VAR static volatile I2C_Type *I2c_Base[I2C_INSTANCE_COUNT] = I2C_BASE_PTRS; /* PRQA S 3678 */

#define CDDI2C_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "CddI2c_MemMap.h"

#define CDDI2C_START_SEC_CONST_BOOLEAN
#include "CddI2c_MemMap.h"

#if (I2C_SLAVE_SUPPORT_ALL_INSTANCE == FALSE)
CDDI2C_CONST static const boolean I2c_SupportSlave[I2C_INSTANCE_COUNT] = I2C_SLAVE_SUPPORT;
#endif

#define CDDI2C_STOP_SEC_CONST_BOOLEAN
#include "CddI2c_MemMap.h"

#define CDDI2C_START_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"
/*I2C hw status Data*/
CDDI2C_VAR static I2C_MasterStateType *I2c_MasterHwStatePtr[I2C_INSTANCE_COUNT];
CDDI2C_VAR static I2C_SlaveStateType *I2c_SlaveHwStatePtr[I2C_INSTANCE_COUNT];

#define CDDI2C_STOP_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"

#if (I2C_DMA_USED == STD_ON)
#define CDDI2C_START_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"

CDDI2C_VAR static CddDma_TransferConfigType MasterTxDmaConfig;
CDDI2C_VAR static CddDma_TransferConfigType MasterRxDmaConfig;

CDDI2C_VAR static CddDma_TransferConfigType SlaveTxDmaConfig;
CDDI2C_VAR static CddDma_TransferConfigType SlaveRxDmaConfig;

#define CDDI2C_STOP_SEC_VAR_CLEARED_UNSPECIFIED
#include "CddI2c_MemMap.h"
#endif

/*==================================================================================================
                                                LOCAL FUNCTIONS
==================================================================================================*/
/*previous declaration*/
void I2c_Lld_SlaveIRQHandler(uint8 Instance);
void I2C_Lld_MasterIRQHandler(uint8 Instance);
#if defined (CPU_YTM32B1ME0) || defined (CPU_YTM32B1MD1) || defined (CPU_YTM32B1MC0)
#ifdef I2C_0_MASTER_MODE_ENABLED
ISR(I2C0_Master_IRQHandler);
#endif
#ifdef I2C_1_MASTER_MODE_ENABLED
ISR(I2C1_Master_IRQHandler);
#endif
#ifdef I2C_2_MASTER_MODE_ENABLED
ISR(I2C2_Master_IRQHandler);
#endif
#ifdef I2C_0_SLAVE_MODE_ENABLED
ISR(I2C0_Slave_IRQHandler);
#endif
#ifdef I2C_1_SLAVE_MODE_ENABLED
ISR(I2C1_Slave_IRQHandler);
#endif
#ifdef I2C_2_SLAVE_MODE_ENABLED
ISR(I2C2_Slave_IRQHandler);
#endif

#elif defined (CPU_YTM32B1HA0)

#if defined(I2C_0_MASTER_MODE_ENABLED) || defined(I2C_0_SLAVE_MODE_ENABLED)
ISR(I2C0_Master_Slave_IRQHandler);
#endif
#if defined(I2C_1_MASTER_MODE_ENABLED) || defined(I2C_1_SLAVE_MODE_ENABLED)
ISR(I2C1_Master_Slave_IRQHandler);
#endif
#if defined(I2C_2_MASTER_MODE_ENABLED) || defined(I2C_2_SLAVE_MODE_ENABLED)
ISR(I2C2_Master_Slave_IRQHandler);
#endif
#if defined(I2C_3_MASTER_MODE_ENABLED) || defined(I2C_3_SLAVE_MODE_ENABLED)
ISR(I2C3_Master_Slave_IRQHandler);
#endif
#if defined(I2C_4_MASTER_MODE_ENABLED) || defined(I2C_4_SLAVE_MODE_ENABLED)
ISR(I2C4_Master_Slave_IRQHandler);
#endif

#endif

#define CDDI2C_START_SEC_CODE
#include "CddI2c_MemMap.h"

/**
 * @brief Set the Master glitch filter for SDA
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Cycles  the Master filter SDA of the module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterDigitFilterSDASet(volatile I2C_Type *BaseAddr, uint8 Cycles)
{
    uint32 Tmp = BaseAddr->MFLTCFG;
    Tmp &= ~I2C_MFLTCFG_FLTSDA_MASK;
    Tmp |= I2C_MFLTCFG_FLTSDA(Cycles);
    BaseAddr->MFLTCFG = Tmp;
}

/**
 * @brief Set the Master glitch filter for SCL
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Cycles  the Master filter SCL of the module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterDigitFilterSCLSet(volatile I2C_Type *BaseAddr, uint8 Cycles)
{
    uint32 Tmp = BaseAddr->MFLTCFG;
    Tmp &= ~I2C_MFLTCFG_FLTSCL_MASK;
    Tmp |= I2C_MFLTCFG_FLTSCL(Cycles);
    BaseAddr->MFLTCFG = Tmp;
}

/**
 * @brief Set the Slave glitch filter for SDA
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Cycles  the Master filter SDA of the module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveDigitFilterSDASet(volatile I2C_Type *BaseAddr, uint8 Cycles)
{
    uint32 Tmp = BaseAddr->MFLTCFG;
    Tmp &= ~I2C_MFLTCFG_FLTSDA_MASK;
    Tmp |= I2C_MFLTCFG_FLTSDA(Cycles);
    BaseAddr->MFLTCFG = Tmp;
}

/**
 * @brief Set the Slave glitch filter for SCL
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Cycles  the Master filter SCL of the module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveDigitFilterSCLSet(volatile I2C_Type *BaseAddr, uint8 Cycles)
{
    uint32 Tmp = BaseAddr->MFLTCFG;
    Tmp &= ~I2C_MFLTCFG_FLTSCL_MASK;
    Tmp |= I2C_MFLTCFG_FLTSCL(Cycles);
    BaseAddr->MFLTCFG = Tmp;
}

/**
 * @brief Set the line idle TimeOut
 *
 * @details This function configures the line idle TimeOut
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Timeout  TimeOut period in clock cycles
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterBusIdleTimeoutSet(volatile I2C_Type *BaseAddr, uint16 Timeout)
{
    uint32 Tmp = BaseAddr->TOCFG;
    Tmp &= ~I2C_TOCFG_IDLE_MASK;
    Tmp |= I2C_TOCFG_IDLE(Timeout);
    BaseAddr->TOCFG = Tmp;
}

/**
 * @brief Set pin low TimeOut for SDA or SCL
 *
 * @details This function configures the pin low TimeOut only for SDA or, for SCL and SDA.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Configuration "0" - Pin Low Timeout Flag will set only for SDA, "1" - Pin Low Timeout Flag
                             will set if either SCL or SDA is low longer than the configured TimeOut.
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterPinLowTimeoutCfg(volatile I2C_Type *BaseAddr, boolean Configuration)
{
    uint32 Tmp = BaseAddr->TOCFG;
    Tmp &= ~I2C_TOCFG_SDA_MASK;
    Tmp |= I2C_TOCFG_SDA(Configuration);
    BaseAddr->TOCFG = Tmp;
}


/**
 * @brief Set the pin low TimeOut
 *
 * @details This function configures the pin low TimeOut
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Timeout TimeOut period in clock cycles
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterPinLowTimeoutSet(volatile I2C_Type *BaseAddr, uint16 Timeout)
{
    uint32 Tmp = BaseAddr->TOCFG;
    Tmp &= ~I2C_TOCFG_LOW_MASK;
    Tmp |= I2C_TOCFG_LOW(Timeout); /*PRQA S 2985*/
    BaseAddr->TOCFG = Tmp;
}

/*!
 * @brief Configure the I2C Master Prescaler
 *
 * @details This function configures the clock Prescaler used for all I2C Master logic,
 * except the digital glitch filters.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Prescaler  I2C Master Prescaler
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterPrescalerSet(volatile I2C_Type *BaseAddr, I2C_MasterPrescalerType Prescaler)
{
    uint32 Tmp = BaseAddr->MFLTCFG;
    Tmp &= ~I2C_MFLTCFG_DIV_MASK;
    Tmp |= I2C_MFLTCFG_DIV(Prescaler); /*PRQA S 2985*/
    BaseAddr->MFLTCFG = Tmp;
}

/*!
 * @brief Set the Data hold time for SDA
 *
 * @details This function sets the minimum number of cycles (minus one) that is used as the
 * Data hold time for SDA. Must be configured less than the minimum SCL low period.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  Value of the Data hold time for SDA
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterDataValidDelaySet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->MCLKCFG;
    Tmp &= ~I2C_MCLKCFG_VALID_MASK;
    Tmp |= I2C_MCLKCFG_VALID(Value);
    BaseAddr->MCLKCFG = Tmp;
}

/*!
 * @brief Set the minimum clock high period
 *
 * @details This function configures the minimum number of cycles (minus one) that the
 * SCL clock is driven high by the Master. The SCL high time is extended by the
 * time it takes to detect a rising edge on the external SCL pin. Ignoring any
 * additional board delay due to external loading, this is equal to
 * (2 + FILTSCL) / 2^PRESCALE cycles.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  minimum clock high period
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterClkHighPeriodSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->MCLKCFG;
    Tmp &= ~I2C_MCLKCFG_HIGH_MASK;
    Tmp |= I2C_MCLKCFG_HIGH(Value);
    BaseAddr->MCLKCFG = Tmp;
}

/*!
 * @brief Set the setup and hold delay for a START / STOP condition
 *
 * @details This function configures the Minimum number of cycles (minus one) that is used
 * by the Master as the setup and hold time for a (repeated) START condition and setup
 * time for a STOP condition. The setup time is extended by the time it takes to detect
 * a rising edge on the external SCL pin. Ignoring any additional board delay due to
 * external loading, this is equal to (2 + FILTSCL) / 2^PRESCALE cycles.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  setup and hold time for a START / STOP condition
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterSetupHoldDelaySet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->MCLKCFG;
    Tmp &= ~I2C_MCLKCFG_STHD_MASK;
    Tmp |= I2C_MCLKCFG_STHD(Value); /*PRQA S 2985*/
    BaseAddr->MCLKCFG = Tmp;
}

/*!
 * @brief Set the minimum clock low period
 *
 * @details This function configures the minimum number of cycles (minus one) that the
 * SCL clock is driven low by the Master. This Value is also used for the
 * minimum bus free time between a STOP and a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  minimum clock low period
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterClkLowPeriodSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->MCLKCFG;
    Tmp &= ~I2C_MCLKCFG_LOW_MASK;
    Tmp |= I2C_MCLKCFG_LOW(Value);
    BaseAddr->MCLKCFG = Tmp;
}

/*!
 * @brief Set the Data hold time for SDA in high-speed mode
 *
 * @details This function sets the minimum number of cycles (minus one) that is used as the
 * Data hold time for SDA in High-Speed mode. Must be configured less than the
 * minimum SCL low period.
 * This setting only has effect during High-Speed mode transfers.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  Value of the Data hold time for SDA
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterDataVldDelayHSSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->HSCLK;
    Tmp &= ~I2C_HSCLK_VALID_MASK;
    Tmp |= I2C_HSCLK_VALID(Value);
    BaseAddr->HSCLK = Tmp;
}

/*!
 * @brief Set the setup and hold time for a START / STOP condition in high-speed mode
 *
 * @details This function configures the Minimum number of cycles (minus one) that is used
 * by the Master as the setup and hold time for a (repeated) START condition and setup
 * time for a STOP condition. The setup time is extended by the time it takes to detect
 * a rising edge on the external SCL pin. Ignoring any additional board delay due to
 * external loading, this is equal to (2 + FILTSCL) / 2^PRESCALE cycles.
 * This setting only has effect during High-Speed mode transfers.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  setup and hold time for a START / STOP condition
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterSetupHoldDlyHSSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->HSCLK;
    Tmp &= ~I2C_HSCLK_STHD_MASK;
    Tmp |= I2C_HSCLK_STHD(Value); /*PRQA S 2985*/
    BaseAddr->HSCLK = Tmp;
}

/*!
 * @brief Set the minimum clock high period in high-speed mode
 *
 * @details This function configures the minimum number of cycles (minus one) that the
 * SCL clock is driven high by the Master. The SCL high time is extended by the
 * time it takes to detect a rising edge on the external SCL pin. Ignoring any
 * additional board delay due to external loading, this is equal to
 * (2 + FILTSCL) / 2^PRESCALE cycles.
 * This setting only has effect during High-Speed mode transfers.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  minimum clock high period
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterClkHighPeriodHSSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->HSCLK;
    Tmp &= ~I2C_HSCLK_HIGH_MASK;
    Tmp |= I2C_HSCLK_HIGH(Value);
    BaseAddr->HSCLK = Tmp;
}

/*!
 * @brief Set the minimum clock low period in high-speed mode
 *
 * @details This function configures the minimum number of cycles (minus one) that the
 * SCL clock is driven low by the Master. This Value is also used for the
 * minimum bus free time between a STOP and a START condition.
 * This setting only has effect during High-Speed mode transfers.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  minimum clock low period
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterClkLowPeriodHSSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    uint32 Tmp = BaseAddr->HSCLK;
    Tmp &= ~I2C_HSCLK_LOW_MASK;
    Tmp |= I2C_HSCLK_LOW(Value);
    BaseAddr->HSCLK = Tmp;
}

/*!
 * @brief Set the pin mode of the module
 *
 * @details This function sets the pin mode of the module. See type I2C_Lld_PinConfigType for
 * a description of available modes.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Configuration  pin mode of the module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterPinConfig(volatile I2C_Type *BaseAddr, I2C_Lld_PinConfigType Configuration)
{
    uint32 Tmp = BaseAddr->MCTRL;
    Tmp &= ~(I2C_MCTRL_PPEN_MASK | I2C_MCTRL_HSMOD_MASK);
    Tmp |= (uint32)Configuration << I2C_MCTRL_PPEN_SHIFT;
    BaseAddr->MCTRL = Tmp;
}

/*!
 * @brief Configure the reaction of the module on NACK reception
 *
 * @details This function configures how the I2C Master reacts when receiving a NACK. NACK responses can
 * be treated normally or ignored. In Ultra-Fast mode it is necessary to configure the module to
 * ignore NACK responses.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Configuration  set reaction of the module on NACK reception
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterNACKConfig(volatile I2C_Type *BaseAddr, I2C_Lld_NackConfigType Configuration)
{
    uint32 RegValue = BaseAddr->MCTRL;
    RegValue &= (uint32)(~I2C_MCTRL_IGACK_MASK);
    RegValue |= I2C_MCTRL_IGACK(Configuration);
    BaseAddr->MCTRL = RegValue;
}


/*!
 * @brief Return the number of words in the transmit FIFO
 *
 * @details This function returns the number of words currently available in the transmit FIFO.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  the number of words in the transmit FIFO
 * @return uint16
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_MasterTxFIFOCountGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->TXFIFO;
    Tmp = (Tmp & I2C_TXFIFO_COUNT_MASK) >> I2C_TXFIFO_COUNT_SHIFT;
    return (uint16) Tmp;
}

/*!
 * @brief Get the size of the Master Transmit FIFO
 *
 * @details  This function returns the size of the Master Transmit FIFO, always a power of 2.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return uint16
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_MasterTxFIFOSizeGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->TXFIFO;
    Tmp = (Tmp & I2C_TXFIFO_SIZE_MASK) >> I2C_TXFIFO_SIZE_SHIFT;
    Tmp = 1UL << Tmp;      /* TX FIFO size = 2^MTXFIFO */
    return (uint16) Tmp;
}

/*!
 * @brief Provide commands and Data for the I2C Master
 *
 * @details  This function stores commands and Data in the transmit FIFO and increments the FIFO
 * write pointer.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Cmd  command for the I2C Master
 * @param[in] Data  Data for the I2C Master
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterTransmitCmd(volatile I2C_Type *BaseAddr, I2C_MasterCommandType Cmd, uint8 Data)
{
    BaseAddr->MDATA = ((uint32) Cmd << I2C_MDATA_START_SHIFT) + (uint32) Data;
}

/*!
 * @brief Set the transmit FIFO watermark
 *
 * @details  This function configures the transmit FIFO watermark. Whenever the number of words in the transmit
 * FIFO is greater than the transmit FIFO watermark, a transmit Data request event is generated.
 * Writing a Value equal or greater than the FIFO size will be truncated.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  number of words in the transmit FIFO that will cause the transmit Data flag to be set
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterTxFIFOWatermarkSet(volatile I2C_Type *BaseAddr, uint16 Value)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_05();
    uint32 Tmp = BaseAddr->TXFIFO;
    Tmp &= ~I2C_TXFIFO_WATER_MASK;
    Tmp |= I2C_TXFIFO_WATER(Value); /*PRQA S 2985*/
    BaseAddr->TXFIFO = Tmp;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_05();
}

/*!
 * @brief Return the number of words in the Receive FIFO
 *
 * @details  This function returns the number of words currently available in the Receive FIFO.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return uint16
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_MasterRxFIFOCountGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->RXFIFO;
    Tmp = (Tmp & I2C_RXFIFO_COUNT_MASK) >> I2C_RXFIFO_COUNT_SHIFT;
    return (uint16) Tmp;
}

/*!
 * @brief Set the Receive FIFO watermark
 *
 * @details  This function configures the Receive FIFO watermark. Whenever the number of words in the Receive
 * FIFO is greater than the Receive FIFO watermark, a Receive Data ready event is generated.
 * Writing a Value equal or greater than the FIFO size will be truncated.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Value  number of words in the Receive FIFO that will cause the Receive Data flag to be set
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterRxFIFOWatermarkSet(volatile I2C_Type *BaseAddr, uint8 Value)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_06();
    uint32 Tmp = BaseAddr->RXFIFO;
    Tmp &= ~I2C_RXFIFO_WATER_MASK;
    Tmp |= I2C_RXFIFO_WATER(Value); /*PRQA S 2985*/
    BaseAddr->RXFIFO = Tmp;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_06();
}

/*!
 * @brief Get the size of the Master Receive FIFO
 *
 * @details  This function returns the size of the Master Receive FIFO, always a power of 2.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return uint16
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_MasterRxFIFOSizeGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->RXFIFO;
    Tmp = (Tmp & I2C_RXFIFO_SIZE_MASK) >> I2C_RXFIFO_SIZE_SHIFT;
    Tmp = 1UL << Tmp;     /* RX FIFO size = 2^MRXFIFO */
    return (uint16) Tmp;
}
/*!
 * @brief Indicate if the I2C Master requests more Data
 *
 * @details  This function returns true when the number of words in the transmit FIFO is equal
 * or less than the transmit FIFO watermark. See function I2C_Set_MasterTxFIFOWatermark()
 * for configuring the transmit FIFO watermark.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterDataReqEventCheck(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_TXIF_MASK) >> I2C_MSTS_TXIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Reset the Master transmit FIFO
 *
 * @details  This function empties the transmit FIFO of the I2C Master.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterTxFIFOCmdReset(volatile I2C_Type *BaseAddr)
{
    BaseAddr->TXFIFO |= I2C_TXFIFO_RESET_MASK;
}

/*!
 * @brief Reset the Master Receive FIFO
 *
 * @details This function empties the Receive FIFO of the I2C Master.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterRxFIFOCmdReset(volatile I2C_Type *BaseAddr)
{
    BaseAddr->RXFIFO |= I2C_RXFIFO_RESET_MASK;
}

/*!
 * @brief Indicate the availability of Receive Data
 *
 * @details This function returns true when the number of words in the Receive FIFO is greater
 * than the Receive FIFO watermark. See function I2C_MasterSetRxFIFOWatermark()
 * for configuring the Receive FIFO watermark.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterRxDataRdyEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_RXIF_MASK) >> I2C_MSTS_RXIF_SHIFT; /*PRQA S 2985*/
    return (boolean) RegValue;
}

/*!
 * @brief Return the received Data
 *
 * @details This function returns Data received by the I2C Master that has not been discarded
 * due to Data match settings or active command, and increments the FIFO read pointer.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return uint8
 */
CDDI2C_FUNC LOCAL_INLINE uint8 I2C_Lld_MasterRxDataGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->MDATA;
    Tmp = (Tmp & I2C_MDATA_DATA_MASK) >> I2C_MDATA_DATA_SHIFT; /*PRQA S 2985*/
    return (uint8) Tmp;
}

/*!
 * @brief Return the configured Receive FIFO watermark
 *
 * @details This function returns the currently configured Value for Receive FIFO watermark
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return uint16
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_MasterRxFIFOWatermarkGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->RXFIFO;
    Tmp = (Tmp & I2C_RXFIFO_WATER_MASK) >> I2C_RXFIFO_WATER_SHIFT; /*PRQA S 2985*/
    return (uint16) Tmp;
}

/*!
 * @brief Check the occurrence of a FIFO error event
 *
 * @details This function returns true if the I2C Master detects an attempt to send or
 * Receive Data without first generating a (repeated) START condition. This can
 * occur if the transmit FIFO underflows when the AUTOSTOP bit is set. When this
 * flag is set, the I2C Master will send a STOP condition (if busy) and will
 * not initiate a new START condition until this flag has been cleared.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterFIFOErrorEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_OPERRIF_MASK) >> I2C_MSTS_OPERRIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Clear the FIFO error event flag
 *
 * @details This function clears the FIFO error event. This event must be cleared before
 * the I2C Master can initiate a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module.
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterFIFOErrorEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->MSTS = ((uint32) 1U << I2C_MSTS_OPERRIF_SHIFT);
}

/*!
 * @brief Check the occurrence of an arbitration lost event
 *
 * @details This function returns true if the I2C Master detects an arbitration lost
 * condition, as defined by the I2C standard. When this flag sets, the I2C
 * Master will release the bus (go idle) and will not initiate a new START
 * condition until this flag has been cleared.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterArbitLostEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_ARBIF_MASK) >> I2C_MSTS_ARBIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Clear the arbitration lost event flag
 *
 * @details This function clears the arbitration lost event. This event must be cleared
 * before the I2C Master can initiate a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterArbitLostEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->MSTS = ((uint32) 1U << I2C_MSTS_ARBIF_SHIFT);
}

/*!
 * @brief Check the occurrence of an unexpected NACK event
 *
 * @details This function returns true if the I2C Master detects a NACK when
 * transmitting an Address or Data. If a NACK is expected for a given Address
 * (as configured by the command word) then the flag will set if a NACK is not
 * generated. When set, the Master will transmit a STOP condition and will not
 * initiate a new START condition until this flag has been cleared.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterNACKDetEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_NACKIF_MASK) >> I2C_MSTS_NACKIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Clear the unexpected NACK event flag
 *
 * @details This function clears the unexpected NACK event. This event must be cleared
 * before the I2C Master can initiate a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterNACKDetEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->MSTS = ((uint32) 1U << I2C_MSTS_NACKIF_SHIFT);
}

/*!
 * @brief Clear all flags in register MSTS
 *
 * @details This function clears the flags in MSTS. It is called when hw is init but the
 * interrupt is generated.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterAllIntcFlagClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->MSTS = I2C_MSTS_STATE_MASK;
}

/**
 * @brief Check the occurrence of an pin low TimeOut event
 *
 * @details This function returns true if the I2C Master detects a
 * pin low TimeOut event. The Pin Low Timeout Flag will set
 * when SCL and/or SDA input is low for more than PINLOW Cycles.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return boolean
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_MasterPinLowTimeoutEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->MSTS;
    RegValue = (RegValue & I2C_MSTS_TOIF_MASK) >> I2C_MSTS_TOIF_SHIFT;
    return (boolean)((1U == RegValue) ? TRUE : FALSE);
}

/**
 * @brief Clear the pin low TimeOut event flag
 *
 * @details This function clears the pin low TimeOut event. This event must be cleared
 * before the I2C Master can initiate a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterPinLowTimeoutEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->MSTS = ((uint32)1U << I2C_MSTS_TOIF_SHIFT);
}

/*!
 * @brief Enable or disable the I2C Master
 *
 * @details This function enables or disables the I2C module in Master mode. If the module
 * is enabled, the transmit FIFO  is not empty and the I2C bus is idle, then
 * the I2C Master will immediately initiate a transfer on the I2C bus.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable the I2C Master
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterEnable(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->MCTRL;
    RegValue &= (uint32)(~I2C_MCTRL_MEN_MASK);
    RegValue |= (uint32)Enable << I2C_MCTRL_MEN_SHIFT; /*PRQA S 2985*/
    BaseAddr->MCTRL = RegValue;
}

/*!
 * @brief Configure the ADDR0 Address for Slave Address match
 *
 * @details This function configures the ADDR0 Value which is used to validate the received
 * Slave Address. In 10-bit mode, the first Address byte is compared to
 * { 11110, ADDR0[10:9] } and the second Address byte is compared to ADDR0[8:1].
 * In 7-bit mode, the Address is compared to ADDR0[7:1]
 * The formula used for Address validation is configured with function
 * I2C_Set_SlaveAddrConfig().
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Addr  ADDR0 Address for Slave Address match
 *  @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveAddr0Set(volatile I2C_Type *BaseAddr, uint16 Addr)
{
    uint32 Tmp = BaseAddr->SADDR;
    Tmp &= ~I2C_SADDR_ADDRA_MASK;
    Tmp |= I2C_SADDR_ADDRA(Addr);
    BaseAddr->SADDR = Tmp;
}

/*!
 * @brief Control Address match Configuration
 *
 * @details This function configures the condition that will cause an Address match to
 * occur. See type I2C_Lld_SlaveAddrConfigType for a description of available options.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Configuration  configures the condition that will cause an Address to match
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveAddrConfigSet(volatile I2C_Type *BaseAddr,
        I2C_Lld_SlaveAddrConfigType Configuration)
{
    uint32 Tmp = BaseAddr->SCTRL;
    Tmp &= ~I2C_SCTRL_ADDRCFG_MASK;
    Tmp |= I2C_SCTRL_ADDRCFG(Configuration);
    BaseAddr->SCTRL = Tmp;
}

/*!
 * @brief Control Slave behaviour when NACK is detected
 *
 * @details This function controls the option to ignore received NACKs. When enabled, the
 * I2C Slave will continue transfers after a NACK is detected. This option is needed
 * for Ultra-Fast mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] NackConfig  Slave behaviour when NACK is detected
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveIgnoreNACKSet(volatile I2C_Type *BaseAddr,
        I2C_Lld_SlaveNackConfigType NackConfig)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_IGACK_MASK);
    RegValue |= (uint32)(NackConfig) << I2C_SCTRL_IGACK_SHIFT;
    BaseAddr->SCTRL = RegValue;
}


/*!
 * @brief Configure the ACK/NACK transmission after a received byte
 *
 * @details This function can be used to instruct the I2C Slave whether to send an ACK or
 * a NACK after receiving a byte. When ACK stall is enabled this function must be
 * called after each matching Address and after each received Data byte. It can also
 * be called when I2C Slave is disabled or idle to configure the default ACK/NACK.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Nack  specifies whether to transmit ACK or NACK
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveTransmitNACKSet(volatile I2C_Type *BaseAddr,
        I2C_Lld_SlaveNackTransferType Nack)
{
    uint32 RegValue = BaseAddr->SACK;
    RegValue &= (uint32)(~I2C_SACK_NACK_MASK);
    RegValue |= (uint32)Nack << I2C_SACK_NACK_SHIFT; /*PRQA S 2985*/
    BaseAddr->SACK = RegValue;
}


/*!
 * @brief Enable or disable clock stretching for the sending of the ACK bit
 *
 * @details This function enables or disables SCL clock stretching during Slave-transmit Address
 * byte(s) and Slave-receiver Address and Data byte(s) to allow software to write the
 * Transmit ACK Register before the ACK or NACK is transmitted. Clock stretching occurs
 * when transmitting the 9th bit and is therefore not compatible with high speed mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  Enable or disable clock stretching
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveACKStallSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_ACKSTALL_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_ACKSTALL_SHIFT;
    BaseAddr->SCTRL = RegValue;
}

/*!
 * @brief Enable or disable clock stretching for Data transmission
 *
 * @details  This function enables or disables SCL clock stretching when the transmit Data
 * flag is set during a Slave-transmit transfer. Clock stretching occurs following
 * the 9th bit and is therefore compatible with high speed mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  Enable or disable clock stretching
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveTXDStallSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_TXSTALL_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_TXSTALL_SHIFT;
    BaseAddr->SCTRL = RegValue;
}

/*!
 * @brief Enable or disable clock stretching for Data reception
 *
 * @details  This function enables or disables SCL clock stretching when Receive Data flag
 * is set during a Slave-Receive transfer. Clock stretching occurs following the 9th
 * bit and is therefore compatible with high speed mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  Enable or disable clock stretching
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveRXStallSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_RXSTALL_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_RXSTALL_SHIFT;
    BaseAddr->SCTRL = RegValue;
}

/*!
 * @brief Enable or disable clock stretching for valid Address reception
 *
 * @details  This function enables or disables SCL clock stretching when the Address valid
 * flag is asserted. Clock stretching only occurs following the 9th bit and is
 * therefore compatible with high speed mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  Enable or disable clock stretching
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveAddrStallSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_ADRSTALL_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_ADRSTALL_SHIFT;
    BaseAddr->SCTRL = RegValue;
}

/*!
 * @brief Control detection of the High-speed Mode Master code
 *
 * @details This function enables or disables the detection of the High-speed Mode
 * Master code of Slave Address 0000_1XX, but does not cause an Address match
 * on this code. When set and any Hs-mode Master code is detected, the Slave
 * filter and ACK stalls are disabled until the next STOP condition is detected.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  Enable/disable the detection of the High-speed Mode Master code
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveHighSpeedModeDetSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_HSEN_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_HSEN_SHIFT;
    BaseAddr->SCTRL = RegValue;
}

#if (I2C_DMA_USED == STD_ON)
/*!
 * @brief Enable/disable Slave Receive Data DMA requests
 *
 * This function enables or disables generation of Rx DMA requests when received
 * Data is available.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable Receive Data DMA requests
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveRxDmaSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_07();
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_RXDMAEN_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_RXDMAEN_SHIFT;
    BaseAddr->SCTRL = RegValue;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_07();
}
#endif /* I2C_DMA_USED == STD_ON */

/*!
 * @brief Return the received Slave Address
 *
 * This function returns the received Slave Address. Reading the Address clears
 * the Address valid event. The Address can be 7-bit or 10-bit (10-bit addresses
 * are prefixed by 11110) and includes the R/W bit in the least significant position.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  received Address
 */
CDDI2C_FUNC LOCAL_INLINE uint16 I2C_Lld_SlaveReceivedAddrGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->SRADDR;
    Tmp = (Tmp & I2C_SRADDR_ADDR_MASK) >> I2C_SRADDR_ADDR_SHIFT; /*PRQA S 2985*/
    return (uint16) Tmp;
}

#if (I2C_DMA_USED == STD_ON)
/*!
 * @brief Enable/disable Slave transmit Data DMA requests
 *
 * This function enables or disables generation of Tx DMA requests when the module
 * requires more Data to transmit.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable transmit Data DMA requests
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveTxDmaSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_08();
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_TXDMAEN_MASK);
    RegValue |= (uint32)(Enable) << I2C_SCTRL_TXDMAEN_SHIFT;
    BaseAddr->SCTRL = RegValue;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_08();
}
#endif /* I2C_DMA_USED == STD_ON */

#if(I2C_HAS_ULTRA_FAST_MODE)
/*!
 * @brief Check the detection of a FIFO overflow or underflow
 *
 * This function checks for the occurrence of a Slave FIFO overflow or underflow.
 * This event can only occur if clock stretching is disabled.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of a FIFO overflow or underflow
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveFIFOErrorEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_OPERRIF_MASK) >> I2C_SSTS_OPERRIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Clear the FIFO overflow or underflow flag
 *
 * This function clears the FIFO overflow or underflow event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveFIFOErrorEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->SSTS = ((uint32) 1U << I2C_SSTS_OPERRIF_SHIFT);
}

#endif /* I2C_HAS_ULTRA_FAST_MODE */

/*!
 * @brief Check the detection of a bit error
 *
 * This function checks for the occurrence of a bit error event. This event occurs
 * if the I2C Slave transmits a logic one and detects a logic zero on the I2C bus. The
 * Slave will ignore the rest of the transfer until the next (repeated) START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of a bit error
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveBitErrorEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_ARBIF_MASK) >> I2C_SSTS_ARBIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Check the detection of a STOP condition
 *
 * This function checks for the detection of a STOP condition, after the I2C Slave
 * matched the last Address byte.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of a STOP condition
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveSTOPDetectEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_STOPIF_MASK) >> I2C_SSTS_STOPIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Check the detection of a repeated START condition
 *
 * This function checks for the detection of a repeated START condition, after
 * the I2C Slave matched the last Address byte. This event does not occur
 * when the Slave first detects a START condition.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of a repeated START condition
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveRepeatedStartEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_RSIF_MASK) >> I2C_SSTS_RSIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Check the validity of the Address Status Register
 *
 * This function checks for the detection of a valid Address. The event is
 * cleared by reading the Address - see function I2C_Get_SlaveReceivedAddr().
 * It can also be cleared by reading the Data register, when Data register has
 * been configured to allow Address reads.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of the validity of the Address Status Register.
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveAddressValidEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_ADDRIF_MASK) >> I2C_SSTS_ADDRIF_SHIFT;
    return (boolean)((1U == RegValue) ? TRUE : FALSE);
}

/*!
 * @brief Provide Data for the I2C Slave transmitter
 *
 * This function provides one byte of Data for the I2C Slave to transmit.
 * Calling this function clears the transmit Data event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Data  Data for the I2C Slave transmitter
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveTransmitData(volatile I2C_Type *BaseAddr, uint8 Data)
{
    BaseAddr->SDATA = (uint32)Data;
}

/*!
 * @brief Return the Data received by the I2C Slave receiver
 *
 * This function returns the Data received by the I2C Slave.
 * Calling this function clears the Receive Data event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  Data received by the I2C Slave receiver
 */
CDDI2C_FUNC LOCAL_INLINE uint8 I2C_Lld_SlaveDataGet(const volatile I2C_Type *BaseAddr)
{
    uint32 Tmp = BaseAddr->SDATA;
    Tmp = (Tmp & I2C_SDATA_DATA_MASK) >> I2C_SDATA_DATA_SHIFT; /*PRQA S 2985*/
    return (uint8) Tmp;
}

/*!
 * @brief Clear the repeated START detect flag
 *
 * This function clears the repeated START detect event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveRepeatStartEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->SSTS = ((uint32) 1U << I2C_SSTS_RSIF_SHIFT);
}

/*!
 * @brief Clear bit error flag
 *
 * This function clears the bit error event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveBitErrorEventClear(volatile I2C_Type *BaseAddr)
{
    BaseAddr->SSTS = ((uint32) 1U << I2C_SSTS_ARBIF_SHIFT);
}

/*!
 * @brief Clear the STOP detect flag
 *
 * This function clears the STOP detect event.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveStopDetEventClr(volatile I2C_Type *BaseAddr)
{
    BaseAddr->SSTS = ((uint32) 1U << I2C_SSTS_STOPIF_SHIFT);
}

/*!
 * @brief Return the state of the specified I2C Slave interrupt
 *
 * This function returns the enabled/disabled state of the Slave interrupt
 * source specified by the interrupt Parameter.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Interrupts  interrupt for which the check is made;
 *  must be one of the following constants:
 *  - I2C_SLAVE_SMBUS_ALERT_RESPONSE  - SMBus Alert Response Interrupt
 *  - I2C_SLAVE_GENERAL_CALL          - General Call Interrupt
 *  - I2C_SLAVE_ADDRESS_MATCH_1       - Address Match 1 Interrupt
 *  - I2C_SLAVE_ADDRESS_MATCH_0       - Address Match 0 Interrupt
 *  - I2C_SLAVE_FIFO_ERROR            - FIFO Error Interrupt
 *  - I2C_SLAVE_BIT_ERROR             - Bit Error Interrupt
 *  - I2C_SLAVE_STOP_DETECT           - STOP Detect Interrupt
 *  - I2C_SLAVE_REPEATED_START        - Repeated Start Interrupt
 *  - I2C_SLAVE_TRANSMIT_ACK          - Transmit ACK Interrupt
 *  - I2C_SLAVE_ADDRESS_VALID         - Address Valid Interrupt
 *  - I2C_SLAVE_RECEIVE_DATA          - Receive Data Interrupt
 *  - I2C_SLAVE_TRANSMIT_DATA         - Transmit Data Interrupt
 * @return  Enable/disable state of specified interrupt
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveIntGet(const volatile I2C_Type *BaseAddr, uint32 Interrupts)
{
    uint32 Tmp = BaseAddr->SIE;
    boolean HasInterrupts = FALSE;
    if ((Tmp & Interrupts) != (uint32) 0U)
    {
        HasInterrupts = TRUE;
    }
    return HasInterrupts;
}

#if (I2C_DMA_USED == STD_ON)
/*!
 * @brief Enable/disable Receive Data DMA requests
 *
 * This function enables or disables generation of Rx DMA requests when Data
 * can be read from the Receive FIFO, as configured by the Receive FIFO watermark.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable DMA requests
 *
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterRxDmaSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_09();
    uint32 RegValue = BaseAddr->MCTRL;
    RegValue &= (uint32)(~I2C_MCTRL_RXDMAEN_MASK);
    RegValue |= (uint32)Enable << I2C_MCTRL_RXDMAEN_SHIFT;
    BaseAddr->MCTRL = RegValue;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_09();
}

/*!
 * @brief Enable/disable transmit Data DMA requests
 *
 * This function enables or disables generation of Tx DMA requests when Data
 * can be written to the transmit FIFO, as configured by the transmit FIFO watermark.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable DMA requests
 *
 * @return void
 */
/* MR12 RULE 2.1 VIOLATION: A project shall not contain unreachable code. In this specific case,
 * needs it for dma transfer but dma feature is not enabled by default, thus, couldn't adhere to M3CM Rule-2.1
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterTxDmaSet(volatile I2C_Type *BaseAddr, boolean Enable)  /* PRQA S 3219 */
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_10();
    uint32 RegValue = BaseAddr->MCTRL;
    RegValue &= (uint32)(~I2C_MCTRL_TXDMAEN_MASK);
    RegValue |= (uint32)Enable << I2C_MCTRL_TXDMAEN_SHIFT;
    BaseAddr->MCTRL = RegValue;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_10();
}
#endif /* I2C_DMA_USED == STD_ON */

/*!
 * @brief Enable or disable specified I2C Slave Interrupts
 *
 * @details  This function can Enable or disable one or more Slave interrupt sources
 * specified by the Interrupts Parameter.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Interrupts  Interrupts to be enabled or disabled;
 *  must be a bitwise or between one or more of the following constants:
 *  - I2C_SLAVE_SMBUS_ALERT_RESPONSE  - SMBus Alert Response Interrupt
 *  - I2C_SLAVE_GENERAL_CALL          - General Call Interrupt
 *  - I2C_SLAVE_ADDRESS_MATCH_1       - Address Match 1 Interrupt
 *  - I2C_SLAVE_ADDRESS_MATCH_0       - Address Match 0 Interrupt
 *  - I2C_SLAVE_FIFO_ERROR            - FIFO Error Interrupt
 *  - I2C_SLAVE_BIT_ERROR             - Bit Error Interrupt
 *  - I2C_SLAVE_STOP_DETECT           - STOP Detect Interrupt
 *  - I2C_SLAVE_REPEATED_START        - Repeated Start Interrupt
 *  - I2C_SLAVE_TRANSMIT_ACK          - Transmit ACK Interrupt
 *  - I2C_SLAVE_ADDRESS_VALID         - Address Valid Interrupt
 *  - I2C_SLAVE_RECEIVE_DATA          - Receive Data Interrupt
 *  - I2C_SLAVE_TRANSMIT_DATA         - Transmit Data Interrupt
 * @param[in] Enable  specifies whether to Enable or disable specified Interrupts
 * @return void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveIntConifg(volatile I2C_Type *BaseAddr, uint32 Interrupts, boolean Enable)
{
    uint32 Tmp = BaseAddr->SIE;
    if (TRUE == Enable)
    {
        Tmp |= Interrupts;
    }
    else
    {
        Tmp &= ~Interrupts;
    }
    BaseAddr->SIE = Tmp;
}

/*!
 * @brief Enable or disable the I2C Slave
 *
 * @details  This function enables or disables the I2C module in Slave mode.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @param[in] Enable  specifies whether to Enable or disable the I2C Slave
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_SlaveEnableSet(volatile I2C_Type *BaseAddr, boolean Enable)
{
    SchM_Enter_CddI2c_CDDI2C_EXCLUSIVE_AREA_11();
    uint32 RegValue = BaseAddr->SCTRL;
    RegValue &= (uint32)(~I2C_SCTRL_SEN_MASK);
    RegValue |= (uint32)Enable << I2C_SCTRL_SEN_SHIFT; /*PRQA S 2985*/
    BaseAddr->SCTRL = RegValue;
    SchM_Exit_CddI2c_CDDI2C_EXCLUSIVE_AREA_11();
}

/*!
 * @brief Check if transmit Data is requested
 *
 * This function checks if the I2C Slave requests Data to transmit. The
 * event is cleared by providing transmit Data - see function
 * I2C_Transmit_SlaveData(). The event can also be automatically cleared
 * if the I2C module detects a NACK or a repeated START or STOP condition
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of a transmit Data request
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveTxDataEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_TXIF_MASK) >> I2C_SSTS_TXIF_SHIFT;
    return (boolean) RegValue;
}

/*!
 * @brief Check the availability of Receive Data
 *
 * This function checks for the availability of Data received by the I2C Slave.
 * The event is cleared by reading the received Data - see function
 * I2C_Lld_SlaveDataGet(). The event is not cleared by calling
 * I2C_Lld_SlaveDataGet() if the Data register is configured to allow Address
 * reads and an Address valid event is active.
 *
 * @param[in] BaseAddr  base Address of the I2C module
 * @return  indication of Receive Data availability
 */
CDDI2C_FUNC LOCAL_INLINE boolean I2C_Lld_SlaveRxDataEventGet(const volatile I2C_Type *BaseAddr)
{
    uint32 RegValue = BaseAddr->SSTS;
    RegValue = (RegValue & I2C_SSTS_RXIF_MASK) >> I2C_SSTS_RXIF_SHIFT; /*PRQA S 2985*/
    return (boolean) RegValue;
}

/**
 * @brief   This function initializes the I2C module to a known
 *         state (use software reset bit to reset the module).
 * @param[in] Instance The I2C Instance number.
 * @return  void
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_Init(uint8 Instance)
{
    /*
     * The MCR[RST] will reset all Master logic and registers to their default state,
     * except for the MCR itself. The SCR[RST] will reset all Slave logic and registers
     * to their default state, except for the SCR itself. So we must reset the control
     * registers manually;
     */
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    BaseAddr->MCTRL = 0x0U;
#if (I2C_SLAVE_SUPPORT_ALL_INSTANCE == FALSE)
    if (TRUE == I2c_SupportSlave[Instance])
    {
        BaseAddr->SCTRL = 0x0U;
    }
#endif
}

/**
 * @brief   This function handles an Address valid event for Slave.
 *
 * @param[in] Instance The I2C Instance number.
 * @param[in] BaseAddr The I2C peripheral base Address.
 * @param[in] Slave The pointer to the I2C Slave state structure.
 * @return  void
*/
/* MR12 RULE 8.13 VIOLATION: In this specific case, to avoid introducing more problems, thus, couldn't adhere to M3CM Rule-8.13
 */
CDDI2C_FUNC static void I2C_Lld_SlaveAddrVldEventHandle(uint32 Instance, volatile I2C_Type *BaseAddr, I2C_SlaveStateType *Slave) /*PRQA S 3673*/
{
    uint16 ReceivedAddr;
    ReceivedAddr = I2C_Lld_SlaveReceivedAddrGet(BaseAddr);
    if ((ReceivedAddr & 1U) != (uint16) 0U)
    {
        /* Request from Master to transmit Data */
        if (Slave->SlaveCallback != NULL_PTR)
        {
            Slave->SlaveCallback(I2C_SLAVE_EVENT_TX_REQ, Slave->CallbackParam);
        }
#ifdef I2C_SUPPORT_TXCFG
        if (Slave->TransferType == I2C_USING_INTERRUPTS)
        {
            /* Enable interrupt for transmitting Data */
            I2C_Lld_SlaveIntConifg(I2c_Base[Instance], (uint32)I2C_SLAVE_TRANSMIT_DATA_INT, TRUE);
        }
#else
        (void)Instance;
#endif
        Slave->TxUnderrunWarning = FALSE;
#if (I2C_DMA_USED == STD_ON)
        if (Slave->TransferType == I2C_USING_DMA)
        {
            /*I2C choose Dma trance Data*/
            SlaveTxDmaConfig = *DmaChannelTransferConfigArray[Slave->DmaTxChannel];
            SlaveTxDmaConfig.SrcTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
            SlaveTxDmaConfig.DestTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
            SlaveTxDmaConfig.SrcOffset = (sint16) 1 << (uint16)DMA_TRANSFER_SIZE_1_BYTE;
            SlaveTxDmaConfig.DestOffset = 0;
            SlaveTxDmaConfig.TransferLoopByteCount = (uint32) 1 << (uint32)DMA_TRANSFER_SIZE_1_BYTE;
            SlaveTxDmaConfig.TriggerCount = (uint32)(Slave->TxSize / ((uint32)1U << (uint32)DMA_TRANSFER_SIZE_1_BYTE));
            /*Check if the byte count is match the DMA transfer size*/
            if (SlaveTxDmaConfig.TriggerCount > 0U)
            {
                (void)CddDma_SetLogicChannelTransfer(Slave->DmaTxChannel, (uint32)Slave->TxBuff, \
                                                     (uint32) & (BaseAddr->SDATA), &SlaveTxDmaConfig);
                CddDma_StartChannel(Slave->DmaTxChannel);
                /* Initiate communication */
                I2C_Lld_SlaveTxDmaSet(BaseAddr, TRUE);
            }
        }
#endif /* I2C_DMA_USED == STD_ON */
    }
    else
    {
        /* Request from Master to Receive Data */
        if (Slave->SlaveCallback != NULL_PTR)
        {
            Slave->SlaveCallback(I2C_SLAVE_EVENT_RX_REQ, Slave->CallbackParam);
        }
#if (I2C_DMA_USED == STD_ON)
        if (Slave->TransferType == I2C_USING_DMA)
        {
            /*I2C choose Dma trance Data*/
            SlaveRxDmaConfig = *DmaChannelTransferConfigArray[Slave->DmaRxChannel];
            SlaveRxDmaConfig.SrcTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
            SlaveRxDmaConfig.DestTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
            SlaveRxDmaConfig.SrcOffset = 0;
            SlaveRxDmaConfig.DestOffset = (sint16) 1 << (uint16)DMA_TRANSFER_SIZE_1_BYTE;
            SlaveRxDmaConfig.TransferLoopByteCount = (uint32) 1 << (uint32)DMA_TRANSFER_SIZE_1_BYTE;
            SlaveRxDmaConfig.TriggerCount = (uint32)(Slave->RxSize / ((uint32)1U << (uint32)DMA_TRANSFER_SIZE_1_BYTE));
            /*Check if the byte count is match the DMA transfer size*/
            if (SlaveRxDmaConfig.TriggerCount > 0U)
            {
                (void)CddDma_SetLogicChannelTransfer(Slave->DmaRxChannel, (uint32) & (BaseAddr->SDATA), \
                                                     (uint32)Slave->RxBuff, &SlaveRxDmaConfig);
                CddDma_StartChannel(Slave->DmaRxChannel);
                /* Initiate communication */
                I2C_Lld_SlaveRxDmaSet(BaseAddr, TRUE);
            }
        }
#endif /* I2C_DMA_USED == STD_ON */
    }
    Slave->Status = I2C_CHN_BUSY_STATUS;
}

/**
 * @brief   This function handles a transmit Data event for Slave.
 *
 * @param[in] BaseAddr The I2C peripheral base Address.
 * @param[in] Slave The pointer to the I2C Slave state structure.
 * @return  void
 */
static void I2C_Lld_SlaveTxDataEventHandle(volatile I2C_Type *BaseAddr, I2C_SlaveStateType *Slave)
{
    if (TRUE == Slave->TxUnderrunWarning)
    {
        /* Another Tx event after underflow warning means the dummy char was sent */
        Slave->Status = I2C_TX_UNDERRUN_STATUS;
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
        if (Slave->SlaveCallback != NULL_PTR)
        {
            Slave->SlaveCallback(I2C_SLAVE_EVENT_UNDERRUN, Slave->CallbackParam);
        }
#endif
    }
    if ((0U == Slave->TxSize) && (Slave->SlaveCallback != NULL_PTR))
    {
        /* Out of Data, call callback to allow user to provide a new buffer */
        Slave->SlaveCallback(I2C_SLAVE_EVENT_TX_EMPTY, Slave->CallbackParam);
    }
    if (0U == Slave->TxSize)
    {
        /*
         * Still no Data, record tx underflow event and send dummy char.
         * Special case after the last tx byte: the device will ask for more Data
         * but the dummy char will not be sent if NACK and then STOP condition are
         * received from Master. So only record a "warning" for now.
         */
        Slave->TxUnderrunWarning = TRUE;
        I2C_Lld_SlaveTransmitData(BaseAddr, (uint8)I2C_DUMMY_DATA);
    }
    else
    {
        I2C_Lld_SlaveTransmitData(BaseAddr, Slave->TxBuff[0U]);
        ++Slave->TxBuff;
        --Slave->TxSize;
    }
}

/**
 * @brief   This function handles a Receive Data event for Slave.
 *
 * @param[in] BaseAddr The I2C peripheral base Address.
 * @param[in] Slave The pointer to the I2C Slave state structure.
 * @return  void
 */
static void I2C_Lld_SlaveRxDataEventHandle(const volatile I2C_Type *BaseAddr, I2C_SlaveStateType *Slave)
{
    if ((0U == Slave->RxSize) && (Slave->SlaveCallback != NULL_PTR))
    {
        /* No more room for Data, call callback to allow user to provide a new buffer */
        Slave->SlaveCallback(I2C_SLAVE_EVENT_RX_FULL, Slave->CallbackParam);
    }
    if (0U == Slave->RxSize)
    {
        /* Still no room for Data, record rx overrun event and dummy read Data */
        Slave->Status = I2C_RX_OVERRUN_STATUS;
        (void) I2C_Lld_SlaveDataGet(BaseAddr);
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
        if (Slave->SlaveCallback != NULL_PTR)
        {
            Slave->SlaveCallback(I2C_SLAVE_EVENT_OVERRUN, Slave->CallbackParam);
        }
#endif
    }
    else
    {
        Slave->RxBuff[0U] = I2C_Lld_SlaveDataGet(BaseAddr);
        ++Slave->RxBuff;
        --Slave->RxSize;
    }
}

/**
 * @brief   This function handles an I2C Master callback event.
 *
 * @param[in] Event The I2C Master event type.
 * @param[in] UserData The Data used for callback function, here is the I2C Instance number.
 * @return  void
 */
CDDI2C_FUNC static void I2c_Lld_MasterCallback(I2C_MasterEventType Event,
        uint8 UserData)
{
    uint8 Instance = UserData;
#ifdef I2C_ERROR_CALLBACK
    if ((I2C_MASTER_EVENT_ERROR_FIFO == Event) || (I2C_MASTER_EVENT_ARBIT_LOST == Event) || (I2C_MASTER_EVENT_NACK == Event))
    {
        I2C_ERROR_CALLBACK((uint8)Event, (uint8)Instance);
    }
    else /* No error Event has occurred */
    {
#ifdef I2C_MODULE_CALLBACK
        I2C_MODULE_CALLBACK((uint8)Event, (uint8)Instance);
#endif /* I2C_MODULE_CALLBACK */
    }
#else /* I2C_ERROR_CALLBACK */
#ifdef I2C_MODULE_CALLBACK
    I2C_MODULE_CALLBACK((uint8)Event, (uint8)Instance);
#endif /* I2C_MODULE_CALLBACK */
#endif
    /* Cast to void to avoid compiler warnings */
    (void) Event;
    (void) Instance;
}

/**
 * @brief   This function handles an I2C Slave callback event.
 *
 * @param[in] Event The I2C Slave event type.
 * @param[in] UserData The Data used for callback function, here is the I2C logic Channel number.
 * @return  void
 */
CDDI2C_FUNC static void I2c_Lld_SlaveCallback(I2C_SlaveEventType Event,
        uint8 UserData)
{
    uint8  Channel = UserData;
    switch (Event)
    {
        case I2C_SLAVE_EVENT_TX_REQ:
        {
            CddI2c_ChannelStatus[Channel] = I2C_CHN_TX;
            break;
        }
        case I2C_SLAVE_EVENT_RX_REQ:
        {
            CddI2c_ChannelStatus[Channel] = I2C_CHN_RX;
            break;
        }
        default:
        {
            /* no action  */
            break;
        }
    }
#ifdef I2C_ERROR_CALLBACK
    if ((I2C_SLAVE_EVENT_UNDERRUN == Event) || (I2C_SLAVE_EVENT_OVERRUN == Event))
    {
        I2C_ERROR_CALLBACK((uint8)Event, (uint8)Channel);
    }
    else /* No error Event has occurred */
    {
#ifdef I2C_MODULE_CALLBACK
        I2C_MODULE_CALLBACK((uint8)Event, (uint8)Channel);
#endif /* I2C_MODULE_CALLBACK */
    }
#else /* I2C_ERROR_CALLBACK */
#ifdef I2C_MODULE_CALLBACK
    I2C_MODULE_CALLBACK((uint8)Event, (uint8)Channel);
#endif /* I2C_MODULE_CALLBACK */
#endif
    /* Cast to void to avoid compiler warnings */
    (void)Channel;
}


/**
 * @brief configures digtal filter for SDA and SCL, bus idle and pin low Timeout
 * @param[in] Instance The I2C Instance number.
 * @param[in] ConfigPtr Pointer to the I2C_MasterConfigType structure
 * @return  void
 *
 */

CDDI2C_FUNC static void I2C_Lld_MasterFeatureConfig(uint8 Instance,
        const I2C_MasterConfigType   *ConfigPtr)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    /* Set digtal filters for SDA and SCL */
    I2C_Lld_MasterDigitFilterSDASet(BaseAddr, ConfigPtr->DigitalFilterSDA);
    I2C_Lld_MasterDigitFilterSCLSet(BaseAddr, ConfigPtr->DigitalFilterSCL);
    /* Set bus idle Timeout */
    I2C_Lld_MasterBusIdleTimeoutSet(BaseAddr, ConfigPtr->BusIdleTimeout);
    /* Configure pin low Timeout for both SDA and SCL */
    I2C_Lld_MasterPinLowTimeoutCfg(BaseAddr, TRUE);
    /* Configure Pin Low Timeout  */
    I2C_Lld_MasterPinLowTimeoutSet(BaseAddr, ConfigPtr->PinLowTimeout);
}

/**
 * @brief configures baud rate register
 * @param[in] BaseAddr The I2C base Address
 * @param[in] BaudRate Pointer to the I2C_BaudRateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_BaudRateConfig(volatile I2C_Type *BaseAddr,
        const I2C_BaudRateType *BaudRate)
{
    /* Set Prescaler */
    I2C_Lld_MasterPrescalerSet(BaseAddr, BaudRate->Prescaler);
    /* Set Data valid delay */
    I2C_Lld_MasterDataValidDelaySet(BaseAddr, (uint8)BaudRate->DataValid);
    /* Set hold delay */
    I2C_Lld_MasterSetupHoldDelaySet(BaseAddr, (uint8)BaudRate->SetHold);
    /* Set clock HIGH period */
    I2C_Lld_MasterClkHighPeriodSet(BaseAddr, (uint8)BaudRate->ClkHi);
    /* Set clock low period */
    I2C_Lld_MasterClkLowPeriodSet(BaseAddr, (uint8)BaudRate->ClkLo);
}

/**
 * @brief configures high speed baud rate register
 * @param[in] BaseAddr The I2C base Address
 * @param[in] BaudRate Pointer to the I2C_BaudRateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_HSBaudRateConfig(volatile I2C_Type *BaseAddr,
        const I2C_BaudRateType *BaudRate)
{
    /* Set Data valid delay */
    I2C_Lld_MasterDataVldDelayHSSet(BaseAddr, (uint8)BaudRate->SetHoldHs);
    /* Set hold delay */
    I2C_Lld_MasterSetupHoldDlyHSSet(BaseAddr, (uint8)BaudRate->DataValidHs);
    /* Set clock HIGH period */
    I2C_Lld_MasterClkHighPeriodHSSet(BaseAddr, (uint8)BaudRate->ClkHiHs);
    /* Set clock low period */
    I2C_Lld_MasterClkLowPeriodHSSet(BaseAddr, (uint8)BaudRate->ClkLoHs);
}

/**
 * @brief Sets the operating mode of the I2C Master
 * @param[in] Instance The I2C Instance number.
 * @param[in] OperatingMode The operating mode of the I2C Master
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterSetOperatingMode(uint8 Instance,
        I2C_ModeType OperatingMode)
{
    volatile I2C_Type *BaseAddr;
    I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
    BaseAddr = I2c_Base[Instance];
#if(I2C_HAS_ULTRA_FAST_MODE)
    if (OperatingMode == I2C_ULTRAFAST_MODE)
    {
        I2C_Lld_MasterPinConfig(BaseAddr, I2C_CFG_2PIN_OUTPUT_ONLY);
        I2C_Lld_MasterNACKConfig(BaseAddr, I2C_NACK_IGNORE);
    }
    else
#endif
    {
        I2C_Lld_MasterPinConfig(BaseAddr, I2C_CFG_2PIN_OPEN_DRAIN);
        I2C_Lld_MasterNACKConfig(BaseAddr, I2C_NACK_RECEIVE);
    }
    Master->OperatingMode = OperatingMode;
}

/**
 * @brief Set the baud rate for any subsequent I2C communication
 * @param[in] Instance The I2C Instance number.
 * @param[in] OperatingMode The operating mode of the I2C Master
 * @param[in] BaudRate Pointer to the I2C_BaudRateType structure
 * @return I2C_StatusType
 *
 */
CDDI2C_FUNC static I2C_StatusType I2C_Lld_MasterSetBaudRateInit(uint8 Instance,
        const I2C_ModeType OperatingMode,
        const I2C_BaudRateType *BaudRate)
{
    volatile I2C_Type *BaseAddr;
    const I2C_MasterStateType *Master;
    I2C_StatusType RetStatus = I2C_CHN_BUSY_STATUS;
    Master = I2c_MasterHwStatePtr[Instance];
    BaseAddr = I2c_Base[Instance];
    /* Check if driver is busy */
    if (TRUE == Master->I2cIdle)
    {
        /* Disable Master */
        I2C_Lld_MasterEnable(BaseAddr, FALSE);
        /* Apply settings */
        I2C_Lld_BaudRateConfig(BaseAddr, BaudRate);
        /* Apply High-speed settings */
        I2C_Lld_HSBaudRateConfig(BaseAddr, BaudRate);
        /* Perform other settings related to the chosen operating mode */
        I2C_Lld_MasterSetOperatingMode(Instance, OperatingMode);
        /* Re-Enable Master */
        I2C_Lld_MasterEnable(BaseAddr, TRUE);
    }
    else
    {
        /* Do nothing */
    }
    return RetStatus;
}

/**
 * @brief Enable or disable specified I2C Master Interrupts
 * @param[in] Instance The I2C Instance number.
 * @param[in] Interrupts The Interrupts to be enabled or disabled
 * @param[in] Enable TRUE to Enable the Interrupts, FALSE to disable them
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterIntConfig(uint8 Instance, uint32 Interrupts, boolean Enable)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    uint32 Tmp = BaseAddr->MIE;
    if (TRUE == Enable)
    {
        Tmp |= Interrupts;
    }
    else
    {
        Tmp &= ~Interrupts;
    }
    BaseAddr->MIE = Tmp;
}

/**
 * @brief Resets the Master software queue
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterResetQueue(I2C_MasterStateType *Master)
{
    Master->CmdQueue.ReadIdx = 0U;
    Master->CmdQueue.WriteIdx = 0U;
}

/**
 * @brief Checks if there are any commands in the Master software queue
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  TRUE if the queue is empty, FALSE otherwise
 *
 */
LOCAL_INLINE boolean I2C_Lld_MasterCmdQueueEmpty(const I2C_MasterStateType *Master)
{
    return ((Master->CmdQueue.WriteIdx == Master->CmdQueue.ReadIdx) ? TRUE : FALSE);
}

/**
 * @brief Transfers commands from the Master software queue to the hardware FIFO
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC LOCAL_INLINE void I2C_Lld_MasterSendQueuedCmd(uint8 Instance, I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    uint16 TxFifoCount = I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
    uint16 TxFifoSize = I2C_Lld_MasterTxFIFOSizeGet(BaseAddr);
    while ((FALSE == I2C_Lld_MasterCmdQueueEmpty(Master)) && (TxFifoCount < TxFifoSize))
    {
        I2C_Lld_MasterTransmitCmd(BaseAddr,
                                  Master->CmdQueue.Cmd[Master->CmdQueue.ReadIdx],
                                  Master->CmdQueue.Data[Master->CmdQueue.ReadIdx]);
        ++(Master->CmdQueue.ReadIdx);
        TxFifoCount = I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
    }
    if (TRUE == I2C_Lld_MasterCmdQueueEmpty(Master))
    {
        /* Reset queue */
        I2C_Lld_MasterResetQueue(Master);
    }
}

/**
 * @brief Configures bandrate and features for I2C Instance
 * @param[in] Instance The I2C Instance number.
 * @param[in] ConfigPtr Pointer to the I2C_MasterConfigType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterConfig(uint8 Instance,
        const I2C_MasterConfigType *ConfigPtr)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    /* Disable Master */
    I2C_Lld_MasterEnable(BaseAddr, FALSE);
    /*Set digtal filters of SDA and SCL timer out feature for Instance*/
    I2C_Lld_MasterFeatureConfig(Instance, ConfigPtr);
    /*Configure baud rate for I2C*/
    (void)I2C_Lld_MasterSetBaudRateInit(Instance, ConfigPtr->OperatingMode, ConfigPtr->BaudrateParam);
    /* Enable Master */
    I2C_Lld_MasterEnable(BaseAddr, TRUE);
}

/**
 * @brief Queues a command in the hardware FIFO or in the Master software queue
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @param[in] Cmd The command to be queued
 * @param[in] Data The Data associated with the command
 * @return  void
 *
 */
CDDI2C_FUNC static  void I2C_Lld_MasterQueueCmd(uint8 Instance,
        I2C_MasterStateType *Master,
        I2C_MasterCommandType Cmd,
        uint8 Data)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    uint16 TxFifoCount = I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
    uint16 TxFifoSize = I2C_Lld_MasterTxFIFOSizeGet(BaseAddr);
    /* Check if there is room in the hardware FIFO */
    if (TxFifoCount < TxFifoSize)
    {
        I2C_Lld_MasterTransmitCmd(BaseAddr, Cmd, Data);
    }
    else
    {
        /* Hardware FIFO full, use software FIFO */
        Master->CmdQueue.Cmd[Master->CmdQueue.WriteIdx] = Cmd;
        Master->CmdQueue.Data[Master->CmdQueue.WriteIdx] = Data;
        ++(Master->CmdQueue.WriteIdx);
    }
}

/**
 * @brief Send start event and Slave Address
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @param[in] Receive TRUE if the transfer is a read, FALSE if it is a write
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterSendAddress(uint8 Instance,
        I2C_MasterStateType *Master,
        boolean Receive)
{
    uint8 AddrByte;
    I2C_MasterCommandType StartCommand;
#if(I2C_HAS_HIGH_SPEED_MODE)
    if ((I2C_HIGHSPEED_MODE == Master->OperatingMode) && (FALSE == Master->HSInProgress))
    {
        /* Initiating High-speed mode - send Master code first */
        I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_START_NACK, Master->MasterCode);
        Master->HSInProgress = TRUE;
    }
    if (TRUE == Master->HSInProgress)
    {
        /* Use high-speed settings after start event in High Speed mode */
        StartCommand = I2C_MASTER_CMD_START_HS;
    }
    else
#endif
    {
        /* Normal START command */
        StartCommand = I2C_MASTER_CMD_START;
    }
    if (TRUE == Master->Is10bitAddr)
    {
        /* 10-bit addressing */
        /* First Address byte: 1111 0XXD, where XX are bits 10 and 9 of Address, and D = 0(transmit) */
        AddrByte = (uint8)(I2C_10BITS_ADDR_INDICATES + ((Master->SlaveAddress >> I2C_10BITS_HIGH_ADDR_SHIFT) & \
                           I2C_10BITS_HIGH_ADDR_MASK) + (uint8) 0U); /*PRQA S 2985*/
        I2C_Lld_MasterQueueCmd(Instance, Master, StartCommand, AddrByte);
        /* Second Address byte: Remaining 8 bits of Address */
        AddrByte = (uint8)(Master->SlaveAddress & I2C_10BITS_LOW_ADDR_MASK);
        I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_TRANSMIT, AddrByte);
        if (TRUE == Receive)
        {
            /* Receiving from 10-bit Slave - must send repeated start and resend first Address byte */
            /* First Address byte: 1111 0XXD, where XX are bits 10 and 9 of Address, and D = 1 (Receive) */
            AddrByte = (uint8)(I2C_10BITS_ADDR_INDICATES + ((Master->SlaveAddress >> I2C_10BITS_HIGH_ADDR_SHIFT) & \
                               I2C_10BITS_HIGH_ADDR_MASK) + (uint8) 1U);
            I2C_Lld_MasterQueueCmd(Instance, Master, StartCommand, AddrByte);
        }
    }
    else
    {
        /* 7-bit addressing */
        /* Address byte: Slave 7-bit Address + D = 0(transmit) or 1 (Receive) */
        AddrByte = (uint8)(((uint32)(Master->SlaveAddress) << 1U) + (uint8) Receive);
        I2C_Lld_MasterQueueCmd(Instance, Master, StartCommand, AddrByte);
    }
}

/**
 * @brief Queues transmit Data in the I2C tx fifo until it is full
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */

CDDI2C_FUNC static void I2C_Lld_MasterQueueData(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    uint16 TxFifoCount = I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
    uint16 TxFifoSize = I2C_Lld_MasterTxFIFOSizeGet(BaseAddr);
    /* Don't queue any Data if there are commands in the software queue */
    if (TRUE == I2C_Lld_MasterCmdQueueEmpty(Master))
    {
        while ((Master->TxSize > 0U) && (TxFifoCount < TxFifoSize))
        {
            I2C_Lld_MasterTransmitCmd(BaseAddr, I2C_MASTER_CMD_TRANSMIT, Master->TxBuff[0U]);
            ++Master->TxBuff;
            --Master->TxSize;
            TxFifoCount = I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
        }
    }
}

/**
 * @brief Ends current transmission or reception
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @param[in] SendStop TRUE if a stop condition should be sent, FALSE otherwise
 * @param[in] ResetFifo TRUE if the FIFO should be reset, FALSE otherwise
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterEndTransfer(uint8 Instance,
        I2C_MasterStateType *Master,
        boolean SendStop,
        boolean ResetFifo)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    /* Disable all events */
    I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT |
                            I2C_MASTER_ARBITRATION_LOST_INT |
                            I2C_MASTER_NACK_DETECT_INT |
                            I2C_MASTER_TRANSMIT_DATA_INT |
                            I2C_MASTER_PIN_LOW_TIMEOUT_INT |
                            I2C_MASTER_RECEIVE_DATA_INT,
                            FALSE);
#if (I2C_DMA_USED == STD_ON)
    if (Master->TransferType == I2C_USING_DMA)
    {
        /* Stop DMA channel */
        if (Master->Direction == I2C_SEND)
        {
            CddDma_StopChannel(Master->DmaTxChannel);
            I2C_Lld_MasterTxDmaSet(BaseAddr, FALSE);
        }
        else
        {
            CddDma_StopChannel(Master->DmaRxChannel);
            I2C_Lld_MasterRxDmaSet(BaseAddr, FALSE);
        }
    }
#endif
    if (TRUE == ResetFifo)
    {
        /* Reset FIFOs if requested */
        I2C_Lld_MasterTxFIFOCmdReset(BaseAddr);
        I2C_Lld_MasterRxFIFOCmdReset(BaseAddr);
    }
    /* Queue STOP command if requested */
    if (TRUE == SendStop)
    {
        I2C_Lld_MasterTransmitCmd(BaseAddr, I2C_MASTER_CMD_STOP, 0U);
#if(I2C_HAS_HIGH_SPEED_MODE)
        Master->HSInProgress = FALSE; /* High-speed transfers end at STOP condition */
#endif
    }
    Master->TxBuff = NULL_PTR;
    Master->TxSize = 0;
    Master->RxBuff = NULL_PTR;
    Master->RxSize = 0;
    Master->I2cIdle = TRUE;
}

/**
 * @brief Slave ends current transmission or reception
 *
 * @param[in] BaseAddr The I2C peripheral base Address.
 * @param[in] Slave Pointer to the I2C_SlaveStateType structure
 * @return  void
*/
static void I2C_Lld_SlaveEndTransfer(volatile I2C_Type *BaseAddr,
                                     I2C_SlaveStateType *Slave)
{
    /* Deactivate events */
    I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                           I2C_SLAVE_FIFO_ERROR_INT |
                           I2C_SLAVE_STOP_DETECT_INT |
                           I2C_SLAVE_REPEATED_START_INT |
                           I2C_SLAVE_ADDRESS_VALID_INT |
                           I2C_SLAVE_RECEIVE_DATA_INT |
                           I2C_SLAVE_TRANSMIT_DATA_INT,
                           FALSE);
#if (I2C_DMA_USED == STD_ON)
    /* For DMA we must disable the DMA request. */
    if (Slave->TransferType == I2C_USING_DMA)
    {
        if (Slave->RxSize != (uint16)0)
        {
            I2C_Lld_SlaveRxDmaSet(BaseAddr, FALSE);
        }
        else
        {
            I2C_Lld_SlaveTxDmaSet(BaseAddr, FALSE);
        }
    }
#endif /* I2C_DMA_USED */
    /* Disable I2C Slave */
    I2C_Lld_SlaveEnableSet(BaseAddr, FALSE);
    Slave->IsTransferInProgress = FALSE;
    Slave->RxBuff = NULL_PTR;
    Slave->RxSize = 0U;
    Slave->TxBuff = NULL_PTR;
    Slave->TxSize = 0U;
    Slave->RepeatedStarts = 0U;
}

/**
 * @brief Handle a transmit request for Master
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterTxDataRequestHdl(uint8 Instance, I2C_MasterStateType *Master)
{
    /* More Data needed for transmission */
    if (FALSE == I2C_Lld_MasterCmdQueueEmpty(Master))
    {
        /* If there are queued commands, send them */
        I2C_Lld_MasterSendQueuedCmd(Instance, Master);
    }
    else if (Master->TxBuff != NULL_PTR)
    {
        /* A transmission is in progress */
        if (0U == Master->TxSize)
        {
            /* There is no more Data in buffer, the transmission is over */
            I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
            /* Signal transfer end for blocking transfers */
            Master->Status = I2C_SUCCESS_STATUS;
            if (Master->MasterCallback != NULL_PTR)
            {
                Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
            }
        }
        else
        {
            /* Queue Data bytes to fill tx fifo */
            I2C_Lld_MasterQueueData(Instance, Master);
        }
    }
    else
    {
        /* No more commands and no transmission in progress - disable tx event */
        I2C_Lld_MasterIntConfig(Instance, (uint32) I2C_MASTER_TRANSMIT_DATA_INT, FALSE);
    }
}

/**
 * @brief Handle a Receive request for Master
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterRxDataRdyEventHdl(uint8 Instance, I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    /* Received Data ready */
    /* Transfer received Data to user buffer */
    while ((I2C_Lld_MasterRxFIFOCountGet(BaseAddr) > 0U) && (Master->RxSize > 0U))
    {
        Master->RxBuff[0U] = I2C_Lld_MasterRxDataGet(BaseAddr);
        ++Master->RxBuff;
        --Master->RxSize;
    }
    if (0U == Master->RxSize)
    {
        /* Done receiving */
        I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
        Master->Status = I2C_SUCCESS_STATUS;
        if (Master->MasterCallback != NULL_PTR)
        {
            Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
        }
    }
    else if (Master->RxSize <= I2C_Lld_MasterRxFIFOWatermarkGet(BaseAddr))
    {
        /* Reduce rx watermark to Receive the last few bytes */
        I2C_Lld_MasterRxFIFOWatermarkSet(BaseAddr, (uint8)(Master->RxSize - 1U));
    }
    else
    {
        /* Continue reception */
    }
}

#if 0
/**
 * @brief Re-initialize the I2C Master
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  I2C_StatusType
 *
 */

CDDI2C_FUNC static I2C_StatusType I2C_Lld_MasterReinit(uint8 Instance, I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr;
    const I2C_BaudRateType *BaudRate;
    BaseAddr = I2c_Base[Instance];
    I2c_MasterHwStatePtr[Instance] = Master;
    /* Re-initialize driver status structure */
    Master->TxBuff = NULL_PTR;
    Master->TxSize = 0;
    Master->RxBuff = NULL_PTR;
    Master->RxSize = 0;
    Master->I2cIdle = TRUE;
    I2C_Lld_MasterResetQueue(Master);
    /* Initialize module */
    I2C_Lld_Init(Instance);
    /* Set baud rate */
    BaudRate = Master->BaudRatePara;
    (void) I2C_Lld_MasterSetBaudRateInit(Instance, Master->OperatingMode, BaudRate);
    /* Set Slave Address */
    I2C_Lld_MasterSetSlaveAddr(Instance, Master->SlaveAddress, Master->Is10bitAddr);
    /* Enable I2C Master */
    I2C_Lld_MasterEnable(BaseAddr, TRUE);
    return (I2C_SUCCESS_STATUS);
}
#endif

/**
 * @brief Initializes send transfer
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */

CDDI2C_FUNC static void I2C_Lld_MasterInitSendTransfer(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr  = I2c_Base[Instance];
    /* Initiate communication */
    I2C_Lld_MasterSendAddress(Instance, Master, FALSE);
    /* Queue Data bytes to fill tx fifo */
    I2C_Lld_MasterQueueData(Instance, Master);
    /* Set tx FIFO watermark */
    I2C_Lld_MasterTxFIFOWatermarkSet(BaseAddr, 0U);
}

/**
 * @brief Handles Master fifo error
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterFIFOErrEventHdl(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr  = I2c_Base[Instance];
    /* FIFO error */
    I2C_Lld_MasterFIFOErrorEventClr(BaseAddr);
    if (I2C_HIGHSPEED_MODE == Master->OperatingMode)
    {
        /* High-speed transfers end at STOP condition */
        Master->HSInProgress = FALSE;
    }
    Master->Status = I2C_HW_ERROR_STATUS;
    /* End transfer: no stop generation (the module will handle that by itself
       if needed), reset FIFOs */
    I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
    if (Master->MasterCallback != NULL_PTR)
    {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
        Master->MasterCallback(I2C_MASTER_EVENT_ERROR_FIFO, Master->CallbackParam);
#else
        Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
    }
}

/**
 * @brief Handles Master arbitration lost event
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterArbitLostEventHdl(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr  = I2c_Base[Instance];
    /* Arbitration lost */
    I2C_Lld_MasterArbitLostEventClr(BaseAddr);
    /* End transfer: no stop generation (the module will handle that by itself
       if needed), reset FIFOs */
    I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
    Master->Status = I2C_ARBITRATION_LOST_STATUS;
    if (Master->MasterCallback != NULL_PTR)
    {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
        Master->MasterCallback(I2C_MASTER_EVENT_ARBIT_LOST, Master->CallbackParam);
#else
        Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
    }
}

/**
 * @brief Handles Master NACK detection event
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterNACKDetEventHdl(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type *BaseAddr  = I2c_Base[Instance];
#if(I2C_HAS_ULTRA_FAST_MODE)
    /* Ignore NACK in Ultra Fast mode */
    if (Master->OperatingMode != I2C_ULTRAFAST_MODE)
    {
#endif
        /* High-speed transfers end at STOP condition */
        Master->HSInProgress = FALSE;
        Master->Status = I2C_RECEIVED_NACK_STATUS;
        /* End transfer: no stop generation (the module will handle that by itself
           if needed), reset FIFOs */
        I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
        if (Master->MasterCallback != NULL_PTR)
        {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
            Master->MasterCallback(I2C_MASTER_EVENT_NACK, Master->CallbackParam);
#else
            Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
        }
        /* Clear NACK flag */
        I2C_Lld_MasterNACKDetEventClr(BaseAddr);
#if(I2C_HAS_ULTRA_FAST_MODE)
    }
#endif
}

/**
 * @brief Checks error events for Master module
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterCheckErrorEvents(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type const *BaseAddr  = I2c_Base[Instance];
    if (TRUE == I2C_Lld_MasterFIFOErrorEventGet(BaseAddr))
    {
        /* Handle FIFO error event */
        I2C_Lld_MasterFIFOErrEventHdl(Instance, Master);
    }
    if (TRUE == I2C_Lld_MasterArbitLostEventGet(BaseAddr))
    {
        /* Handle arbitration lost event */
        I2C_Lld_MasterArbitLostEventHdl(Instance, Master);
    }
    if (TRUE == I2C_Lld_MasterNACKDetEventGet(BaseAddr))
    {
        /* Handle Received NACK */
        I2C_Lld_MasterNACKDetEventHdl(Instance, Master);
    }
}

/**
 * @brief Sync send transfer handler
 * @param[in] Instance The I2C Instance number.
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterSend(uint8 Instance)
{
    volatile I2C_Type const *BaseAddr = I2c_Base[Instance];
    I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
    boolean MasterCmdQueueEmpty = FALSE;
    /* Check which event caused the interrupt */
    if (TRUE == I2C_Lld_MasterDataReqEventCheck(BaseAddr))
    {
        /* More Data needed for transmission */
        if (FALSE == I2C_Lld_MasterCmdQueueEmpty(Master))
        {
            /* If there are queued commands, send them */
            I2C_Lld_MasterSendQueuedCmd(Instance, Master);
        }
        else
        {
            MasterCmdQueueEmpty = TRUE;
        }
    }
    if (TRUE == MasterCmdQueueEmpty)
    {
        if (Master->TxBuff != NULL_PTR)
        {
            /* A transmission is in progress */
            if (0U == Master->TxSize)
            {
                /* There is no more Data in buffer, the transmission is over */
                I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
                Master->Status = I2C_SUCCESS_STATUS;
                if (Master->MasterCallback != NULL_PTR)
                {
                    Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
                }
            }
            else
            {
                /* Queue Data bytes to fill tx fifo */
                I2C_Lld_MasterQueueData(Instance, Master);
            }
        }
        else
        {
            /* else case */
        }
    }
    /* Check error event */
    I2C_Lld_MasterCheckErrorEvents(Instance, Master);
}

/**
 * @brief Configures interrupt Receive transfer
 * @param[in] Instance The I2C Instance number.
 * @param[in] RxSize The number of bytes to Receive
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterInterruptRxInit(uint8 Instance,
        uint16 RxSize)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
    uint16 RxBytes;
    /* Send Address */
    I2C_Lld_MasterSendAddress(Instance, Master, TRUE);
    if (I2C_MAX_DATA_RECEIVE_BYTE_PER_CMD < RxSize)
    {
        /* Queue Receive command for RxSize bytes */
        I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_RECEIVE, (uint8)(I2C_MAX_DATA_RECEIVE_BYTE_PER_CMD - 1U));
    }
    else
    {
        /* Queue Receive command for RxSize bytes */
        I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_RECEIVE, (uint8)(RxSize - 1U));
    }
    /* Set rx FIFO watermark */
    RxBytes = I2C_Lld_MasterRxFIFOSizeGet(BaseAddr);
    if (RxBytes > RxSize)
    {
        RxBytes = (uint8)RxSize;
    }
    /* Set RX watermark */
    I2C_Lld_MasterRxFIFOWatermarkSet(BaseAddr, (uint8)(RxBytes - 1U));
}

/**
 * @brief Read Data Receive from RX FIFO
 * @param[in] Instance The I2C Instance number.
 * @param[in] Master Pointer to the I2C_MasterStateType structure
 * @return  void
 *
 */

CDDI2C_FUNC static void I2C_Lld_MasterGetReceivedData(uint8 Instance,
        I2C_MasterStateType *Master)
{
    volatile I2C_Type const *BaseAddr = I2c_Base[Instance];
    /* Read Data from RX FIFO */
    while ((I2C_Lld_MasterRxFIFOCountGet(BaseAddr) > 0U) && (Master->RxSize > 0U))
    {
        Master->RxBuff[0U] = I2C_Lld_MasterRxDataGet(BaseAddr);
        ++Master->RxBuff;
        --Master->RxSize;
        ++Master->RxDataByteCount;
    }
}

/**
 * @brief Sync Receive transfer handler
 * @param[in] Instance The I2C Instance number.
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_MasterReceive(uint8 Instance)
{
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
    if (TRUE == I2C_Lld_MasterRxDataRdyEventGet(BaseAddr))
    {
        /* Read Data from RX FIFO */
        I2C_Lld_MasterGetReceivedData(Instance, Master);
        if (0U == Master->RxSize)
        {
            /* Done receiving */
            I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
            Master->Status = I2C_SUCCESS_STATUS;
            if (Master->MasterCallback != NULL_PTR)
            {
                Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
            }
        }
        else if (Master->RxSize <= I2C_Lld_MasterRxFIFOWatermarkGet(BaseAddr))
        {
            I2C_Lld_MasterRxFIFOWatermarkSet(BaseAddr, (uint8)(Master->RxSize - 1U));
        }
        else
        {
            /*Do nothing*/
        }
    }
    /* Check error event */
    I2C_Lld_MasterCheckErrorEvents(Instance, Master);
}

#if (I2C_DMA_USED == STD_ON)
/*!
 * @brief   This function will process TX DMA transfer complete interrupt.
 * @details main purpose of this function is to create a function compatible with DMA callback type
 *
 * @param[in] Parameter The parameters to be used in the callback function, here used for index of the I2c moudle
 *
 * @return void
 */
CDDI2C_FUNC static void I2c_Lld_MasterCompleteDmaTx(void *Parameter)
{
    uint8 Instance = (uint8)((uint32) Parameter);
    I2C_MasterStateType *Master;
    volatile I2C_Type *BaseAddr = I2c_Base[Instance];
    Master = I2c_MasterHwStatePtr[Instance];
    Master->TxSize = 0U;
    /* Set tx FIFO watermark */
    I2C_Lld_MasterTxFIFOWatermarkSet(BaseAddr, 0U);
    /* Disable transmit Data DMA requests */
    I2C_Lld_MasterTxDmaSet(BaseAddr, FALSE);
    /* Enable Tx interrupt */
    I2C_Lld_MasterIntConfig(Instance, (uint32) I2C_MASTER_TRANSMIT_DATA_INT, TRUE);
}

/*!
 * @brief   This function will process RX DMA transfer complete interrupt.
 * @details main purpose of this function is to create a function compatible with DMA callback type
 *
 * @param[in] Parameter The parameters to be used in the callback function, here used for index of the I2c moudle
 *
 * @return void
 */
CDDI2C_FUNC static void I2c_Lld_MasterCompleteDmaRx(void *Parameter)
{
    uint8 Instance = (uint8)((uint32) Parameter);
    I2C_MasterStateType *Master;
    Master = I2c_MasterHwStatePtr[Instance];
    /* Signal transfer end for blocking transfers */
    I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
    Master->Status = I2C_SUCCESS_STATUS;
    if (Master->MasterCallback != NULL_PTR)
    {
        Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
    }
}

/*!
 * @brief   If errors are detected during DMA transfer the Error interrupt will be trigged, if DMA error interrupt is enabled.
 * @details main purpose of this function is to check DMA errors on Tx/Rx channel
 *
 * @param[in] Parameter The parameters to be used in the callback function, here used for index of the I2c moudle
 *
 * @return void
 */
CDDI2C_FUNC static void I2c_Lld_MasterDmaTransferError(void *Parameter)
{
    uint8 Instance = (uint8)((uint32) Parameter);
    I2C_MasterStateType *Master;
    Master = I2c_MasterHwStatePtr[Instance];
    /* Signal transfer end for blocking transfers */
    I2C_Lld_MasterEndTransfer(Instance, Master, Master->SendStop, FALSE);
    Master->Status = I2C_DMA_ERROR_STATUS;
    if (Master->MasterCallback != NULL_PTR)
    {
        Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
    }
}
#endif /* I2C_DMA_USED == STD_ON */

/**
 * @brief Slave end transfer handler
 *
 * @param[in] Slave Pointer to the I2C_SlaveStateType structure
 * @param[in] BaseAddr The I2C peripheral base Address.
 * @return  void
 */
CDDI2C_FUNC static void I2C_Lld_SlaveEndTransferHandler(I2C_SlaveStateType *Slave, volatile I2C_Type *BaseAddr)
{
    if (Slave != NULL_PTR)
    {
        /* Stop DMA channel if Slave is transferring Data in DMA mode */
#if (I2C_DMA_USED == STD_ON)
        if (Slave->TransferType == I2C_USING_DMA)
        {
            CddDma_StopChannel(Slave->DmaRxChannel);
            CddDma_StopChannel(Slave->DmaTxChannel);
        }
#endif
        if (FALSE == Slave->SlaveListening)
        {
            I2C_Lld_SlaveEndTransfer(BaseAddr, Slave);
        }
        if (Slave->SlaveCallback != NULL_PTR)
        {
            Slave->SlaveCallback(I2C_SLAVE_EVENT_STOP, Slave->CallbackParam);
        }
    }
    else
    {
        /* Do nothing */
    }
}

/**
 * @brief Sets the operating mode of the I2C Slave
 * @param[in] Instance The I2C Instance number.
 * @param[in] OperatingMode The operating mode of the I2C Slave
 * @return  void
 *
 */

CDDI2C_FUNC static void I2C_Lld_SlaveSetOperatingMode(uint8 Instance, I2C_ModeType OperatingMode)
{
    volatile I2C_Type *BaseAddr;
    I2C_SlaveStateType *Slave;
    BaseAddr = I2c_Base[Instance];
    Slave = I2c_SlaveHwStatePtr[Instance];
#if(I2C_HAS_ULTRA_FAST_MODE == STD_ON)
    if (OperatingMode == I2C_ULTRAFAST_MODE)
    {
        I2C_Lld_SlaveIgnoreNACKSet(BaseAddr, I2C_SLAVE_NACK_KEEP_TRANSFER);
        I2C_Lld_SlaveTransmitNACKSet(BaseAddr, I2C_SLAVE_TRANSMIT_NACK);
        /* Disable all clock stretching in ultra-fast mode */
        I2C_Lld_SlaveACKStallSet(BaseAddr, FALSE);
        I2C_Lld_SlaveTXDStallSet(BaseAddr, FALSE);
        I2C_Lld_SlaveRXStallSet(BaseAddr, FALSE);
        I2C_Lld_SlaveAddrStallSet(BaseAddr, FALSE);
    }
    else
#endif
    {
        I2C_Lld_SlaveIgnoreNACKSet(BaseAddr, I2C_SLAVE_NACK_END_TRANSFER);
        I2C_Lld_SlaveTransmitNACKSet(BaseAddr, I2C_SLAVE_TRANSMIT_ACK);
        /* Enable clock stretching except ACKSTALL (we don't need to send ACK/NACK manually) */
        I2C_Lld_SlaveACKStallSet(BaseAddr, FALSE);
        I2C_Lld_SlaveTXDStallSet(BaseAddr, TRUE);
        I2C_Lld_SlaveRXStallSet(BaseAddr, TRUE);
        I2C_Lld_SlaveAddrStallSet(BaseAddr, TRUE);
    }
#if(I2C_HAS_HIGH_SPEED_MODE)
    if (OperatingMode == I2C_HIGHSPEED_MODE)
    {
        /* Enable detection of the High-speed Mode Master code */
        I2C_Lld_SlaveHighSpeedModeDetSet(BaseAddr, TRUE);
    }
    else
#endif
    {
        /* Disable detection of the High-speed Mode Master code */
        I2C_Lld_SlaveHighSpeedModeDetSet(BaseAddr, FALSE);
    }
    Slave->OperatingMode = OperatingMode;
}

/**
 * @brief Sets the events for the I2C Slave
 * @param[in] Instance The I2C Instance number.
 * @return  void
 *
 */
CDDI2C_FUNC static void I2C_Lld_SlaveActivateEvents(uint8 Instance)
{
    volatile I2C_Type *const BaseAddr = I2c_Base[Instance];
    I2C_SlaveStateType const *Slave = I2c_SlaveHwStatePtr[Instance];
#if (I2C_DMA_USED == STD_ON)
    if (I2C_USING_DMA == Slave->TransferType)
    {
        /* Activate events */
        I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                               I2C_SLAVE_FIFO_ERROR_INT |
                               I2C_SLAVE_STOP_DETECT_INT |
                               I2C_SLAVE_REPEATED_START_INT |
                               I2C_SLAVE_ADDRESS_VALID_INT,
                               TRUE);
        /* Enable I2c Slave DMA*/
        I2C_Lld_SlaveRxDmaSet(BaseAddr, TRUE);
        I2C_Lld_SlaveTxDmaSet(BaseAddr, TRUE);
    }
#endif
    if (I2C_USING_INTERRUPTS == Slave->TransferType)
    {
        /* Activate events */
#ifdef I2C_SUPPORT_TXCFG
        I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                               I2C_SLAVE_FIFO_ERROR_INT |
                               I2C_SLAVE_STOP_DETECT_INT |
                               I2C_SLAVE_REPEATED_START_INT |
                               I2C_SLAVE_ADDRESS_VALID_INT |
                               I2C_SLAVE_RECEIVE_DATA_INT,
                               TRUE);
#else
        I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                               I2C_SLAVE_FIFO_ERROR_INT |
                               I2C_SLAVE_STOP_DETECT_INT |
                               I2C_SLAVE_REPEATED_START_INT |
                               I2C_SLAVE_ADDRESS_VALID_INT |
                               I2C_SLAVE_RECEIVE_DATA_INT |
                               I2C_SLAVE_TRANSMIT_DATA_INT,
                               TRUE);
#endif
    }
    /* Enable I2C Slave */
    I2C_Lld_SlaveEnableSet(BaseAddr, TRUE);
}


/*==================================================================================================
 *                                   GLOBAL FUNCTIONS
==================================================================================================*/

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterInit
 * Description   : initialize the I2C Master mode driver
 *
 * Implements : I2C_Lld_MasterInit_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterInit(uint8 Instance,
        const I2C_MasterConfigType *UserConfigPtr)
{
    I2C_StatusType RetVal = I2C_SUCCESS_STATUS;
    if (NULL_PTR == UserConfigPtr)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        volatile I2C_Type *BaseAddr = I2c_Base[Instance];
        I2c_MasterHwStatePtr[Instance] = &I2c_MasterStatus[Instance];
        I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
        /* Initialize driver status structure */
        Master->Direction = I2C_SEND;
        Master->RxBuff = NULL_PTR;
        Master->RxSize = 0;
        Master->TxBuff = NULL_PTR;
        Master->Status = I2C_SUCCESS_STATUS;
        Master->I2cIdle = TRUE;
        Master->SlaveAddress = UserConfigPtr->SlaveAddress;
        Master->Is10bitAddr = UserConfigPtr->Is10bitAddr;
        Master->TransferType = UserConfigPtr->TransferType;
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
        Master->TimeoutValue = UserConfigPtr->TimeoutValue;
#endif
        /* Save DMA channel number which used in I2C transfer */
#if(I2C_DMA_USED == STD_ON)
        Master->DmaTxChannel = UserConfigPtr->DmaTxChannel;
        Master->DmaRxChannel = UserConfigPtr->DmaRxChannel;
#endif/* (I2C_DMA_USED == STD_ON)*/
        Master->MasterCallback = I2c_Lld_MasterCallback;
        Master->CallbackParam = UserConfigPtr->CallbackParam;
        /*Store bandrate Parameter*/
        Master->BaudrateParam = UserConfigPtr->BaudrateParam;
        Master->ModuleWorkingClock = UserConfigPtr->ModuleWorkingClock;
        /*Initialize the semaphore*/
        I2C_Lld_MasterResetQueue(Master);
        /* Initialize module */
        I2C_Lld_Init(Instance);
        /* Configure the bandrate and feature for I2C transfer*/
        I2C_Lld_MasterConfig(Instance, UserConfigPtr);
        /*configure the Slave Address*/
        I2C_Lld_MasterSetSlaveAddr(Instance, UserConfigPtr->SlaveAddress, UserConfigPtr->Is10bitAddr);
        /* Enable I2C Master */
        I2C_Lld_MasterEnable(BaseAddr, TRUE);
        RetVal = I2C_SUCCESS_STATUS;
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterDeinit
 * Description   : deinitialize the I2C Master mode driver
 *
 * Implements : I2C_Lld_MasterDeinit_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterDeinit(uint8 Instance)
{
    const I2C_MasterStateType *Master;
    I2C_StatusType RetVal = I2C_SUCCESS_STATUS;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
        if (NULL_PTR == Master)
        {
            RetVal = I2C_PARAM_ERROR_STATUS;
        }
        else
        {
            volatile I2C_Type *BaseAddr = I2c_Base[Instance];
            I2c_MasterHwStatePtr[Instance] = NULL_PTR;
            /* Disable Master */
            I2C_Lld_MasterEnable(BaseAddr, FALSE);
        }
        /*Asserted a software reset*/
        I2C_REST_VIA_IPC->CTRL[Instance] |= (uint32)I2C_IPC_CTRL_SWRESET_MASK;
        /*De-assert the software reset*/
        I2C_REST_VIA_IPC->CTRL[Instance] &= (uint32)(~I2C_IPC_CTRL_SWRESET_MASK);
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterSendData
 * Description   : perform a non-blocking send transaction on the I2C bus
 *
 * Implements : I2C_Lld_MasterSendData_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterSendData(uint8 Instance,
        const uint8 *TxBuff,
        uint16 TxSize,
        boolean SendStop)
{
    I2C_MasterStateType *Master;
    Std_ReturnType StdRevalue = E_OK;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
        /* Check the I2C HW init or not which specfied by Instance
         * Check the Tx buffer and Data length.
         */
        if ((NULL_PTR == Master) || (NULL_PTR == TxBuff) || (0U == TxSize))
        {
            RetValue = I2C_PARAM_ERROR_STATUS;
            StdRevalue = E_NOT_OK;
        }
        else
        {
            /*Do nothing*/
        }
    }
    /*Check the driver or not*/
    if (E_OK == StdRevalue)
    {
        if (TRUE == Master->I2cIdle)
        {
            volatile I2C_Type *BaseAddr = I2c_Base[Instance];
            /* Copy parameters to driver state structure */
            Master->TxBuff = TxBuff;
            Master->TxSize = TxSize;
            Master->SendStop = SendStop;
            Master->I2cIdle = FALSE;
            Master->Status = I2C_CHN_BUSY_STATUS;
            Master->Direction = I2C_SEND;
            RetValue = I2C_CHN_BUSY_STATUS;
#if (I2C_DMA_USED == STD_ON)
            if (I2C_USING_DMA == Master->TransferType)
            {
                /*I2C choose Dma trance Data*/
                I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT |
                                        I2C_MASTER_ARBITRATION_LOST_INT |
                                        I2C_MASTER_NACK_DETECT_INT,
                                        TRUE);
                /*I2C choose Dma trance Data*/
                MasterTxDmaConfig = *DmaChannelTransferConfigArray[Master->DmaTxChannel];
                MasterTxDmaConfig.SrcTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
                MasterTxDmaConfig.DestTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
                MasterTxDmaConfig.SrcOffset = (sint16) 1 << (uint16)DMA_TRANSFER_SIZE_1_BYTE;
                MasterTxDmaConfig.DestOffset = 0;
                MasterTxDmaConfig.TransferLoopByteCount = (uint32) 1 << (uint32)DMA_TRANSFER_SIZE_1_BYTE;
                MasterTxDmaConfig.TriggerCount = (uint32)(Master->TxSize / ((uint32)1U << (uint32)DMA_TRANSFER_SIZE_1_BYTE));
                /* Configure watermarks for transmit DMA for Master */
                uint32 TxBytes = I2C_Lld_MasterTxFIFOSizeGet(BaseAddr);
                if (TxBytes > Master->TxSize)
                {
                    TxBytes = Master->TxSize;
                }
                I2C_Lld_MasterTxFIFOWatermarkSet(BaseAddr, (uint16)(TxBytes - 1U));
                (void)CddDma_SetLogicChannelTransfer(Master->DmaTxChannel, (uint32)Master->TxBuff, \
                                                     (uint32) & (BaseAddr->MDATA), &MasterTxDmaConfig);
                CddDma_InstallCallback(Master->DmaTxChannel, I2c_Lld_MasterCompleteDmaTx, (void *)((uint32)Instance));
                CddDma_InstallErrorCallback(Master->DmaTxChannel, I2c_Lld_MasterDmaTransferError, (void *)((uint32)Instance));
                CddDma_StartChannel(Master->DmaTxChannel);
                /* Initiate communication */
                I2C_Lld_MasterSendAddress(Instance, Master, FALSE);
                I2C_Lld_MasterTxDmaSet(BaseAddr, TRUE);
            }
            else
#endif/*(I2C_DMA_USED == STD_ON)*/
            {
                /* Initiate communication */
                I2C_Lld_MasterSendAddress(Instance, Master, FALSE);
                /* Queue Data bytes to fill tx fifo */
                I2C_Lld_MasterQueueData(Instance, Master);
                /* Set tx FIFO watermark */
                I2C_Lld_MasterTxFIFOWatermarkSet(BaseAddr, 0U);
                /* Enable relevant events */
#if(I2C_HAS_ULTRA_FAST_MODE)
                if (Master->OperatingMode == I2C_ULTRAFAST_MODE)
                {
                    /* Do not Enable NACK event reporting in ultra-fast mode */
                    I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT |
                                            I2C_MASTER_ARBITRATION_LOST_INT |
                                            I2C_MASTER_TRANSMIT_DATA_INT,
                                            TRUE);
                }
                else
#endif
                {
                    I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT |
                                            I2C_MASTER_ARBITRATION_LOST_INT |
                                            I2C_MASTER_NACK_DETECT_INT |
                                            I2C_MASTER_PIN_LOW_TIMEOUT_INT |
                                            I2C_MASTER_TRANSMIT_DATA_INT,
                                            TRUE);
                }
            }
        }
        else
        {
            RetValue = I2C_BUS_BUSY_STATUS;
        }
    }
    else
    {
        /*Do nothing*/
    }
    return RetValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterSendDataBlocking
 * Description   : perform a blocking send transaction on the I2C bus
 *
 * Implements : I2C_Lld_MasterSendDataBlocking_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterSendDataBlocking(uint8 Instance,
        const uint8 *TxBuff,
        uint16 TxSize,
        boolean SendStop)
{
    I2C_MasterStateType *Master;
    Std_ReturnType StdRevalue = E_OK;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
    uint32 TimeOut = 0;
#endif
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
        /*Check the I2C HW init or not which specfied by Instance*/
        if (NULL_PTR == Master)
        {
            RetValue = I2C_PARAM_ERROR_STATUS;
            StdRevalue = E_NOT_OK;
        }
        else
        {
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            TimeOut = Master->TimeoutValue;
#endif
            /*Check the Tx buffer and Data length*/
            if ((NULL_PTR == TxBuff) || (0U == TxSize))
            {
                RetValue = I2C_PARAM_ERROR_STATUS;
                StdRevalue = E_NOT_OK;
            }
            else
            {
                /*Do nothing*/
            }
        }
    }
    /*Check the driver or not*/
    if (E_OK == StdRevalue)
    {
        if (TRUE == Master->I2cIdle)
        {
            Master->TxSize = TxSize;
            Master->TxBuff = TxBuff;
            Master->Direction = I2C_SEND;
            Master->SendStop = SendStop;
            Master->I2cIdle = FALSE;
            Master->Status = I2C_CHN_BUSY_STATUS;
            /* Initiate send transfer */
            I2C_Lld_MasterInitSendTransfer(Instance, Master);
            /* Master send Data,and waiting for transfer compeleted */
            do
            {
                I2C_Lld_MasterSend(Instance);
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
                --TimeOut;
#endif
            }
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            while ((I2C_Lld_MasterGetTransferStatus(Instance, NULL_PTR) == I2C_CHN_BUSY_STATUS) && (TimeOut > 0U));
#else
            while (I2C_Lld_MasterGetTransferStatus(Instance, NULL_PTR) == I2C_CHN_BUSY_STATUS);
#endif
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            if (0U == TimeOut)
            {
                RetValue = I2C_TIMEOUT_STATUS;
            }
            else
#endif
            {
                RetValue = Master->Status;
            }
        }
        else
        {
            RetValue = I2C_BUS_BUSY_STATUS;
        }
    }
    else
    {
        /*Do nothing*/
    }
    return RetValue;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterReceiveData
 * Description   : perform a non-blocking Receive transaction on the I2C bus
 *
 * Implements : I2C_Lld_MasterReceiveData_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterReceiveData(uint8 Instance,
        uint8 *RxBuff,
        uint16 RxSize,
        boolean SendStop)
{
    I2C_MasterStateType *Master;
    Std_ReturnType StdRevalue = E_OK;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
        /* Check the I2C HW init or not which specfied by Instance and the Rx buffer and Data length.*/
        if ((NULL_PTR == Master) || (NULL_PTR == RxBuff) || (0U == RxSize))
        {
            RetValue = I2C_PARAM_ERROR_STATUS;
            StdRevalue = E_NOT_OK;
        }
    }
#if(I2C_HAS_ULTRA_FAST_MODE)
    if ((E_OK == StdRevalue) && (I2C_ULTRAFAST_MODE == Master->OperatingMode))
    {
        StdRevalue = E_NOT_OK;
        RetValue = I2C_PARAM_ERROR_STATUS;
    }
#endif /*(I2C_HAS_ULTRA_FAST_MODE)*/
    if (E_OK == StdRevalue)
    {
        if (TRUE == Master->I2cIdle)
        {
            volatile I2C_Type *BaseAddr;
            uint16 RxBytes;
            BaseAddr = I2c_Base[Instance];
            /* Copy parameters to driver state structure */
            Master->RxSize = RxSize;
            Master->I2cIdle = FALSE;
            Master->SendStop = SendStop;
            Master->RxBuff = RxBuff;
            Master->Status = I2C_CHN_BUSY_STATUS;
#if (I2C_DMA_USED == STD_ON)
            if (Master->TransferType == I2C_USING_DMA)
            {
                /*I2C choose Dma trance Data*/
                I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT |
                                        I2C_MASTER_ARBITRATION_LOST_INT |
                                        I2C_MASTER_NACK_DETECT_INT,
                                        TRUE);
                /*I2C choose Dma trance Data*/
                MasterRxDmaConfig = *DmaChannelTransferConfigArray[Master->DmaRxChannel];
                MasterRxDmaConfig.SrcTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
                MasterRxDmaConfig.DestTransferSize = DMA_TRANSFER_SIZE_1_BYTE;
                MasterRxDmaConfig.SrcOffset = 0;
                MasterRxDmaConfig.DestOffset = (sint16) 1 << (uint16)DMA_TRANSFER_SIZE_1_BYTE;
                MasterRxDmaConfig.TransferLoopByteCount = (uint32) 1 << (uint32)DMA_TRANSFER_SIZE_1_BYTE;
                MasterRxDmaConfig.TriggerCount = (uint32)(Master->RxSize / ((uint32)1U << (uint32)DMA_TRANSFER_SIZE_1_BYTE));
                /* Configure watermarks for Receive DMA for Master */
                I2C_Lld_MasterRxFIFOWatermarkSet(BaseAddr, 0U);
                (void)CddDma_SetLogicChannelTransfer(Master->DmaRxChannel, (uint32) & (BaseAddr->MDATA), \
                                                     (uint32)Master->RxBuff, &MasterRxDmaConfig);
                CddDma_InstallCallback(Master->DmaRxChannel, I2c_Lld_MasterCompleteDmaRx, (void *)((uint32)Instance));
                CddDma_InstallErrorCallback(Master->DmaRxChannel, I2c_Lld_MasterDmaTransferError, (void *)((uint32)Instance));
                CddDma_StartChannel(Master->DmaRxChannel);
                /* Initiate communication */
                I2C_Lld_MasterSendAddress(Instance, Master, TRUE);
                I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_RECEIVE, (uint8)(RxSize - 1U));
                I2C_Lld_MasterRxDmaSet(BaseAddr, TRUE);
            }
            else
#endif
            {
                /* Initiate communication */
                I2C_Lld_MasterSendAddress(Instance, Master, TRUE);
                /* Queue Receive command for RxSize bytes */
                I2C_Lld_MasterQueueCmd(Instance, Master, I2C_MASTER_CMD_RECEIVE, (uint8)(RxSize - 1U));
                /* Set rx FIFO watermark */
                RxBytes = I2C_Lld_MasterRxFIFOSizeGet(BaseAddr);
                if (RxBytes > RxSize)
                {
                    RxBytes = RxSize;
                }
                I2C_Lld_MasterRxFIFOWatermarkSet(BaseAddr, (uint8)(RxBytes - 1U));
                /* Enable relevant events */
                if (FALSE == I2C_Lld_MasterCmdQueueEmpty(Master))
                {
                    /* Enable tx event too if there are commands in the software FIFO */
                    I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT | I2C_MASTER_ARBITRATION_LOST_INT |
                                            I2C_MASTER_NACK_DETECT_INT | I2C_MASTER_TRANSMIT_DATA_INT |
                                            I2C_MASTER_RECEIVE_DATA_INT, TRUE);
                }
                else
                {
                    I2C_Lld_MasterIntConfig(Instance, I2C_MASTER_FIFO_ERROR_INT | I2C_MASTER_ARBITRATION_LOST_INT |
                                            I2C_MASTER_NACK_DETECT_INT | I2C_MASTER_RECEIVE_DATA_INT, TRUE);
                }
            }
            RetValue = Master->Status;
        }
        else
        {
            RetValue = I2C_BUS_BUSY_STATUS;
        }
    }
    return RetValue;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterRxDataBlocking
 * Description   : perform a blocking Receive transaction on the I2C bus
 *
 * Implements : I2C_Lld_MasterReceiveDataBlocking_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterRxDataBlocking(uint8 Instance,
        uint8 *RxBuff,
        uint16 RxSize,
        boolean SendStop)
{
    I2C_MasterStateType *Master;
    Std_ReturnType StdRevalue = E_OK;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
    uint32 TimeOut = 0;
#endif
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
        /*Check the I2C HW init or not which specfied by Instance*/
        if (NULL_PTR == Master)
        {
            RetValue = I2C_PARAM_ERROR_STATUS;
            StdRevalue = E_NOT_OK;
        }
        else
        {
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            TimeOut = Master->TimeoutValue;
#endif
            /*Check the Rx buffer and Data length*/
            if ((NULL_PTR == RxBuff) || (0U == RxSize))
            {
                RetValue = I2C_PARAM_ERROR_STATUS;
                StdRevalue = E_NOT_OK;
            }
            else
            {
                /*Do nothing*/
            }
        }
    }
    if (E_OK == StdRevalue)
    {
        if (TRUE == Master->I2cIdle)
        {
            Master->RxSize = RxSize;
            Master->RxBuff = RxBuff;
            Master->Direction = I2C_RECEIVE;
            Master->SendStop = SendStop;
            Master->I2cIdle = FALSE;
            Master->Status = I2C_CHN_BUSY_STATUS;
            I2C_Lld_MasterInterruptRxInit(Instance, RxSize);
            Master->RxDataByteCount = 0U;
            do
            {
                /* start transfer the blocking Data*/
                I2C_Lld_MasterReceive(Instance);
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
                --TimeOut;
#endif
            }
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            while ((I2C_Lld_MasterGetTransferStatus(Instance, NULL_PTR) == I2C_CHN_BUSY_STATUS) && (TimeOut > 0U));
#else
            while (I2C_Lld_MasterGetTransferStatus(Instance, NULL_PTR) == I2C_CHN_BUSY_STATUS);
#endif
#if (CDDI2C_SYNC_TRANSFER_TIMEOUT_EN == STD_ON)
            if (0U == TimeOut)
            {
                RetValue = I2C_TIMEOUT_STATUS;
            }
            else
#endif
            {
                RetValue = Master->Status;
            }
        }
        else
        {
            RetValue = I2C_BUS_BUSY_STATUS;
        }
    }
    else
    {
        /*Do nothing*/
    }
    return RetValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterGetTransferStatus
 * Description   : return the current status of the I2C Master transfer
 *
 * When performing an a-sync (non-blocking) transfer, the user can call this function
 * to ascertain the state of the current transfer. In addition, if the transfer is still
 * in progress, the user can get the number of words that should be Receive.
 *
 * Implements : I2C_Lld_MasterGetTransferStatus_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_MasterGetTransferStatus(uint8 Instance,
        uint32 *BytesRemaining)
{
    const I2C_MasterStateType *Master;
    Std_ReturnType StdRevalue = E_OK;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Master = I2c_MasterHwStatePtr[Instance];
    }
    /*Check the I2C HW init or not which specfied by Instance*/
    if ((E_OK == StdRevalue) && (NULL_PTR == Master))
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
        StdRevalue = E_NOT_OK;
    }
    else
    {
        /*Do nothing*/
    }
    if (E_OK == StdRevalue)
    {
        if ((BytesRemaining != NULL_PTR) && (Master->TransferType == I2C_USING_INTERRUPTS))
        {
            const volatile I2C_Type *BaseAddr = I2c_Base[Instance];
            if (Master->TxSize > 0U)
            {
                /* Send Data */
                /* Remaining bytes = bytes in buffer + bytes in tx FIFO */
                *BytesRemaining = Master->TxSize + (uint32) I2C_Lld_MasterTxFIFOCountGet(BaseAddr);
            }
            else if (Master->RxSize > 0U)
            {
                /* Receive Data */
                /* Remaining bytes = free space in buffer - bytes in rx FIFO */
                *BytesRemaining = Master->RxSize - (uint32) I2C_Lld_MasterRxFIFOCountGet(BaseAddr);
            }
            else
            {
                *BytesRemaining = 0U;
            }
        }
        RetValue =  Master->Status;
    }
    else
    {
        /*Do nothing*/
    }
    return RetValue;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterIRQHandler
 * Description   : handle non-blocking Master operation when I2C interrupt occurs
 *
 *END**************************************************************************/
CDDI2C_FUNC void I2C_Lld_MasterIRQHandler(uint8 Instance) /*PRQA S 1505*/
{
    volatile I2C_Type *BaseAddr = NULL_PTR;
    I2C_MasterStateType *Master = NULL_PTR;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        /* code */
    }
    else
    {
        BaseAddr = I2c_Base[Instance];
        Master = I2c_MasterHwStatePtr[Instance];
        if (NULL_PTR != Master)
        {
            /* Check which event caused the interrupt */
            if (TRUE == I2C_Lld_MasterDataReqEventCheck(BaseAddr))
            {
                I2C_Lld_MasterTxDataRequestHdl(Instance, Master);
            }
            if (TRUE == I2C_Lld_MasterRxDataRdyEventGet(BaseAddr))
            {
                I2C_Lld_MasterRxDataRdyEventHdl(Instance, Master);
            }
            if (TRUE == I2C_Lld_MasterFIFOErrorEventGet(BaseAddr))
            {
                /* FIFO error */
                I2C_Lld_MasterFIFOErrorEventClr(BaseAddr);
#if(I2C_HAS_HIGH_SPEED_MODE)
                /* High-speed transfers end at STOP condition */
                Master->HSInProgress = FALSE;
#endif
                Master->Status = I2C_HW_ERROR_STATUS;
                /* End transfer: no stop generation (the module will handle that by itself
                if needed), reset FIFOs */
                I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
                if (Master->MasterCallback != NULL_PTR)
                {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
                    Master->MasterCallback(I2C_MASTER_EVENT_ERROR_FIFO, Master->CallbackParam);
#else
                    Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
                }
            }
            if (TRUE == I2C_Lld_MasterArbitLostEventGet(BaseAddr))
            {
                /* Arbitration lost */
                I2C_Lld_MasterArbitLostEventClr(BaseAddr);
                /* End transfer: no stop generation (the module will handle that by itself
                if needed), reset FIFOs */
                I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
                Master->Status = I2C_ARBITRATION_LOST_STATUS;
                if (Master->MasterCallback != NULL_PTR)
                {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
                    Master->MasterCallback(I2C_MASTER_EVENT_ARBIT_LOST, Master->CallbackParam);
#else
                    Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
                }
            }
            if (TRUE == I2C_Lld_MasterNACKDetEventGet(BaseAddr))
            {
                /* Received NACK */
#if(I2C_HAS_ULTRA_FAST_MODE)
                /* Ignore NACK in Ultra Fast mode */
                if (Master->OperatingMode != I2C_ULTRAFAST_MODE)
                {
#endif
#if(I2C_HAS_HIGH_SPEED_MODE)
                    /* High-speed transfers end at STOP condition */
                    Master->HSInProgress = FALSE;
#endif
                    Master->Status = I2C_RECEIVED_NACK_STATUS;
                    /* End transfer: no stop generation (the module will handle that by itself
                    if needed), reset FIFOs */
                    I2C_Lld_MasterEndTransfer(Instance, Master, FALSE, TRUE);
                    if (Master->MasterCallback != NULL_PTR)
                    {
#if (CDDI2C_EVENT_ERROR_DETECT == STD_ON)
                        Master->MasterCallback(I2C_MASTER_EVENT_NACK, Master->CallbackParam);
#else
                        Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
#endif
                    }
                    /* Clear NACK flag */
                    I2C_Lld_MasterNACKDetEventClr(BaseAddr);
#if(I2C_HAS_ULTRA_FAST_MODE)
                }
#endif
            }
            /* Check Pin Timeout Flag */
            if (TRUE == I2C_Lld_MasterPinLowTimeoutEventGet(BaseAddr))
            {
                if (Master->MasterCallback != NULL_PTR)
                {
                    Master->MasterCallback(I2C_MASTER_EVENT_END_TRANSFER, Master->CallbackParam);
                }
                /* Clear pin low Timeout flag */
                I2C_Lld_MasterPinLowTimeoutEventClr(BaseAddr);
            }
        }
        else
        {
            /*The hw is not init ,but the ISR generate exceptionally,clear all INTC flag and exit*/
            I2C_Lld_MasterAllIntcFlagClr(BaseAddr);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterSetSlaveAddr
 * Description   : set the Slave Address for any subsequent I2C communication
 *
 * Implements : I2C_Lld_MasterSetSlaveAddr_Activity
 *END**************************************************************************/
CDDI2C_FUNC void I2C_Lld_MasterSetSlaveAddr(uint32 Instance, const uint16 Address, const boolean Is10bitAddr)
{
    I2C_MasterStateType *Master;
    Master = I2c_MasterHwStatePtr[Instance];
    Master->SlaveAddress = Address;
    Master->Is10bitAddr = Is10bitAddr;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_MasterSetHighSpeedMode
 * Description   : Sets high speed mode for Master
 *
 *END**************************************************************************/
CDDI2C_FUNC void I2C_Lld_MasterSetHighSpeedMode(uint8 Instance,
        boolean HighSpeedEnabled)
{
    I2C_MasterStateType *Master = I2c_MasterHwStatePtr[Instance];
    if (TRUE == HighSpeedEnabled)
    {
        /* Set high speed operating mode */
        Master->OperatingMode = I2C_HIGHSPEED_MODE;
    }
    else
    {
        /* High speed mode is not selected */
        Master->OperatingMode = I2C_STANDARD_MODE;
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_SlaveInit
 * Description   : initialize the I2C Slave mode driver
 *
 * Implements : I2C_Lld_SlaveInit_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_SlaveInit(uint8 Instance,
        const I2C_SlaveConfigType *UserConfigPtr)
{
    I2C_StatusType RetVal = I2C_SUCCESS_STATUS;
    if (NULL_PTR == UserConfigPtr)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        volatile I2C_Type *BaseAddr = I2c_Base[Instance];
        I2c_SlaveHwStatePtr[Instance] = &I2c_SlaveStatus[Instance];
        I2C_SlaveStateType *Slave = I2c_SlaveHwStatePtr[Instance];
        /* Initialize driver status structure */
        Slave->Status = I2C_SUCCESS_STATUS;
        Slave->SlaveListening = UserConfigPtr->SlaveListening;
        Slave->SlaveCallback = I2c_Lld_SlaveCallback;
        Slave->CallbackParam = UserConfigPtr->CallbackParam;
        Slave->TxBuff = NULL_PTR;
        Slave->RxBuff = NULL_PTR;
        Slave->TxSize = 0U;
        Slave->RxSize = 0U;
        Slave->TransferType = UserConfigPtr->TransferType;
#if (I2C_DMA_USED == STD_ON)
        /* Store DMA channel number used in transfer */
        Slave->DmaTxChannel = UserConfigPtr->DmaTxChannel;
        Slave->DmaRxChannel = UserConfigPtr->DmaRxChannel;
#endif /*(I2C_DMA_USED == STD_ON)*/
        Slave->IsTransferInProgress = FALSE;
        Slave->Is10bitAddress = UserConfigPtr->Is10bitAddr;
        Slave->RepeatedStarts = 0U;
        /* Initialize module */
        I2C_Lld_Init(Instance);
        /* Configure Slave Address */
        I2C_Lld_SlaveAddr0Set(BaseAddr, UserConfigPtr->SlaveAddress);
        if (TRUE == UserConfigPtr->Is10bitAddr)
        {
            I2C_Lld_SlaveAddrConfigSet(BaseAddr, ADDR_MATCH_0_10BIT);
        }
        else
        {
            I2C_Lld_SlaveAddrConfigSet(BaseAddr, ADDR_MATCH_0_7BIT);
        }
        /* Configure operating mode */
        I2C_Lld_SlaveSetOperatingMode(Instance, UserConfigPtr->OperatingMode);
        /* Set digtal filters for SDA and SCL */
        I2C_Lld_SlaveDigitFilterSDASet(BaseAddr, UserConfigPtr->DigitalFilterSDA);
        I2C_Lld_SlaveDigitFilterSCLSet(BaseAddr, UserConfigPtr->DigitalFilterSCL);
        if (TRUE == UserConfigPtr->SlaveListening)
        {
#if (I2C_DMA_USED == STD_ON)
            if (Slave->TransferType == I2C_USING_DMA)
            {
                /* Activate events */
                I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                                       I2C_SLAVE_FIFO_ERROR_INT |
                                       I2C_SLAVE_STOP_DETECT_INT |
                                       I2C_SLAVE_REPEATED_START_INT |
                                       I2C_SLAVE_ADDRESS_VALID_INT,
                                       TRUE);
                /* Enable I2c Slave DMA*/
                I2C_Lld_SlaveRxDmaSet(BaseAddr, TRUE);
                I2C_Lld_SlaveTxDmaSet(BaseAddr, TRUE);
            }
#endif /*(I2C_DMA_USED == STD_ON)*/
            if (Slave->TransferType == I2C_USING_INTERRUPTS)
            {
                /* Activate events */
#ifdef I2C_SUPPORT_TXCFG
                I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                                       I2C_SLAVE_FIFO_ERROR_INT |
                                       I2C_SLAVE_STOP_DETECT_INT |
                                       I2C_SLAVE_REPEATED_START_INT |
                                       I2C_SLAVE_ADDRESS_VALID_INT |
                                       I2C_SLAVE_RECEIVE_DATA_INT,
                                       TRUE);
#else
                I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_BIT_ERROR_INT |
                                       I2C_SLAVE_FIFO_ERROR_INT |
                                       I2C_SLAVE_STOP_DETECT_INT |
                                       I2C_SLAVE_REPEATED_START_INT |
                                       I2C_SLAVE_ADDRESS_VALID_INT |
                                       I2C_SLAVE_RECEIVE_DATA_INT |
                                       I2C_SLAVE_TRANSMIT_DATA_INT,
                                       TRUE);
#endif
            }
            /* Enable I2C Slave */
            I2C_Lld_SlaveEnableSet(BaseAddr, TRUE);
        }
    }
    return RetVal;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_SlaveDeinit
 * Description   : de-initialize the I2C Slave mode driver
 *
 * Implements : I2C_Lld_SlaveDeinit_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_SlaveDeinit(uint8 Instance)
{
    I2C_StatusType RetVal = I2C_SUCCESS_STATUS;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetVal = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        I2C_SlaveStateType const *Slave = I2c_SlaveHwStatePtr[Instance];
        if (NULL_PTR == Slave)
        {
            RetVal = I2C_PARAM_ERROR_STATUS;
        }
        else
        {
            volatile I2C_Type *BaseAddr;
            BaseAddr = I2c_Base[Instance];
#if (I2C_DMA_USED == STD_ON)
            if (Slave->TransferType == I2C_USING_DMA)
            {
                /* Disable I2C DMA requests. */
                (void) I2C_Lld_SlaveRxDmaSet(BaseAddr, FALSE);
                (void) I2C_Lld_SlaveTxDmaSet(BaseAddr, FALSE);
            }
#endif /*(I2C_DMA_USED == STD_ON)*/
            I2c_SlaveHwStatePtr[Instance] = NULL_PTR;
            /* Disable I2C Slave */
            I2C_Lld_SlaveEnableSet(BaseAddr, FALSE);
            /*Asserted a software reset*/
            I2C_REST_VIA_IPC->CTRL[Instance] |= (uint32)I2C_IPC_CTRL_SWRESET_MASK;
            /*De-assert the software reset*/
            I2C_REST_VIA_IPC->CTRL[Instance] &= (uint32)(~I2C_IPC_CTRL_SWRESET_MASK);
        }
    }
    return RetVal;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_SlaveSetTxBuffer
 * Description   : Provide a buffer for transmitting Data.
 *
 * Implements : I2C_Lld_SlaveSetTxBuffer_Activity
 *END**************************************************************************/
CDDI2C_FUNC Std_ReturnType I2C_Lld_SlaveSetTxBuffer(uint8 Instance,
        const uint8 *TxBuff,
        uint16 TxSize)
{
    I2C_SlaveStateType *Slave = NULL_PTR;
    Std_ReturnType StdRevalue = E_OK;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Slave = I2c_SlaveHwStatePtr[Instance];
        if (NULL_PTR == Slave)
        {
            StdRevalue = E_NOT_OK;
        }
        else if ((NULL_PTR == TxBuff) || (0U == TxSize))
        {
            StdRevalue = E_NOT_OK;
        }
        else
        {
            Slave->TxBuff = TxBuff;
            Slave->TxSize = TxSize;
        }
    }
    return StdRevalue;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_SlaveSetRxBuffer
 * Description   : Provide a buffer for receiving Data.
 *
 * Implements : I2C_Lld_SlaveSetRxBuffer_Activity
 *END**************************************************************************/
CDDI2C_FUNC Std_ReturnType I2C_Lld_SlaveSetRxBuffer(uint8 Instance,
        uint8 *RxBuff,
        uint16 RxSize)
{
    I2C_SlaveStateType *Slave = NULL_PTR;
    Std_ReturnType StdRevalue = E_OK;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        StdRevalue = E_NOT_OK;
    }
    else
    {
        Slave = I2c_SlaveHwStatePtr[Instance];
        if (NULL_PTR == Slave)
        {
            StdRevalue = E_NOT_OK;
        }
        else if ((NULL_PTR == RxBuff) || (0U == RxSize))
        {
            StdRevalue = E_NOT_OK;
        }
        else
        {
            Slave->RxBuff = RxBuff;
            Slave->RxSize = RxSize;
        }
    }
    return StdRevalue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_Lld_SlaveGetTransferStatus
 * Description   : return the current status of the I2C Slave transfer
 *
 * When performing an a-sync (non-blocking) transfer, the user can call this function
 * to ascertain the state of the current transfer. In addition, if the transfer is still
 * in progress, the user can get the number of words that should be Receive.
 *
 * Implements : I2C_Lld_SlaveGetTransferStatus_Activity
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_SlaveGetTransferStatus(uint32 Instance,
        uint32 *BytesRemaining)
{
    const I2C_SlaveStateType *Slave;
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        Slave = I2c_SlaveHwStatePtr[Instance];
        /*Check the I2C HW init or not which specfied by Instance*/
        if (NULL_PTR == Slave)
        {
            RetValue = I2C_PARAM_ERROR_STATUS;
        }
        else
        {
            if ((BytesRemaining != NULL_PTR) && (Slave->TransferType == I2C_USING_INTERRUPTS))
            {
                if (Slave->TxSize > 0U)
                {
                    /* Send Data */
                    *BytesRemaining = Slave->TxSize;
                }
                else
                {
                    *BytesRemaining = 0U;
                }
            }
            else
            {
                /*Do nothing*/
            }
            RetValue =  Slave->Status;
        }
    }
    return RetValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_StartListening
 * Description   : Makes a Slave channel available for processing request in case
 *                 Slave is in not listening mode
 * Implements    : I2c_Ip_StartListening_Activity
 *
 *END**************************************************************************/
CDDI2C_FUNC I2C_StatusType I2C_Lld_StartListening(uint8 Instance)
{
    I2C_StatusType RetValue = I2C_SUCCESS_STATUS;
    /*Check the Instance number is valid or invalid*/
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        RetValue = I2C_PARAM_ERROR_STATUS;
    }
    else
    {
        I2C_Lld_SlaveActivateEvents(Instance);
    }
    return RetValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : I2c_Lld_SlaveIRQHandler
 * Description   : handle non-blocking Slave operation when I2C interrupt occurs
 *
 *END**************************************************************************/
CDDI2C_FUNC void I2c_Lld_SlaveIRQHandler(uint8 Instance)  /*PRQA S 1505*/
{
    volatile I2C_Type *BaseAddr = NULL_PTR;
    I2C_SlaveStateType *Slave = NULL_PTR;
    boolean StopDetect = FALSE;
    boolean RepeatStartDetect = FALSE;
    if (Instance >= I2C_INSTANCE_COUNT)
    {
        /* code */
    }
    else
    {
        BaseAddr = I2c_Base[Instance];
        Slave = I2c_SlaveHwStatePtr[Instance];
        if (NULL_PTR != Slave)
        {
            /* Check which event caused the interrupt */
            if (TRUE == I2C_Lld_SlaveAddressValidEventGet(BaseAddr))
            {
                I2C_Lld_SlaveAddrVldEventHandle(Instance, BaseAddr, Slave);
            }
            if (TRUE == I2C_Lld_SlaveTxDataEventGet(BaseAddr))
            {
                if (TRUE == I2C_Lld_SlaveIntGet(BaseAddr, (uint32)I2C_SLAVE_TRANSMIT_DATA_INT))
                {
                    I2C_Lld_SlaveTxDataEventHandle(BaseAddr, Slave);
                }
                else
                {
                    /*Do nothing*/
                }
            }
            if (TRUE == I2C_Lld_SlaveRxDataEventGet(BaseAddr))
            {
                if (TRUE == I2C_Lld_SlaveIntGet(BaseAddr, (uint32)I2C_SLAVE_RECEIVE_DATA_INT))
                {
                    I2C_Lld_SlaveRxDataEventHandle(BaseAddr, Slave);
                }
                else
                {
                    /*Do nothing*/
                }
            }
            StopDetect = I2C_Lld_SlaveSTOPDetectEventGet(BaseAddr);
            RepeatStartDetect = I2C_Lld_SlaveRepeatedStartEventGet(BaseAddr);
            if (TRUE == RepeatStartDetect)
            {
                ++Slave->RepeatedStarts;
                if ((1U == Slave->RepeatedStarts) && (TRUE == Slave->Is10bitAddress))
                {
                    RepeatStartDetect = FALSE;
                    I2C_Lld_SlaveRepeatStartEventClr(BaseAddr);
                }
            }
            if ((TRUE == StopDetect) || (TRUE == RepeatStartDetect))
            {
                /* Either STOP or repeated START have the same meaning here: the current transfer is over */
                I2C_Lld_SlaveStopDetEventClr(BaseAddr);
                I2C_Lld_SlaveRepeatStartEventClr(BaseAddr);
#ifdef I2C_SUPPORT_TXCFG
                /* Deactivate Interrupts for transmitting Data */
                I2C_Lld_SlaveIntConifg(BaseAddr, (uint32)I2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif
                if (Slave->Status == I2C_CHN_BUSY_STATUS)
                {
                    /* Report success if no error was recorded */
                    Slave->Status = I2C_SUCCESS_STATUS;
                }
                I2C_Lld_SlaveEndTransferHandler(Slave, BaseAddr);
            }
            /* Check for Slave errors */
            if (TRUE == I2C_Lld_SlaveBitErrorEventGet(BaseAddr))
            {
                Slave->Status = I2C_HW_ERROR_STATUS;
                I2C_Lld_SlaveBitErrorEventClear(BaseAddr);
#ifdef I2C_SUPPORT_TXCFG
                /* Deactivate Interrupts for transmitting Data */
                I2C_Lld_SlaveIntConifg(BaseAddr, (uint32)I2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif
                I2C_Lld_SlaveEndTransferHandler(Slave, BaseAddr);
            }
#if(I2C_HAS_ULTRA_FAST_MODE)
            if (TRUE == I2C_Lld_SlaveFIFOErrorEventGet(BaseAddr))
            {
                /* In Ultra-Fast mode clock stretching is disabled, so it is possible to get
                   this event if the Slave can't keep up */
                Slave->Status = I2C_RX_OVERRUN_STATUS;
                I2C_Lld_SlaveFIFOErrorEventClr(BaseAddr);
#if I2C_SUPPORT_TXCFG
                /* Deactivate Interrupts for transmitting Data */
                I2C_Lld_SlaveIntConifg(BaseAddr, I2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif
                I2C_Lld_SlaveEndTransferHandler(Slave, BaseAddr);
            }
#endif
        }
        else
        {
            /*Do nothing*/
        }
    }
}

#if defined (CPU_YTM32B1ME0) || defined (CPU_YTM32B1MD1) || defined (CPU_YTM32B1MC0)

#ifdef I2C_0_MASTER_MODE_ENABLED
CDDI2C_FUNC ISR(I2C0_Master_IRQHandler)
{
    I2C_Lld_MasterIRQHandler(0);
}
#endif

#ifdef I2C_1_MASTER_MODE_ENABLED
CDDI2C_FUNC ISR(I2C1_Master_IRQHandler)
{
    I2C_Lld_MasterIRQHandler(1);
}
#endif

#ifdef I2C_2_MASTER_MODE_ENABLED
CDDI2C_FUNC ISR(I2C2_Master_IRQHandler)
{
    I2C_Lld_MasterIRQHandler(2);
}
#endif

#ifdef I2C_0_SLAVE_MODE_ENABLED
CDDI2C_FUNC ISR(I2C0_Slave_IRQHandler)
{
    I2c_Lld_SlaveIRQHandler(0);
}
#endif

#ifdef I2C_1_SLAVE_MODE_ENABLED
CDDI2C_FUNC ISR(I2C1_Slave_IRQHandler)
{
    I2c_Lld_SlaveIRQHandler(1);
}
#endif

#ifdef I2C_2_SLAVE_MODE_ENABLED
CDDI2C_FUNC ISR(I2C2_Slave_IRQHandler)
{
    I2c_Lld_SlaveIRQHandler(2);
}
#endif

#elif defined (CPU_YTM32B1HA0)

#if defined(I2C_0_MASTER_MODE_ENABLED) || defined(I2C_0_SLAVE_MODE_ENABLED)
CDDI2C_FUNC ISR(I2C0_Master_Slave_IRQHandler)
{
#ifdef I2C_0_MASTER_MODE_ENABLED
    I2C_Lld_MasterIRQHandler(0);
#else
    I2c_Lld_SlaveIRQHandler(0);
#endif
}
#endif

#if defined(I2C_1_MASTER_MODE_ENABLED) || defined(I2C_1_SLAVE_MODE_ENABLED)
CDDI2C_FUNC ISR(I2C1_Master_Slave_IRQHandler)
{
#ifdef I2C_1_MASTER_MODE_ENABLED
    I2C_Lld_MasterIRQHandler(1);
#else
    I2c_Lld_SlaveIRQHandler(1);
#endif
}
#endif

#if defined(I2C_2_MASTER_MODE_ENABLED) || defined(I2C_2_SLAVE_MODE_ENABLED)
CDDI2C_FUNC ISR(I2C2_Master_Slave_IRQHandler)
{
#ifdef I2C_2_MASTER_MODE_ENABLED
    I2C_Lld_MasterIRQHandler(2);
#else
    I2c_Lld_SlaveIRQHandler(2);
#endif
}
#endif

#if defined(I2C_3_MASTER_MODE_ENABLED) || defined(I2C_3_SLAVE_MODE_ENABLED)
CDDI2C_FUNC ISR(I2C3_Master_Slave_IRQHandler)
{
#ifdef I2C_3_MASTER_MODE_ENABLED
    I2C_Lld_MasterIRQHandler(3);
#else
    I2c_Lld_SlaveIRQHandler(3);
#endif
}
#endif

#if defined(I2C_4_MASTER_MODE_ENABLED) || defined(I2C_4_SLAVE_MODE_ENABLED)
CDDI2C_FUNC ISR(I2C4_Master_Slave_IRQHandler)
{
#ifdef I2C_4_MASTER_MODE_ENABLED
    I2C_Lld_MasterIRQHandler(4);
#else
    I2c_Lld_SlaveIRQHandler(4);
#endif
}
#endif

#else
#error "No valid CPU defined!"
#endif

#define CDDI2C_STOP_SEC_CODE
#include "CddI2c_MemMap.h"

#ifdef __cplusplus
}
#endif

/* End of file CddI2c_Lld.c */

