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

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                          INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/

#include "Lpuart_Uart_Ip.h"
#include "Lpuart_Uart_Ip_HwAccess.h"
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
    #include "Dma_Ip.h"
#endif

#ifdef LPUART_UART_IP_DEV_ERROR_DETECT
    #if (LPUART_UART_IP_DEV_ERROR_DETECT == STD_ON)
        #include "Devassert.h"
    #endif /* (STD_ON == LPUART_UART_IP_DEV_ERROR_DETECT) */
#endif /* idfef LPUART_UART_IP_DEV_ERROR_DETECT */

/*==================================================================================================
*                                 SOURCE FILE VERSION INFORMATION
==================================================================================================*/

#define LPUART_UART_IP_VENDOR_ID_C                      43
#define LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C       4
#define LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C       4
#define LPUART_UART_IP_AR_RELEASE_REVISION_VERSION_C    0
#define LPUART_UART_IP_SW_MAJOR_VERSION_C               1
#define LPUART_UART_IP_SW_MINOR_VERSION_C               0
#define LPUART_UART_IP_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                       FILE VERSION CHECKS
==================================================================================================*/
/* Checks against Lpuart_Uart_Ip.h */
#if (LPUART_UART_IP_VENDOR_ID_C != LPUART_UART_IP_VENDOR_ID)
    #error "Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h have different vendor ids"
#endif
#if ((LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C    != LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION) || \
     (LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C    != LPUART_UART_IP_AR_RELEASE_MINOR_VERSION) || \
     (LPUART_UART_IP_AR_RELEASE_REVISION_VERSION_C != LPUART_UART_IP_AR_RELEASE_REVISION_VERSION))
     #error "AUTOSAR Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h are different"
#endif
#if ((LPUART_UART_IP_SW_MAJOR_VERSION_C != LPUART_UART_IP_SW_MAJOR_VERSION) || \
     (LPUART_UART_IP_SW_MINOR_VERSION_C != LPUART_UART_IP_SW_MINOR_VERSION) || \
     (LPUART_UART_IP_SW_PATCH_VERSION_C != LPUART_UART_IP_SW_PATCH_VERSION))
    #error "Software Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h are different"
#endif

/* Checks against Lpuart_Uart_Ip_HwAccess.h */
#if (LPUART_UART_IP_VENDOR_ID_C != LPUART_UART_IP_HWACCESS_VENDOR_ID)
    #error "Lpuart_Uart_Ip.c and Lpuart_Uart_Ip_HwAccess.h have different vendor ids"
#endif
#if ((LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C    != LPUART_UART_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION) || \
     (LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C    != LPUART_UART_IP_HWACCESS_AR_RELEASE_MINOR_VERSION) || \
     (LPUART_UART_IP_AR_RELEASE_REVISION_VERSION_C != LPUART_UART_IP_HWACCESS_AR_RELEASE_REVISION_VERSION))
     #error "AUTOSAR Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip_HwAccess.h are different"
#endif
#if ((LPUART_UART_IP_SW_MAJOR_VERSION_C != LPUART_UART_IP_HWACCESS_SW_MAJOR_VERSION) || \
     (LPUART_UART_IP_SW_MINOR_VERSION_C != LPUART_UART_IP_HWACCESS_SW_MINOR_VERSION) || \
     (LPUART_UART_IP_SW_PATCH_VERSION_C != LPUART_UART_IP_HWACCESS_SW_PATCH_VERSION))
    #error "Software Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip_HwAccess.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Checks against Dma_Ip.h */
    #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
        #if ((LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C != DMA_IP_AR_RELEASE_MAJOR_VERSION_H) || \
             (LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C != DMA_IP_AR_RELEASE_MINOR_VERSION_H))
            #error "AutoSar Version Numbers of Lpuart_Uart_Ip.c and Dma_Ip.h are different"
        #endif
    #endif
    /* Checks against Devassert.h */
    #ifdef LPUART_UART_IP_DEV_ERROR_DETECT
    #if (STD_ON == LPUART_UART_IP_DEV_ERROR_DETECT)
        /* Check if Lpuart_Uart_Ip.c file and Devassert.h file are of the same Autosar version */
        #if ((LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C    != DEVASSERT_AR_RELEASE_MAJOR_VERSION) || \
         (LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C    != DEVASSERT_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of Lpuart_Uart_Ip.c and Devassert.h are different"
        #endif
    #endif /* (STD_ON == LPUART_UART_IP_DEV_ERROR_DETECT) */
    #endif /* #ifdef LPUART_UART_IP_DEV_ERROR_DETECT */


#endif
/*==================================================================================================
*                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                          LOCAL MACROS
==================================================================================================*/

#ifdef LPUART_UART_IP_DEV_ERROR_DETECT
    #if (LPUART_UART_IP_DEV_ERROR_DETECT == STD_ON)
        #define LPUART_UART_IP_DEV_ASSERT(x)      DevAssert(x)
    #else
        #define LPUART_UART_IP_DEV_ASSERT(x)      (void)(x)
    #endif
#endif

/* @brief Address of the least significant byte or word in a 32-bit register (depends on endianness) */
#define LPUART_UART_IP_LSBW_ADDR(reg)  ((uint32)(&(reg)))

/*==================================================================================================
*                                         LOCAL CONSTANTS
==================================================================================================*/

#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
    #define LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION             (10U)
    #define LPUART_UART_IP_DMA_LEAST_CONFIG_LIST_DIMENSION       (2U)
#endif

/*==================================================================================================
*                                         LOCAL VARIABLES
==================================================================================================*/
#define UART_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_MemMap.h"

/** @brief Array of UART driver runtime state structures */
Lpuart_Uart_Ip_StateStructureType Lpuart_Uart_Ip_apStateStructure[LPUART_UART_IP_NUMBER_OF_INSTANCES];

#define UART_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_MemMap.h"

#define UART_START_SEC_VAR_CLEARED_UNSPECIFIED
#include "Uart_MemMap.h"

/* Pointer to lpuart runtime state structure */
Lpuart_Uart_Ip_StateStructureType * Lpuart_Uart_Ip_apStateStructuresArray[LPUART_UART_IP_NUMBER_OF_INSTANCES];

/** @brief User config structure. */
const Lpuart_Uart_Ip_UserConfigType * Lpuart_Uart_Ip_apUserConfig[LPUART_UART_IP_NUMBER_OF_INSTANCES];

#define UART_STOP_SEC_VAR_CLEARED_UNSPECIFIED
#include "Uart_MemMap.h"

#define UART_START_SEC_CONST_UNSPECIFIED
#include "Uart_MemMap.h"

/* Table of base addresses for lpuart instances. */
static LPUART_Type * const Lpuart_Uart_Ip_apBases[LPUART_UART_IP_NUMBER_OF_INSTANCES] = IP_LPUART_BASE_PTRS;

#define UART_STOP_SEC_CONST_UNSPECIFIED
#include "Uart_MemMap.h"


/*==================================================================================================
*                                        GLOBAL CONSTANTS
==================================================================================================*/

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

/*==================================================================================================
*                                    LOCAL FUNCTION PROTOTYPES
==================================================================================================*/

/*==================================================================================================
*                                         LOCAL FUNCTIONS
==================================================================================================*/
#define UART_START_SEC_CODE
#include "Uart_MemMap.h"

static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingInt(const uint8 Instance,
                                                                      const uint8 * TxBuff,
                                                                      const uint32 TxSize);
static void Lpuart_Uart_Ip_CompleteSendDataUsingInt(const uint8 Instance);
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingInt(const uint8 Instance,
                                                                         uint8 * RxBuff,
                                                                         const uint32 RxSize);
static void Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(const uint8 Instance);
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingDma(const uint8 Instance,
                                                                      const uint8 * TxBuff,
                                                                      const uint32 TxSize);
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingDma(const uint8 Instance,
                                                                         uint8 * RxBuff,
                                                                         const uint32 RxSize);
static void Lpuart_Uart_Ip_SetupIntDmaMode(const uint8 Instance, boolean Enable);
#endif

static void Lpuart_Uart_Ip_PutData(const uint8 Instance);
static void Lpuart_Uart_Ip_GetData(const uint8 Instance);
static void Lpuart_Uart_Ip_RxIrqHandler(const uint8 Instance);
static void Lpuart_Uart_Ip_TxEmptyIrqHandler(const uint8 Instance);
static void Lpuart_Uart_Ip_TxCompleteIrqHandler(const uint8 Instance);
static void Lpuart_Uart_Ip_ErrIrqHandler(const uint8 Instance);
static void Lpuart_Uart_Ip_StartGetData(const uint8 Instance, uint32 * StartTime, uint32 * ElapsedTicks, uint32 TimeoutTicks);

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

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_Init
 * Description   : This function initializes a LPUART instance for operation.
 * This function will initialize the run-time state structure to keep track of
 * the on-going transfers, ungate the clock to the LPUART module, initialize the
 * module to user defined settings and default settings, configure the IRQ state
 * structure and enable the module-level interrupt to the core, and enable the
 * LPUART module transmitter and receiver.
 *
 * Implements    : Lpuart_Uart_Ip_Init_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_Init_Activity*/
void Lpuart_Uart_Ip_Init(const uint8 Instance, const Lpuart_Uart_Ip_UserConfigType * UserConfig)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(UserConfig != NULL_PTR);
    /* Check if current instance is already initialized. */
    LPUART_UART_IP_DEV_ASSERT(NULL_PTR == Lpuart_Uart_Ip_apStateStructuresArray[Instance]);
    /* Check if Baudrate parameters are valid value */
    LPUART_UART_IP_DEV_ASSERT(UserConfig->BaudOverSamplingRatio <= 0x20U);
    LPUART_UART_IP_DEV_ASSERT((UserConfig->BaudRateDivisor <= 0x1FFFU) && \
                              (UserConfig->BaudRateDivisor >= 1U));

    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];
    Lpuart_Uart_Ip_StateStructureType *UartStatePtr;
    uint32 Index;
    uint8 *ClearStructPtr;

    Lpuart_Uart_Ip_apStateStructuresArray[Instance] = UserConfig->StateStruct;
    UartStatePtr = Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    Lpuart_Uart_Ip_apUserConfig[Instance] =  UserConfig;
    ClearStructPtr = (uint8 *)UartStatePtr;

#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
    /* In DMA mode, only 7-bits and 8-bits chars are supported */
    LPUART_UART_IP_DEV_ASSERT((UserConfig->TransferType != LPUART_UART_IP_USING_DMA) || \
                              ((LPUART_UART_IP_7_BITS_PER_CHAR == UserConfig->BitCountPerChar) || \
                               (LPUART_UART_IP_8_BITS_PER_CHAR == UserConfig->BitCountPerChar)));

#endif /* (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) */


    /* For 10 bits per char, parity bit cannot be enabled */
    LPUART_UART_IP_DEV_ASSERT((UserConfig->BitCountPerChar != LPUART_UART_IP_10_BITS_PER_CHAR) || \
                              (LPUART_UART_IP_PARITY_DISABLED == UserConfig->ParityMode));

    /* Clear the state struct for this instance. */
    for (Index = 0; Index < sizeof(Lpuart_Uart_Ip_StateStructureType); Index++)
    {
        ClearStructPtr[Index] = 0;
    }


    /* Initialize the LPUART instance */
    Lpuart_Uart_Ip_Hw_Init(Base);

    /* Check if Osr is between 4x and 7x oversampling.
     * If so, then "BOTHEDGE" sampling must be turned on */
    if (UserConfig->BaudOverSamplingRatio < 8U)
    {
        Lpuart_Uart_Ip_EnableBothEdgeSamplingCmd(Base);
    }

    /* Program the Osr value (bit value is one less than actual value) */
    Lpuart_Uart_Ip_SetOversamplingRatio(Base, (uint32)UserConfig->BaudOverSamplingRatio -1U);

    /* Write the Sbr value to the BAUD registers */
    Lpuart_Uart_Ip_SetBaudRateDivisor(Base, UserConfig->BaudRateDivisor);

    if (UserConfig->ParityMode != LPUART_UART_IP_PARITY_DISABLED)
    {
        Lpuart_Uart_Ip_SetBitCountPerChar(Base, UserConfig->BitCountPerChar, TRUE);
    }
    else
    {
        Lpuart_Uart_Ip_SetBitCountPerChar(Base, UserConfig->BitCountPerChar, FALSE);
    }
    Lpuart_Uart_Ip_SetParityMode(Base, UserConfig->ParityMode);
    Lpuart_Uart_Ip_SetStopBitCount(Base, UserConfig->StopBitsCount);

    /* Initialize last driver operation status */
    UartStatePtr->TransmitStatus = LPUART_UART_IP_STATUS_SUCCESS;
    UartStatePtr->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;
    /* Set the initial baudrate from user's structure */
    UartStatePtr->BaudRate = UserConfig->BaudRate;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_Deinit
 * Description   : This function shuts down the UART by disabling interrupts and
 *                 transmitter/receiver.
 *
 * Implements    : Lpuart_Uart_Ip_Deinit_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_Deinit_Activity*/
void Lpuart_Uart_Ip_Deinit(const uint8 Instance)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;
    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];

    /* Check if current instance is already de-initialized or is gated.*/
    LPUART_UART_IP_DEV_ASSERT(Lpuart_Uart_Ip_apStateStructuresArray[Instance] != NULL_PTR);

    Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, LPUART_UART_IP_TIMEOUT_VALUE_US, LPUART_UART_IP_TIMEOUT_TYPE);
    /* Wait until the data is completely shifted out of shift register */
    while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_COMPLETE) && \
           !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
    {}
    /* Disble  Tx data register empty and transmission complete interrupt */

    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_COMPLETE, FALSE);

    /* Disble  Rx data register full */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE);

    /* Disable error interrupts */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_OVERRUN, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_PARITY_ERR_FLAG, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_NOISE_ERR_FLAG, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_FRAME_ERR_FLAG, FALSE);

    /* Clear our saved pointer to the state structure */
    Lpuart_Uart_Ip_apStateStructuresArray[Instance] = NULL_PTR;

}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SyncSend
 * Description   : Send out multiple bytes of data using polling method.
 *
 * Implements    : Lpuart_Uart_Ip_SyncSend_Activity
 *END**************************************************************************/
 /* implements     Lpuart_Uart_Ip_SyncSend_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SyncSend(const uint8 Instance,
                                                  const uint8 *TxBuff,
                                                  const uint32 TxSize,
                                                  const uint32 Timeout)
{
    /* Check the validity of the parameters */
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(TxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(TxSize > 0U);

    LPUART_Type * Base;
    Lpuart_Uart_Ip_StateStructureType * UartState;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;
    boolean IsReturn = FALSE;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_SUCCESS;
    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);

    SchM_Enter_Uart_UART_EXCLUSIVE_AREA_00();
    /* Check driver is not busy transmitting data from a previous asynchronous call */
    if (UartState->IsTxBusy)
    {
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_00();
        RetVal = LPUART_UART_IP_STATUS_BUSY;
        IsReturn = TRUE;
    }
    if (!IsReturn)
    {
        UartState->IsTxBusy = TRUE;
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_00();
        UartState->TxBuff = TxBuff;
        UartState->TxSize = TxSize;

        UartState->TransmitStatus = LPUART_UART_IP_STATUS_BUSY;

        /* Disble  Tx data register empty and transmission complete interrupt */
        Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE);
        Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_COMPLETE, FALSE);

        /* Enable the LPUART transmitter */
        Lpuart_Uart_Ip_SetTransmitterCmd(Base, TRUE);
        Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, Timeout, LPUART_UART_IP_TIMEOUT_TYPE);

        while ((UartState->TxSize > 0U) && \
                !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
            Lpuart_Uart_Ip_PutData(Instance);
            while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_DATA_REG_EMPTY)  && \
                   !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
            {}
        }

        /* Disable the LPUART transmitter */
        Lpuart_Uart_Ip_SetTransmitterCmd(Base, FALSE);

        /* Check if Timeout occur */
        if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
            UartState->TransmitStatus = LPUART_UART_IP_STATUS_TIMEOUT;
        }else /* The transmit process is complete */
        {
            UartState->TransmitStatus = LPUART_UART_IP_STATUS_SUCCESS;
        }
        UartState->IsTxBusy = FALSE;
        RetVal = UartState->TransmitStatus;
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_AsyncSend
 * Description   : This function sends data out through the LPUART module using
 * non-blocking method. The function will return immediately after calling this
 * function.
 *
 * Implements    : Lpuart_Uart_Ip_AsyncSend_Activity
 *END**************************************************************************/
 /* implements     Lpuart_Uart_Ip_AsyncSend_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AsyncSend(const uint8 Instance,
                                                   const uint8 * TxBuff,
                                                   const uint32 TxSize)
{
    /* Check the validity of the parameters */
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(TxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(TxSize > 0U);
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    Lpuart_Uart_Ip_StateStructureType * UartState;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_SUCCESS;
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    boolean IsReturn = FALSE;

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);

    SchM_Enter_Uart_UART_EXCLUSIVE_AREA_01();
    /* Check it's not busy transmitting data from a previous function call */
    if (UartState->IsTxBusy)
    {
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_01();
        RetVal = LPUART_UART_IP_STATUS_BUSY;
        IsReturn = TRUE;
    }
    if (!IsReturn)
    {
        UartState->IsTxBusy = TRUE;
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_01();

        LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);
        LPUART_UART_IP_DEV_ASSERT((LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType) ||
                                  (LPUART_UART_IP_USING_DMA == UartUserCfg->TransferType));
        if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
        {
            /* Start the transmission process using interrupts */
            RetVal = Lpuart_Uart_Ip_StartSendDataUsingInt(Instance, TxBuff, TxSize);
        }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
        else
        {
            /* Start the transmission process using DMA */
            RetVal = Lpuart_Uart_Ip_StartSendDataUsingDma(Instance, TxBuff, TxSize);
        }
#endif
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_GetTransmitStatus
 * Description   : This function returns whether the previous LPUART transmit has
 * finished. When performing non-blocking transmit, the user can call this
 * function to ascertain the state of the current transmission:
 * in progress (or busy) or complete (success). In addition, if the transmission
 * is still in progress, the user can obtain the number of words that have been
 * currently transferred.
 *
 * Implements    : Lpuart_Uart_Ip_GetTransmitStatus_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_GetTransmitStatus_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_GetTransmitStatus(const uint8 Instance, uint32 * BytesRemaining)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
    const Dma_Ip_LogicChannelInfoParamType DmaLogicChnParam = DMA_IP_CH_GET_CURRENT_ITER_COUNT;
#endif
    UartState = (const Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);

    if (BytesRemaining != NULL_PTR)
    {
        if (UartState->IsTxBusy)
        {
            /* Fill in the bytes not transferred yet. */
            if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
            {
                /* In interrupt-based communication, the remaining bytes are retrieved
                 * from the state structure
                 */
                *BytesRemaining = UartState->TxSize;;
            }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
            else
            {
                /* In DMA-based communication, the remaining bytes are retrieved
                 * from the current DMA major loop count
                 */
                (void)Dma_Ip_GetLogicChannelParam(UartUserCfg->TxDMAChannel, DmaLogicChnParam, BytesRemaining);
            }
#endif
        }
        else
        {
            *BytesRemaining = 0;
        }
    }

    return UartState->TransmitStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_AbortSendingData
 * Description   : This function terminates an non-blocking LPUART transmission
 * early. During a non-blocking LPUART transmission, the user has the option to
 * terminate the transmission early if the transmission is still in progress.
 *
 * Implements    : Lpuart_Uart_Ip_AbortSendingData_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_AbortSendingData_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AbortSendingData(const uint8 Instance)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);

    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];
    boolean IsReturn = FALSE;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_SUCCESS;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);

    /* Check if a transfer is running. */
    if (!UartState->IsTxBusy)
    {
        RetVal = LPUART_UART_IP_STATUS_SUCCESS;
        IsReturn = TRUE;
    }
    if (!IsReturn)
    {
        /* Update the tx status */
        UartState->TransmitStatus = LPUART_UART_IP_STATUS_ABORTED;

        /* Stop the running transfer. */
        if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
        {
            Lpuart_Uart_Ip_CompleteSendDataUsingInt(Instance);
        }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
        else
        {
            /* Release the DMA channel */
            (void)Dma_Ip_SetLogicChannelCommand(UartUserCfg->TxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
            Lpuart_Uart_Ip_CompleteSendUsingDma(Instance);
        }
#endif
        /* Flush the Tx Buffer */
        Lpuart_Uart_Ip_FlushTxBuffer(Base);
        RetVal = LPUART_UART_IP_STATUS_SUCCESS;
    }
    return RetVal;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SyncReceive
 * Description   : Receive multiple bytes of data using polling method.
 *
 * Implements    : Lpuart_Uart_Ip_SyncReceive_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_SyncReceive_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SyncReceive(const uint8 Instance,
                                                     uint8 *RxBuff,
                                                     const uint32 RxSize,
                                                     const uint32 Timeout)
{
    /* Check the validity of the parameters */
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(RxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(RxSize > 0U);

    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];
    Lpuart_Uart_Ip_StateStructureType * UartState;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;
    boolean IsReturn = FALSE;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_SUCCESS;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);

    SchM_Enter_Uart_UART_EXCLUSIVE_AREA_02();
    /* Check driver is not busy receiving data from a previous asynchronous call */
    if (UartState->IsRxBusy)
    {
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_02();
        RetVal = LPUART_UART_IP_STATUS_BUSY;
        IsReturn = TRUE;
    }
    if (!IsReturn)
    {
        UartState->IsRxBusy = TRUE;
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_02();
        UartState->RxBuff = RxBuff;
        UartState->RxSize = RxSize;
        UartState->ReceiveStatus = LPUART_UART_IP_STATUS_BUSY;

        /* Disble  Rx data register full */
        Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE);
        /* Enable the LPUART receiver */
        Lpuart_Uart_Ip_SetReceiverCmd((LPUART_Type *)Base, TRUE);

        Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, Timeout, LPUART_UART_IP_TIMEOUT_TYPE);

        Lpuart_Uart_Ip_StartGetData(Instance, &StartTime, &ElapsedTicks, TimeoutTicks);

        /* Check if Timeout occur */
        if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_TIMEOUT;
        }

        /* Check other success receiving case*/
        if (LPUART_UART_IP_STATUS_BUSY == UartState->ReceiveStatus)
        {
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;
        }

        if ((0U == UartState->RxSize) && (LPUART_UART_IP_STATUS_RX_OVERRUN == UartState->ReceiveStatus))
        {
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;
        }

        /* Disable the LPUART receiver */
        Lpuart_Uart_Ip_SetReceiverCmd((LPUART_Type *)Base, FALSE);

        UartState->IsRxBusy = FALSE;

        /* Read dummy to clear RDRF flag */
        (void)Lpuart_Uart_Ip_Getchar(Base);

        RetVal = UartState->ReceiveStatus;
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_StartGetData
 * Description   : Start Getting Data in SyncReceive mode
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_StartGetData(const uint8 Instance, uint32 * StartTime, uint32 * ElapsedTicks, uint32 TimeoutTicks)
{
        Lpuart_Uart_Ip_StateStructureType * UartState;
        UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
        LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];
        uint8 StatusIndex = 0U;
        uint32 Mask = 0U;
        const Lpuart_Uart_Ip_StatusFlagType Lpuart_Uart_Ip_StatusFlagTypeArray[4U] = {LPUART_UART_IP_RX_OVERRUN,
                                                                                      LPUART_UART_IP_FRAME_ERR,
                                                                                      LPUART_UART_IP_NOISE_DETECT,
                                                                                      LPUART_UART_IP_PARITY_ERR};
        const Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_ReceiveStatusArray[4U] = {LPUART_UART_IP_STATUS_RX_OVERRUN,
                                                                                 LPUART_UART_IP_STATUS_FRAMING_ERROR,
                                                                                 LPUART_UART_IP_STATUS_NOISE_ERROR,
                                                                                 LPUART_UART_IP_STATUS_PARITY_ERROR};
        const uint32 Lpuart_Uart_Ip_StatusRegMask[4U] = {LPUART_STAT_OR_MASK,
                                                         LPUART_STAT_FE_MASK,
                                                         LPUART_STAT_NF_MASK,
                                                         LPUART_STAT_PF_MASK};
        while ((UartState->RxSize > 0U) && \
                !Lpuart_Uart_Ip_CheckTimeout(StartTime, ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
            /* Wait until data reception flag is set or timeout occurs if there is an error during reception */
            while (!Lpuart_Uart_Ip_GetStatusFlag((const LPUART_Type*)Base, LPUART_UART_IP_DATA_REG_FULL) && \
                   !Lpuart_Uart_Ip_CheckTimeout(StartTime, ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
            {}
            /* Check for errors on received data */
            for(StatusIndex = 0U; StatusIndex <= 3U; StatusIndex++)
            {
              if(Lpuart_Uart_Ip_GetStatusFlag((const LPUART_Type*)Base, Lpuart_Uart_Ip_StatusFlagTypeArray[StatusIndex]))
              {
                UartState->ReceiveStatus = Lpuart_Uart_Ip_ReceiveStatusArray[StatusIndex];
                Mask |= Lpuart_Uart_Ip_StatusRegMask[StatusIndex];
              }
            }

            if(Mask > 0U)
            {
              /* Disable the LPUART receiver */
              Lpuart_Uart_Ip_SetReceiverCmd((LPUART_Type *)Base, FALSE);
              /* Clear the flag */
              Lpuart_Uart_Ip_ClearStatusFlagWithMask(Base, Mask);
              break;
            }
            else
            {
              /* Get received data */
              Lpuart_Uart_Ip_GetData(Instance);
            }
        }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_ReceiveData
 * Description   : This function receives data from LPUART module using
 * non-blocking method.  This function returns immediately after initiating the
 * receive function. The application has to get the receive status to see when
 * the receive is complete. In other words, after calling non-blocking get
 * function, the application must get the receive status to check if receive
 * is completed or not.
 *
 * Implements    : Lpuart_Uart_Ip_ReceiveData_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_AsyncReceive_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AsyncReceive(const uint8 Instance,
                                                      uint8 * RxBuff,
                                                      const uint32 RxSize)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(RxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(RxSize > 0U);

    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    Lpuart_Uart_Ip_StateStructureType * UartState;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_SUCCESS;
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    boolean IsReturn = FALSE;

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);

    SchM_Enter_Uart_UART_EXCLUSIVE_AREA_03();
    /* Check it's not busy receiving data from a previous function call */
    if (UartState->IsRxBusy)
    {
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_03();
        RetVal = LPUART_UART_IP_STATUS_BUSY;
        IsReturn = TRUE;
    }
    if (!IsReturn)
    {
        UartState->IsRxBusy = TRUE;
        SchM_Exit_Uart_UART_EXCLUSIVE_AREA_03();

        LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);
        LPUART_UART_IP_DEV_ASSERT((LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType) ||
                                  (LPUART_UART_IP_USING_DMA == UartUserCfg->TransferType));

        if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
        {
            /* Start the reception process using interrupts */
            RetVal = Lpuart_Uart_Ip_StartReceiveDataUsingInt(Instance, RxBuff, RxSize);
        }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
        else
        {
            /* Start the reception process using DMA */
            RetVal = Lpuart_Uart_Ip_StartReceiveDataUsingDma(Instance, RxBuff, RxSize);
        }
#endif
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_GetReceiveStatus
 * Description   : This function returns whether the previous LPUART receive is
 * complete. When performing a non-blocking receive, the user can call this
 * function to ascertain the state of the current receive progress: in progress
 * or complete. In addition, if the receive is still in progress, the user can
 * obtain the number of words that have been currently received.
 *
 * Implements    : Lpuart_Uart_Ip_GetReceiveStatus_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_GetReceiveStatus_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_GetReceiveStatus(const uint8 Instance, uint32 * BytesRemaining)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
    const Dma_Ip_LogicChannelInfoParamType DmaLogicChnParam = DMA_IP_CH_GET_CURRENT_ITER_COUNT;
#endif
    UartState = (const Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);

    if (BytesRemaining != NULL_PTR)
    {
        if (UartState->IsRxBusy)
        {
            /* Fill in the bytes transferred. */
            if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
            {
                /* In interrupt-based communication, the remaining bytes are retrieved
                 * from the state structure
                 */
                *BytesRemaining = UartState->RxSize;
            }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
            else
            {
                /* In DMA-based communication, the remaining bytes are retrieved
                 * from the current DMA major loop count
                 */
                (void)Dma_Ip_GetLogicChannelParam(UartUserCfg->RxDMAChannel, DmaLogicChnParam, BytesRemaining);
            }
#endif
        }
        else
        {
            *BytesRemaining = 0;
        }
    }

    return UartState->ReceiveStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_AbortReceivingData
 * Description   : Terminates a non-blocking receive early.
 *
 * Implements    : Lpuart_Uart_Ip_AbortReceivingData_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_AbortReceivingData_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AbortReceivingData(const uint8 Instance)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);

    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(UartUserCfg != NULL_PTR);
    boolean IsReturn = FALSE;
    Lpuart_Uart_Ip_StatusType RetVal = LPUART_UART_IP_STATUS_ERROR;

    /* Check if a transfer is running. */
    if (!UartState->IsRxBusy)
    {
        RetVal = LPUART_UART_IP_STATUS_SUCCESS;
        IsReturn = TRUE;
    }

    if (!IsReturn)
    {
        /* Update the rx status */
        UartState->ReceiveStatus = LPUART_UART_IP_STATUS_ABORTED;

        /* Stop the running transfer. */
        if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
        {
            Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(Instance);
        }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
        else
        {
            /* Release the DMA channel */
            (void)Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
            Lpuart_Uart_Ip_CompleteReceiveUsingDma(Instance);
        }
#endif
        /* Clear all the error flags */
        Lpuart_Uart_Ip_ClearErrorFlags(Base);
        /* Flush the Rx Buffer */
        Lpuart_Uart_Ip_FlushRxBuffer(Base);
        RetVal = LPUART_UART_IP_STATUS_SUCCESS;
    }
    return RetVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SetBaudRate
 * Description   : Configures the LPUART baud rate.
 * In some LPUART instances the user must disable the transmitter/receiver
 * before calling this function.
 * Generally, this may be applied to all LPUARTs to ensure safe operation.
 *
 * Implements    : Lpuart_Uart_Ip_SetBaudRate_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_SetBaudRate_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetBaudRate(const uint8 Instance,
                                                     const Lpuart_Uart_Ip_BaudrateType DesiredBaudrate,
                                                     const uint32 ClockFrequency)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);

    uint16 Sbr;
    uint16 Idx;
    uint16 SbrTemp;
    uint32 Osr;
    uint32 TempDiff;
    uint32 CalculatedBaud;
    uint32 BaudDiff;
    uint32 MaxOsr;
    uint32 ExpectedBaud = (uint32)DesiredBaudrate;
    LPUART_Type * Base = Lpuart_Uart_Ip_apBases[Instance];
    Lpuart_Uart_Ip_StateStructureType * UartState;
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    Lpuart_Uart_Ip_StatusType Status = LPUART_UART_IP_STATUS_ERROR;

    LPUART_UART_IP_DEV_ASSERT(UartState != NULL_PTR);

    if ((TRUE == UartState->IsTxBusy) || (TRUE == UartState->IsRxBusy))
    {
        Status = LPUART_UART_IP_STATUS_BUSY;
    }
    else
    {
        /* Check if current instance is clock gated off. */
        LPUART_UART_IP_DEV_ASSERT(ClockFrequency > 0U);
        /* Check if the desired baud rate can be configured with the current protocol clock. */
        LPUART_UART_IP_DEV_ASSERT(ClockFrequency >= (ExpectedBaud * 5U));

        /* This lpuart instantiation uses a slightly different baud rate calculation
         * The idea is to use the best OSR (over-sampling rate) possible
         * Note, Osr is typically hard-set to 16 in other lpuart instantiations
         * First calculate the baud rate using the minimum OSR possible (4) */
        Osr = 4;
        Sbr = (uint16)(ClockFrequency / (ExpectedBaud * Osr));
        CalculatedBaud = (ClockFrequency / ((uint32)Osr * (uint32)Sbr));
        if (CalculatedBaud > ExpectedBaud)
        {
            BaudDiff = CalculatedBaud - ExpectedBaud;
        }
        else
        {
            BaudDiff = ExpectedBaud - CalculatedBaud;
        }
        /* find maximum Osr */
        MaxOsr = ClockFrequency / ExpectedBaud;
        if (MaxOsr > 32U)
        {
            MaxOsr = 32U;
        }
        /* loop to find the best Osr value possible, one that generates minimum BaudDiff
         * iterate through the rest of the supported values of Osr */
        if (MaxOsr >= 5U)
        {
            for (Idx = 5U; Idx <= MaxOsr; Idx++)
            {
                /* calculate the temporary Sbr value   */
                SbrTemp = (uint16)(ClockFrequency / (ExpectedBaud * Idx));
                /* calculate the baud rate based on the temporary Osr and Sbr values */
                CalculatedBaud = (ClockFrequency / ((uint32)Idx * (uint32)SbrTemp));

                if (CalculatedBaud > ExpectedBaud)
                {
                    TempDiff = CalculatedBaud - ExpectedBaud;
                }
                else
                {
                    TempDiff = ExpectedBaud - CalculatedBaud;
                }

                if (TempDiff <= BaudDiff)
                {
                    BaudDiff = TempDiff;
                    Osr = Idx;  /* update and store the best Osr value calculated */
                    Sbr = SbrTemp;  /* update store the best Sbr value calculated */
                }
            }
        }
        /* Check if Osr is between 4x and 7x oversampling.
         * If so, then "BOTHEDGE" sampling must be turned on */
        if (Osr < 8U)
        {
            Lpuart_Uart_Ip_EnableBothEdgeSamplingCmd(Base);
        }

        /* program the Osr value (bit value is one less than actual value) */
        Lpuart_Uart_Ip_SetOversamplingRatio(Base, (Osr - 1U));

        /* write the Sbr value to the BAUD registers */
        Lpuart_Uart_Ip_SetBaudRateDivisor(Base, Sbr);

        UartState->BaudRate = CalculatedBaud;

        Status = LPUART_UART_IP_STATUS_SUCCESS;
    }
    return Status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_GetBaudRate
 * Description   : Returns the LPUART configured baud rate.
 *
 * Implements    : Lpuart_Uart_Ip_GetBaudRate_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_GetBaudRate_Activity*/
void Lpuart_Uart_Ip_GetBaudRate(const uint8 Instance, uint32 * ConfiguredBaudRate)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(ConfiguredBaudRate != NULL_PTR);
    const Lpuart_Uart_Ip_StateStructureType * UartState;

    UartState = (const Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    *ConfiguredBaudRate = UartState->BaudRate;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SetTxBuffer
 * Description   : Sets the driver internal reference to the tx buffer.
 *                 Can be called from the tx callback to provide a different
 *                 buffer for continuous transmission.
 *
 * Implements    : Lpuart_Uart_Ip_SetTxBuffer_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_SetTxBuffer_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetTxBuffer(const uint8 Instance,
                                                     const uint8 * TxBuff,
                                                     const uint32 TxSize)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(TxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(TxSize > 0U);
    Lpuart_Uart_Ip_StateStructureType * UartState;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    UartState->TxBuff = TxBuff;
    UartState->TxSize = TxSize;

    return LPUART_UART_IP_STATUS_SUCCESS;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SetRxBuffer
 * Description   : Sets the driver internal reference to the rx buffer.
 *                 Can be called from the rx callback to provide a different
 *                 buffer for continuous reception.
 *
 * Implements    : Lpuart_Uart_Ip_SetRxBuffer_Activity
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_SetRxBuffer_Activity*/
Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetRxBuffer(const uint8 Instance,
                                                     uint8 * RxBuff,
                                                     const uint32 RxSize)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);
    LPUART_UART_IP_DEV_ASSERT(RxBuff != NULL_PTR);
    LPUART_UART_IP_DEV_ASSERT(RxSize > 0U);
    Lpuart_Uart_Ip_StateStructureType * UartState;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartState->RxBuff = RxBuff;
    UartState->RxSize = RxSize;

    return LPUART_UART_IP_STATUS_SUCCESS;
}

//zhengchao
static void Lpuart_Uart_Ip_RxIdleIrqHandler(uint32 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;

    LPUART_Type * Base;

    Base = Lpuart_Uart_Ip_apBases[Instance];

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[Instance];

//    /* Disable receive idle interrupt. */
//    Lpuart_Uart_Ip_SetIntMode(Base, (uint32)LPUART_CTRL_ILIE_SHIFT, FALSE);
    /* Clear idle flag*/
    Base->STAT |= LPUART_STAT_IDLE(0);

    /* Invoke callback if there is one */

    if (UartUserCfg->Callback != NULL_PTR)
    {
    	UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_RECV_IDLE,UartUserCfg->CallbackParam);
    }
    UartState->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;
    //Dio_WriteChannel(DioConf_DioChannel_PTE1_GPIO_OUT_MCU_LED2,STD_ON);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_IrqHandler
 * Description   : Interrupt handler for LPUART.
 * This handler uses the buffers stored in the Lpuart_Uart_Ip_StateStructureType structs to transfer
 * data. This is not a public API as it is called by IRQ whenever an interrupt
 * occurs.
 *
 *END**************************************************************************/
/* implements     Lpuart_Uart_Ip_IrqHandler_Activity*/
void Lpuart_Uart_Ip_IrqHandler(const uint8 Instance)
{
    LPUART_UART_IP_DEV_ASSERT(Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES);

    LPUART_Type * Base;
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (const Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    boolean IsReturn = FALSE;

    /* Case of spurious interrupt when driver is not at all initialized or it is not in transmit/receive process*/
    if (NULL_PTR == UartState)
    {
        /* Read dummy to clear RDRF flag if it is set*/
        (void)Lpuart_Uart_Ip_Getchar(Base);
        /* Clear all the error flags */
        Lpuart_Uart_Ip_ClearErrorFlags(Base);
        /* Transmit flags can not be cleared, return to exit */
    }
    else
    {
        Lpuart_Uart_Ip_ErrIrqHandler(Instance);
        /* Handle receive data full interrupt */
        if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_DATA_REG_FULL))
        {
            if (Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_RX_DATA_REG_FULL))
            {
                Lpuart_Uart_Ip_RxIrqHandler(Instance);
            }
            /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */
            else
            {
                /* Read dummy to clear RDRF flag */
                (void)Lpuart_Uart_Ip_Getchar(Base);
            }
            IsReturn = TRUE;
        }
        /* Handle transmitter data register empty interrupt */
        if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_DATA_REG_EMPTY) && (FALSE == IsReturn))
        {
            if (Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY))
            {
                Lpuart_Uart_Ip_TxEmptyIrqHandler(Instance);
                IsReturn = TRUE;
            }
            /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */
            else
            {
                /* Do nothing, because TDRE can not clear without affecting to normal operation*/
            }
        }
        /* Handle transmission complete interrupt */
        if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_COMPLETE) && (FALSE == IsReturn))
        {
            if (Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_TX_COMPLETE))
            {
                Lpuart_Uart_Ip_TxCompleteIrqHandler(Instance);
            }
            /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */
            else
            {
                /* Do nothing, because TC can not clear without affecting to normal operation*/
            }
        }

        /*Handle receiving data idle interrupt*///zhengchao
		if (Lpuart_Uart_Ip_GetStatusFlag(Base, (uint32)LPUART_UART_IP_IDLE) && (FALSE == IsReturn))
		{
			if (Lpuart_Uart_Ip_GetIntMode(Base, (uint32)LPUART_UART_IP_IDLE))
			{
//				Dio_WriteChannel(DioConf_DioChannel_PTE0_GPIO_OUT_MCU_LED1,STD_OFF);
				Lpuart_Uart_Ip_RxIdleIrqHandler(Instance);
//				Dio_WriteChannel(DioConf_DioChannel_PTE0_GPIO_OUT_MCU_LED1,STD_ON);
				//return;
			}
			else
			{
				/* Do nothing*/
			}
		}
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_RxIrqHandler
 * Description   : Rx Interrupt handler for LPUART.
 * This function treats the rx full interrupt.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_RxIrqHandler(const uint8 Instance)
{
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Get data and put in receive buffer  */
    Lpuart_Uart_Ip_GetData(Instance);

    /* Check if this was the last byte in the current buffer */
    if (0U == UartState->RxSize)
    {
        /* Invoke callback if there is one (callback may reset the rx buffer for continuous reception) */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_RX_FULL, UartUserCfg->CallbackParam);
        }
    }

    /* Finish reception if this was the last byte received */
    if (0U == UartState->RxSize)
    {
        /* Complete transfer (disable rx logic) */
        Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(Instance);

        /* Invoke callback if there is one */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_END_TRANSFER, UartUserCfg->CallbackParam);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_TxEmptyIrqHandler
 * Description   : Tx Empty Interrupt handler for LPUART.
 * This function treats the tx empty interrupt.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_TxEmptyIrqHandler(const uint8 Instance)
{
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Check if there are any more bytes to send */
    if (UartState->TxSize > 0U)
    {
        /* Transmit the data */
        Lpuart_Uart_Ip_PutData(Instance);

        /* Check if this was the last byte in the current buffer */
        if ((0U == UartState->TxSize) && (UartUserCfg->Callback != NULL_PTR))
        {
            /* Invoke callback if there is one (callback may reset the tx buffer for continuous transmission)*/
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_TX_EMPTY, UartUserCfg->CallbackParam);
        }
        /* If there's no new data, disable tx empty interrupt and enable transmission complete interrupt */
        if (0U == UartState->TxSize)
        {
            Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE);
            Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_COMPLETE, TRUE);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_TxCompleteIrqHandler
 * Description   : Tx Complete Interrupt handler for LPUART.
 * This function treats the tx complete interrupt.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_TxCompleteIrqHandler(const uint8 Instance)
{
    const Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;

    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    if (0U == UartState->TxSize)
    {
        if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
        {
            /* Complete the interrupt based transfer */
            Lpuart_Uart_Ip_CompleteSendDataUsingInt(Instance);
        }
        /* Invoke callback if there is one */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_END_TRANSFER, UartUserCfg->CallbackParam);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_ErrIrqHandler
 * Description   : Error Interrupt handler for LPUART.
 * This function treats the error interrupts.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_ErrIrqHandler(const uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    boolean IsError = FALSE;
    boolean IsReturn = FALSE;
    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Handle receive overrun interrupt */
    if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_RX_OVERRUN))
    {
        /* Clear the flag */
        Lpuart_Uart_Ip_ClearStatusFlag(Base, LPUART_UART_IP_RX_OVERRUN);
        /* Case of spurious interrupt when interrupt enable bit is not set*/
        if (!Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_RX_OVERRUN))
        {
            IsReturn = TRUE;
        }
        else
        {
            /* Update the status */
            IsError = TRUE;
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_RX_OVERRUN;
        }
    }
    /* Handle framing error interrupt */
    if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_FRAME_ERR) && (FALSE == IsReturn))
    {
        /* Clear the flag */
        Lpuart_Uart_Ip_ClearStatusFlag(Base, LPUART_UART_IP_FRAME_ERR);
        /* Case of spurious interrupt when interrupt enable bit is not set*/
        if (!Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_FRAME_ERR_FLAG))
        {
            IsReturn = TRUE;
        }
        else
        {
            /* Update the status */
            IsError = TRUE;
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_FRAMING_ERROR;
        }
    }
    /* Handle parity error interrupt */
    if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_PARITY_ERR) && (FALSE == IsReturn))
    {
        /* Clear the flag */
        Lpuart_Uart_Ip_ClearStatusFlag(Base, LPUART_UART_IP_PARITY_ERR);
        /* Case of spurious interrupt when interrupt enable bit is not set*/
        if (!Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_PARITY_ERR_FLAG))
        {
            IsReturn = TRUE;
        }
        else
        {
            /* Update the status */
            IsError = TRUE;
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_PARITY_ERROR;
        }
    }
    /* Handle noise error interrupt */
    if (Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_NOISE_DETECT) && (FALSE == IsReturn))
    {
        /* Clear the flag */
        Lpuart_Uart_Ip_ClearStatusFlag(Base, LPUART_UART_IP_NOISE_DETECT);
        /* Case of spurious interrupt when interrupt enable bit is not set*/
        if (!Lpuart_Uart_Ip_GetIntMode(Base, LPUART_UART_IP_INT_NOISE_ERR_FLAG))
        {
            IsReturn = TRUE;
        }
        else
        {
            /* Update the internal status */
            IsError = TRUE;
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_NOISE_ERROR;
        }
    }
    if (FALSE == IsReturn)
    {
        if (TRUE == IsError)
        {
            if (LPUART_UART_IP_USING_INTERRUPTS == UartUserCfg->TransferType)
            {
                /* Complete the transfer (disable rx logic) */
                Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(Instance);
            }
#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
            else
            {
                /* Complete the transfer (stop DMA channel) */
                (void)Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
                Lpuart_Uart_Ip_CompleteReceiveUsingDma(Instance);
            }
#endif
            /* Invoke callback if there is one */
            if (UartUserCfg->Callback != NULL_PTR)
            {
                UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_ERROR, UartUserCfg->CallbackParam);
            }
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_StartSendDataUsingInt
 * Description   : Initiate (start) a transmit by beginning the process of
 * sending data and enabling the interrupt.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingInt(const uint8 Instance,
                                                                      const uint8 * TxBuff,
                                                                      const uint32 TxSize)
{
    LPUART_Type * Base;
    Lpuart_Uart_Ip_StateStructureType * UartState;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    /* initialize the module driver state structure */
    UartState->TxBuff = TxBuff;
    UartState->TxSize = TxSize;
    UartState->TransmitStatus = LPUART_UART_IP_STATUS_BUSY;

    /* Enable the LPUART transmitter */
    Lpuart_Uart_Ip_SetTransmitterCmd(Base, TRUE);

    /* Enable tx empty interrupt */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, TRUE);

    return LPUART_UART_IP_STATUS_SUCCESS;
}

#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_StartSendDataUsingDma
 * Description   : Initiate (start) a transmit by beginning the process of
 * sending data using DMA transfers.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingDma(const uint8 Instance,
                                                                      const uint8 * TxBuff,
                                                                      const uint32 TxSize)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    Dma_Ip_LogicChannelTransferListType DmaTransferList[LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION];
    Dma_Ip_ReturnType DmaReturnStatus;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Set up parameters for Dma_Ip_LogicChannelTransferListType */
    DmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    DmaTransferList[0].Value = (uint32)TxBuff;
    DmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    DmaTransferList[1].Value = LPUART_UART_IP_LSBW_ADDR(Base->DATA);
    DmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    DmaTransferList[2].Value = 1;
    DmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    DmaTransferList[3].Value = 0;
    DmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    DmaTransferList[4].Value = TxSize;
    DmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    DmaTransferList[5].Value = 1;
    DmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    DmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    DmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    DmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    DmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
    DmaTransferList[8].Value = 1;
    DmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
    DmaTransferList[9].Value = 1;

    /* Update state structure */
    UartState->TxBuff = TxBuff;
    UartState->TxSize = 0U;
    UartState->TransmitStatus = LPUART_UART_IP_STATUS_BUSY;

    /* Configure the transfer control descriptor for the DMA channel */
    DmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(UartUserCfg->TxDMAChannel, DmaTransferList, LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION);
    LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);

    /* Start the DMA channel */
    DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->TxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
    LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
    /* Enable the LPUART transmitter */
    Lpuart_Uart_Ip_SetTransmitterCmd(Base, TRUE);

    /* Enable tx DMA requests for the current instance */
    Lpuart_Uart_Ip_SetTxDmaCmd(Base, TRUE);

    return LPUART_UART_IP_STATUS_SUCCESS;
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_CompleteSendDataUsingInt
 * Description   : Finish up a transmit by completing the process of sending
 * data and disabling the interrupt.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_CompleteSendDataUsingInt(const uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    LPUART_Type * Base;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    if (LPUART_UART_IP_STATUS_BUSY != UartState->TransmitStatus)
    {
        /* If the transfer is aborted or timed out, disable tx empty interrupt */
        Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE);
    }

    /* Disable transmission complete interrupt */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_TX_COMPLETE, FALSE);

    Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, LPUART_UART_IP_TIMEOUT_VALUE_US, LPUART_UART_IP_TIMEOUT_TYPE);
    /* Wait until the data is completely shifted out of shift register */
    while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_COMPLETE) && \
           !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
    {}

    if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
    {
        /* In case timeout occur */
        UartState->TransmitStatus = LPUART_UART_IP_STATUS_ERROR;
    }
    /* Disable transmitter */
    Lpuart_Uart_Ip_SetTransmitterCmd(Base, FALSE);

    if (LPUART_UART_IP_STATUS_BUSY == UartState->TransmitStatus)
    {
        /* If the transfer is completed, update the transmit status */
        UartState->TransmitStatus = LPUART_UART_IP_STATUS_SUCCESS;
    }

    /* Update the internal busy flag */
    UartState->IsTxBusy = FALSE;
}

#if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON)

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_CompleteSendUsingDma
 * Description   : Finish up a transmit by completing the process of sending
 * data and disabling the DMA requests. This is a callback for DMA major loop
 * completion, so it must match the DMA callback signature.
 *
 *END**************************************************************************/
void Lpuart_Uart_Ip_CompleteSendUsingDma(uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    Dma_Ip_LogicChannelTransferListType DmaTransferList[LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION];
    Dma_Ip_ReturnType DmaReturnStatus;
    Dma_Ip_LogicChannelStatusType DmaStatus;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Get Dma Ip Logic Channel Status */
    (void)Dma_Ip_GetLogicChannelStatus(UartUserCfg->TxDMAChannel, &DmaStatus);
    if (DMA_IP_CH_ERROR_STATE == DmaStatus.ChStateValue)
    {
        /* Reset the Dma Channel Error status. */
        DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->TxDMAChannel, DMA_IP_CH_CLEAR_ERROR);

        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
        /* Update transmit status */
        UartState->TransmitStatus = LPUART_UART_IP_STATUS_ERROR;
        /* Invoke callback if there is one */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_ERROR, UartUserCfg->CallbackParam);
        }
    }

    /* Invoke the callback when the buffer is finished;
     * Application can provide another buffer inside the callback by calling Lpuart_Uart_Ip_SetTxBuffer */
    if (LPUART_UART_IP_STATUS_BUSY == UartState->TransmitStatus)
    {
        /* Invoke callback if there is one (callback may reset the tx buffer for continuous transmission)*/
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_TX_EMPTY, UartUserCfg->CallbackParam);
        }
    }

    /* If the callback has updated the tx buffer, update the DMA descriptor to continue the transfer;
     * otherwise, stop the current transfer.
     */
    if ((UartState->TxSize > 0U) && (UartState->TransmitStatus != LPUART_UART_IP_STATUS_ERROR))
    {
        /* Set up parameters for Dma_Ip_LogicChannelTransferListType */
        DmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
        DmaTransferList[0].Value = (uint32)(UartState->TxBuff);
        /* Update tx size and major loop count parameters for Dma_Ip_LogicChannelTransferListType */
        DmaTransferList[1].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
        DmaTransferList[1].Value = UartState->TxSize;

        /* Re-configure the transfer control descriptor for the DMA channel */
        DmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(UartUserCfg->TxDMAChannel, DmaTransferList, LPUART_UART_IP_DMA_LEAST_CONFIG_LIST_DIMENSION);
        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);

        /* Now that this tx is set up, clear remaining bytes count */
        UartState->TxSize = 0U;

        /* Re-start the channel */
        DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->TxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
    }
    else
    {
        /* Disable tx DMA requests for the current instance */
        Lpuart_Uart_Ip_SetTxDmaCmd(Base, FALSE);

        /* Wait until the last transmission complete */
        Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, LPUART_UART_IP_TIMEOUT_VALUE_US, LPUART_UART_IP_TIMEOUT_TYPE);
        while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_TX_COMPLETE) && \
           !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {}

        if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
            /* In case timeout occur */
            UartState->TransmitStatus = LPUART_UART_IP_STATUS_ERROR;
        }

        /* Disable the transmitter */
        Lpuart_Uart_Ip_SetTransmitterCmd(Base, FALSE);

        if (LPUART_UART_IP_STATUS_BUSY == UartState->TransmitStatus)
        {
            /* If the transfer is completed, update the transmit status */
            UartState->TransmitStatus = LPUART_UART_IP_STATUS_SUCCESS;
            /* Invoke callback if there is one */
            if (UartUserCfg->Callback != NULL_PTR)
            {
                UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_END_TRANSFER, UartUserCfg->CallbackParam);
            }
        }

        /* Update the busy flag */
        UartState->IsTxBusy = FALSE;
    }
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_StartReceiveDataUsingInt
 * Description   : Initiate (start) a receive by beginning the process of
 * receiving data and enabling the interrupt.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingInt(const uint8 Instance,
                                                                         uint8 * RxBuff,
                                                                         const uint32 RxSize)
{
    LPUART_Type * Base;
    Lpuart_Uart_Ip_StateStructureType * UartState;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    /* Initialize the module driver state struct to indicate transfer in progress
     * and with the buffer and byte count data. */
    UartState->IsRxBusy = TRUE;
    UartState->RxBuff = RxBuff;
    UartState->RxSize = RxSize;
    UartState->ReceiveStatus = LPUART_UART_IP_STATUS_BUSY;

    /* Clear all the error flags */
    Lpuart_Uart_Ip_ClearErrorFlags(Base);
    /* Flush the Tx Buffer */
    Lpuart_Uart_Ip_FlushRxBuffer(Base);

    /* Enable the receiver */
    Lpuart_Uart_Ip_SetReceiverCmd(Base, TRUE);

    /* Enable error interrupts */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_OVERRUN, TRUE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_PARITY_ERR_FLAG, TRUE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_NOISE_ERR_FLAG, TRUE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_FRAME_ERR_FLAG, TRUE);

    /* Enable receive data full interrupt */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_DATA_REG_FULL, TRUE);

    return LPUART_UART_IP_STATUS_SUCCESS;
}

#if (STD_ON == LPUART_UART_IP_HAS_DMA_ENABLED)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_StartReceiveDataUsingDma
 * Description   : Initiate (start) a receive by beginning the process of
 * receiving data using DMA transfers.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingDma(const uint8 Instance,
                                                                         uint8 * RxBuff,
                                                                         const uint32 RxSize)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    Dma_Ip_LogicChannelTransferListType DmaTransferList[LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION];
    Dma_Ip_ReturnType DmaReturnStatus;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Clear all the error flags */
    Lpuart_Uart_Ip_ClearErrorFlags(Base);
    /* Flush the Tx Buffer */
    Lpuart_Uart_Ip_FlushRxBuffer(Base);

    /* Set up parameters for Dma_Ip_LogicChannelTransferListType */
    DmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    DmaTransferList[0].Value = LPUART_UART_IP_LSBW_ADDR(Base->DATA);
    DmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    DmaTransferList[1].Value = (uint32)RxBuff;
    DmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    DmaTransferList[2].Value = 0;
    DmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    DmaTransferList[3].Value = 1;
    DmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    DmaTransferList[4].Value = RxSize;
    DmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    DmaTransferList[5].Value = 1;
    DmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    DmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    DmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    DmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    DmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
    DmaTransferList[8].Value = 1;
    DmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
    DmaTransferList[9].Value = 1;

    /* Update the state structure */
    UartState->RxBuff = RxBuff;
    UartState->RxSize = 0U;
    UartState->IsRxBusy = TRUE;
    UartState->ReceiveStatus = LPUART_UART_IP_STATUS_BUSY;

    /* Configure the transfer control descriptor for the DMA channel */
    DmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(UartUserCfg->RxDMAChannel, DmaTransferList, LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION);
    LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);

    /* Start the DMA channel */
    DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
    LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);

    /* Enable the receiver */
    Lpuart_Uart_Ip_SetReceiverCmd(Base, TRUE);
    /* Enable error interrupts and enable rx DMA requests for the current instance */
    Lpuart_Uart_Ip_SetupIntDmaMode(Instance, TRUE);

    return LPUART_UART_IP_STATUS_SUCCESS;
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_CompleteReceiveDataUsingInt
 * Description   : Finish up a receive by completing the process of receiving data
 * and disabling the interrupt.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(const uint8 Instance)
{
    LPUART_Type * Base;
    Lpuart_Uart_Ip_StateStructureType * UartState;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];

    /* Disable all error interrupts */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_OVERRUN, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_PARITY_ERR_FLAG, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_NOISE_ERR_FLAG, FALSE);
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_FRAME_ERR_FLAG, FALSE);

    /* Disable receive data full and rx overrun interrupt. */
    Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE);

    /* In Abort case, the transmission need to stop instantly */
    if (UartState->ReceiveStatus == LPUART_UART_IP_STATUS_ABORTED)
    {
        Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, LPUART_UART_IP_TIMEOUT_VALUE_US/10, LPUART_UART_IP_TIMEOUT_TYPE);
        /* Wait until the data is completely received */
        while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_DATA_REG_FULL) && \
               !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {}

        if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
        {
          /* In case timeout occur */
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_ERROR;
        }
    }

    /* Disable receiver */
    Lpuart_Uart_Ip_SetReceiverCmd(Base, FALSE);

    /* Read dummy to clear RDRF flag */
    (void)Lpuart_Uart_Ip_Getchar(Base);

    /* Update the information of the module driver state */
    UartState->IsRxBusy = FALSE;

    if (LPUART_UART_IP_STATUS_BUSY == UartState->ReceiveStatus)
    {
        UartState->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;
    }
}

#if (STD_ON == LPUART_UART_IP_HAS_DMA_ENABLED)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_CompleteReceiveUsingDma
 * Description   : Finish up a receive by completing the process of receiving data
 * and disabling the DMA requests. This is a callback for DMA major loop
 * completion, so it must match the DMA callback signature.
 *
 *END**************************************************************************/
void Lpuart_Uart_Ip_CompleteReceiveUsingDma(uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    Dma_Ip_LogicChannelTransferListType DmaTransferList[LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION];
    Dma_Ip_ReturnType DmaReturnStatus;
    Dma_Ip_LogicChannelStatusType DmaStatus;
    uint32 StartTime;
    uint32 TimeoutTicks;
    uint32 ElapsedTicks = 0;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    /* Get Dma Ip Logic Channel Status */
    (void)Dma_Ip_GetLogicChannelStatus(UartUserCfg->RxDMAChannel, &DmaStatus);

    if (DMA_IP_CH_ERROR_STATE == DmaStatus.ChStateValue)
    {
        /* Reset the Dma Channel Error status. */
        DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_CLEAR_ERROR);

        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
        /* Update transmit status */
        UartState->ReceiveStatus = LPUART_UART_IP_STATUS_ERROR;
        /* Invoke callback if there is one */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_ERROR, UartUserCfg->CallbackParam);
        }
    }

    /* Invoke the callback when the buffer is finished */
    if (LPUART_UART_IP_STATUS_BUSY == UartState->ReceiveStatus)
    {
        /* Application can provide another buffer inside the callback by calling Lpuart_Uart_Ip_SetRxBuffer */
        if (UartUserCfg->Callback != NULL_PTR)
        {
            UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_RX_FULL, UartUserCfg->CallbackParam);
        }
    }

    /* If the callback has updated the rx buffer, update the DMA descriptor to continue the transfer;
     * otherwise, stop the current transfer.
     */
    if ((UartState->RxSize > 0U) && (UartState->ReceiveStatus != LPUART_UART_IP_STATUS_ERROR))
    {
        /* Set up parameters for Dma_Ip_LogicChannelTransferListType */
        DmaTransferList[0].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
        DmaTransferList[0].Value = (uint32)(UartState->RxBuff);
        DmaTransferList[1].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
        DmaTransferList[1].Value = UartState->RxSize;

        /* Re-configure the transfer control descriptor for the DMA channel */
        DmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(UartUserCfg->RxDMAChannel, DmaTransferList, LPUART_UART_IP_DMA_LEAST_CONFIG_LIST_DIMENSION);
        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);

        /* Now that this rx is set up, clear remaining bytes count */
        UartState->RxSize = 0U;

        /* Re-start the channel */
        DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
        LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
    }
    else
    {
        /* Disable error interrupts and disable rx DMA requests for the current instance*/
        Lpuart_Uart_Ip_SetupIntDmaMode(Instance, FALSE);

        /* In Abort case, the transmission need to stop instantly */
        if (UartState->ReceiveStatus == LPUART_UART_IP_STATUS_ABORTED)
        {
            /* Wait until the last transmission complete */
            Lpuart_Uart_Ip_StartTimeout(&StartTime, &TimeoutTicks, LPUART_UART_IP_TIMEOUT_VALUE_US/10, LPUART_UART_IP_TIMEOUT_TYPE);
            while (!Lpuart_Uart_Ip_GetStatusFlag(Base, LPUART_UART_IP_DATA_REG_FULL) && \
               !Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
            {}
            if (Lpuart_Uart_Ip_CheckTimeout(&StartTime, &ElapsedTicks, TimeoutTicks, LPUART_UART_IP_TIMEOUT_TYPE))
            {
              /* In case timeout occur */
                UartState->ReceiveStatus = LPUART_UART_IP_STATUS_ERROR;
            }
        }

        /* Disable receiver */
        Lpuart_Uart_Ip_SetReceiverCmd(Base, FALSE);

        /* Read dummy to clear RDRF flag */
        (void)Lpuart_Uart_Ip_Getchar(Base);

        /* Update the information of the module driver state */
        UartState->IsRxBusy = FALSE;

        /* If the current reception hasn't been aborted, update the status and call the callback */
        if (LPUART_UART_IP_STATUS_BUSY == UartState->ReceiveStatus)
        {
            UartState->ReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS;

            /* Call the callback to notify application that the transfer is complete */
            if (UartUserCfg->Callback != NULL_PTR)
            {
                UartUserCfg->Callback(Instance, LPUART_UART_IP_EVENT_END_TRANSFER, UartUserCfg->CallbackParam);
            }
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_SetupIntDmaMode
 * Description   : Setup error interrupts and Setup rx DMA requests for
 * the current instance
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_SetupIntDmaMode(const uint8 Instance, boolean Enable)
{
      LPUART_Type * Base;
      Base = Lpuart_Uart_Ip_apBases[Instance];

      /* Setup error interrupts */
      Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_RX_OVERRUN, 0);
      Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_PARITY_ERR_FLAG, Enable);
      Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_NOISE_ERR_FLAG, Enable);
      Lpuart_Uart_Ip_SetIntMode(Base, LPUART_UART_IP_INT_FRAME_ERR_FLAG, Enable);
      /* Setup rx DMA requests for the current instance */
      Lpuart_Uart_Ip_SetRxDmaCmd(Base, Enable);
}

#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_PutData
 * Description   : Write data to the buffer register, according to configured
 * word length.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_PutData(const uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    LPUART_Type * Base;
    uint16 Data16b;
    uint8 Data8b;

    Base = Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    if ((LPUART_UART_IP_7_BITS_PER_CHAR == UartUserCfg->BitCountPerChar) || (LPUART_UART_IP_8_BITS_PER_CHAR == UartUserCfg->BitCountPerChar))
    {
        Data8b = *(UartState->TxBuff);
        /* Update the state structure */
        ++UartState->TxBuff;
        --UartState->TxSize;
        /* Transmit the data */
        Lpuart_Uart_Ip_Putchar(Base, Data8b);
    }
    else
    {
        Data16b = (uint16)(*UartState->TxBuff);
        /* Update the state structure */
        if (1U == UartState->TxSize)
        {
            ++UartState->TxBuff;
            --UartState->TxSize;
        }
        else
        {
            ++UartState->TxBuff;
            Data16b |= (uint16)(((uint16)(*UartState->TxBuff)) << 8U);

            ++UartState->TxBuff;
            UartState->TxSize -= 2U;
        }

        /* Transmit the data */
        if (LPUART_UART_IP_9_BITS_PER_CHAR == UartUserCfg->BitCountPerChar)
        {
            Lpuart_Uart_Ip_Putchar9(Base, Data16b);
        }
        else
        {
            Lpuart_Uart_Ip_Putchar10(Base, Data16b);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Uart_Ip_GetData
 * Description   : Read data from the buffer register, according to configured
 * word length.
 * This is not a public API as it is called from other driver functions.
 *
 *END**************************************************************************/
static void Lpuart_Uart_Ip_GetData(const uint8 Instance)
{
    Lpuart_Uart_Ip_StateStructureType * UartState;
    const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
    const LPUART_Type * Base;
    uint16 Data16b;

    Base = (const LPUART_Type *)Lpuart_Uart_Ip_apBases[Instance];
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
    UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];

    if ((LPUART_UART_IP_7_BITS_PER_CHAR == UartUserCfg->BitCountPerChar) || (LPUART_UART_IP_8_BITS_PER_CHAR == UartUserCfg->BitCountPerChar))
    {
        /* Receive the data */
        *(UartState->RxBuff) = Lpuart_Uart_Ip_Getchar(Base);
        if (LPUART_UART_IP_7_BITS_PER_CHAR == UartUserCfg->BitCountPerChar)
        {
            *(UartState->RxBuff) &= 0x7FU;
        }
        /* Update the state structure */
        ++UartState->RxBuff;
        --UartState->RxSize;
    }
    else
    {
        if (LPUART_UART_IP_9_BITS_PER_CHAR == UartUserCfg->BitCountPerChar)
        {
            Data16b = Lpuart_Uart_Ip_Getchar9(Base);
        }
        else
        {
            Data16b = Lpuart_Uart_Ip_Getchar10(Base);
        }
        /* Get the data and update state structure */
        if (1U == UartState->RxSize)
        {
            *(UartState->RxBuff) = (uint8)Data16b;
            ++UartState->RxBuff;
            --UartState->RxSize;
        }
        else
        {
            /* Write the least significant bits to the receive buffer */
            *(UartState->RxBuff) = (uint8)(Data16b & 0xFFU);
            ++UartState->RxBuff;
            /* Write the ninth bit to the subsequent byte in the rx buffer */
            *UartState->RxBuff = (uint8)(Data16b >> 8U);
            ++UartState->RxBuff;
            UartState->RxSize -= 2U;
        }
    }
}

#define UART_STOP_SEC_CODE
#include "Uart_MemMap.h"

#ifdef __cplusplus
}

/** @} */

#endif
