/*!
* @file     Lin_Hw.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Lin - USART.
*           File containing the low level driver of the USART IP.
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_01-Otc-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/


#ifdef __cplusplus
extern "C"{
#endif

#include "Usart_Reg.h"
#include "Lin.h"
#include "Lin_Hw.h"
#include "StdRegMacros.h"
#include "SchM_Lin.h"
#include "Mcu_RcmTypes.h"
#include "Mcu_RcmReg.h"
#include "modules.h"

#if (STD_ON == USART_MODULE_ENABLE)
#include "CDD_Usart.h"
#endif
/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup LIN_Driver
  * @brief LIN driver modules
  @{
*/

/** @defgroup LIN_Macros
  @{
*/
/*******************************************************************************
                     VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define LIN_HW_VENDOR_ID                         0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define LIN_HW_AR_RELEASE_MAJOR_VERSION          0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define LIN_HW_AR_RELEASE_MINOR_VERSION          0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define LIN_HW_AR_RELEASE_REVISION_VERSION       0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define LIN_HW_SW_MAJOR_VERSION                  0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define LIN_HW_SW_MINOR_VERSION                  0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define LIN_HW_SW_PATCH_VERSION                  0x00U
/**@} end of group LIN_Macros */
/*******************************************************************************
                             VERSION CHECK
*******************************************************************************/
/* Make sure the vendor ids are the same between Lin_USART.c and Lin.h */
#if (LIN_HW_VENDOR_ID != LIN_H_VENDOR_ID)
    #error "Vendor ids mismatch between Lin_USART.c and Lin.h"
#endif /* LIN_HW_VENDOR_ID != LIN_H_VENDOR_ID */

/* Make sure the vendor ids are the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_VENDOR_ID != USART_REG_H_VENDOR_ID)
    #error "Vendor ids mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* LIN_HW_VENDOR_ID != CDD_USART_H_VENDOR_ID */

/* Make sure the vendor ids are the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_VENDOR_ID != USART_REG_H_VENDOR_ID)
    #error "Vendor ids mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* LIN_HW_VENDOR_ID != USART_REG_H_VENDOR_ID */
 
/* Make sure the AUTOSAR major version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_AR_RELEASE_MAJOR_VERSION != LIN_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR major Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_AR_RELEASE_MAJOR_VERSION != LIN_H_AR_RELEASE_MAJOR_VERSION)} */ 
/* Make sure the AUTOSAR minor version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_AR_RELEASE_MINOR_VERSION != LIN_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR minor Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_AR_RELEASE_MINOR_VERSION != LIN_H_AR_RELEASE_MINOR_VERSION)} */  
/* Make sure the AUTOSAR revision version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_AR_RELEASE_REVISION_VERSION != LIN_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR revision Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_AR_RELEASE_REVISION_VERSION != LIN_H_AR_RELEASE_REVISION_VERSION)} */  

/* Make sure the software major version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_SW_MAJOR_VERSION != LIN_H_SW_MAJOR_VERSION)
    #error "Software major Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_SW_MAJOR_VERSION != LIN_H_SW_MAJOR_VERSION)} */
/* Make sure the software minor version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_SW_MINOR_VERSION != LIN_H_SW_MINOR_VERSION)
    #error "Software minor Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_SW_MINOR_VERSION != LIN_H_SW_MINOR_VERSION)} */
/* Make sure the software patch version number is the same between Lin_USART.c and Lin.h */
#if (LIN_HW_SW_PATCH_VERSION != LIN_H_SW_PATCH_VERSION)
    #error "Software patch Version Numbers mismatch between Lin_USART.c and Lin.h"
#endif /* {(LIN_HW_SW_PATCH_VERSION != LIN_H_SW_PATCH_VERSION)} */
  
/* Make sure the AUTOSAR major version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_MAJOR_VERSION != USART_REG_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR major Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_MAJOR_VERSION != CDD_USART_H_AR_RELEASE_MAJOR_VERSION)} */ 
/* Make sure the AUTOSAR minor version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_MINOR_VERSION != USART_REG_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR minor Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_MINOR_VERSION != USART_REG_H_AR_RELEASE_MINOR_VERSION)} */  
/* Make sure the AUTOSAR revision version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_REVISION_VERSION != USART_REG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR revision Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_REVISION_VERSION != CDD_USART_H_AR_RELEASE_REVISION_VERSION)} */

/* Make sure the software major version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_MAJOR_VERSION != USART_REG_H_SW_MAJOR_VERSION)
    #error "Software major Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_MAJOR_VERSION != CDD_USART_H_SW_MAJOR_VERSION)} */
/* Make sure the software minor version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_MINOR_VERSION != USART_REG_H_SW_MINOR_VERSION)
    #error "Software minor Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_MINOR_VERSION != CDD_USART_H_SW_MINOR_VERSION)} */
/* Make sure the software patch version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_PATCH_VERSION != USART_REG_H_SW_PATCH_VERSION)
    #error "Software patch Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_PATCH_VERSION != CDD_USART_H_SW_PATCH_VERSION)} */

/* Make sure the AUTOSAR major version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_MAJOR_VERSION != USART_REG_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR major Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_MAJOR_VERSION != USART_REG_H_AR_RELEASE_MAJOR_VERSION)} */ 
/* Make sure the AUTOSAR minor version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_MINOR_VERSION != USART_REG_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR minor Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_MINOR_VERSION != USART_REG_H_AR_RELEASE_MINOR_VERSION)} */  
/* Make sure the AUTOSAR revision version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_AR_RELEASE_REVISION_VERSION != USART_REG_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR revision Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_AR_RELEASE_REVISION_VERSION != USART_REG_H_AR_RELEASE_REVISION_VERSION)} */
  
/* Make sure the software major version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_MAJOR_VERSION != USART_REG_H_SW_MAJOR_VERSION)
    #error "Software major Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_MAJOR_VERSION != USART_REG_H_SW_MAJOR_VERSION)} */
/* Make sure the software minor version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_MINOR_VERSION != USART_REG_H_SW_MINOR_VERSION)
    #error "Software minor Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_MINOR_VERSION != USART_REG_H_SW_MINOR_VERSION)} */
/* Make sure the software patch version number is the same between Lin_USART.c and Usart_Reg.h */
#if (LIN_HW_SW_PATCH_VERSION != USART_REG_H_SW_PATCH_VERSION)
    #error "Software patch Version Numbers mismatch between Lin_USART.c and Usart_Reg.h"
#endif /* {(LIN_HW_SW_PATCH_VERSION != USART_REG_H_SW_PATCH_VERSION)} */

#ifdef ENABLE_INTERMODULE_MCAL_CHECK 
    /* Make sure the AUTOSAR major version number is the same between Lin_USART.c and StdRegMacros.h */
    #if (LIN_HW_AR_RELEASE_MAJOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major Version Numbers mismatch between Lin_USART.c and StdRegMacros.h"
    #endif /* {(LIN_HW_AR_RELEASE_MAJOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MAJOR_VERSION)} */ 
    /* Make sure the AUTOSAR minor version number is the same between Lin_USART.c and StdRegMacros.h */
    #if (LIN_HW_AR_RELEASE_MINOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor Version Numbers mismatch between Lin_USART.c and StdRegMacros.h"
    #endif /* {(LIN_HW_AR_RELEASE_MINOR_VERSION != STD_REG_MACROS_H_AR_RELEASE_MINOR_VERSION)} */  
  
    /* Make sure the AUTOSAR major version number is the same between Lin_USART.c and SchM_Lin.h */
    #if (LIN_HW_AR_RELEASE_MAJOR_VERSION != SCHM_LIN_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major Version Numbers mismatch between Lin_USART.c and SchM_Lin.h"
    #endif /* {(LIN_HW_AR_RELEASE_MAJOR_VERSION != SCHM_LIN_H_AR_RELEASE_MAJOR_VERSION)} */ 
    /* Make sure the AUTOSAR minor version number is the same between Lin_USART.c and SchM_Lin.h */
    #if (LIN_HW_AR_RELEASE_MINOR_VERSION != SCHM_LIN_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor Version Numbers mismatch between Lin_USART.c and SchM_Lin.h"
    #endif /* {(LIN_HW_AR_RELEASE_MINOR_VERSION != SCHM_LIN_H_AR_RELEASE_MINOR_VERSION)} */  
#endif

#if (USART_MODULE_ENABLE == STD_ON)
    #if ((defined USART1_ENABLE) && (defined LIN_USART1) && (USART1_ENABLE == STD_ON))
        #error "Running USART1 and LIN protocols concurrently on the same physical interface"
    #elif ((defined USART2_ENABLE) && (defined LIN_USART2) && (USART_ENABLE == STD_ON))
        #error "Running USART2 and LIN protocols concurrently on the same physical interface"
    #endif
#endif

/*******************************************************************************
                              LOCAL VARIABLE
*******************************************************************************/
/** @defgroup LIN_Variable
  @{
*/
#define LIN_START_SEC_VAR_NO_INIT_BOOLEAN
#include "Lin_MemMap.h"

/** Store the USART Checksum type */
static volatile VAR(boolean, LIN_VAR) g_LinStoreUsartChecksumType;

#define LIN_STOP_SEC_VAR_NO_INIT_BOOLEAN
#include "Lin_MemMap.h"

#define LIN_START_SEC_VAR_NO_INIT_8
#include "Lin_MemMap.h"

/** Store USART data for sending or receiving */
static volatile VAR(uint8, LIN_VAR) g_LinUsartDataBuffer[LIN_USART_MAX_COUNT][LIN_HW_MAXIMUM_BUFFER_LENGTH];
/** Points to the next byte in the USART buffer to send or receive */
static volatile VAR(uint8, LIN_VAR) g_LinUsartNextByteBufferPtr[LIN_USART_MAX_COUNT];
/** USART lndicates the actual size of the buffer */
static volatile VAR(uint8, LIN_VAR) g_LinUsartBufferLength[LIN_USART_MAX_COUNT];
static volatile VAR(uint8, LIN_VAR) g_LinUsartWakeupFlag[LIN_USART_MAX_COUNT];
volatile VAR(uint8, LIN_VAR) g_state;
volatile VAR(uint8, LIN_VAR) g_currentId;
volatile VAR(uint8, LIN_VAR) g_frameIndex;
volatile VAR(uint8, LIN_VAR) g_checkSum;
volatile VAR(uint16, LIN_VAR) g_idleTimeoutCnt; 
volatile VAR(uint16, LIN_VAR) g_respFrameTimeoutCnt;
P2VAR(uint8, AUTOMATIC, LIN_VAR) g_dataPtr;

#define LIN_STOP_SEC_VAR_NO_INIT_8
#include "Lin_MemMap.h"

#define LIN_START_SEC_VAR_INIT_8
#include "Lin_MemMap.h"

VAR(uint8, LIN_VAR) g_sendBuf[9] = {0,0,0,0,0,0,0,0,0 };
VAR(uint8, LIN_VAR) g_responseBuf[9] = {0,0,0,0,0,0,0,0,0 };
volatile VAR(uint8, LIN_VAR) g_cntByte=0;
volatile VAR(uint8, LIN_VAR) g_pid = 0x80;
volatile VAR(uint16, LIN_VAR) g_receiveOnceFlg = 0;
Lin_StateType g_linState = LIN_ERROR;

#define LIN_STOP_SEC_VAR_INIT_8
#include "Lin_MemMap.h"

/**@} end of group LIN_Variable */
/*******************************************************************************
                              LOCAL FUNCTION
*******************************************************************************/
/** @defgroup LIN_Fuctions
  @{
*/
#define LIN_START_SEC_CODE
#include "Lin_MemMap.h"
 
static FUNC (void, LIN_CODE) Lin_Hw_CopyRxData(CONST(uint8, AUTOMATIC) ChannelID, P2VAR(uint8, AUTOMATIC, LIN_APPL_DATA) linSduPointer);
static FUNC (void, LIN_CODE) Lin_Hw_PidCalculate(VAR(uint8, AUTOMATIC) ChannelID, VAR(uint8, AUTOMATIC) u8FrameID);
static FUNC (uint32, LIN_CODE) Lin_Hw_ChecksumCalculate(VAR(uint8, AUTOMATIC) ChannelID, VAR(Lin_FrameCsModelType, AUTOMATIC) checksumModel);
#ifdef LIN_MASTER_NODECFG
static FUNC (void, LIN_CODE) Lin_Hw_RxBuffFullIsrProcess(CONST(uint8, AUTOMATIC) usartChannelID, VAR(uint8, AUTOMATIC) logicChannelID);
static FUNC (void, LIN_CODE) Lin_Hw_IdleLineInterrupt_ProcessingCode(CONST(uint8, AUTOMATIC) usartChannelID, VAR(uint8, AUTOMATIC) logicChannelID);
LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_LinState_TxRxInterrupt (VAR(uint8, AUTOMATIC) Id,
                                                                 VAR(uint8, AUTOMATIC) ChanID,
                                                                 VAR(uint8, AUTOMATIC) LogicalChan);
static FUNC (void, LIN_CODE) Lin_Hw_SlaveResponseInterruptHandler(CONST(uint8, AUTOMATIC) usartChannelID, \
                                                                      CONST(uint8, AUTOMATIC) logicalChannelID, \
                                                                      CONST(uint32, AUTOMATIC) linDataReg);
#endif
static FUNC (Lin_StatusType, LIN_CODE) Lin_Hw_DataTranferGetStatus(CONST(uint8, AUTOMATIC) ChannelID, CONST(uint8, AUTOMATIC) linFrameError);
static FUNC (Lin_StatusType, LIN_CODE) Lin_Hw_HeaderTranferGetStatus(CONST(uint8, AUTOMATIC) ChannelID, CONST(uint8, AUTOMATIC) linFrameError);

LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_ClearTxRx(VAR(uint8, AUTOMATIC) ChanID);
LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_RxInterrupt(VAR(uint8, AUTOMATIC) ChanID,
                                                     VAR(boolean, AUTOMATIC) EnaInterrupt);
LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_EnaTxinterrupt(VAR(uint8, AUTOMATIC) ChanID);
LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_SetChanFrameState(VAR(uint8, AUTOMATIC) LogicalChannel,
                                                           VAR(uint8, AUTOMATIC) ChanID,
                                                           VAR(uint32, AUTOMATIC) RegMask,
                                                           VAR(Lin_InterruptErrorsType, AUTOMATIC) error);

#ifdef LIN_SLAVE_NODECFG
/*!
* @brief         Get the rx data
*
* @param[in]     Usart: point to physical address of Usart
*
* @retval        uint16
*
* @note          None
*/
static FUNC (uint16, LIN_CODE) Lin_Hw_GetRxData(VAR(uint8, AUTOMATIC) UsartId)
{
    VAR(uint16, AUTOMATIC) rxData = 0;
    rxData = (uint16_t)(REG_READ32(USART_RXDATA_REG_ADDR(UsartId)) & (uint16_t)0x01FF);
    return rxData;
}

/*!
* @brief         Set the tx data
*
* @param[in]     UsartId: Usart index
* @param[in]     Data: Data for send
*
* @retval        uint16
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_SetTxData(VAR(uint8, AUTOMATIC) UsartId,VAR(uint8, AUTOMATIC) Data)
{
    REG_WRITE32(USART_TXDATA_REG_ADDR(UsartId),Data);
}

/*!
* @brief         Frame Check
*
* @param[in]     Buffer: data for check
* @param[in]     Id: protect id
*
* @retval        uint8
*
* @note          None
*/
static FUNC (uint8, LIN_CODE) Lin_Hw_CheckSum(P2CONST(uint8, AUTOMATIC, LIN_APPL_CONST) Buffer, VAR(uint8, AUTOMATIC) Pid)
{
    VAR(uint8, AUTOMATIC) length = 0;
    VAR(uint16, AUTOMATIC) checkSum = 0;
    
    for(length = 0; length < 8U; length++)
    {
        checkSum += Buffer[length];
        if(checkSum > 0xFFu)
        {
            checkSum -= 0xFFu;
        }
        else
        {
            /* do nothing */
        }
    }
    
    if((Pid != 0x3Cu)&&(Pid != 0x7Du)) 
    {
        checkSum += Pid;
    }
    else
    {
        /* do nothing, the diagnostic frame adopts a classical checksum. */
    }
    if(checkSum > 0xFFu)
    {
        checkSum -= 0xFFu;
    }
    else
    {
        /* do nothing */
    }
    
    return (uint8)((~checkSum) & 0xFFu);
}

/*!
* @brief         PID Check and return current id
*
* @param[in]     Pid: protect id
*
* @retval        current id
*
* @note          None
*/
 static FUNC (uint8, LIN_CODE) Lin_Hw_ProcessParity(VAR(uint8, AUTOMATIC) Pid)
{
    VAR(uint8, AUTOMATIC) parity;
    VAR(uint8, AUTOMATIC) ret;

    parity =((uint8)((BITT(Pid, 0u)^BITT(Pid, 1u)^BITT(Pid, 2u)^BITT(Pid, 4u)) << 6u) |
            ((uint8)(~(BITT(Pid, 1u)^BITT(Pid, 3u)^BITT(Pid, 4u)^BITT(Pid, 5u))) << 7u));

    if((Pid & 0xC0u) != parity)
    {
        ret = 0xFFu;
    }
    else
    {
        ret = (uint8_t)(Pid & 0x3Fu); 
    }
    return (ret);  
}

/*!
* @brief         Check whether the received frame is a configured frame by verifying it against the configuration message table.
*
* @param[in]     Id: frame id
*
* @retval        current frame id
*
* @note          None
*/
 static FUNC (uint8, LIN_CODE) Lin_Hw_CheckUsedId(VAR(uint8, AUTOMATIC) Id)
{
    VAR(uint8, AUTOMATIC) i;
    VAR(uint8, AUTOMATIC) retId = 0xFF;
    for(i = 0; i < g_linMsgTblLen; i++)
    {
        if(g_linMsgCfgTable[i].id == Id)
        {
            retId = i;
            break;
        }
        else
        {
            /* do nothiing */
        }
    }
    return (retId);
}

/*!
* @brief         Write slave response data
*
* @param[in]     Ch: Send data
* @param[in]     UsartId: Usart index
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_PutChar(VAR(uint8, AUTOMATIC) Ch, VAR(uint8, AUTOMATIC) UsartId) 
{
    VAR(uint16, AUTOMATIC) cnt = 300;
    while(cnt > 0U) 
    {
        cnt--;
        if(USART_STS_TXBEFLG_MASK == (REG_READ32(USART_STS_REG_ADDR(UsartId)) & USART_STS_TXBEFLG_MASK))
        {
            Lin_Hw_SetTxData(UsartId,Ch);
            break;
        } 
        else
        {
            /* nothing */
        }
    }
}

/*!
* @brief         Process received pid event from master
*
* @param[in]     Pid: Received pid from master 
* @param[in]     UsartIdx: Usart index
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_ProcessPid(VAR(uint8, AUTOMATIC) Pid, VAR(uint8, AUTOMATIC) UsartIdx)
{
    VAR(Lin_ResponseType, AUTOMATIC) action = LIN_IDLE;
    /* get frame g_frameIndex */
    g_frameIndex = Lin_Hw_CheckUsedId(Pid);
    if (0xFFu == g_frameIndex)
    {
        action = LIN_IDLE;
    }
    else
    {
        /* allowing the application layer to perform special logic processing based on the PID */
        Lin_PidReceivedNotification(Pid, g_frameIndex);
        
        /* Determine the data transmission direction */
        if ((uint8)SLAVE_TO_MASTER == g_linMsgCfgTable[g_frameIndex].data_dir)
        {
            action = LIN_SET;
        }
        else if ((uint8)MASTER_TO_SLAVE == g_linMsgCfgTable[g_frameIndex].data_dir)
        {
            action = LIN_RECEIVE;
        }
        else
        {
            /* nothing */
        }
    }
    switch (action)
    {
        case LIN_RECEIVE:
             /* Receive response (Slave as Receiver) */
             g_cntByte = 0;
             g_dataPtr = g_responseBuf;
             g_state = RECV_DATA;
             break;
        case LIN_SET:
            /* Set response(Slave as Publisher) */
            g_cntByte = 1;

            /* Parse configuration or application layer data into the transmission buffer */
            Lin_GetTxDataNotification(g_frameIndex, g_sendBuf);
        
            /* Send First byte */
            Lin_Hw_PutChar(g_sendBuf[0], UsartIdx);
            /* Set LIN Status */
            g_state = SEND_DATA;
            break;
        default:
            g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
            g_state = IDLE;
            /* Clear the status and re-enable Break detection interrupt */
            REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(UsartIdx), USART_CTRL1_RXBNEIEN_MASK);
            REG_BIT_SET32(USART_INTFCLR_REG_ADDR(UsartIdx), USART_INTFCLR_LBDCLR_MASK);
            REG_BIT_SET32(USART_CTRL2_REG_ADDR(UsartIdx), USART_CTRL2_LBDIEN_MASK);
            break;
    }
}

#endif

/*!
* @brief         Copy the data received from the USART data registers to linSduPointer.
*
* @param[in]     ChannelID:     LIN channel ID
* @param[out]    linSduPointer: A Pointer to the receive buffer
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_CopyRxData(CONST(uint8, AUTOMATIC) ChannelID, P2VAR(uint8, AUTOMATIC, LIN_APPL_DATA) linSduPointer)
{
    VAR(uint8, AUTOMATIC) tempIndex = (uint8)0U;
    VAR(uint8, AUTOMATIC) bufferLength;

    bufferLength = (uint8)(g_LinUsartBufferLength[ChannelID] - (uint8)3U);
    
    while(tempIndex < bufferLength)
    {
        linSduPointer[tempIndex] = g_LinUsartDataBuffer[ChannelID][(uint8)USART_DATA_POSITION + tempIndex];
        tempIndex++;
    }
}

/*!
* @brief         Calculate the Protected Identifier based on the Frame ID.
*
* @param[in]     ChannelID:     LIN channel ID
*                u8FrameID:     Frame ID
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_PidCalculate(VAR(uint8, AUTOMATIC) ChannelID, VAR(uint8, AUTOMATIC) u8FrameID)
{
    VAR(uint32, AUTOMATIC) TempValue1;
    VAR(uint32, AUTOMATIC) TempValue2;

    TempValue1 = (uint32)(((uint32)u8FrameID) & (uint32)USART_FRAME_ID_MASK);
    TempValue2 = u8FrameID;
    /* Calculate the parity bit P1 = !(ID1 ^ ID3 ^ ID4 ^ ID5) */
    TempValue1 |= ((((TempValue2 >> 1) ^ (TempValue2 >> 3) ^ (TempValue2 >> 4) ^ (TempValue2 >> 5)) & 
                   ((uint32)1U)) ^ ((uint32)1U)) << (uint32)7U;
    /* Calculate the parity bit P0 = (ID0 ^ ID1 ^ ID2 ^ ID4) */
    TempValue1 |= (((TempValue2) ^ (TempValue2 >> 1U) ^ (TempValue2 >> 2U) ^ (TempValue2 >> 4U)) & 
                   ((uint32)1U)) << (uint32)6U;
    g_LinUsartDataBuffer[ChannelID][USART_PID_BYTE_POSITION] = (uint8)TempValue1;
}

/*!
* @brief         Calculate LIN Checksum.
*
* @param[in]     ChannelID:     LIN channel ID
*                checksumModel: check mode
*
* @retval        uint32
*
* @note          None
*/
static FUNC (uint32, LIN_CODE) Lin_Hw_ChecksumCalculate(VAR(uint8, AUTOMATIC) ChannelID, VAR(Lin_FrameCsModelType, AUTOMATIC) checksumModel)
{
    VAR(uint32, AUTOMATIC) checksum = (uint32)0U;
    VAR(uint32, AUTOMATIC) transfer = (uint32)0U;
    VAR(uint32, AUTOMATIC) dataLength = (uint32)0U;
    VAR(uint32, AUTOMATIC) dataIndex = (uint32)0U;

    dataLength = ((uint32)g_LinUsartBufferLength[ChannelID]) - ((uint32)3U);
    /* Enhanced Model */
    if(LIN_ENHANCED_CS == checksumModel)
    {
        checksum = (uint32)g_LinUsartDataBuffer[ChannelID][USART_PID_BYTE_POSITION];
    }
    else
    {
        /* nothing */
    }

    while(dataIndex < dataLength)
    {
        checksum += (uint32)g_LinUsartDataBuffer[ChannelID][(uint8)USART_DATA_POSITION + (uint8)dataIndex];
        transfer = checksum >> (uint32)8U;
        checksum = (checksum & ((uint32)0xFFU)) + transfer;
        dataIndex++;
    }

    checksum = (~(checksum)) & ((uint32)0xFFU);
    return checksum;
}

#ifdef LIN_MASTER_NODECFG
/*!
* @brief         Interrupt handler for an Idle line detected on USART.
*
* @param[in]     usartChannelID:     usart channel ID
*                logicChannelID:      logic Channel ID
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_IdleLineInterrupt_ProcessingCode(CONST(uint8, AUTOMATIC) usartChannelID, 
    VAR(uint8, AUTOMATIC) logicChannelID)
{
    VAR(uint8, AUTOMATIC) tempLogicalChannel = (uint8)logicChannelID;

    SchM_Enter_Lin_LIN_CRITICAL_SECTION20();
    {
        /* Clear the interrupt flag of an idle line */
        REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                   (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                   (~USART_INTFCLR_MASK)) | 
                   USART_INTFCLR_IDLECLR_MASK));
        /* Disable Idle Line Interruption */
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), 
                        USART_CTRL1_IDLEIEN_MASK);
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION20();
    /* Update Wake up Flag */
    g_LinUsartWakeupFlag[tempLogicalChannel] = (uint8)TRUE;
    /* Check whether the channel status of LIN is LIN_CH_SLEEP_STATE */
    if ((uint8)LIN_CH_SLEEP_STATE != g_LinChannelStatus[tempLogicalChannel])
    {
        /* nothing */
    }
    else
    {
        /* Clear data in the Rx buffer */
        REG_READ32(USART_RXDATA_REG_ADDR(usartChannelID));
        SchM_Enter_Lin_LIN_CRITICAL_SECTION21();
        {
            /* Clear Error Flag */
            REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                       (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                       (~USART_INTFCLR_MASK)) | 
                       USART_INTFCLR_ERR_FLAGS_MASK));
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION21();
         /* Check whether wakeup detection is enabled */
         if ((uint8)STD_ON != g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChWakeupEn)
         {
            /* nothing */
         }
         else
         {
            /* Indicates a valid timer wake up event to ECU Status manager */
            EcuM_CheckWakeup(g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChEcuMWakeupSrc);
            /* Reset the frame error status to LIN_NO_INT_ERROR */
            g_LinChannelFrameErrorStatus[tempLogicalChannel] = (uint8)LIN_NO_INT_ERROR;
            /* Change the LIN channel frame operation status to LIN_CHANNEL_READY_STATE */
            g_LinChannelFrameStatus[tempLogicalChannel] = (uint8)LIN_CHANNEL_READY_STATE;
            /* You cab set the channel status */
            g_LinChannelStatus[tempLogicalChannel] = (uint8)LIN_CH_OPERATIONAL;
         }
    }
}

/*!
* @brief         Interrupt handler for full RX Data Register on USART in slave response command
*
* @param[in]     usartChannelID:     usart channel ID
*                logicalChannelID:    logical channel ID
*                linDataReg:          Value of the data register
*
* @retval        void
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_SlaveResponseInterruptHandler(CONST(uint8, AUTOMATIC) usartChannelID, \
                                                                      CONST(uint8, AUTOMATIC) logicalChannelID, \
                                                                      CONST(uint32,AUTOMATIC) linDataReg)
{
    VAR(uint8, AUTOMATIC) linFrameID;
    VAR(uint8, AUTOMATIC) linCheckSum;
    VAR(uint8, AUTOMATIC) bufferLength;
    VAR(uint8, AUTOMATIC) nextByteBufferPtr;
    VAR(uint8, AUTOMATIC) tempValue1;

    bufferLength = g_LinUsartBufferLength[logicalChannelID];
    nextByteBufferPtr = g_LinUsartNextByteBufferPtr[logicalChannelID];
    /* Get the last TX byte */
    tempValue1 = g_LinUsartDataBuffer[logicalChannelID][nextByteBufferPtr];
    
    if((uint8)USART_PID_BYTE_POSITION < nextByteBufferPtr)
    {
        /* Store RX data */
        g_LinUsartDataBuffer[logicalChannelID][nextByteBufferPtr] = (uint8)(linDataReg & USART_RXDATA_RXDATA_MASK);
        /* Update LIN channel frame operation status to LIN_CHANNEL_RX_ONGOING_STATE */
        g_LinChannelFrameStatus[logicalChannelID] = (uint8)LIN_CHANNEL_RX_ONGOING_STATE;
        /* The last byte was received */
        if(nextByteBufferPtr != (bufferLength - (uint8)1U))
        {
            SchM_Enter_Lin_LIN_CRITICAL_SECTION18();
            {
                /* Enable RX Interrupt */
                REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXBNEIEN_MASK);
            }
            SchM_Exit_Lin_LIN_CRITICAL_SECTION18();
        }
        else
        {
            linFrameID = g_LinUsartDataBuffer[logicalChannelID][USART_PID_BYTE_POSITION];
            /* Checksum exist Error */
            if(linFrameID == (uint8)USART_SLAVE_RESPOND_DIAGNOSTIC_PID)
            {
                linCheckSum = (uint8)Lin_Hw_ChecksumCalculate(logicalChannelID, LIN_CLASSIC_CS);
            }
            else
            {
                if ((boolean)TRUE == g_LinStoreUsartChecksumType)
                {
                    /* The type is enhance checksum */
                    linCheckSum = (uint8)Lin_Hw_ChecksumCalculate(logicalChannelID, LIN_ENHANCED_CS);
                }
                else
                {
                    /* The type is classic checksum */
                    linCheckSum = (uint8)Lin_Hw_ChecksumCalculate(logicalChannelID, LIN_CLASSIC_CS);
                }
            }
            if(linCheckSum != (uint8)(linDataReg & USART_RXDATA_RXDATA_MASK))
            {
                /* Set LIN channel frame error status to LIN_CHECKSUM_INT_ERROR */
                g_LinChannelFrameErrorStatus[logicalChannelID] = (uint8)LIN_CHECKSUM_INT_ERROR;
            }
            else
            {
                /* Update LIN channel frame operation status to LIN_CHANNEL_RX_COMPLETE_STATE */
                g_LinChannelFrameStatus[logicalChannelID] = (uint8)LIN_CHANNEL_RX_COMPLETE_STATE;
            }
        }
    }
    else if(((uint8)(linDataReg & USART_RXDATA_RXDATA_MASK) != tempValue1) && ((uint8)USART_PID_BYTE_POSITION == nextByteBufferPtr))
    {
        /* Bit error */
        g_LinChannelFrameErrorStatus[logicalChannelID] = (uint8)LIN_BIT_INT_ERROR;
    }
    else if(USART_STS_NEFLG_MASK == (linDataReg & USART_STS_NEFLG_MASK))
    {
        /* Change the LIN channel frame error status to LIN_NOISE_INT_ERROR */
        g_LinChannelFrameErrorStatus[logicalChannelID] = (uint8)LIN_NOISE_INT_ERROR;
    }
    else
    {
        /* Update LIN channel frame operation status to LIN_CHANNEL_TX_HEADER_COMPLETE_STATE */
        g_LinChannelFrameStatus[logicalChannelID] = (uint8)LIN_CHANNEL_TX_HEADER_COMPLETE_STATE;
        SchM_Enter_Lin_LIN_CRITICAL_SECTION13();
        {
            /* Enable RX Interrupt */
            REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXBNEIEN_MASK);
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION13();
    }
}
#endif

/*!
* @brief         Gets the state of the LIN drive when the channel transfers data
*
* @param[in]     ChannelID:            LIN channel ID
*                linFrameError:        Frame transmission error status of the Lin Channel
*
* @retval        LIN_NOT_OK:           Development error,and not the following.
*                LIN_TX_OK:            transmission is OK.
*                LIN_TX_BUSY:          Ongoing transmission of header or response.
*                LIN_TX_ERROR:         An error occurred while sending the response.
*                LIN_RX_OK:            Reception response is OK.
*                LIN_RX_BUSY:          Ongoing reception where at least one byte has been received.
*                LIN_RX_ERROR:         Error occurred during reception.
*
* @note          None
*/
static FUNC (Lin_StatusType, LIN_CODE) Lin_Hw_DataTranferGetStatus(CONST(uint8, AUTOMATIC) ChannelID, CONST(uint8, AUTOMATIC) linFrameError)
{
    VAR(Lin_StatusType, AUTOMATIC) tempReturnVal = LIN_NOT_OK;
    VAR(uint8, AUTOMATIC) linChFrameState;
    VAR(uint8, AUTOMATIC) txHeaderCommand;

    txHeaderCommand = g_LinTXHeaderCommand[ChannelID];
    linChFrameState = g_LinChannelFrameStatus[ChannelID];

    if(linFrameError == (uint8)LIN_BIT_INT_ERROR)
    {
        tempReturnVal = LIN_TX_ERROR;
    }
    else if(linFrameError == (uint8)LIN_NOISE_INT_ERROR)
    {
        if((uint8)LIN_TX_SLAVE_RES_COMMAND_ID == g_LinTXHeaderCommand[ChannelID])
        {
            tempReturnVal = LIN_RX_ERROR;
        }
        else
        {
            tempReturnVal = LIN_TX_ERROR;
        }
    }
    else if(linFrameError == (uint8)LIN_FRAMING_INT_ERROR)
    {
        tempReturnVal = LIN_RX_ERROR;
    }
    else if(linFrameError == (uint8)LIN_NO_INT_ERROR)
    {
        if(((uint8)LIN_TX_SLAVE_RES_COMMAND_ID == g_LinTXHeaderCommand[ChannelID]) &&
          ((uint8)LIN_CHANNEL_RX_ONGOING_STATE == g_LinChannelFrameStatus[ChannelID]))
        {
            tempReturnVal = LIN_RX_BUSY;
        }
        else if (((uint8)LIN_TX_SLAVE_TO_SLAVE_COMMAND_ID == txHeaderCommand) && 
                 ((uint8)LIN_CHANNEL_TX_COMPLETE_STATE == linChFrameState))
        {
            tempReturnVal = LIN_TX_OK;
        }
        else
        {
            tempReturnVal = LIN_TX_BUSY;
        }
    }
    else
    {
        /* nothing */
    }
    return tempReturnVal;
}

/*!
* @brief         Gets the state of the LIN drive when the channel transfers header
*
* @param[in]     ChannelID:            LIN channel ID
*                linFrameError:        Frame transmission error status of the Lin Channel
*
* @retval        LIN_NOT_OK:           Development error,and not the following.
*                LIN_TX_OK:            transmission is OK.
*                LIN_TX_BUSY:          Ongoing transmission of header or response.
*                LIN_TX_HEADER_ERROR:  An error occurred during header transmission.
*                LIN_RX_NO_REPONSE:    No data was received.
*
* @note          None
*/
static FUNC (Lin_StatusType, LIN_CODE) Lin_Hw_HeaderTranferGetStatus(CONST(uint8, AUTOMATIC) ChannelID, CONST(uint8, AUTOMATIC) linFrameError)
{
    VAR(Lin_StatusType, AUTOMATIC) tempReturnVal = LIN_NOT_OK;
    VAR(uint8, AUTOMATIC) linChFrameState;
    VAR(uint8, AUTOMATIC) txHeaderCommand;

    txHeaderCommand = g_LinTXHeaderCommand[ChannelID];
    linChFrameState = g_LinChannelFrameStatus[ChannelID];
    
    if(linFrameError == (uint8)LIN_BIT_INT_ERROR)
    {
        tempReturnVal = LIN_TX_HEADER_ERROR;
    }
    else if(linFrameError == (uint8)LIN_NO_INT_ERROR)
    {
        if(((uint8)LIN_TX_SLAVE_TO_SLAVE_COMMAND_ID == txHeaderCommand) && 
           ((uint8)LIN_CHANNEL_TX_HEADER_COMPLETE_STATE == linChFrameState))
        {
            tempReturnVal = LIN_TX_OK;
        }
        else if(((uint8)LIN_TX_SLAVE_RES_COMMAND_ID == txHeaderCommand) && 
                ((uint8)LIN_CHANNEL_TX_HEADER_COMPLETE_STATE == linChFrameState))
        {
            tempReturnVal = LIN_RX_NO_RESPONSE;
        }
        else
        {
            tempReturnVal = LIN_TX_BUSY;
        }
    }
    else
    {
        tempReturnVal = LIN_NOT_OK;
    }
    return tempReturnVal;
}

#ifdef LIN_MASTER_NODECFG
/*!
* @brief         Interrupt Handling Program for RX data register full on USART.
*
* @param[in]     usartChannelID:     usart channel ID
*                logicChannelID:      logic Channel ID
*
* @retval        uint32
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_RxBuffFullIsrProcess(CONST(uint8, AUTOMATIC) usartChannelID, VAR(uint8, AUTOMATIC) logicChannelID)
{
    VAR(uint8, AUTOMATIC) tempLogicalChannel = (uint8)logicChannelID;
    VAR(uint8, AUTOMATIC) linHeaderCommand;
    VAR(uint8, AUTOMATIC) bufferLength;
    VAR(uint8, AUTOMATIC) nextByteBufferPtr;
    VAR(uint32,AUTOMATIC) linDataReg;
    VAR(uint8, AUTOMATIC) tempValue1;

    SchM_Enter_Lin_LIN_CRITICAL_SECTION12();
    {
        /* Disable RX Interrupt */
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXBNEIEN_MASK);
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION12();
    /* Read data register */
    linDataReg = REG_READ32(USART_RXDATA_REG_ADDR(usartChannelID));
    linHeaderCommand = g_LinTXHeaderCommand[tempLogicalChannel];
    bufferLength = g_LinUsartBufferLength[tempLogicalChannel];
    nextByteBufferPtr = g_LinUsartNextByteBufferPtr[tempLogicalChannel];
    /* Get the last byte transferred */
    tempValue1 = g_LinUsartDataBuffer[tempLogicalChannel][nextByteBufferPtr];
    if(nextByteBufferPtr < bufferLength)
    {
        if(nextByteBufferPtr == (uint8)USART_SYNCH_BYTE_POSITION)
        {
            if((uint8)(linDataReg & USART_RXDATA_RXDATA_MASK) == tempValue1)
            {
                SchM_Enter_Lin_LIN_CRITICAL_SECTION25();
                {
                    /* Enable TX Interrupt */
                    REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_TXBEIEN_MASK);
                }
                SchM_Exit_Lin_LIN_CRITICAL_SECTION25();
            }
            else
            {
                /* Bit error */
                g_LinChannelFrameErrorStatus[tempLogicalChannel] = (uint8)LIN_BIT_INT_ERROR;
            }
        }
        else
        {
            if(linHeaderCommand == (uint8)LIN_TX_SLAVE_TO_SLAVE_COMMAND_ID)
            {
                /* Verify the received data */
                if((uint8)(linDataReg & USART_RXDATA_RXDATA_MASK) != tempValue1)
                {
                    /* Bit error */
                    g_LinChannelFrameErrorStatus[tempLogicalChannel] = (uint8)LIN_BIT_INT_ERROR;
                }
                else
                {
                    g_LinChannelFrameStatus[tempLogicalChannel] = (uint8)LIN_CHANNEL_TX_HEADER_COMPLETE_STATE;
                }
            }
            else if(linHeaderCommand == (uint8)LIN_TX_SLAVE_RES_COMMAND_ID)
            {
                /* If the frame is from a response frame,an interrupt is processed */
                Lin_Hw_SlaveResponseInterruptHandler(usartChannelID, tempLogicalChannel, linDataReg);
            }
            else if(linHeaderCommand == (uint8)LIN_TX_MASTER_RES_COMMAND_ID)
            {
                /* Verify the received data */
                if((uint8)(linDataReg & USART_RXDATA_RXDATA_MASK) == tempValue1)
                {
                    /* The last byte was received */
                    if(nextByteBufferPtr != (bufferLength - (uint8)1U))
                    {
                        SchM_Enter_Lin_LIN_CRITICAL_SECTION15();
                        {
                            /* Enable TX Interrupt */
                            REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_TXBEIEN_MASK);
                        }
                        SchM_Exit_Lin_LIN_CRITICAL_SECTION15(); 
                    }
                    else
                    {
                        g_LinChannelFrameStatus[tempLogicalChannel] = (uint8)LIN_CHANNEL_TX_COMPLETE_STATE;
                    }
                }
                else
                {
                    /* Bit error */
                    g_LinChannelFrameErrorStatus[tempLogicalChannel] = (uint8)LIN_BIT_INT_ERROR;
                }
            }
            else if(linHeaderCommand == (uint8)LIN_TX_SLEEP_COMMAND_ID)
            {
                /* Verify the received data */
                if((uint8)(linDataReg & USART_RXDATA_RXDATA_MASK) == tempValue1)
                {
                    /* The last byte was received */
                    if(nextByteBufferPtr != (bufferLength - (uint8)1U))
                    {
                        SchM_Enter_Lin_LIN_CRITICAL_SECTION17();
                        {
                            /* Enable TX Interrupt */
                            REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), 
                                          USART_CTRL1_TXBEIEN_MASK);
                        }
                        SchM_Exit_Lin_LIN_CRITICAL_SECTION17();
                    }
                    else
                    {
                      g_LinTXHeaderCommand[tempLogicalChannel] = (uint8)LIN_TX_NO_COMMAND_ID;
                        /* Reset data buffer length */
                        g_LinUsartBufferLength[tempLogicalChannel] = (uint8)0U;
                        SchM_Enter_Lin_LIN_CRITICAL_SECTION16();
                        {
                            /* Enable wake up inspect */
                            /* Clear the RX Pin Active Edge Interrupt Flag */
                            REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                                       (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                                       (~USART_INTFCLR_MASK)) | 
                                       USART_INTFCLR_WSMCLR_MASK));
                            /* Enable the RX Input Active Edge Interrupt Enable */
                            REG_BIT_SET32(USART_CTRL3_REG_ADDR(usartChannelID), 
                                          USART_CTRL3_WSMIEN_MASK);
                        }
                        SchM_Exit_Lin_LIN_CRITICAL_SECTION16();
                    }                          
                }
                else
                {
                    /* Bit error */
                    g_LinChannelFrameErrorStatus[tempLogicalChannel] = (uint8)LIN_BIT_INT_ERROR;
                }
            }
            else
            {
                /* nothing */
            }
        }
        if (((uint8)LIN_NO_INT_ERROR !=g_LinChannelFrameErrorStatus[tempLogicalChannel]) && \
        ((uint8)LIN_TX_SLEEP_COMMAND_ID == linHeaderCommand))
        {
        SchM_Enter_Lin_LIN_CRITICAL_SECTION14();
        {
            g_LinTXHeaderCommand[tempLogicalChannel] = (uint8)LIN_TX_NO_COMMAND_ID;
            /* Enable wake up inspect */
            /* Clear the RX Pin Active Edge Interrupt Flag */
            REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                       (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                       (~USART_INTFCLR_MASK)) | 
                       USART_INTFCLR_WSMCLR_MASK));
            /* Enable the RX Input Active Edge Interrupt Enable */
            REG_BIT_SET32(USART_CTRL3_REG_ADDR(usartChannelID), USART_CTRL3_WSMIEN_MASK);
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION14();
        }
        else
        {
            /* nothing */
        }
        /* Increase data Buffer Pointer */
        g_LinUsartNextByteBufferPtr[tempLogicalChannel] = g_LinUsartNextByteBufferPtr[tempLogicalChannel] + 1U;
    }
    else
    {
        /* nothing */
    }
}
#endif

LOCAL_INLINE FUNC (void, LIN_CODE) Lin_Hw_ConfigBaudrate(CONST(uint8, AUTOMATIC) usartChannelID,CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(uint8, AUTOMATIC) usartId = usartChannelID;
    VAR(uint8, AUTOMATIC) channelId = ChannelID;
    VAR(uint32, AUTOMATIC) temp = 0;
    VAR(uint32, AUTOMATIC) fCLK = 0;
    VAR(uint32, AUTOMATIC) intDiv = 0;
    VAR(uint32, AUTOMATIC) fractionalDiv = 0;
    VAR(uint32, AUTOMATIC) tempBitVal = 0;
    VAR(uint32, AUTOMATIC) usartSel = 0;

    if (usartId == 0U)
    {
        usartSel = (REG_READ32(RCM_CFG3_REG_ADDR) & RCM_CFG3_USART1SEL_MASK) >> 
                     RCM_CFG3_USART1SEL_SHIFT;
    }
    else
    {
        usartSel = (REG_READ32(RCM_CFG3_REG_ADDR) & RCM_CFG3_USART2SEL_MASK) >> 
                     RCM_CFG3_USART2SEL_SHIFT;
    }
    switch (usartSel)
    {
        case 0x00U:
            fCLK = Mcu_Rcm_ReadPCLKFreq();
            break;
        case 0x01U:
            fCLK = Mcu_Rcm_ReadSYSCLKFreq();
            break;
        case 0x03U:
            fCLK = HSI_VALUE;
            break;
        default:
            /* nothing */
            break;
    }
    
    /* Compute the integer part */
    tempBitVal = REG_BIT_GET32(USART_CTRL1_REG_ADDR(usartId),USART_CTRL1_OSMCFG_MASK);
    /* Oversampling by 8 */
    if (tempBitVal != (uint32)RESET) 
    {
        intDiv = ((25u * fCLK) / (2u * (g_LinPCCfgPointer->linChannelConfigArr[channelId]->channelBaudrate)));
    }
    /* Oversampling by 16 */
    else 
    {
        intDiv = ((25u * fCLK) / (4u * (g_LinPCCfgPointer->linChannelConfigArr[channelId]->channelBaudrate)));
    }

    temp = (intDiv / 100u) << 4u;
    fractionalDiv = intDiv - (100u * (temp >> 4u));

    /* Implement the fractional part in the register */
    tempBitVal = REG_BIT_GET32(USART_CTRL1_REG_ADDR(usartId),USART_CTRL1_OSMCFG_MASK);
    /* Oversampling by 8 */
    if (tempBitVal != (uint32)RESET)
    {
        temp |= ((((fractionalDiv * 8u) + 50u) / 100u)) & ((uint8_t)0x07u);
    }
    /* Oversampling by 16 */
    else 
    {
        temp |= ((((fractionalDiv * 16u) + 50u) / 100u)) & ((uint8_t)0x0Fu);
    }

    REG_WRITE32(USART_BR_REG_ADDR(usartId),temp);
}
/*******************************************************************************
                              GLOBAL FUNCTION
*******************************************************************************/
/*!
* @brief         Initialize LIN channel
*
* @param[in]     ChannelID: LIN channel ID
*
* @retval        void
*
* @note          None
*/
FUNC(void, LIN_CODE) Lin_Hw_InitLinChannel(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(uint8, AUTOMATIC) usartChannelID;
    VAR(uint32, AUTOMATIC) countValue = (uint32)0U;

    /* Gets the HW Lin channel from the logical channel */
     usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
    /* Check whether the wake up detection function is enabled */
     if (((uint8) STD_ON == g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linChWakeupEn) &&
        (USART_INTFCLR_IDLECLR_MASK == (REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                                         USART_INTFCLR_IDLECLR_MASK)))
     {
        /* Report directly to EcuM via EcuM_SetWakeupEvent */
        EcuM_SetWakeupEvent(g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linChEcuMWakeupSrc);
     }
    else
    {
        /* nothing */
    }
    /* Reset USART register */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_UEN_MASK);
    SchM_Enter_Lin_LIN_CRITICAL_SECTION0();
    {
        /* Disable USART RX and TX */
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXEN_MASK);
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_TXEN_MASK);
        /* Configure interrupt length */
        REG_BIT_SET32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_LBDLCFG_MASK);
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_DBLCFG0_MASK);

        /* Example Initialize the baud rate */
        REG_RMW32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_OSMCFG_MASK,0); //Oversampling Mode Configure 16

        Lin_Hw_ConfigBaudrate(usartChannelID,ChannelID);

        /* Configure the LSB to be the first of the transmission after the start bit */
        REG_BIT_CLEAR32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_MSBFEN_MASK);
        /* No hardware parity is generated or checked */
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_PCEN_MASK);
        /* Disable all interrupts */
        REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                   (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                            (~USART_INTFCLR_MASK)) | 
                            USART_INTFCLR_MASK));
        REG_RMW32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_IE_FLAGS_MASK, (uint32)0x0);
        REG_RMW32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_LBDIEN_MASK, (uint32)0x0);
        REG_RMW32(USART_CTRL3_REG_ADDR(usartChannelID), USART_CTRL3_IE_FLAGS_MASK, (uint32)0x0);

        /* Clear Wake-up flag */
        g_LinUsartWakeupFlag[ChannelID] = (uint8)FALSE;
        /* Enable USART TX */
        REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_TXEN_MASK);
        /* Enable USART RX */
        REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXEN_MASK);

        REG_BIT_SET32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_LINMEN_MASK);
        REG_BIT_CLEAR32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_CLKEN_MASK);
        REG_BIT_CLEAR32(USART_CTRL2_REG_ADDR(usartChannelID), USART_CTRL2_STOPCFG_MASK);

        REG_BIT_CLEAR32(USART_CTRL3_REG_ADDR(usartChannelID), USART_CTRL3_HDEN_MASK);

        SchM_Enter_Lin_LIN_CRITICAL_SECTION1();
        /* When USART TX is enabled,the leading character of the next full character frame is automatically queued */
        while(countValue <= (LIN_OPERATION_TIMEOUT + (uint32)1U))
        {
            if((USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK) == 
               (REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & (USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK)))
            {
                break;
            }
            else
            {
                countValue++;
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION1();
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION0();

    SchM_Enter_Lin_LIN_CRITICAL_SECTION26();
    {
        /* Enable USART RX and TX Interrupt */
        REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_RXBNEIEN_MASK);
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(usartChannelID), USART_CTRL1_TXBEIEN_MASK);
        /* Reset buffer region length */
        g_LinUsartBufferLength[ChannelID] = (uint8)0U;
        /* Check whether wake up detection by interrupt is enabled */
        if ((uint8) STD_ON == g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linChWakeupEn)
        {
                Lin_Hw_RxInterrupt(usartChannelID,TRUE);
        } 
        else
        {
            /* nothing */
        }    
    }
    REG_BIT_SET32(USART_CTRL1_REG_ADDR(usartChannelID),USART_CTRL1_UEN_MASK);
    SchM_Exit_Lin_LIN_CRITICAL_SECTION26();
}

/*!
* @brief         Check that the LIN channel has wake-up
*
* @param[in]     ChannelID:            LIN channel ID
*
* @retval        E_OK:                 If the LIN Channel has the wake up flag set
*                E_NOT_OK:             Otherwise
*
* @note          None
*/
FUNC (Std_ReturnType, LIN_CODE) Lin_Hw_CheckChannelWakeup(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(Std_ReturnType, AUTOMATIC) tempReturnValue;

    tempReturnValue = g_LinUsartWakeupFlag[ChannelID];

    if((uint8)TRUE != tempReturnValue)
    {
        /* Do nothing */
    }
    else
    {
        /* Reset Wake up Flag */
        g_LinUsartWakeupFlag[ChannelID] = (uint8)FALSE;
    }

    return tempReturnValue;
}


/*!
* @brief         Set the channel status to sleep,but no go-to-sleep-command occurs
*
* @param[in]     ChannelID:   LIN channel ID
*
* @retval        E_NOT_OK:    Timeout
*                E_OK:        No Timeout
*
* @note          None
*/
FUNC (Std_ReturnType, LIN_CODE) Lin_Hw_GoToSleepStatus(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(Std_ReturnType, AUTOMATIC) tempReturnVal = (uint8)E_NOT_OK;
    VAR(uint32, AUTOMATIC) volatile countValue = 0U;
    VAR(uint8, AUTOMATIC) usartChannelID;

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
 
    SchM_Enter_Lin_LIN_CRITICAL_SECTION6();
    {
        Lin_Hw_ClearTxRx(usartChannelID);
        SchM_Enter_Lin_LIN_CRITICAL_SECTION1();
        /* wait for the current frame to cancel */
        while(countValue <= (LIN_OPERATION_TIMEOUT + ((uint32)1U)))
        {
            if( (USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK) == ( REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & (USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK)))
            {
                tempReturnVal = (uint8)E_OK;
                break;
            }
            else
            {
                countValue = countValue + 1U;
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION1();
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION6();
    /* Remove USART Rx Buffer */
    REG_READ32(USART_RXDATA_REG_ADDR(usartChannelID));
    /* Reset buffer region length */
    g_LinUsartBufferLength[ChannelID] = (uint8)0U;
    /* Set g_LinTXHeaderCommand value to LIN_TX_NO_COMMAND_ID */
    g_LinTXHeaderCommand[ChannelID] = (uint8)LIN_TX_NO_COMMAND_ID;
    /* Set Channel Status to Sleep */
    g_LinChannelStatus[ChannelID] = (uint8)LIN_CH_SLEEP_STATE;

    if((uint8)E_OK == tempReturnVal)
    {
        /* go to Sleep mode */
        SchM_Enter_Lin_LIN_CRITICAL_SECTION7();
        {
            Lin_Hw_RxInterrupt(usartChannelID,TRUE);
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION7();
    }
    else
    {
        /* nothing */
    }
    return tempReturnVal;
}

/*!             Gets the status of the LIN driver when Channel is operating.
* @brief         When running,view the current LIN driver status
*
* @param[in]     ChannelID:    LIN channel ID
*
* @param[out]    linSduPointer: Pointer to the buffer where the current SDU is stored
*
* @retval        LIN_NOT_OK          : Development or production error
*                LIN_TX_OK           : LIN transmission completed
*                LIN_TX_BUSY         : Ongoing transmission of header or response
*                LIN_TX_HEADER_ERROR : Error occurred during header transmission
*                LIN_TX_ERROR        : Error occurred during response transmission
*                LIN_RX_OK           : Reception of correct response
*                LIN_RX_BUSY         : Reception in progress
*                LIN_RX_ERROR        : Error generated during reception
*                LIN_RX_NO_REPONSE   : No data byte was received
*                LIN_OPERATIONAL     : The channel is ready for the next header transfer,and no data is available
*
* @note          None
*/
FUNC(Lin_StatusType, LIN_CODE) Lin_Hw_GetStatus(CONST(uint8, AUTOMATIC) ChannelID, P2VAR(uint8, AUTOMATIC, LIN_APPL_DATA) linSduPointer)
{
    VAR(Lin_StatusType,AUTOMATIC) tempReturnValue = LIN_NOT_OK;
    VAR(uint8, AUTOMATIC) u8ChannelFrameStatus;
    VAR(uint8, AUTOMATIC) linFrameError;
    VAR(uint8, AUTOMATIC) txHeaderCommand;
    VAR(uint8, AUTOMATIC) u8Temp2;
    VAR(uint8, AUTOMATIC) tempValue1;

    tempValue1 = g_LinUsartNextByteBufferPtr[ChannelID];
    u8Temp2 = g_LinUsartBufferLength[ChannelID];
    txHeaderCommand = g_LinTXHeaderCommand[ChannelID];
    
    /* Frame TX */
    if(((uint8)0U) != u8Temp2)
    {
        linFrameError = g_LinChannelFrameErrorStatus[ChannelID];
        if(((uint8)USART_PID_BYTE_POSITION + ((uint8)1U)) >= tempValue1)
        {
            /* Header TX */
            tempReturnValue = Lin_Hw_HeaderTranferGetStatus(ChannelID, linFrameError);
        }
        else if(u8Temp2 > tempValue1)
        {
            /* Data TX */
            tempReturnValue = Lin_Hw_DataTranferGetStatus(ChannelID, linFrameError);
        }
        else
        {
            linFrameError = g_LinChannelFrameErrorStatus[ChannelID];
            if(u8Temp2 == tempValue1)
            {
                u8ChannelFrameStatus = g_LinChannelFrameStatus[ChannelID];
                /* The last byte has been TX/RX */
                if(linFrameError == (uint8)LIN_FRAMING_INT_ERROR)
                {
                    tempReturnValue = LIN_RX_ERROR;
                }
                else if(linFrameError == (uint8)LIN_NOISE_INT_ERROR)
                {
                    if((uint8)LIN_TX_SLAVE_RES_COMMAND_ID == txHeaderCommand)
                    {
                        tempReturnValue = LIN_RX_ERROR;
                    }
                    else
                    {
                        tempReturnValue = LIN_TX_ERROR;
                    }
                }
                else if(linFrameError == (uint8)LIN_NO_INT_ERROR)
                {
                    if((uint8)LIN_CHANNEL_RX_COMPLETE_STATE == u8ChannelFrameStatus)
                    {
                        /* Copy data from the hardware buffer */
                        Lin_Hw_CopyRxData(ChannelID, linSduPointer);
                        g_LinUsartBufferLength[ChannelID] = (uint8)0U;
                        tempReturnValue = LIN_RX_OK;
                    }
                    else if((uint8)LIN_CHANNEL_TX_COMPLETE_STATE == u8ChannelFrameStatus)
                    {
                        tempReturnValue = LIN_TX_OK;
                        g_LinUsartBufferLength[ChannelID] = (uint8)0U;
                    }
                    else
                    {
                        tempReturnValue = LIN_NOT_OK;
                    }
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                tempReturnValue = LIN_NOT_OK;
            }
        }
    }
    /* USART is idle */
    else
    {
        tempReturnValue = LIN_OPERATIONAL;
    }
    return tempReturnValue;
}

/*!
* @brief         Sends a wake up signal to the LIN bus
*
* @param[in]     ChannelID:   LIN channel ID
*
* @retval        void
*
* @note          None
*/
FUNC (void, LIN_CODE) Lin_Hw_SendWakeUpFrame(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(uint8, AUTOMATIC) wakeupByte;
    VAR(uint8, AUTOMATIC) usartChannelID;
    VAR(uint32, AUTOMATIC) countValue = (uint32)0U;

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
    wakeupByte = (uint8)((LIN_MINIMUM_LENGTH_WAKEUP_PULSE/LIN_HW_BIT_LENGTH32(g_LinPCCfgPointer->linChannelConfigArr[ChannelID]->channelBaudrate)) + (uint8)1U);
    wakeupByte = (uint8)(~((uint8)((uint8)((uint32)1U << wakeupByte) - (uint8)1U)));

    SchM_Enter_Lin_LIN_CRITICAL_SECTION8();
    {
        Lin_Hw_ClearTxRx(usartChannelID);
        SchM_Enter_Lin_LIN_CRITICAL_SECTION1();
        /* wait for the USART transmitter to become available */
        while(countValue <= (LIN_OPERATION_TIMEOUT + (uint32)1U))
        {
            if((USART_STS_TXBEFLG_MASK | 
                USART_STS_TXCFLG_MASK) != 
               (REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & 
               (USART_STS_TXBEFLG_MASK | 
                USART_STS_TXCFLG_MASK)))
            {
                countValue++;
            }
            else
            {
                break;
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION1();
        /* If the LIN channel is already sleeping,the buffer length is reset */
        if ((uint8)LIN_CH_SLEEP_STATE != g_LinChannelStatus[ChannelID])
        {
            /* nothing */
        }
        else
        {
            g_LinUsartBufferLength[ChannelID] = (uint8)0U;
        }
        Lin_Hw_RxInterrupt(usartChannelID,FALSE);
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION8();
    /* Send Wakeup request */
    REG_WRITE32(USART_TXDATA_REG_ADDR(usartChannelID), wakeupByte);

}

/*!
* @brief         Wake up the LIN channel
**
* @param[in]     ChannelID:   LIN channel ID
**
* @retval        void
**
* @note          None
*/
FUNC(void, LIN_CODE) Lin_Hw_WakeupChannel(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(uint8, AUTOMATIC) usartChannelID;

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;

    /* If the LIN channel is already sleeping,the buffer length is reset */
    if ((uint8)LIN_CH_SLEEP_STATE != g_LinChannelStatus[ChannelID])
    {
        /* nothing */
    }
    else
    {
        g_LinUsartBufferLength[ChannelID] = (uint8)0U;
    }
    SchM_Enter_Lin_LIN_CRITICAL_SECTION9();
    {
        Lin_Hw_ClearTxRx(usartChannelID);
        Lin_Hw_RxInterrupt(usartChannelID,FALSE);
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION9();
}


/*!
* @brief         Prepares and send a go-to-sleep-command frame on Channel
*
* @param[in]     ChannelID:   LIN channel ID
*
* @retval        E_NOT_OK:    Timeout
*                E_OK:        No Timeout
*
* @note          None
*/
FUNC (Std_ReturnType, LIN_CODE) Lin_Hw_SendGoToSleepFrame(CONST(uint8, AUTOMATIC) ChannelID)
{
    VAR(Std_ReturnType, AUTOMATIC) tempReturnVal = (uint8)E_NOT_OK;
    VAR(uint32, AUTOMATIC) volatile countValue = 0U;
    VAR(uint8, AUTOMATIC) usartChannelID;
    VAR(uint8, AUTOMATIC) num = 0U;    

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
 
    SchM_Enter_Lin_LIN_CRITICAL_SECTION4();
    {
        Lin_Hw_ClearTxRx(usartChannelID);
        SchM_Enter_Lin_LIN_CRITICAL_SECTION1();
        /* wait for the current frame to cancel */
        while(countValue <= (LIN_OPERATION_TIMEOUT + ((uint32)1U)))
        {
            if((USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK) != 
               (REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & (USART_STS_TXBEFLG_MASK | USART_STS_TXCFLG_MASK)))
            {
                countValue = countValue + 1U;
            }
            else
            {
                tempReturnVal = (uint8)E_OK;
                break;
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION1();
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION4();
    /* Remove USART Rx Buffer */
    REG_READ32(USART_RXDATA_REG_ADDR(usartChannelID));
    if((uint8)E_OK == tempReturnVal)
    {
        g_LinUsartBufferLength[ChannelID] = LIN_HW_MAXIMUM_BUFFER_LENGTH;
        /* Prepare header,Synch byte */
        g_LinUsartDataBuffer[ChannelID][USART_SYNCH_BYTE_POSITION] = LIN_HW_SYNC_BYTE;
        /* Protected identifier */
        Lin_Hw_PidCalculate(ChannelID, USART_MASTER_DEMAND_DIAGNOSTIC_ID);
        /* The Go to sleep command is :[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] */
        g_LinUsartDataBuffer[ChannelID][(uint8)2U] = USART_0_SLEEP_DATA;
        for(num = 3U; num <= 9U; num++)
        {
            g_LinUsartDataBuffer[ChannelID][(uint8)num] = USART_255_SLEEP_DATA;
        }
        /* The Classic checksum to enter the sleep frame is 0x00  */
        g_LinUsartDataBuffer[ChannelID][g_LinUsartBufferLength[ChannelID] - ((uint8)1U)] = 
          (uint8)Lin_Hw_ChecksumCalculate(ChannelID, LIN_CLASSIC_CS);
        /* Set the next byte to send the sync byte. This will be used for complete transmission interruption */
        g_LinUsartNextByteBufferPtr[ChannelID] = USART_SYNCH_BYTE_POSITION;
        SchM_Enter_Lin_LIN_CRITICAL_SECTION5();
        {
            Lin_Hw_EnaTxinterrupt(usartChannelID);
            /* Set header command type is sleep */
            g_LinTXHeaderCommand[ChannelID] = (uint8)LIN_TX_SLEEP_COMMAND_ID;
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION5();   
    }
    else
    {
        /* nothing */
    }
    return tempReturnVal;
}

/*!
* @brief         Sends the response part of the LIN frame
*
* @param[in]     ChannelID:   LIN channel ID
* @param[in]     pduInfoPointer: pointer to PDU that contains the PID, Checksum model,
*                               Response type, Dl and SDU data pointers
*
* @retval        void
*
* @note          None
*/
FUNC (void, LIN_CODE) Lin_Hw_SendFrameResponse(CONST(uint8, AUTOMATIC) ChannelID, P2CONST(Lin_PduType, AUTOMATIC, LIN_APPL_CONST) pduInfoPointer)
{
    VAR(uint8, AUTOMATIC) linFrameID;
    VAR(uint8, AUTOMATIC) usartChannelID;
    VAR(uint8, AUTOMATIC) u8Loop = (uint8)0U;

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
 
    /* Tx Buffer Prepare */
    for(u8Loop = (uint8)0U; u8Loop < ((pduInfoPointer->Dl > LIN_HW_MAXIMUM_DATA_LENGTH) ? LIN_HW_MAXIMUM_DATA_LENGTH : pduInfoPointer->Dl); u8Loop++)
    {
        g_LinUsartDataBuffer[ChannelID][(uint8)USART_DATA_POSITION + u8Loop] = pduInfoPointer->SduPtr[u8Loop];
    }
    linFrameID = pduInfoPointer->Pid;
    if(linFrameID == (uint8)USART_SLAVE_RESPOND_DIAGNOSTIC_ID)
    {
        g_LinUsartDataBuffer[ChannelID][g_LinUsartBufferLength[ChannelID] - ((uint8)1U)] = 
          (uint8)Lin_Hw_ChecksumCalculate(ChannelID, LIN_CLASSIC_CS);
    }
    else
    {
        if ((boolean)TRUE == g_LinStoreUsartChecksumType)
        {
            /* The type is enhance checksum */
            g_LinUsartDataBuffer[ChannelID][g_LinUsartBufferLength[ChannelID] - ((uint8)1U)] = 
              (uint8)Lin_Hw_ChecksumCalculate(ChannelID, LIN_ENHANCED_CS);
            g_LinStoreUsartChecksumType = (boolean)TRUE;
        }
        else
        {
            /* The type is classic checksum */
            g_LinUsartDataBuffer[ChannelID][g_LinUsartBufferLength[ChannelID] - ((uint8)1U)] = 
              (uint8)Lin_Hw_ChecksumCalculate(ChannelID, LIN_CLASSIC_CS);
            g_LinStoreUsartChecksumType = (boolean)FALSE;
        }
    }
    /* TX Header */
    /* Set the next byte to send the sync byte. This will be used for complete transmission interruption */
    g_LinUsartNextByteBufferPtr[ChannelID] = USART_SYNCH_BYTE_POSITION;

    SchM_Enter_Lin_LIN_CRITICAL_SECTION3();
    {
        Lin_Hw_EnaTxinterrupt(usartChannelID);
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION3();
}

/*!
* @brief         Sends the header part of the LIN frame
*
* @param[in]     ChannelID:   LIN channel ID
* @param[in]     pduInfoPointer: pointer to PDU that contains the PID, Checksum model,
*                             Response type, Dl and SDU data pointers
*
* @retval        E_NOT_OK:    Timeout
*                E_OK:        No Timeout
*
* @note          None
*/
FUNC (Std_ReturnType, LIN_CODE) Lin_Hw_SendFrameHeader(CONST(uint8, AUTOMATIC) ChannelID, P2CONST(Lin_PduType, AUTOMATIC, LIN_APPL_CONST) pduInfoPointer)
{
    VAR(Std_ReturnType, AUTOMATIC) tempReturnVal = (uint8)E_NOT_OK;
    VAR(uint8, AUTOMATIC) usartChannelID;
    VAR(uint32, AUTOMATIC) volatile countValue = 0U;

    /* Gets the HW Lin channel from the logical channel */
    usartChannelID = g_LinChCfgPtr[ChannelID]->channelConfigPCPtr->linHwCh;
 
    SchM_Enter_Lin_LIN_CRITICAL_SECTION1();
    {
        /* Stop any transmission in progress */
        Lin_Hw_ClearTxRx(usartChannelID);
        SchM_Enter_Lin_LIN_CRITICAL_SECTION10();
        /* wait for the current frame to cancel */
        while(countValue <= (LIN_OPERATION_TIMEOUT + (uint32)1U))
        {
            if((USART_STS_TXBEFLG_MASK | 
                USART_STS_TXCFLG_MASK) != 
               (REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & 
               (USART_STS_TXBEFLG_MASK | 
                USART_STS_TXCFLG_MASK)))
            {
                countValue = countValue + 1U;
            }
            else
            {
                tempReturnVal = (uint8)E_OK;
                break;
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION10();
    }
    SchM_Exit_Lin_LIN_CRITICAL_SECTION1();
    /* Remove USART Rx Buffer */
    REG_READ32(USART_RXDATA_REG_ADDR(usartChannelID));
    if((uint8)E_OK == tempReturnVal)
    {
        /* Reset the error status global flag */
        g_LinChannelFrameErrorStatus[ChannelID] = (uint8)LIN_NO_INT_ERROR;
        /* Set the checksum type for interrupt */
        if (LIN_ENHANCED_CS != pduInfoPointer->Cs)
        {
            /* Update the LIN Checksum type to LIN_CLASSIC_CS */
            g_LinStoreUsartChecksumType = (boolean)FALSE;
        }
        else
        {
            /* Update the LIN Checksum type to LIN_ENHANCED_CS */
            g_LinStoreUsartChecksumType = (boolean)TRUE;
        }
        /* If the host wants to send a response frame,set the header status to TRUE */
        if (LIN_SLAVE_RESPONSE == pduInfoPointer->Drc)
        {
            g_LinTXHeaderCommand[ChannelID] = (uint8)LIN_TX_SLAVE_RES_COMMAND_ID;
            g_LinChannelFrameStatus[ChannelID] = (uint8)LIN_CHANNEL_RECEIVE_NOTHING_STATE;
        }
        else if(LIN_MASTER_RESPONSE == pduInfoPointer->Drc)
        {
            g_LinTXHeaderCommand[ChannelID] = (uint8)LIN_TX_MASTER_RES_COMMAND_ID;
            /* Update LIN channel frame operation status to LIN_CHANNEL_READY_STATE */
            g_LinChannelFrameStatus[ChannelID] = (uint8)LIN_CHANNEL_READY_STATE;
        }
        else
        {
            g_LinTXHeaderCommand[ChannelID] = (uint8)LIN_TX_SLAVE_TO_SLAVE_COMMAND_ID;
            g_LinChannelFrameStatus[ChannelID] = (uint8)LIN_CHANNEL_RECEIVE_NOTHING_STATE;
        }
        /* The buffer inclusion [sync byte, pid, data, checksum] */
        g_LinUsartBufferLength[ChannelID] = ((uint8)3U) + ((pduInfoPointer->Dl > LIN_HW_MAXIMUM_DATA_LENGTH) ? LIN_HW_MAXIMUM_DATA_LENGTH : pduInfoPointer->Dl);
        /* Write the synchronization byte and PID in the transfer buffer */
        g_LinUsartDataBuffer[ChannelID][USART_SYNCH_BYTE_POSITION] = LIN_HW_SYNC_BYTE;
        Lin_Hw_PidCalculate(ChannelID, pduInfoPointer->Pid);
        /* Set data direction */
        if (LIN_MASTER_RESPONSE != pduInfoPointer->Drc)
        {
            /* TX Header */
            /* Set the next byte to send the sync byte. This will be used for complete transmission interruption */
            g_LinUsartNextByteBufferPtr[ChannelID] = USART_SYNCH_BYTE_POSITION;
            SchM_Enter_Lin_LIN_CRITICAL_SECTION2();
            {
                Lin_Hw_EnaTxinterrupt(usartChannelID);
            }
            SchM_Exit_Lin_LIN_CRITICAL_SECTION2();
        }
        else
        {
            /* Do nothing */
        }
    }
    else
    {
        /* nothing */
    }
    return tempReturnVal;
}

#ifdef LIN_MASTER_NODECFG
/*!
* @brief         Interrupt handler for master node
*
* @param[in]     ChannelId: channel ID
* @param[in]     LogicalChannel: logical channel index
* @param[in]     LinSts: lin status
* @param[in]     linEnInterrupt: lin interrupts has enabled 
*
* @retval        usart reset status
*
* @note          None
*/
static FUNC (boolean, LIN_CODE) Lin_Hw_MasterProcess(VAR(uint8, AUTOMATIC) ChannelId, VAR(uint8, AUTOMATIC) LogicalChannel, VAR(uint32, AUTOMATIC) LinSts, VAR(uint32, AUTOMATIC) linEnInterrupt)
{
    boolean usartResetSts = (boolean)FALSE;
    /* Transmit Interrupt */
    /* Set the TX data register null flag */
    if((USART_STS_TXBEFLG_MASK == (LinSts & USART_STS_TXBEFLG_MASK)) && (USART_CTRL1_TXBEIEN_MASK == (linEnInterrupt & USART_CTRL1_TXBEIEN_MASK)))
    {
        Lin_Hw_LinState_TxRxInterrupt(10,ChannelId,LogicalChannel);
    }
    /* Complete Transmission Interrupt */
    /* set the Transmission Complete Flag */
    else if ((USART_STS_TXCFLG_MASK == (LinSts & USART_STS_TXCFLG_MASK)) && (USART_CTRL1_TXCIEN_MASK == (linEnInterrupt & USART_CTRL1_TXCIEN_MASK)))
    {
        Lin_Hw_LinState_TxRxInterrupt(11,ChannelId,LogicalChannel);
    }
    /* Receive Data Register Full Flag set */
    else if ((USART_STS_RXBNEFLG_MASK == (LinSts & USART_STS_RXBNEFLG_MASK)) && (USART_CTRL1_RXBNEIEN_MASK == (linEnInterrupt & USART_CTRL1_RXBNEIEN_MASK)))
    {
        Lin_Hw_RxBuffFullIsrProcess(ChannelId, LogicalChannel);
    }
    /* An Idle Line Interruption was Detected */
    else if ((USART_STS_IDLEFLG_MASK == (LinSts & USART_STS_IDLEFLG_MASK)) && (USART_CTRL1_IDLEIEN_MASK == (linEnInterrupt & USART_CTRL1_IDLEIEN_MASK)))
    {
        Lin_Hw_IdleLineInterrupt_ProcessingCode(ChannelId, LogicalChannel);
    }
    else
    {
        /* The USART hardware should reset, Disable Transfer Completion and Transfer Data register air break */
        usartResetSts = (boolean)TRUE;
    }
    return usartResetSts;
}
#endif

#ifdef LIN_SLAVE_NODECFG
/*!
* @brief         Interrupt handler for slave node
*
* @param[in]     ChannelId: channel ID
* @param[in]     LinSts: lin status
*
* @retval        None
*
* @note          None
*/
static FUNC (void, LIN_CODE) Lin_Hw_SlaveProcess(VAR(uint8, AUTOMATIC) ChannelId, VAR(uint32, AUTOMATIC) LinSts)
{
    VAR(uint8, AUTOMATIC) ch;
    VAR(uint8, AUTOMATIC) sendData;
    VAR(uint8, LIN_VAR) idx = g_cntByte;
    if(USART_STS_LBDFLG_MASK == (LinSts & USART_STS_LBDFLG_MASK))
    {
        /* Clear LIN Break Detection Flag */
        REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId),USART_INTFCLR_LBDCLR_MASK | USART_INTFCLR_TXCCLR_MASK);
        (void)Lin_Hw_GetRxData(ChannelId);
        REG_BIT_CLEAR32(USART_CTRL2_REG_ADDR(ChannelId),USART_CTRL2_LBDIEN_MASK);
        REG_BIT_SET32(USART_CTRL1_REG_ADDR(ChannelId),USART_CTRL1_RXBNEIEN_MASK);
        g_state = RECV_SYN;
    }
    else if(USART_STS_FEFLG_MASK == (LinSts & USART_STS_FEFLG_MASK))
    {
        REG_WRITE32(USART_INTFCLR_REG_ADDR(ChannelId),0xFFFF);
        (void)(uint8)Lin_Hw_GetRxData(ChannelId);
        
        g_idleTimeoutCnt=MAX_IDLE_TIMEOUT;
        g_state=IDLE;
        
        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId), USART_CTRL1_RXBNEIEN_MASK);
        REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
        REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);
    }
    else if((USART_STS_RXBNEFLG_MASK == (LinSts & USART_STS_RXBNEFLG_MASK)) || (USART_STS_TXCFLG_MASK == (LinSts & USART_STS_TXCFLG_MASK)))
    {
        ch = (uint8)Lin_Hw_GetRxData(ChannelId);
        switch(g_state)
        {
            case IDLE:
                REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId),USART_CTRL1_RXBNEIEN_MASK);
                REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId),USART_INTFCLR_LBDCLR_MASK);
                REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId),USART_CTRL2_LBDIEN_MASK);
                break;
            
            case RECV_SYN:
                if (0x55u == ch)
                {
                    g_state = RECV_PID;
                }
                else
                {
                    g_state = IDLE;
                    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId),USART_CTRL1_RXBNEIEN_MASK);
                    REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId),USART_INTFCLR_LBDCLR_MASK);
                    REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId),USART_CTRL2_LBDIEN_MASK);
                }
                break;
                                            
            case RECV_PID:
                g_pid = ch;
                g_currentId = Lin_Hw_ProcessParity(ch);
                if(g_currentId != 0xFFu)
                {
                    /* ID received correctly - parity OK */
                    Lin_Hw_ProcessPid(g_currentId,ChannelId);
                    g_respFrameTimeoutCnt = MAX_FRAME_TIMEOUT; 
                }
                else
                {
                    /* ID Parity Error */
                    g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
                    g_state = IDLE;
                    
                    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId), USART_CTRL1_RXBNEIEN_MASK);
                    REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
                    REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);

                }
                break;
                                            
            case RECV_DATA:
                *(g_dataPtr) = ch;
                g_dataPtr++;
                if(g_cntByte == 8U)
                {
                    if(Lin_Hw_CheckSum(g_responseBuf, g_pid) == ch)
                    {  
                        g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
                        g_state = IDLE;
                        g_receiveOnceFlg = 1;
                        REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId), USART_CTRL1_RXBNEIEN_MASK | USART_CTRL1_TXCIEN_MASK | USART_CTRL1_TXBEIEN_MASK);
                        REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
                        REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);
                    }
                    else
                    {
                        g_idleTimeoutCnt=MAX_IDLE_TIMEOUT;
                        g_state = IDLE;
                    }
                }
                else
                {
                    /* nothing */
                }
                g_cntByte = idx + 1U;
                break;
                                    
             case SEND_DATA:
                 /* TX Buffer Empty - Checksum Sent */
                if(REG_BIT_GET32(USART_STS_REG_ADDR(ChannelId),USART_STS_TXBEFLG_MASK) == 0u)
                {
                    /* Set max idle timeout */
                    g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
                    g_state = IDLE;
                
                    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId), USART_CTRL1_RXBNEIEN_MASK);
                    REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
                    REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);
                    break;
                }
                else
                {
                    /* nothing */
                }
                /* Send checksum byte */
                if(g_cntByte == 8U)  
                {                    
                    sendData = Lin_Hw_CheckSum(g_sendBuf, g_linMsgCfgTable[g_frameIndex].protected_id);
                    g_checkSum = sendData;
                    g_state = SEND_DATA_COMPLETED;    
                    Lin_Hw_PutChar (sendData, ChannelId); 
                }
                else
                {
                    if(g_sendBuf[g_cntByte-1U] == ch) 
                    {
                        /* Send byte next */                    
                        sendData = g_sendBuf[g_cntByte];
                        Lin_Hw_PutChar (sendData, ChannelId);  
                        g_cntByte = idx + 1U;
                    }
                    else
                    {
                        /* Set max idle timeout */
                        g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
                        g_state = IDLE;
    
                        REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
                        REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);
                        break;
                    }
                 }                    
                 break;
                                             
            case SEND_DATA_COMPLETED:
                 /* set lin status: successful_transfer */
                 g_idleTimeoutCnt = MAX_IDLE_TIMEOUT;
                 g_state = IDLE;
                 
                 REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChannelId), USART_CTRL1_RXBNEIEN_MASK);
                 REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChannelId), USART_INTFCLR_LBDCLR_MASK);
                 REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChannelId), USART_CTRL2_LBDIEN_MASK);
                 break;

            default:
                /* nothing */
                break;
        }
    }
    else
    {
        /* nothing */
    }
}
#endif 

/*!
* @brief         Interrupt handler for transmission and receive on USART
*
* @param[in]     usartChannelID:   Usart channel ID
*
* @retval        void
*
* @note          None
*/
FUNC(void, LIN_CODE) Lin_Hw_TxRxInterrupt_ProcessingCode(CONST(uint8, AUTOMATIC) usartChannelID)
{
    VAR(boolean, AUTOMATIC) UsartReset = (boolean)FALSE;
    
    VAR(uint32, AUTOMATIC) LinStatus = 0;
    VAR(uint32, AUTOMATIC) rawStatus = 0;
    VAR(uint8, AUTOMATIC) tempLogicalChannel = (uint8)0U;
    #ifdef LIN_MASTER_NODECFG
        VAR(uint32, AUTOMATIC) linEnableInterrupt;
    #endif
    /* Check that the driver is initialized */
    if(NULL_PTR == g_LinPCCfgPointer)
    {
        /* The USART hardware should reset, Disable Transfer Completion and Transfer Data register air break */
        UsartReset = (boolean)TRUE;
    }
    else
    {
        while(LIN_MAX_HW_AVAILABLE_CH_COUNT > tempLogicalChannel)
        {
            if((sint32)usartChannelID != g_ChannelHWMap[g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChId])
            {
                tempLogicalChannel++;
            }
            else
            {
                break;
            }
        }
        if(LIN_MAX_HW_AVAILABLE_CH_COUNT <= tempLogicalChannel)
        {
            /* The USART hardware should reset, Disable Transfer Completion and Transfer Data register air break */
            UsartReset = (boolean)TRUE;
        }
        else
        {
            /* Get the index of the logical channel index from the physical channel */
            rawStatus = REG_READ32(USART_STS_REG_ADDR(usartChannelID));
            LinStatus = rawStatus & (USART_STS_INT_FLAGS_MASK | USART_STS_IDLEFLG_MASK);
            if ((uint32)0U == LinStatus)
            {
                /* nothing */
            }
            else 
            {
                if(usartChannelID == (uint8)0U)
                {
                #if defined(LIN_USART1_NODETYPE) && (0U == LIN_USART1_NODETYPE)
                    #ifdef LIN_MASTER_NODECFG
                        tempLogicalChannel = g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChId;
                        linEnableInterrupt = REG_READ32(USART_CTRL1_REG_ADDR(usartChannelID)) & USART_CTRL1_IE_FLAGS_MASK;
                        UsartReset = Lin_Hw_MasterProcess(usartChannelID,tempLogicalChannel,LinStatus,linEnableInterrupt);
                    #endif
                #else
                    #ifdef LIN_SLAVE_NODECFG
                        Lin_Hw_SlaveProcess(usartChannelID,LinStatus);
                    #endif
                #endif
                }
                else
                {
                #if defined(LIN_USART2_NODETYPE) && (0U == LIN_USART2_NODETYPE)
                    #ifdef LIN_MASTER_NODECFG
                        tempLogicalChannel = g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChId;
                        linEnableInterrupt = REG_READ32(USART_CTRL1_REG_ADDR(usartChannelID)) & USART_CTRL1_IE_FLAGS_MASK;
                        UsartReset = Lin_Hw_MasterProcess(usartChannelID,tempLogicalChannel,LinStatus,linEnableInterrupt);
                    #endif
                #else
                    #ifdef LIN_SLAVE_NODECFG
                        Lin_Hw_SlaveProcess(usartChannelID,LinStatus);
                    #endif
                #endif
                }
            }
        }
    }   
    if((boolean)TRUE != UsartReset)
    {
      /* nothing */
    }
    else
    {
        SchM_Enter_Lin_LIN_CRITICAL_SECTION22();
        {
            /* Unknown interrupts,reset all flags */
            REG_WRITE32(USART_STS_REG_ADDR(usartChannelID), 
                       (uint32)((REG_READ32(USART_STS_REG_ADDR(usartChannelID)) & 
                       (~USART_INTFCLR_MASK)) |
                        USART_STS_INT_FLAGS_MASK));
            Lin_Hw_ClearTxRx(usartChannelID);
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION22();
    }

    return;
}

/*!
* @brief         Interrupt handler for error on USART
**
* @param[in]     usartChannelID:   Usart channel ID
**
* @retval        void
**
* @note          None
*/
FUNC (void, LIN_CODE) Lin_Hw_ErrorInterrupt_ProcessingCode(CONST(uint8, AUTOMATIC) usartChannelID)
{
    VAR(uint8, AUTOMATIC) tempLogicalChannel = (uint8)0U;
    VAR(uint32, AUTOMATIC) LinStatus;
    VAR(uint32, AUTOMATIC) linEnableInterrupt2;
    VAR(uint32, AUTOMATIC) linEnableInterrupt3;
    /* Check if driver is initialized */
    if(NULL_PTR == g_LinPCCfgPointer)
    {
        /* Unknown Error Interrupts */
        SchM_Enter_Lin_LIN_CRITICAL_SECTION24();
        {
            /* Reset all error interrupt flags */
            REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                       (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                       (~USART_INTFCLR_MASK)) | 
                        USART_INTFCLR_ERR_FLAGS_MASK));
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION24();
    }
    else
    {
        while(LIN_MAX_HW_AVAILABLE_CH_COUNT > tempLogicalChannel)
        {
             if((sint32)usartChannelID != g_ChannelHWMap[g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChId])
             {
                tempLogicalChannel++;
            }
            else
            {
                break;
            }
        }

        SchM_Enter_Lin_LIN_CRITICAL_SECTION23();
        {
            /* Unknown Error Interrupts */
            if(LIN_MAX_HW_AVAILABLE_CH_COUNT <= tempLogicalChannel)
            {
                /* Reset all error interrupt flags */
                REG_WRITE32(USART_INTFCLR_REG_ADDR(usartChannelID), 
                           (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(usartChannelID)) & 
                           (~USART_INTFCLR_MASK)) | 
                            USART_INTFCLR_ERR_FLAGS_MASK));
            }
            else
            {
                /* Get the logical channel index from physical channel */
                tempLogicalChannel = g_LinChCfgPtr[tempLogicalChannel]->channelConfigPCPtr->linChId;
                LinStatus = REG_READ32(USART_STS_REG_ADDR(usartChannelID));
                linEnableInterrupt2 = REG_READ32(USART_CTRL2_REG_ADDR(usartChannelID)) & USART_CTRL2_LBDIEN_MASK;
                linEnableInterrupt3 = REG_READ32(USART_CTRL3_REG_ADDR(usartChannelID)) & USART_CTRL3_IE_FLAGS_MASK;

                /* Receiver Overrun Flag */
                if((USART_STS_OVREFLG_MASK == (LinStatus & USART_STS_OVREFLG_MASK)) && 
                   (USART_CTRL3_OVRDEDIS_MASK == (linEnableInterrupt3 & USART_CTRL3_OVRDEDIS_MASK)))
                {
                    Lin_Hw_SetChanFrameState(tempLogicalChannel,
                                             usartChannelID,
                                             USART_STS_OVREFLG_MASK,
                                             LIN_BUFFER_OVER_RUN_INT_ERROR);
                }
                /* Noise Flag */
                else if((USART_STS_NEFLG_MASK == (LinStatus & USART_STS_NEFLG_MASK)) && 
                        (USART_CTRL3_ERRIEN_MASK == (linEnableInterrupt3 & USART_CTRL3_ERRIEN_MASK)))
                {
                    Lin_Hw_SetChanFrameState(tempLogicalChannel,
                                             usartChannelID,
                                             USART_STS_NEFLG_MASK,
                                             LIN_NOISE_INT_ERROR);
                }
                /* Framing Error Flag */
                else if((USART_STS_FEFLG_MASK == (LinStatus & USART_STS_FEFLG_MASK)) && 
                        (USART_CTRL3_ERRIEN_MASK == (linEnableInterrupt3 & USART_CTRL3_ERRIEN_MASK)))
                {
                    if(USART_CTRL2_LBDIEN_MASK == linEnableInterrupt2)
                    {
                        /* LIN break may raise FE before LBD; keep waiting for break detection. */
                        REG_BIT_SET32(USART_INTFCLR_REG_ADDR(usartChannelID), USART_INTFCLR_FECLR_MASK);
                    }
                    else
                    {
                        Lin_Hw_SetChanFrameState(tempLogicalChannel,
                                                 usartChannelID,
                                                 USART_STS_FEFLG_MASK,
                                                 LIN_FRAMING_INT_ERROR);
                    }
                }
                /* Unknown Error Interrupts */
                else
                {
                    /* Reset all error interrupt flags */
                    REG_BIT_SET32(USART_INTFCLR_REG_ADDR(usartChannelID),USART_INTFCLR_ERR_FLAGS_MASK);
                }
            }
        }
        SchM_Exit_Lin_LIN_CRITICAL_SECTION23();
    }
    return;
}

#ifdef LIN_MASTER_NODECFG
LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_LinState_TxRxInterrupt (VAR(uint8, AUTOMATIC) Id,
                                                                 VAR(uint8, AUTOMATIC) ChanID,
                                                                 VAR(uint8, AUTOMATIC) LogicalChan)
{
    VAR(uint8, AUTOMATIC) tempValue;
    VAR(uint8, AUTOMATIC) nextByteBufferPtr;
    
    switch (Id)
    {
        case 19:
            SchM_Enter_Lin_LIN_CRITICAL_SECTION19();
            {
                /* Clear the RX Input Active Edge Interrupt Flag */
                REG_WRITE32(USART_INTFCLR_REG_ADDR(ChanID), 
                           (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(ChanID)) &
                           (~USART_INTFCLR_MASK)) | 
                            USART_INTFCLR_WSMCLR_MASK));

                tempValue = g_LinChannelStatus[LogicalChan];
                /* Check whether the Lin channel status is LIN_CH_SLEEP_STATE */
                if ((uint8)LIN_CH_SLEEP_STATE == tempValue)
                {
                    /* set the idle flag after receiving an idle character */
                    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID),USART_CTRL1_RXBNEIEN_MASK);
                    REG_BIT_SET32(USART_CTRL2_REG_ADDR(ChanID), USART_INTFCLR_LBDCLR_MASK);
                    REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChanID), USART_CTRL2_LBDIEN_MASK);
                }
                else
                {
                    /* Do nothing */
                }
            }
            SchM_Exit_Lin_LIN_CRITICAL_SECTION19();
            break;
        case 11:
            SchM_Enter_Lin_LIN_CRITICAL_SECTION11();
            {
                /* Disable TX Complete Interrupt */
                REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXCIEN_MASK);

                /* wait Break Frame Complete */
                while(((uint32)(REG_READ32(USART_STS_REG_ADDR(ChanID))) & USART_STS_TXBFFLG_MASK) !=  0)
                {
                    /* do nothing */
                }

                /* Enable Error Interrupts */
                REG_BIT_SET32(USART_INTFCLR_REG_ADDR(ChanID),USART_INTFCLR_ERR_FLAGS_MASK);

                REG_RMW32(USART_CTRL3_REG_ADDR(ChanID), USART_CTRL3_ERRIEN_MASK,1);

                /* Remove USART Rx Buffer */
                REG_READ32(USART_RXDATA_REG_ADDR(ChanID));

                /* Enable RX Interrupt */
                REG_BIT_SET32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_RXBNEIEN_MASK);
            }
            SchM_Exit_Lin_LIN_CRITICAL_SECTION11();

            /* TX the next byte */
            nextByteBufferPtr = g_LinUsartNextByteBufferPtr[LogicalChan];
            REG_WRITE32(USART_TXDATA_REG_ADDR(ChanID), 
                        g_LinUsartDataBuffer[LogicalChan][nextByteBufferPtr]);
            break;
        case 10:
            SchM_Enter_Lin_LIN_CRITICAL_SECTION10();
            {
                /* Disable TX Interrupts */
                REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXBEIEN_MASK);
                /* Enable RX Interrupt */
                REG_BIT_SET32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_RXBNEIEN_MASK);
            }
            SchM_Exit_Lin_LIN_CRITICAL_SECTION10();

            /* TX the next byte */
            nextByteBufferPtr = g_LinUsartNextByteBufferPtr[LogicalChan];
            REG_WRITE32(USART_TXDATA_REG_ADDR(ChanID), g_LinUsartDataBuffer[LogicalChan][nextByteBufferPtr]);
            break;
        default: 
            break;
    }
}
#endif 

LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_SetChanFrameState(VAR(uint8, AUTOMATIC) LogicalChannel,
                                                           VAR(uint8, AUTOMATIC) ChanID,
                                                           VAR(uint32, AUTOMATIC) RegMask,
                                                           VAR(Lin_InterruptErrorsType, AUTOMATIC) error)
{
    /* Clear Receiver Overrun Flag */
    REG_WRITE32(USART_INTFCLR_REG_ADDR(ChanID), 
               (uint32)((REG_READ32(USART_STS_REG_ADDR(ChanID)) & 
               (~USART_INTFCLR_MASK)) | 
                RegMask));
    /* Disable Transmit Interrupt */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXBEIEN_MASK);
    /* Disable Receiver Interrupt */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_RXBNEIEN_MASK);
    /* Set LIN channel frame error status to LIN_BUFFER_OVER_RUN_INT_ERROR */
    g_LinChannelFrameErrorStatus[LogicalChannel] = (uint8)error;
}


LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_ClearTxRx(VAR(uint8, AUTOMATIC) ChanID)
{
    /* Disable TX Interrupt */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXBEIEN_MASK);
    /* Disable RX Interrupt */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_RXBNEIEN_MASK);
    /* Disable TX Complete Interrupt */
    REG_BIT_CLEAR32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXCIEN_MASK);
}

LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_RxInterrupt(VAR(uint8, AUTOMATIC) ChanID,
                                                     VAR(boolean, AUTOMATIC) EnaInterrupt)
{
    /* Disable wake-up detection */
    /* Clear the Wakeup From Stop Mode Flag */
    REG_WRITE32(USART_INTFCLR_REG_ADDR(ChanID),
               (uint32)((REG_READ32(USART_INTFCLR_REG_ADDR(ChanID)) &
               (~USART_INTFCLR_MASK)) |
               USART_INTFCLR_WSMCLR_MASK));
    if(EnaInterrupt == (boolean)TRUE)
    {
        /* Enable Wakeup from Stop mode interrupt */
        REG_BIT_SET32(USART_CTRL3_REG_ADDR(ChanID), USART_CTRL3_WSMIEN_MASK);
    }
    else
    {
        /* Disable Wakeup from Stop mode interrupt */
        REG_BIT_CLEAR32(USART_CTRL3_REG_ADDR(ChanID), USART_CTRL3_WSMIEN_MASK);
    }
}

LOCAL_INLINE FUNC(void, LIN_CODE) Lin_Hw_EnaTxinterrupt(VAR(uint8, AUTOMATIC) ChanID)
{
    /* Disable error interrupt */
    REG_RMW32(USART_CTRL3_REG_ADDR(ChanID), USART_CTRL3_ERRIEN_MASK, 0);
    /* Remove USART Rx Buffer */
    REG_READ32(USART_RXDATA_REG_ADDR(ChanID));
    /* TX break character */
    REG_WRITE32(USART_REQUEST_REG_ADDR(ChanID), USART_REQUEST_TXBFQ_MASK);
    /* Enable TX Complete Interrupt */
    REG_BIT_SET32(USART_CTRL1_REG_ADDR(ChanID), USART_CTRL1_TXCIEN_MASK);
}

#if defined(LIN_USART2)
/*!
* @brief    This function is an interrupt handling function: interrupt that occurred at LIN_USART2
*/
ISR(USART2_IRQHandler)
{
    Lin_Hw_TxRxInterrupt_ProcessingCode(LIN_USART2);
    Lin_Hw_ErrorInterrupt_ProcessingCode(LIN_USART2);
    EXIT_INTERRUPT();
}
#endif

#if defined(LIN_USART1)
/*!
* @brief    This function is an interrupt handling function: interrupt that occurred at LIN_USART1
*/
ISR(USART1_IRQHandler)
{
    Lin_Hw_TxRxInterrupt_ProcessingCode(LIN_USART1);
    Lin_Hw_ErrorInterrupt_ProcessingCode(LIN_USART1);
    EXIT_INTERRUPT();
}
#endif
    
#define LIN_STOP_SEC_CODE
#include "Lin_MemMap.h"

/**@} end of group LIN_Fuctions */
#ifdef __cplusplus
}
#endif 
/**@} end of group LIN_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
