/*!
* @file     CDD_Usart.c
*
* @version  1.0.0
*
* @brief    Usart Driver implementations
*
* @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 "stdio.h"
#include "Reg_eSys.h"
#include "CDD_Usart.h"
#include "Usart_Hw.h"
#include "CDD_Usart_Cfg.h"

#include "g32a1085.h"

#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
#include "Det.h"
#endif

#if (STD_ON == USART_DMA_SUPPORT)
#include "Mcu_SysCfgReg.h"
#include "Mcu_SysCfgTypes.h"
#include "CDD_Pdl.h"
#endif

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup USART_Driver
  * @brief USART driver modules
  @{
*/

/** @defgroup USART_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define CDD_USART_DRV_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CDD_USART_DRV_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CDD_USART_DRV_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CDD_USART_DRV_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define CDD_USART_DRV_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CDD_USART_DRV_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CDD_USART_DRV_SW_PATCH_VERSION                       0x00U

/**@} end of group USART_Macros */
/*******************************************************************************
                              GLOBAL VARIABLE
*******************************************************************************/
/** @defgroup USART_Variable
  @{
*/

/** Pointer to lpuart runtime state structure */
Usart_StateType g_lpuartStatus[USART_INSTANCE_CNT] = 
{
    {
    .usartId       = USART1_ID,
    .mode          = USART_MODE_NONE,
    .modeSelect    = USART_FULL_DUPLEX_ASYN,
    .rxDmaChannel  = 0u,
    .txDmaChannel  = 0u,
    .rxStatus      = STATUS_USART_SUCCESS,
    .txStatus      = STATUS_USART_SUCCESS,
    .rxBusy        = (boolean)FALSE,
    .txBusy        = (boolean)FALSE,
    .rxBlocking    = (boolean)FALSE,
    .txBlocking    = (boolean)FALSE,
    .rxLen         = 0u,
    .txLen         = 0u,
    .rxBuffer      = (uint16 *)0,
    .txBuffer      = (const uint8 *)0,
    .transferType  = USART_USE_DMA,
    .wordLength    = USART_WORD_LEN_8B,
    .stopBits      = USART_STOP_BIT_1,
    .parity        = USART_PARITY_NONE,
    },
    {
    .usartId       = USART1_ID,
    .mode          = USART_MODE_NONE,
    .modeSelect    = USART_FULL_DUPLEX_ASYN,
    .rxDmaChannel  = 0u,
    .txDmaChannel  = 0u,
    .rxStatus      = STATUS_USART_SUCCESS,
    .txStatus      = STATUS_USART_SUCCESS,
    .rxBusy        = (boolean)FALSE,
    .txBusy        = (boolean)FALSE,
    .rxBlocking    = (boolean)FALSE,
    .txBlocking    = (boolean)FALSE,
    .rxLen         = 0u,
    .txLen         = 0u,
    .rxBuffer      = (uint16 *)0,
    .txBuffer      = (const uint8 *)0,
    .transferType  = USART_USE_DMA,
    .wordLength    = USART_WORD_LEN_8B,
    .stopBits      = USART_STOP_BIT_1,
    .parity        = USART_PARITY_NONE,
    }
};

#if (STD_ON == USART_DMA_SUPPORT)
/** usart dma channel config */
Pdl_DmaChHwConfigType g_usartDmaChHwConfigPtr[] =
{
    {
    .memAddr = 0,
    .periphAddr = 0,
    .dir = (Pdl_DmaDirType)DMA_DIR_PERIPHERAL,
    .bufSize = 0,
    .memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_BYTE,
    .periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_BYTE,
    .memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_DISABLE,
    .periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE,
    .circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE,
    .priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_LOW,
    .mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE
    }, //Tx
    {
    .memAddr = 0,
    .periphAddr = 0,
    .dir = (Pdl_DmaDirType)DMA_DIR_PERIPHERAL,
    .bufSize = 0,
    .memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_BYTE,
    .periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_BYTE,
    .memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_DISABLE,
    .periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE,
    .circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE,
    .priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_LOW,
    .mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE
    } //Rx
};

#endif

/**@} end of group USART_Variable */
/*******************************************************************************
                         LOCAL FUNCTION PROTOTYPES
*******************************************************************************/
/** @defgroup USART_Fuctions
  @{
*/

static FUNC(void, USART_CODE) Usart_DisableAllRxInterrupts(Usart_UsartIdType usartId);
static FUNC(void, USART_CODE) Usart_DisableAllTxInterrupts(Usart_UsartIdType usartId);
static FUNC(void, USART_CODE) Usart_ResetRxRuntimeState(Usart_StateType * states, Usart_StatusType status);
static FUNC(void, USART_CODE) Usart_ResetTxRuntimeState(Usart_StateType * states, Usart_StatusType status);
static FUNC(Usart_StatusType, USART_CODE) Usart_StartTxDataUsingInt(Usart_UsartIdType usartId,
                                                                    const uint8 *txBuf,
                                                                    uint32 txLen);
static FUNC(Usart_StatusType, USART_CODE) Usart_StartRxDataUsingInt(Usart_UsartIdType usartId,
                                                                    uint16 *rxBuf,
                                                                    uint32 rxLen);
#if (STD_ON == USART_DMA_SUPPORT)
static FUNC(Usart_StatusType, USART_CODE) Usart_StartTxDataUsingDma(Usart_UsartIdType usartId,
                                                                    const uint8 *txBuf,
                                                                    uint32 txLen);
static FUNC(Usart_StatusType, USART_CODE) Usart_StartRxDataUsingDma(Usart_UsartIdType usartId,
                                                                    uint16 *rxBuf,
                                                                    uint32 rxLen);
static FUNC(void, USART_CODE) Usart_DmaUsart1RxInit(void);
static FUNC(void, USART_CODE) Usart_DmaUsart1TxInit(void);
static FUNC(void, USART_CODE) Usart_DmaUsart2RxInit(void);
static FUNC(void, USART_CODE) Usart_DmaUsart2TxInit(void);
#endif
/*******************************************************************************
                              LOCAL FUNCTION
*******************************************************************************/
/*!
* @brief       Disables all RX-related USART interrupts (polling safe)
*/
static FUNC(void, USART_CODE) Usart_DisableAllRxInterrupts(Usart_UsartIdType usartId)
{
    Usart_Hw_OperationInterrupt(usartId, USART_INT_ERRIE, DISABLE);
    Usart_Hw_OperationInterrupt(usartId, USART_INT_PEIE, DISABLE);
    Usart_Hw_OperationInterrupt(usartId, USART_INT_RXTOIE, DISABLE);
    Usart_Hw_OperationInterrupt(usartId, USART_INT_RXBNEIE, DISABLE);
}

/*!
* @brief       Disables all TX-related USART interrupts (polling safe)
*/
static FUNC(void, USART_CODE) Usart_DisableAllTxInterrupts(Usart_UsartIdType usartId)
{
    Usart_Hw_OperationInterrupt(usartId, USART_INT_TXBEIE, DISABLE);
    Usart_Hw_OperationInterrupt(usartId, USART_INT_TXCIE, DISABLE);
}

/*!
* @brief       Clears driver RX runtime state after transfer ends
*/
static FUNC(void, USART_CODE) Usart_ResetRxRuntimeState(Usart_StateType * states, Usart_StatusType status)
{
    states->rxBusy = (boolean)FALSE;
    states->rxLen = 0U;
    states->rxBuffer = (uint16 *)0;
    states->rxStatus = status;
}

/*!
* @brief       Clears driver TX runtime state after transfer ends
*/
static FUNC(void, USART_CODE) Usart_ResetTxRuntimeState(Usart_StateType * states, Usart_StatusType status)
{
    states->txBusy = (boolean)FALSE;
    states->txLen = 0U;
    states->txBuffer = (const uint8 *)0;
    states->txStatus = status;
}

/*******************************************************************************
                              GLOBAL FUNCTION
*******************************************************************************/
/*!
* @brief       Initializes all USART channels based on configuration array
*
* @param       usartConfig     Pointer to USART configuration array
*
* @retval      None
*
* @note        Performs null pointer check and reports error via DET
* @note        Initializes runtime status structures and hardware registers
* @note        Conditionally initializes DMA support if enabled in config
*/
FUNC(void, USART_CODE) Usart_Init(P2CONST(Usart_ConfigType, AUTOMATIC, USART_APPL_CONST) usartConfig)
{
    uint32 index = 0U;  
    Usart_StateType *tempStates = NULL;
    
    /* Check if the input pointer is valid */
    if (NULL == usartConfig)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_INIT_SVC_ID, USART_E_PARAM_POINTER);
#endif
    }
    else
    {
        /* Initialize each USART channel in sequence */
        for (index = 0U; index < (uint32)USART_CHANNEL_NUM; index++)
        {
            /* Obtain and record the pointer to the runtime status structure */
            tempStates = &g_lpuartStatus[usartConfig[index].usartId];
            
            /* Configure runtime status according to the provided settings */
            tempStates->usartId        = usartConfig[index].usartId;
            tempStates->mode           = usartConfig[index].mode;
            tempStates->modeSelect     = usartConfig[index].modeSelect;
            tempStates->txDmaChannel   = usartConfig[index].txDmaChannel;
            tempStates->rxDmaChannel   = usartConfig[index].rxDmaChannel;
            tempStates->transferType   = usartConfig[index].transferType;
            tempStates->wordLength     = usartConfig[index].wordLength;
            tempStates->rxStatus       = STATUS_USART_SUCCESS;
            tempStates->txStatus       = STATUS_USART_SUCCESS;
            tempStates->stopBits       = usartConfig[index].stopBits;
            tempStates->parity         = usartConfig[index].parity;

            
            if (tempStates->modeSelect == USART_HALF_DUPLEX)
            {
                Usart_Hw_OperationHalfDuplex(tempStates->usartId,ENABLE);
            }
            else if (tempStates->modeSelect == USART_FULL_DUPLEX_SYN)
            {
                Usart_Hw_OperationSynchronousMode(tempStates->usartId,ENABLE);
                Usart_Hw_OperationCPolHigh(tempStates->usartId,g_usartSyncConfg[tempStates->usartId].clkPol);
                Usart_Hw_OperationCPhaTwo(tempStates->usartId,g_usartSyncConfg[tempStates->usartId].clkPha);
                Usart_Hw_OperationLastBitOutput(tempStates->usartId,g_usartSyncConfg[tempStates->usartId].lastBitOutput);
            }
            else
            {
                /* nothing */
            }
            
            /* Call the hardware-later function to configure registers */
            Usart_Hw_Config(tempStates->usartId, &usartConfig[index]);
            
            /* Enable the USART channel */
            Usart_Hw_Operation(tempStates->usartId, ENABLE);
            
            Usart_Hw_ClearStatusFlag(tempStates->usartId, (uint32)USART_FLAG_TXC); 
            
#if (STD_ON == USART_DMA_SUPPORT)
            if ((tempStates->transferType == USART_USE_DMA) &&
                (tempStates->usartId == USART1_ID))
            {
                Usart_DmaUsart1RxInit();
                Usart_DmaUsart1TxInit();
            }
            else if ((tempStates->transferType == USART_USE_DMA) &&
                     (tempStates->usartId == USART2_ID))
            {
                Usart_DmaUsart2RxInit();
                Usart_DmaUsart2TxInit();
            }
#endif
        }
    }
}


/**
* @brief       Sends data via the USART using polling mode.
*
* @details
* This function transmits the specified number of bytes from a given buffer
* through the USART in polling mode. It continuously checks if the transmit
* buffer is empty (TXBE) before sending each byte. If a timeout occurs while
* waiting, it reports an error and returns STATUS_USART_TIMEOUT.
*
* Key steps:
* 1. Validates input parameters such as usartId and the pointer to the buffer (txBuf).
* 2. Checks if the USART is currently busy or if it only supports RX mode.
* 3. Enables the USART transmitter, then sends data byte-by-byte.
* 4. After all bytes have been transmitted, waits for the TXC (transmission complete) flag.
* 5. Disables the USART transmitter and updates internal state before returning.
*
* @param[in]  usartId  The identifier of the USART channel to use.
* @param[in]  txBuf    Pointer to the data buffer to be transmitted.
* @param[in]  txLen    The number of bytes to send (if 9-bit mode is used, it decrements
*                      by 2 for each transmission).
*
* @note
* - If txBuf is NULL, the function reports an invalid pointer error (USART_E_PARAM_POINTER) via Det_ReportError().
* - If the USART is already busy transmitting data, a state transition error (USART_E_STATE_TRANSITION) is reported.
* - If the USART is configured only for RX mode, the function returns STATUS_USART_UNSUPPORTED.
* - For 9-bit word length, each data item is 2 bytes.
*
* @return
* - STATUS_USART_SUCCESS  Transmission completed successfully.
* - STATUS_USART_ERROR    A parameter or state error occurred.
* - STATUS_USART_TIMEOUT  Transmission timed out.
* - STATUS_USART_UNSUPPORTED  The current mode does not support TX operations.
*/
FUNC(Usart_StatusType, USART_CODE) Usart_TxDataPolling(Usart_UsartIdType usartId, 
                                                        const uint8 *txBuf, 
                                                        uint32 txLen)
{
    Usart_StatusType result = STATUS_USART_SUCCESS;
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    uint32 timeout = TXBE_POLLING_TIMEOUT;
    uint8 txStarted = 0U;
    uint32 tempTxLen = txLen;
    const uint8 * tempVal = NULL; 

    if ((boolean)FALSE == Usart_Hw_GetUsartState(usartId))
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATAPOLLING_SVC_ID, USART_E_UNINIT);
#endif
        result = STATUS_USART_ERROR;
    }
    /* Check for NULL buffer pointer */
    else if (NULL == txBuf)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATAPOLLING_SVC_ID, USART_E_PARAM_POINTER);
        result = STATUS_USART_ERROR;
#endif
    }
    /* Check if TX is already busy */
    else if ((boolean)0 != tempStates->txBusy)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATAPOLLING_SVC_ID, USART_E_STATE_TRANSITION);
#endif
        result = STATUS_USART_ERROR;
    }    
    /* Check if current mode supports transmission */
    else if (tempStates->mode == USART_MODE_RX)
    {
        result = STATUS_USART_UNSUPPORTED;
    }  
    /* If no data length is specified, simply return */
    else if (0U == tempTxLen)
    {
        /* nothing */
    }
    else
    {
        /* Polling mode: ensure tx USART interrupts stay disabled */
        Usart_DisableAllTxInterrupts(usartId);

        /* Mark TX as busy and enable transmitter */
        tempStates->txBusy = TRUE;
        tempStates->txStatus = STATUS_USART_BUSY;
        Usart_Hw_OperationDirectionMode(usartId, USART_MODE_TX, ENABLE);
        txStarted = 1U;

        /* Save pointer and begin transmitting */
        tempStates->txBuffer = txBuf;
        tempStates->txLen = txLen;
        tempVal = tempStates->txBuffer;
        
        /* Send data until txLen is exhausted */
        while (tempTxLen > 0U)
        {
            timeout = TXBE_POLLING_TIMEOUT;
            /* Wait for TX buffer empty (TXBE) flag */
            while (timeout > 0U)
            {
                --timeout;
                if ((uint8)0 == Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_TXBE))
                {
                    /* nothing */
                }
                else
                {
                    break;
                }
            }
            if ((uint32)timeout == (uint32)0)
            {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
                (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                                    USART_TXDATAPOLLING_SVC_ID, USART_E_TIMEOUT);
#endif
                result = STATUS_USART_TIMEOUT;
                break;
            }
            else
            {
                /* nothing */
            }

            /* Write data to hardware */
            Usart_Hw_TxData(usartId, tempVal);
            
            if (tempStates->modeSelect == USART_HALF_DUPLEX)
            {
                if (*tempVal != Usart_Hw_RxData(tempStates->usartId))
                {
                    tempStates->txStatus = STATUS_USART_ERROR;
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                /* nothing */
            }

            /* Decrement length differently if 9-bit data is used */
            if (g_lpuartStatus[usartId].parity != USART_PARITY_NONE)
            {
                ++tempVal;
                --tempTxLen;
            }
            else
            {
                if (tempStates->wordLength == USART_WORD_LEN_9B)
                {
                    ++tempVal;
                    ++tempVal;
                    tempTxLen -= 2U;
                }
                else
                {
                    ++tempVal;
                    --tempTxLen;
                }
            }
        }
        
        /* Wait for the transmission to complete (TXC flag) */
        timeout = TXBE_POLLING_TIMEOUT;
        while ((uint8)0 == Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_TXC))
        {
            --timeout;
            if (timeout == 0U)
            {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
                (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                                USART_TXDATAPOLLING_SVC_ID, USART_E_TIMEOUT);
#endif
                result = STATUS_USART_ERROR;
                break;
            }
            else
            {
                /* nothing */
            }
        }
    }

    if (txStarted == 1U)
    {
        /* Disable the transmitter and clear runtime state */
        Usart_Hw_OperationDirectionMode(usartId, USART_MODE_TX, DISABLE);
        Usart_DisableAllTxInterrupts(usartId);
        Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_TXC);
        if (result != STATUS_USART_SUCCESS)
        {
            Usart_ResetTxRuntimeState(tempStates, result);
        }
        else
        {
            Usart_ResetTxRuntimeState(tempStates, STATUS_USART_SUCCESS);
        }
    }
    else
    {
        /* nothing */
    }

    return result;
}


/**
* @brief       Receives data using the USART interface in polling mode.
*
* @details
* This function receives a specified number of data units via a given USART channel in
* polling mode. It checks for data availability (RXBNE) before each read. It then reads
* one data element at a time, storing it into the supplied buffer. If errors such as
* parity, framing, noise, or overrun occur, the function sets the corresponding error
* status and clears the hardware error flag. After completion or upon error, the RX 
* operation is disabled and the function returns the status.
*
* Key steps:
* 1. Validates input parameters, such as the pointer rxBuf, ensuring it is not NULL.
* 2. Checks if the USART is already busy receiving data or if the current mode is not RX-capable.
* 3. Enables the RX direction, starts polling, and waits for RXBNE (Receive Buffer Not Empty) flag.
* 4. Reads each data element into rxBuf and checks for any hardware error flags.
* 5. Disables RX upon completion or error, and returns the corresponding status code.
*
* @param[in]  usartId  The USART channel identifier (0..USART_CHANNEL_NUM-1).
* @param[out] rxBuf    Pointer to a buffer where the received data will be stored.
* @param[in]  rxLen    The number of data units to receive (bytes for 8-bit mode, 
*                      or half-word steps for 9-bit mode).
*
* @note
* - For 9-bit word length, each received data element increments the buffer pointer by 2
*   and decreases rxLen by 2.
* - If an error flag is detected (parity, framing, noise, or overrun), the function returns
*   immediately after clearing the flag and sets the corresponding error status.
* - If rxBuf is NULL, a null pointer error (USART_E_PARAM_POINTER) is reported, and the
*   function returns STATUS_USART_ERROR.
* - If the USART is busy or in an unsupported mode, it also returns an error status.
*
* @return
* - STATUS_USART_SUCCESS        Data reception was successful.
* - STATUS_USART_ERROR          A parameter or state transition error occurred.
* - STATUS_USART_BUSY           The USART is currently busy.
* - STATUS_USART_UNSUPPORTED    The current mode does not support RX operation.
* - STATUS_USART_PARITY_ERROR   A parity error was detected during reception.
* - STATUS_USART_FRAMING_ERROR  A framing error was detected.
* - STATUS_USART_NOISE_ERROR    A noise error was detected.
* - STATUS_USART_RX_OVERRUN     An overrun error was detected.
*/
FUNC(Usart_StatusType, USART_CODE) Usart_RxDataPolling(Usart_UsartIdType usartId,
                                                       uint16 *rxBuf,
                                                       uint32 rxLen)
{
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
    uint32 timeout = TXBE_POLLING_TIMEOUT;
    uint8 rxStarted = 0U;
    uint32 tempRxLen = rxLen;
    uint16 * tempVal = NULL;
    uint8 tempFlag = 0;
    
    if ((boolean)FALSE == Usart_Hw_GetUsartState(usartId))
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_RXDATAPOLLING_SVC_ID, USART_E_UNINIT);
#endif
        result = STATUS_USART_ERROR;
    }
    /* Check if the provided buffer pointer is valid */
    else if (NULL == rxBuf)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_RXDATAPOLLING_SVC_ID, USART_E_PARAM_POINTER);
#endif
        result = STATUS_USART_ERROR;
    }
    /* Check if the receiver is already busy */
    else if ((boolean)0 != tempStates->rxBusy)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_RXDATAPOLLING_SVC_ID, USART_E_STATE_TRANSITION);
#endif
        result = STATUS_USART_BUSY;
    }
    /* Check if the USART supports RX mode */
    else if (tempStates->mode == USART_MODE_TX)
    {
        result = STATUS_USART_UNSUPPORTED;
    }
    else
    {
        /* Polling mode: ensure rx USART interrupts stay disabled */
        Usart_DisableAllRxInterrupts(usartId);
        Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_RXTOF);

        /* Mark the receiver as busy and enable RX direction */
        tempStates->rxBusy = TRUE;
        tempStates->rxStatus = STATUS_USART_BUSY;
        Usart_Hw_OperationDirectionMode(usartId, USART_MODE_RX, ENABLE);
        
        rxStarted = 1U;
        
        tempStates->rxBuffer = rxBuf;
        tempStates->rxLen = rxLen;
        tempVal = tempStates->rxBuffer;
        
        /* Receive data in polling mode */
        while ((tempRxLen > 0U) && (result != STATUS_USART_TIMEOUT))
        {
            timeout = TXBE_POLLING_TIMEOUT;
            /* Wait for data to become available (RXBNE) */
            while (timeout > 0U)
            {
                /* Potential timeout logic could be inserted here if needed. */
                
                --timeout;
                if ((uint8)0 == Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_RXBNE))
                {
                    break;
                }
                else
                {
                    /* nothing */
                }
            }
            if ((uint32)timeout == (uint32)0)
            {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
                (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_RXDATAPOLLING_SVC_ID, USART_E_TIMEOUT);
#endif
                result = STATUS_USART_TIMEOUT;
            }
            else
            {
                /* Read one data element */
                *tempVal = Usart_Hw_RxData(usartId);
                
                if (g_lpuartStatus[usartId].parity != USART_PARITY_NONE)
                {
                    if (tempStates->wordLength == USART_WORD_LEN_9B)
                    {
                        *tempVal = *tempVal &(uint16)0xFF;
                    }
                    else if (tempStates->wordLength == USART_WORD_LEN_8B)
                    {
                        *tempVal = *tempVal & (uint16)0xEF;
                    }
                    else
                    {
                        /* nothing */
                    }
                }
                else if (tempStates->wordLength == USART_WORD_LEN_8B)
                {
                    *tempVal = *tempVal & (uint16)0xFFU;
                }
                else
                {
                    /* nothing */
                }
                --tempRxLen;
                ++tempVal;
                
                /* Check and clear any error flags */
                if ((uint8)0 != Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_PEF))
                {
                    result = STATUS_USART_PARITY_ERROR;
                    Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_PEF);
                    tempFlag = 1;
                }
                else if ((uint8)0 != Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_FEF))
                {
                    result = STATUS_USART_FRAMING_ERROR;
                    Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_FEF);
                    tempFlag = 1;
                }
                else if ((uint8)0 != Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_NEF))
                {
                    result = STATUS_USART_NOISE_ERROR;
                    Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_NEF);
                    tempFlag = 1;
                }
                else if ((uint8)0 != Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_OVRE))
                {
                    result = STATUS_USART_RX_OVERRUN;
                    Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_OVRE);
                    tempFlag = 1;
                }
                else
                {
                    tempFlag = 0;
                }
                        
                if (tempFlag == (uint8)1)
                {
                    break;
                }
                else
                {
                    /* nothing */
                }
            }
        }
    }

    if (rxStarted == 1U)
    {
        /* Disable the RX direction and clear runtime state */
        Usart_Hw_OperationDirectionMode(usartId, USART_MODE_RX, DISABLE);
        Usart_DisableAllRxInterrupts(usartId);
        Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_RXTOF);
        Usart_ResetRxRuntimeState(tempStates, result);
    }
    else
    {
        /* nothing */
    }
    
    return result;
}



/**
* @brief       Transmits data based on the configured transfer method (interrupt or DMA).
*
* @details
* This function checks the validity of the transmission buffer pointer (txBuf) and the current
* USART operating mode. If valid, it calls either a DMA-based transmit function or an interrupt-based 
* transmit function depending on the USART configuration.  
*
* Operational flow:
* 1. Validates the pointer to the transmit buffer. If it's NULL, reports an error (USART_E_PARAM_POINTER).
* 2. Checks if the USART is configured for RX-only mode (USART_MODE_RX):
*    - If yes, the function returns STATUS_USART_UNSUPPORTED.
* 3. Depending on transferType (USART_USE_DMA or interrupt-based), calls the corresponding 
*    data transmission function:
*    - Usart_StartTxDataUsingDma()
*    - Usart_StartTxDataUsingInt()
* 4. Returns a status code indicating success or failure.
*
* @param[in]  usartId  The identifier for the USART channel to use.
* @param[in]  txBuf    Pointer to the buffer holding data to be transmitted.
* @param[in]  txLen    The length of the data buffer (in bytes).
*
* @note
* - This function does not handle the actual byte-by-byte transmission in polling mode.
* - Caller must ensure the USART is properly initialized and configured before invoking this function.
* - If txBuf is invalid, an error is logged via Det_ReportError() and STATUS_USART_ERROR is returned.
*
* @return
* - STATUS_USART_SUCCESS    The data transmission routine was successfully initiated.
* - STATUS_USART_ERROR      The pointer to the transmit buffer was invalid (NULL).
* - STATUS_USART_UNSUPPORTED The USART is in RX mode only.
* - Other status codes      Depending on the DMA or interrupt starting routine.
*/
FUNC(Usart_StatusType, USART_CODE) Usart_TxData(Usart_UsartIdType usartId,
                                                const uint8 *txBuf,
                                                uint32 txLen)
{
    Usart_StateType const * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
  
    if ((boolean)FALSE == Usart_Hw_GetUsartState(usartId))
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATA_SVC_ID, USART_E_UNINIT);
#endif
        result = STATUS_USART_ERROR;
    }
    else
    {
        /* Check if the transmit buffer pointer is valid */
        if (NULL == txBuf)
        {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
            /* Report error: invalid pointer */
            (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID,
                            USART_INSTANCE_MODULE_ID,
                            USART_TXDATA_SVC_ID,
                            USART_E_PARAM_POINTER);
#endif
            result = STATUS_USART_ERROR;
        }
        else
        {
            /* Check if current mode supports transmission */
            if (tempStates->mode == USART_MODE_RX)
            {
                result = STATUS_USART_UNSUPPORTED;
            }
            else
            {
#if (STD_ON == USART_DMA_SUPPORT)
                /* Choose between DMA and interrupt-based transfer */
                if (tempStates->transferType == USART_USE_DMA)
                {
                    result = Usart_StartTxDataUsingDma(usartId, txBuf, txLen);
                }
                else
                {
#endif
                    result = Usart_StartTxDataUsingInt(usartId, txBuf, txLen);
#if (STD_ON == USART_DMA_SUPPORT)
                }
#endif
            }
        }
    }
    
    return result;
}



/**
* @brief       Receives data using either DMA or interrupt-based methods, depending on configuration.
*
* @details
* This function initiates a receive operation for a specified USART channel (usartId).
* It first verifies that rxBuf is not NULL, then checks whether the USART is
* able to receive data (not in TX-only mode). Depending on transferType, it calls
* either a DMA-based function (Usart_StartRxDataUsingDma) or an interrupt-based
* function (Usart_StartRxDataUsingInt) to process the incoming data.
*
* Operational steps:
* 1. Verifies the pointer to the receive buffer. If NULL, calls Det_ReportError() and returns STATUS_USART_ERROR.
* 2. Checks if the current mode is RX-capable (not in USART_MODE_TX).
* 3. Chooses the appropriate transfer method based on transferType (DMA or interrupt).
* 4. Initiates the receive routine via the corresponding helper function.
*
* @param[in]   usartId  The ID number of the USART channel to be used.
* @param[out]  rxBuf    Pointer to the buffer where received data will be stored.
* @param[in]   rxLen    The length of the receive buffer (in words or bytes, depending 
*                       on the USART word length).
*
* @note 
* - The caller is responsible for ensuring that the hardware, clocks, etc. have been 
*   correctly configured, and that the USART is in a valid state for reception.
* - If rxBuf is invalid, an error is reported and the function terminates early.
*
* @return
* - STATUS_USART_SUCCESS      Receive operation was successfully initiated.
* - STATUS_USART_ERROR        The receive buffer pointer was invalid (NULL), so an error was reported.
* - STATUS_USART_UNSUPPORTED  The USART is in TX-only mode and does not support receiving data.
* - Other status codes        Depending on the outcome of DMA or interrupt-based initiation.
*/
FUNC(Usart_StatusType, USART_CODE) Usart_RxData(Usart_UsartIdType usartId,
                                                uint16 *rxBuf,
                                                uint32 rxLen)
{
    Usart_StateType const * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
  
    if ((boolean)FALSE == Usart_Hw_GetUsartState(usartId))
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATA_SVC_ID, USART_E_UNINIT);
#endif
        result = STATUS_USART_ERROR;
    }
    else
    {
        /* Validate the receive buffer pointer */
        if (NULL == rxBuf)
        {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
            (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID,
                            USART_INSTANCE_MODULE_ID,
                            USART_RXDATA_SVC_ID,
                            USART_E_PARAM_POINTER);
#endif
            result = STATUS_USART_ERROR;
        }
        else
        {
            /* Check if the USART is not in a mode that supports RX */
            if (tempStates->mode == USART_MODE_TX)
            {
                result = STATUS_USART_UNSUPPORTED;
            }
            else
            {
#if (STD_ON == USART_DMA_SUPPORT)
                /* Determine whether to use DMA or interrupt-driven reception */
                if (tempStates->transferType == USART_USE_DMA)
                {
                    result = Usart_StartRxDataUsingDma(usartId, rxBuf, rxLen);
                }
                else
                {
#endif
                    result = Usart_StartRxDataUsingInt(usartId, rxBuf, rxLen);
#if (STD_ON == USART_DMA_SUPPORT)
                }
#endif
            }
        }
    }
    return result;
}


/**
* @brief       Retrieves the USART status for the specified direction (TX or RX).
*
* @details
* This function checks whether the transmit or receive operation is currently active
* (i.e., txBusy or rxBusy). If the operation is idle, it sets bytesRemain (if not NULL) 
* to zero. Otherwise, it obtains the remaining byte (or word) count and returns the 
* associated status for the ongoing operation. For DMA-based workflows, further 
* implementation details may need to be added.
*
* Operational steps:
* 1. Checks the dir parameter (USART_MODE_RX or USART_MODE_TX).
* 2. If bytesRemain is not NULL for RX mode and the receive is busy, returns 
*    rxLen as the number of remaining units to be received.
* 3. If bytesRemain is NULL for RX mode and the receive is busy, no remaining 
*    count is updated, but the current rxStatus is returned.
* 4. Similarly for TX mode, determines whether the transmitter is busy, updates 
*    the bytesRemain if applicable, and returns txStatus.
* 5. If an error or invalid pointer is detected for RX mode, logs it via 
*    Det_ReportError() and sets result accordingly.
*
* @param[in]  usartId       The identifier for the USART channel to query.
* @param[in]  dir           The direction for which to get the status, either USART_MODE_RX or USART_MODE_TX.
* @param[out] bytesRemain   Pointer to a variable that, on return, contains the remaining 
*                           byte count for the given direction; can be NULL.
*
* @note
* - If the function is called in RX mode but bytesRemain is NULL (and rxBusy is true),
*   the function does not update the remaining count, just returns the current status code.
* - If the USART is not busy, bytesRemain is set to 0 to indicate there is no operation in progress.
* - For DMA mode, additional logic is needed to accurately retrieve the remaining bytes
*   from the DMA controller (currently left as a placeholder comment).
*
* @return
* - STATUS_USART_SUCCESS    Operation is valid; returns the current number of remaining bytes if applicable.
* - STATUS_USART_ERROR      A parameter pointer was invalid (in RX mode with a NULL pointer).
* - Other status codes      Depending on current rxStatus or txStatus if the USART is busy.
*/
FUNC(Usart_StatusType, USART_CODE) Usart_GetStatus(Usart_UsartIdType usartId, 
                                                   Usart_DirectionType dir, 
                                                   uint32 *bytesRemain)
{
    Usart_StateType const * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
    
    if ((boolean)FALSE == Usart_Hw_GetUsartState(usartId))
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID, USART_INSTANCE_MODULE_ID,
                        USART_TXDATA_SVC_ID, USART_E_UNINIT);
#endif
        result = STATUS_USART_ERROR;
    }
    else
    {
        if (dir == USART_MODE_RX)
        {
            /* If direction is RX, check pointer validity */
            if (NULL == bytesRemain)
            {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
                (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID,
                                USART_INSTANCE_MODULE_ID,
                                USART_GETSTATUS_SVC_ID,
                                USART_E_PARAM_POINTER);
#endif
                result = STATUS_USART_ERROR;
            }
            else
            {
                /* If RX is not busy, no bytes remain */
                if ((uint8)0 == tempStates->rxBusy)
                {
                    *bytesRemain = 0U;
                    result = tempStates->rxStatus;
                }
                else
                {
                    if (tempStates->transferType == USART_USE_DMA)
                    {
                        /* Placeholder: Retrieve RX remaining bytes from DMA controller if needed. */
                        *bytesRemain = tempStates->rxLen;
                    }
                    else
                    {
                        *bytesRemain = tempStates->rxLen;
                    }
                    result = tempStates->rxStatus;
                }
            }
        }
        else if (dir == USART_MODE_TX)
        {
            /* If direction is TX but 'bytesRemain' is NULL, we only return txStatus */
            if (NULL == bytesRemain)
            {
                result = tempStates->txStatus;
            }
            else
            {
                /* If TX is not busy, no bytes remain */
                if ((uint8)0 == tempStates->txBusy)
                {
                    *bytesRemain = 0U;
                    result = tempStates->txStatus;
                }
                else
                {
                    if (tempStates->transferType == USART_USE_DMA)
                    {
                        /* Placeholder: Retrieve TX remaining bytes from DMA controller if needed. */
                        *bytesRemain = tempStates->txLen;
                    }
                    else
                    {
                        *bytesRemain = tempStates->txLen;
                    }
                    result = tempStates->txStatus;
                }
            }
        }
        else
        {
            /* nothing */
        }
    }
    return result;
}


/*!
* @brief         This function is used to return the Usart module version information
*
* @param[in]     VersionInfo:  A pointer to the variable where version information is stored.
*
* @retval        void
*
*/
FUNC(void, USART_CODE) Usart_GetVersionInfo(Std_VersionInfoType * VersionInfo)
{
    
    if (VersionInfo == NULL)
    {
#if (STD_ON == USART_DEV_ERR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CDD_USART_H_MODULE_ID,USART_INSTANCE_MODULE_ID,
                        USART_GETVERSIONINFO_SVC_ID,USART_E_PARAM_POINTER);
#endif
    }
    else
    {
        VersionInfo->sw_major_version = (uint8)CDD_USART_H_SW_MAJOR_VERSION;
        VersionInfo->sw_minor_version = (uint8)CDD_USART_H_SW_MINOR_VERSION;
        VersionInfo->sw_patch_version = (uint8)CDD_USART_H_SW_PATCH_VERSION;
        VersionInfo->moduleID = (uint16)CDD_USART_H_MODULE_ID;
        VersionInfo->vendorID = (uint16)CDD_USART_H_VENDOR_ID;
    }
}


/*******************************************************************************
                             LOCAL FUNCTION
*******************************************************************************/
/*!
* @brief       Initiates interrupt-driven USART transmission
* 
* @param       usartId   USART peripheral identifier
* @param       txBuf     Pointer to transmit data buffer
* @param       txLen     Number of bytes to transmit
* 
* @return      Operation status (STATUS_USART_SUCCESS/BUSY)
* 
* @note        State machine control flow:
*              1. Checks transmitter busy flag
*              2. Sets internal state to BUSY
*              3. Enables transmitter hardware
*              4. Enables TX buffer empty interrupt
*
*/
static FUNC(Usart_StatusType, USART_CODE) Usart_StartTxDataUsingInt(Usart_UsartIdType usartId,
                                          const uint8 * txBuf,
                                          uint32 txLen)
{
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
    
    if ((uint8)0 != tempStates->txBusy)
    {
        result = STATUS_USART_BUSY;
    }
    else
    {
        Usart_DisableAllTxInterrupts(usartId);

        tempStates->txStatus = STATUS_USART_BUSY;
        tempStates->txBusy = TRUE;
        tempStates->txBuffer = txBuf;
        tempStates->txLen = txLen;
        
        Usart_Hw_OperationDirectionMode(usartId,USART_MODE_TX,ENABLE);
        Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_TXC);
        Usart_Hw_OperationInterrupt(usartId,USART_INT_TXBEIE,ENABLE);
    } 
    return result;
}



/*!
* @brief       Initiates interrupt-driven USART reception
* 
* @param       usartId   USART peripheral identifier
* @param       rxBuf     Pointer to receive data buffer
* @param       rxLen     Number of bytes to receive
* 
* @return      Operation status (STATUS_USART_SUCCESS/BUSY)
* 
* @note        Enables multiple RX-related interrupts:
*              - PEIE:   Parity error interrupt
*              - RXTOIE: Receive timeout interrupt
*              - RXBNEIE: RX buffer not empty interrupt
*
*/
static FUNC(Usart_StatusType, USART_CODE) Usart_StartRxDataUsingInt(Usart_UsartIdType usartId,
                                          uint16 *rxBuf,
                                          uint32 rxLen)
{
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
    
    if ((uint8)0 != tempStates->rxBusy)
    {
        result = STATUS_USART_BUSY;
    }
    else
    {
        Usart_DisableAllRxInterrupts(usartId);

        tempStates->rxStatus = STATUS_USART_BUSY;
        tempStates->rxBusy = TRUE;
        tempStates->rxBuffer = rxBuf;
        tempStates->rxLen = rxLen;

        Usart_Hw_ClearStatusFlag(usartId, (uint32)USART_FLAG_RXTOF);
        Usart_Hw_OperationDirectionMode(usartId,USART_MODE_RX,ENABLE);
      
        Usart_Hw_OperationInterrupt(usartId,USART_INT_ERRIE,ENABLE);
        Usart_Hw_OperationInterrupt(usartId,USART_INT_PEIE,ENABLE);
        Usart_Hw_OperationInterrupt(usartId,USART_INT_RXTOIE,ENABLE);
      
        Usart_Hw_OperationInterrupt(usartId,USART_INT_RXBNEIE,ENABLE);
    } 
    return result;
}



#if (STD_ON == USART_DMA_SUPPORT)
/*!
* @brief       Initiates DMA-driven USART transmission
* 
* @param       usartId   USART peripheral identifier
* @param       txBuf     Pointer to transmit data buffer
* @param       txLen     Number of bytes to transmit
* 
* @return      Operation status (STATUS_USART_SUCCESS/BUSY)
* 
* @note        DMA channel mapping:
*              - USART1: DMA Channel 2
*              - USART2: DMA Channel 4
* @note        DMA configuration steps:
*              1. Sets data length
*              2. Configures peripheral address (USART TX register)
*              3. Configures memory address (application buffer)
*              4. Enables DMA channel
*
*/
static FUNC(Usart_StatusType, USART_CODE) Usart_StartTxDataUsingDma(Usart_UsartIdType usartId,
                                          const uint8 *txBuf,
                                          uint32 txLen)
{
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
  
    if (tempStates->txBusy)
    {
        result = STATUS_USART_BUSY;
    }
    else
    {
        tempStates->txStatus = STATUS_USART_BUSY;
        tempStates->txBusy = TRUE;
        tempStates->txBuffer = txBuf;
        tempStates->txLen = txLen;

        if (USART1_ID == usartId)
        {
            Pdl_TopDmaChDataNumSet(DMA_HW_CH2, txLen);
            Pdl_TopDmaPAddrRefresh(DMA_HW_CH2, USART1_TX_DMA_ADDR);
            Pdl_TopDmaMAddrRefresh(DMA_HW_CH2, (uint32)txBuf);

            Pdl_TopDmaChEn(DMA_HW_CH2);
        }
        else if (USART2_ID == usartId)
        {
            Pdl_TopDmaChDataNumSet(DMA_HW_CH4, txLen);
            Pdl_TopDmaPAddrRefresh(DMA_HW_CH4, USART2_TX_DMA_ADDR);
            Pdl_TopDmaMAddrRefresh(DMA_HW_CH4, (uint32)txBuf);

            Pdl_TopDmaChEn(DMA_HW_CH4);
        }
    }
    return result;
}


/*!
* @brief       Initiates DMA-driven USART reception
* 
* @param       usartId   USART peripheral identifier
* @param       rxBuf     Pointer to receive data buffer
* @param       rxLen     Number of bytes to receive
* 
* @return      Operation status (STATUS_USART_SUCCESS/BUSY)
* 
* @note        DMA channel mapping:
*              - USART1: DMA Channel 3
*              - USART2: DMA Channel 5
* @note        Half-word (16-bit) access used for all USARTs
*
*/
static FUNC(Usart_StatusType, USART_CODE) Usart_StartRxDataUsingDma(Usart_UsartIdType usartId,
                                          uint16 *rxBuf,
                                          uint32 rxLen)
{
    Usart_StateType * tempStates = &g_lpuartStatus[usartId];
    Usart_StatusType result = STATUS_USART_SUCCESS;
  
    if (tempStates->rxBusy)
    {
        result = STATUS_USART_BUSY;
    }
    else
    {
        tempStates->rxStatus = STATUS_USART_BUSY;
        tempStates->rxBusy = TRUE;
        tempStates->rxBuffer = rxBuf;
        tempStates->rxLen = rxLen;

        if (USART1_ID == usartId)
        {
            Pdl_TopDmaChDataNumSet(DMA_HW_CH3, rxLen);
            Pdl_TopDmaPAddrRefresh(DMA_HW_CH3, USART1_RX_DMA_ADDR);
            Pdl_TopDmaMAddrRefresh(DMA_HW_CH3, (uint32)rxBuf);

            Pdl_TopDmaChEn(DMA_HW_CH3);
        }
        else if (USART2_ID == usartId)
        {
            Pdl_TopDmaChDataNumSet(DMA_HW_CH5, rxLen);
            Pdl_TopDmaPAddrRefresh(DMA_HW_CH5, USART2_RX_DMA_ADDR);
            Pdl_TopDmaMAddrRefresh(DMA_HW_CH5, (uint32)rxBuf);

            Pdl_TopDmaChEn(DMA_HW_CH5);
        }
    }
    return result;
}


/*!
* @brief       Configures DMA for USART1 reception
* 
* @param       None
* 
* @return      None
* 
* @note        Fixed DMA configuration for USART1 RX:
*              - Direction: Peripheral-to-memory
*              - Data width: 16-bit (half-word)
*              - Peripheral increment: Disabled
*              - Memory increment: Enabled
*              - Circular mode: Disabled
*              - Priority: High
* @note        Clears DMA Channel 3 transfer complete flag
*
*/
static FUNC(void, USART_CODE) Usart_DmaUsart1RxInit(void)
{
    Pdl_DmaChHwConfigType tempDmaConfig;
    
    tempDmaConfig.memAddr = 0;
    tempDmaConfig.periphAddr = 0;
    tempDmaConfig.dir = (Pdl_DmaDirType)DMA_DIR_PERIPHERAL;
    tempDmaConfig.bufSize = 0;
    tempDmaConfig.memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_HALFWORD;
    tempDmaConfig.periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_HALFWORD;
    tempDmaConfig.memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_ENABLE;
    tempDmaConfig.periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE;
    tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE;
    tempDmaConfig.priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_HIGHT;
    tempDmaConfig.mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE;

    /* configure the DMA */
    Pdl_TopDmaChConfig(DMA_HW_CH3, &tempDmaConfig);
    
    /* Disable Request of RxDma */
    Pdl_Dma_ClrStsFlag(DMA1_INT_FLAG_TF3);
}


/*!
* @brief       Configures DMA for USART1 transmission
* 
* @param       None
* 
* @return      None
* 
* @note        Fixed DMA configuration for USART1 TX:
*              - Direction: Memory-to-peripheral
*              - Data width: 8-bit (byte)
*              - Peripheral increment: Disabled
*              - Memory increment: Enabled
*              - Circular mode: Disabled
*              - Priority: High
* @note        Clears DMA Channel 2 transfer complete flag
*
*/
static FUNC(void, USART_CODE) Usart_DmaUsart1TxInit(void)
{
    Pdl_DmaChHwConfigType tempDmaConfig;
    
    tempDmaConfig.memAddr = 0;
    tempDmaConfig.periphAddr = 0;
    tempDmaConfig.dir = (Pdl_DmaDirType)DMA_DIR_MEMORY;
    tempDmaConfig.bufSize = 0;
    tempDmaConfig.memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_BYTE;
    tempDmaConfig.periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_BYTE;
    tempDmaConfig.memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_ENABLE;
    tempDmaConfig.periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE;
    tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE;
    tempDmaConfig.priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_HIGHT;
    tempDmaConfig.mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE;
    
    /* configure the DMA */
    Pdl_TopDmaChConfig(DMA_HW_CH2, &tempDmaConfig);
    /* Disable Request of TxDma */
    Pdl_Dma_ClrStsFlag(DMA1_INT_FLAG_TF2);
}


/*!
* @brief       Configures DMA for USART2 reception
* 
* @param       None
* 
* @return      None
* 
* @note        Fixed DMA configuration for USART2 RX:
*              - Direction: Peripheral-to-memory
*              - Data width: 16-bit (half-word)
*              - Peripheral increment: Disabled
*              - Memory increment: Enabled
*              - Circular mode: Disabled
*              - Priority: High
* @note        Clears DMA Channel 5 transfer complete flag
*
*/
static FUNC(void, USART_CODE) Usart_DmaUsart2RxInit(void)
{
    Pdl_DmaChHwConfigType tempDmaConfig;
    
    tempDmaConfig.memAddr = 0;
    tempDmaConfig.periphAddr = 0;
    tempDmaConfig.dir = (Pdl_DmaDirType)DMA_DIR_PERIPHERAL;
    tempDmaConfig.bufSize = 0;
    tempDmaConfig.memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_HALFWORD;
    tempDmaConfig.periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_HALFWORD;
    tempDmaConfig.memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_ENABLE;
    tempDmaConfig.periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE;
    tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE;
    tempDmaConfig.priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_HIGHT;
    tempDmaConfig.mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE;

    /** configure the DMA */
    Pdl_TopDmaChConfig(DMA_HW_CH5, &tempDmaConfig);
    
    /** Disable Request of RxDma */
    Pdl_Dma_ClrStsFlag(DMA1_INT_FLAG_TF5);
}


/*!
* @brief       Configures DMA for USART2 transmission
* 
* @param       None
* 
* @return      None
* 
* @note        Fixed DMA configuration for USART2 TX:
*              - Direction: Memory-to-peripheral
*              - Data width: 8-bit (byte)
*              - Peripheral increment: Disabled
*              - Memory increment: Enabled
*              - Circular mode: Disabled
*              - Priority: High
* @note        Clears DMA Channel 4 transfer complete flag
*
*/
static FUNC(void, USART_CODE) Usart_DmaUsart2TxInit(void)
{
    Pdl_DmaChHwConfigType tempDmaConfig;
    
    tempDmaConfig.memAddr = 0;
    tempDmaConfig.periphAddr = 0;
    tempDmaConfig.dir = (Pdl_DmaDirType)DMA_DIR_MEMORY;
    tempDmaConfig.bufSize = 0;
    tempDmaConfig.memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_BYTE;
    tempDmaConfig.periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_BYTE;
    tempDmaConfig.memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_ENABLE;
    tempDmaConfig.periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE;
    tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE;
    tempDmaConfig.priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_HIGHT;
    tempDmaConfig.mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE;
    
    /* configure the DMA */
    Pdl_TopDmaChConfig(DMA_HW_CH4, &tempDmaConfig);
    /* Disable Request of TxDma */
    Pdl_Dma_ClrStsFlag(DMA1_INT_FLAG_TF4);
}
#endif

/*!
* @brief    put redefinition
*/
FUNC(int32, USART_CODE) Usart_PutRedefinition(Usart_UsartIdType usartId, const int32 * ch)
{
    Usart_Hw_TxData(usartId,(const uint8 *)ch);
    /* wait for the data to be send  */
    while (Usart_Hw_ReadStatusFlag(usartId, USART_FLAG_TXBE) == (uint8)RESET)
    {
        /* nothing */
    }

    return (*ch);
}

/**@} end of group USART_Fuctions */
/**@} end of group USART_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
