/*================================================================================================== * Project : RTD AUTOSAR 4.4 * Platform : CORTEXM * Peripheral : FLEXIO * Dependencies : * * Autosar Version : 4.4.0 * Autosar Revision : ASR_REL_4_4_REV_0000 * Autosar Conf.Variant : * SW Version : 0.9.0 * Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326 * * (c) Copyright 2020 - 2021 NXP Semiconductors * All Rights Reserved. * * NXP Confidential. This software is owned or controlled by NXP and may only be * used strictly in accordance with the applicable license terms. By expressly * accepting such terms or by downloading, installing, activating and/or otherwise * using the software, you are agreeing that you have read, and that you agree to * comply with and are bound by, such license terms. If you do not agree to be * bound by the applicable license terms, then you may not retain, install, * activate or otherwise use the software. ==================================================================================================*/ /** * @file Lpuart_Uart_Ip.c * @defgroup lpuart_uart_ip Lpuart UART IPL * @addtogroup lpuart_uart_ip Lpuart UART IPL * @{ */ #ifdef __cplusplus extern "C"{ #endif /*================================================================================================== * INCLUDE FILES * 1) system and project includes * 2) needed interfaces from external units * 3) internal and external interfaces from this unit ==================================================================================================*/ #include "Lpuart_Uart_Ip.h" #include "Lpuart_Uart_Ip_HwAccess.h" #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) #include "Dma_Ip.h" #endif #ifdef LPUART_UART_IP_DEV_ERROR_DETECT #if (LPUART_UART_IP_DEV_ERROR_DETECT == STD_ON) #include "Devassert.h" #endif /* (STD_ON == LPUART_UART_IP_DEV_ERROR_DETECT) */ #endif /* idfef LPUART_UART_IP_DEV_ERROR_DETECT */ /*================================================================================================== * SOURCE FILE VERSION INFORMATION ==================================================================================================*/ #define LPUART_UART_IP_VENDOR_ID_C 43 #define LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C 4 #define LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C 4 #define LPUART_UART_IP_AR_RELEASE_REVISION_VERSION_C 0 #define LPUART_UART_IP_SW_MAJOR_VERSION_C 0 #define LPUART_UART_IP_SW_MINOR_VERSION_C 9 #define LPUART_UART_IP_SW_PATCH_VERSION_C 0 /*================================================================================================== * FILE VERSION CHECKS ==================================================================================================*/ /* Checks against Lpuart_Uart_Ip.h */ #if (LPUART_UART_IP_VENDOR_ID_C != LPUART_UART_IP_VENDOR_ID) #error "Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h have different vendor ids" #endif #if ((LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION_C != LPUART_UART_IP_AR_RELEASE_MAJOR_VERSION) || \ (LPUART_UART_IP_AR_RELEASE_MINOR_VERSION_C != LPUART_UART_IP_AR_RELEASE_MINOR_VERSION) || \ (LPUART_UART_IP_AR_RELEASE_REVISION_VERSION_C != LPUART_UART_IP_AR_RELEASE_REVISION_VERSION)) #error "AUTOSAR Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h are different" #endif #if ((LPUART_UART_IP_SW_MAJOR_VERSION_C != LPUART_UART_IP_SW_MAJOR_VERSION) || \ (LPUART_UART_IP_SW_MINOR_VERSION_C != LPUART_UART_IP_SW_MINOR_VERSION) || \ (LPUART_UART_IP_SW_PATCH_VERSION_C != LPUART_UART_IP_SW_PATCH_VERSION)) #error "Software Version Numbers of Lpuart_Uart_Ip.c and Lpuart_Uart_Ip.h are different" #endif /*================================================================================================== * LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS) ==================================================================================================*/ /*================================================================================================== * LOCAL MACROS ==================================================================================================*/ #ifdef LPUART_UART_IP_DEV_ERROR_DETECT #if (LPUART_UART_IP_DEV_ERROR_DETECT == STD_ON) #define LPUART_UART_DEV_ASSERT(x) DevAssert(x) #else #define LPUART_UART_DEV_ASSERT(x) (void)(x) #endif #endif /* @brief Address of the least significant byte or word in a 32-bit register (depends on endianness) */ #define LPUART_UART_IP_LSBW_ADDR(reg) ((uint32)(&(reg))) /*================================================================================================== * LOCAL CONSTANTS ==================================================================================================*/ #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) #define LPUART_UART_DMA_CONFIG_LIST_DIMENSION (10U) #define LPUART_UART_DMA_LEAST_CONFIG_LIST_DIMENSION (2U) #endif /*================================================================================================== * LOCAL VARIABLES ==================================================================================================*/ #define UART_START_SEC_VAR_NO_INIT_UNSPECIFIED_NO_CACHEABLE /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" /** @brief Array of UART driver runtime state structures */ Lpuart_Uart_Ip_StateStructureType Lpuart_Uart_Ip_apStateStructure[LPUART_UART_IP_NUMBER_OF_INSTANCES]; #define UART_STOP_SEC_VAR_NO_INIT_UNSPECIFIED_NO_CACHEABLE /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" #define UART_START_SEC_VAR_NO_INIT_UNSPECIFIED /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" /* Pointer to lpuart runtime state structure */ static Lpuart_Uart_Ip_StateStructureType * Lpuart_Uart_Ip_apStateStructuresArray[LPUART_UART_IP_NUMBER_OF_INSTANCES]; /** @brief User config structure. */ const Lpuart_Uart_Ip_UserConfigType * Lpuart_Uart_Ip_apUserConfig[LPUART_UART_IP_NUMBER_OF_INSTANCES]; #define UART_STOP_SEC_VAR_NO_INIT_UNSPECIFIED /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" #define UART_START_SEC_CONST_UNSPECIFIED /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" /* Table of base addresses for lpuart instances. */ static LPUART_Type * const Lpuart_Uart_Ip_apBases[LPUART_UART_IP_NUMBER_OF_INSTANCES] = FEATURE_LPUART_IP_SPECIFIC_BASE_PTR; #define UART_STOP_SEC_CONST_UNSPECIFIED /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) #define UART_START_SEC_CONST_BOOLEAN /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" /** @brief Table storing DMA capabilities for LPUART instances. */ static const boolean Lpuart_Uart_Ip_InstHasDma[LPUART_UART_IP_NUMBER_OF_INSTANCES] = FEATURE_LPUART_IP_INST_HAS_DMA; #define UART_STOP_SEC_CONST_BOOLEAN /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" #endif /*================================================================================================== * GLOBAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * GLOBAL VARIABLES ==================================================================================================*/ /*================================================================================================== * LOCAL FUNCTION PROTOTYPES ==================================================================================================*/ /*================================================================================================== * LOCAL FUNCTIONS ==================================================================================================*/ #define UART_START_SEC_CODE /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingInt(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize); static void Lpuart_Uart_Ip_CompleteSendDataUsingInt(uint32 u32Instance); static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingInt(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize); static void Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(uint32 u32Instance); #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingDma(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize); static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingDma(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize); #endif static void Lpuart_Uart_Ip_PutData(uint32 u32Instance); static void Lpuart_Uart_Ip_GetData(uint32 u32Instance); static void Lpuart_Uart_Ip_RxIrqHandler(uint32 u32Instance); static void Lpuart_Uart_Ip_TxEmptyIrqHandler(uint32 u32Instance); static void Lpuart_Uart_Ip_TxCompleteIrqHandler(uint32 u32Instance); static void Lpuart_Uart_Ip_ErrIrqHandler(uint32 u32Instance); static void Lpuart_Uart_Ip_StartGetData(LPUART_Type * pBase, uint32 u32Instance, uint32 u32StartTime); /*================================================================================================== * GLOBAL FUNCTIONS ==================================================================================================*/ /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_Init * Description : This function initializes a LPUART instance for operation. * This function will initialize the run-time state structure to keep track of * the on-going transfers, ungate the clock to the LPUART module, initialize the * module to user defined settings and default settings, configure the IRQ state * structure and enable the module-level interrupt to the core, and enable the * LPUART module transmitter and receiver. * * Implements : Lpuart_Uart_Ip_Init_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_Init_Activity*/ void Lpuart_Uart_Ip_Init(uint32 u32Instance, const Lpuart_Uart_Ip_UserConfigType * pUserConfig) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pUserConfig != NULL_PTR); /* Check if current instance is already initialized. */ LPUART_UART_DEV_ASSERT(Lpuart_Uart_Ip_apStateStructuresArray[u32Instance] == NULL_PTR); /* Check if Baudrate parameters are valid value */ LPUART_UART_DEV_ASSERT(pUserConfig->u8BaudOverSamplingRatio <= 0x20U); LPUART_UART_DEV_ASSERT((pUserConfig->u32BaudRateDivisor <= 0x1FFFU) && \ (pUserConfig->u32BaudRateDivisor >= 1U)); LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; Lpuart_Uart_Ip_StateStructureType *pUartStatePtr; uint32 u32Index; Lpuart_Uart_Ip_apStateStructuresArray[u32Instance] = pUserConfig->pStateStruct; pUartStatePtr = Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; Lpuart_Uart_Ip_apUserConfig[u32Instance] = pUserConfig; #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) /* In DMA mode, only 7-bits and 8-bits chars are supported */ LPUART_UART_DEV_ASSERT((pUserConfig->eTransferType != LPUART_UART_IP_USING_DMA) || \ (((pUserConfig->eBitCountPerChar == LPUART_UART_IP_7_BITS_PER_CHAR) || \ (pUserConfig->eBitCountPerChar == LPUART_UART_IP_8_BITS_PER_CHAR)) && \ Lpuart_Uart_Ip_InstHasDma[u32Instance])); #endif /* (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) */ /* For 10 bits per char, parity bit cannot be enabled */ LPUART_UART_DEV_ASSERT((pUserConfig->eBitCountPerChar != LPUART_UART_IP_10_BITS_PER_CHAR) || \ (pUserConfig->eParityMode == LPUART_UART_IP_PARITY_DISABLED)); /* Clear the state struct for this instance. */ uint8 *pClearStructPtr = (uint8 *)pUartStatePtr; for (u32Index = 0; u32Index < sizeof(Lpuart_Uart_Ip_StateStructureType); u32Index++) { pClearStructPtr[u32Index] = 0; } /* Initialize the LPUART instance */ LPUART_Uart_Init(pBase); /* Check if osr is between 4x and 7x oversampling. * If so, then "BOTHEDGE" sampling must be turned on */ if (pUserConfig->u8BaudOverSamplingRatio < 8U) { LPUART_Uart_EnableBothEdgeSamplingCmd(pBase); } /* Program the osr value (bit value is one less than actual value) */ LPUART_Uart_SetOversamplingRatio(pBase, (uint32)(pUserConfig->u8BaudOverSamplingRatio - 1U)); /* Write the sbr value to the BAUD registers */ LPUART_Uart_SetBaudRateDivisor(pBase, pUserConfig->u32BaudRateDivisor); if (pUserConfig->eParityMode != LPUART_UART_IP_PARITY_DISABLED) { LPUART_Uart_SetBitCountPerChar(pBase, pUserConfig->eBitCountPerChar, TRUE); } else { LPUART_Uart_SetBitCountPerChar(pBase, pUserConfig->eBitCountPerChar, FALSE); } LPUART_Uart_SetParityMode(pBase, pUserConfig->eParityMode); LPUART_Uart_SetStopBitCount(pBase, pUserConfig->eStopBitsCount); /* Initialize last driver operation status */ pUartStatePtr->eTransmitStatus = LPUART_UART_IP_STATUS_SUCCESS; pUartStatePtr->eReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS; /* Set the initial baudrate from user's structure */ pUartStatePtr->u32BaudRate = pUserConfig->u32BaudRate; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_Deinit * Description : This function shuts down the UART by disabling interrupts and * transmitter/receiver. * * Implements : Lpuart_Uart_Ip_Deinit_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_Deinit_Activity*/ void Lpuart_Uart_Ip_Deinit(uint32 u32Instance) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); uint32 u32StartTime; LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; /* Check if current instance is already de-initialized or is gated.*/ LPUART_UART_DEV_ASSERT(Lpuart_Uart_Ip_apStateStructuresArray[u32Instance] != NULL_PTR); u32StartTime = OsIf_GetCounter(LPUART_UART_IP_TIMEOUT_TYPE); /* Wait until the data is completely shifted out of shift register */ while (!LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_TX_COMPLETE) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) {} /* Disble Tx data register empty and transmission complete interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_COMPLETE, FALSE); /* Disble Rx data register full */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE); /* Disable error interrupts */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG, FALSE); /* Clear our saved pointer to the state structure */ Lpuart_Uart_Ip_apStateStructuresArray[u32Instance] = NULL_PTR; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_SyncSend * Description : Send out multiple bytes of data using polling method. * * Implements : Lpuart_Uart_Ip_SyncSend_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_SyncSend_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SyncSend(uint32 u32Instance, const uint8 *pTxBuff, uint32 u32TxSize) { /* Check the validity of the parameters */ LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pTxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32TxSize > 0U); LPUART_Type * pBase; Lpuart_Uart_Ip_StateStructureType * pUartState; uint32 u32StartTime; boolean bIsReturn = FALSE; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_SUCCESS; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); SchM_Enter_Uart_UART_EXCLUSIVE_AREA_00(); /* Check driver is not busy transmitting data from a previous asynchronous call */ if (pUartState->bIsTxBusy) { SchM_Exit_Uart_UART_EXCLUSIVE_AREA_00(); retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } if(!bIsReturn) { pUartState->bIsTxBusy = TRUE; SchM_Exit_Uart_UART_EXCLUSIVE_AREA_00(); pUartState->pTxBuff = pTxBuff; pUartState->u32TxSize = u32TxSize; pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_BUSY; /* Disble Tx data register empty and transmission complete interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_COMPLETE, FALSE); /* Enable the LPUART transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, TRUE); u32StartTime = OsIf_GetCounter(LPUART_UART_IP_TIMEOUT_TYPE); while ((pUartState->u32TxSize > 0U) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) { Lpuart_Uart_Ip_PutData(u32Instance); while (!LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_TX_DATA_REG_EMPTY) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) {} } /* Disable the LPUART transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, FALSE); /* Check if Timeout occur */ if(pUartState->u32TxSize > 0U) { pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_TIMEOUT; }else /* The transmit process is complete */ { pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_SUCCESS; } pUartState->bIsTxBusy = FALSE; retVal = pUartState->eTransmitStatus; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_AsyncSend * Description : This function sends data out through the LPUART module using * non-blocking method. The function will return immediately after calling this * function. * * Implements : Lpuart_Uart_Ip_AsyncSend_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_AsyncSend_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AsyncSend(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize) { /* Check the validity of the parameters */ LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pTxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32TxSize > 0U); const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; Lpuart_Uart_Ip_StateStructureType * pUartState; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_SUCCESS; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; boolean bIsReturn = FALSE; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); SchM_Enter_Uart_UART_EXCLUSIVE_AREA_01(); /* Check it's not busy transmitting data from a previous function call */ if (pUartState->bIsTxBusy) { SchM_Exit_Uart_UART_EXCLUSIVE_AREA_01(); retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } if(!bIsReturn) { pUartState->bIsTxBusy = TRUE; SchM_Exit_Uart_UART_EXCLUSIVE_AREA_01(); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); LPUART_UART_DEV_ASSERT((pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) || (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_DMA)); if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* Start the transmission process using interrupts */ retVal = Lpuart_Uart_Ip_StartSendDataUsingInt(u32Instance, pTxBuff, u32TxSize); } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* Start the transmission process using DMA */ retVal = Lpuart_Uart_Ip_StartSendDataUsingDma(u32Instance, pTxBuff, u32TxSize); } #endif } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_GetTransmitStatus * Description : This function returns whether the previous LPUART transmit has * finished. When performing non-blocking transmit, the user can call this * function to ascertain the state of the current transmission: * in progress (or busy) or complete (success). In addition, if the transmission * is still in progress, the user can obtain the number of words that have been * currently transferred. * * Implements : Lpuart_Uart_Ip_GetTransmitStatus_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_GetTransmitStatus_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_GetTransmitStatus(uint32 u32Instance, uint32 * pBytesRemaining) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) const Dma_Ip_LogicChannelInfoParamType eDmaLogicChnParam = DMA_IP_CH_GET_CURRENT_ITER_COUNT; #endif pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); if (pBytesRemaining != NULL_PTR) { if (pUartState->bIsTxBusy) { /* Fill in the bytes not transferred yet. */ if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* In interrupt-based communication, the remaining bytes are retrieved * from the state structure */ *pBytesRemaining = pUartState->u32TxSize;; } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* In DMA-based communication, the remaining bytes are retrieved * from the current DMA major loop count */ Dma_Ip_GetLogicChannelParam(pUartUserCfg->u8TxDMAChannel, eDmaLogicChnParam, pBytesRemaining); } #endif } else { *pBytesRemaining = 0; } } return pUartState->eTransmitStatus; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_AbortSendingData * Description : This function terminates an non-blocking LPUART transmission * early. During a non-blocking LPUART transmission, the user has the option to * terminate the transmission early if the transmission is still in progress. * * Implements : Lpuart_Uart_Ip_AbortSendingData_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_AbortSendingData_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AbortSendingData(uint32 u32Instance) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; boolean bIsReturn = FALSE; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_SUCCESS; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); /* Check if a transfer is running. */ if (!pUartState->bIsTxBusy) { retVal = LPUART_UART_IP_STATUS_SUCCESS; bIsReturn = TRUE; } if(!bIsReturn) { /* Update the tx status */ pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_ABORTED; /* Stop the running transfer. */ if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { Lpuart_Uart_Ip_CompleteSendDataUsingInt(u32Instance); } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* Release the DMA channel */ (void)Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8TxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST); Lpuart_Uart_Ip_CompleteSendUsingDma(u32Instance); } #endif /* Flush the Tx Buffer */ LPUART_Uart_FlushTxBuffer(pBase); retVal = LPUART_UART_IP_STATUS_SUCCESS; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_SyncReceive * Description : Receive multiple bytes of data using polling method. * * Implements : Lpuart_Uart_Ip_SyncReceive_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_SyncReceive_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SyncReceive(uint32 u32Instance, uint8 *pRxBuff, uint32 u32RxSize) { /* Check the validity of the parameters */ LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pRxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32RxSize > 0U); LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; Lpuart_Uart_Ip_StateStructureType * pUartState; uint32 u32StartTime; uint32 u32ElapsedTime; uint32 u32TimeoutTicks; boolean bIsReturn = FALSE; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_SUCCESS; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); SchM_Enter_Uart_UART_EXCLUSIVE_AREA_02(); /* Check driver is not busy receiving data from a previous asynchronous call */ if (pUartState->bIsRxBusy) { SchM_Exit_Uart_UART_EXCLUSIVE_AREA_02(); retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } if(!bIsReturn) { pUartState->bIsRxBusy = TRUE; SchM_Exit_Uart_UART_EXCLUSIVE_AREA_02(); pUartState->pRxBuff = pRxBuff; pUartState->u32RxSize = u32RxSize; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_BUSY; /* Disble Rx data register full */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE); /* Enable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, TRUE); u32StartTime = OsIf_GetCounter(LPUART_UART_IP_TIMEOUT_TYPE); Lpuart_Uart_Ip_StartGetData(pBase, u32Instance, u32StartTime); u32ElapsedTime = OsIf_GetElapsed(&u32StartTime, LPUART_UART_IP_TIMEOUT_TYPE); u32TimeoutTicks = OsIf_MicrosToTicks((uint32)LPUART_UART_IP_TIMEOUT_VALUE_US, LPUART_UART_IP_TIMEOUT_TYPE); /* Check if Timeout occur */ if (u32ElapsedTime >= u32TimeoutTicks) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_TIMEOUT; } /* Check other success receiving case*/ if (pUartState->eReceiveStatus == LPUART_UART_IP_STATUS_BUSY) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS; } if ((pUartState->u32RxSize == 0U) && (pUartState->eReceiveStatus == LPUART_UART_IP_STATUS_RX_OVERRUN)) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS; } /* Disable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, FALSE); pUartState->bIsRxBusy = FALSE; /* Read dummy to clear RDRF flag */ (void)LPUART_Uart_Getchar(pBase); retVal = pUartState->eReceiveStatus; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_StartGetData * Description : Start Getting Data in SyncReceive mode * *END**************************************************************************/ static void Lpuart_Uart_Ip_StartGetData(LPUART_Type * pBase, uint32 u32Instance, uint32 u32StartTime) { Lpuart_Uart_Ip_StateStructureType * pUartState; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; while ((pUartState->u32RxSize > 0U) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) { /* Wait until data reception flag is set or timeout occurs if there is an error during reception */ while (!LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_DATA_REG_FULL) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) {} /* Check for errors on received data */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_RX_OVERRUN)) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_RX_OVERRUN; /* Disable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, FALSE); /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_RX_OVERRUN); break; } else if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_FRAME_ERR)) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_FRAMING_ERROR; /* Disable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, FALSE); /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_FRAME_ERR); break; } else if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_NOISE_DETECT)) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_NOISE_ERROR; /* Disable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, FALSE); /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_NOISE_DETECT); break; } else if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_PARITY_ERR)) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_PARITY_ERROR; /* Disable the LPUART receiver */ LPUART_Uart_SetReceiverCmd((LPUART_Type *)pBase, FALSE); /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_PARITY_ERR); break; } else { /* Get received data */ Lpuart_Uart_Ip_GetData(u32Instance); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_ReceiveData * Description : This function receives data from LPUART module using * non-blocking method. This function returns immediately after initiating the * receive function. The application has to get the receive status to see when * the receive is complete. In other words, after calling non-blocking get * function, the application must get the receive status to check if receive * is completed or not. * * Implements : Lpuart_Uart_Ip_ReceiveData_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_AsyncReceive_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AsyncReceive(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pRxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32RxSize > 0U); const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; Lpuart_Uart_Ip_StateStructureType * pUartState; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_SUCCESS; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; boolean bIsReturn = FALSE; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); SchM_Enter_Uart_UART_EXCLUSIVE_AREA_03(); /* Check it's not busy receiving data from a previous function call */ if (pUartState->bIsRxBusy) { SchM_Exit_Uart_UART_EXCLUSIVE_AREA_03(); retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } if(!bIsReturn) { pUartState->bIsRxBusy = TRUE; SchM_Exit_Uart_UART_EXCLUSIVE_AREA_03(); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); LPUART_UART_DEV_ASSERT((pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) || (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_DMA)); if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* Start the reception process using interrupts */ retVal = Lpuart_Uart_Ip_StartReceiveDataUsingInt(u32Instance, pRxBuff, u32RxSize); } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* Start the reception process using DMA */ retVal = Lpuart_Uart_Ip_StartReceiveDataUsingDma(u32Instance, pRxBuff, u32RxSize); } #endif } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_GetReceiveStatus * Description : This function returns whether the previous LPUART receive is * complete. When performing a non-blocking receive, the user can call this * function to ascertain the state of the current receive progress: in progress * or complete. In addition, if the receive is still in progress, the user can * obtain the number of words that have been currently received. * * Implements : Lpuart_Uart_Ip_GetReceiveStatus_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_GetReceiveStatus_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_GetReceiveStatus(uint32 u32Instance, uint32 * pBytesRemaining) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) const Dma_Ip_LogicChannelInfoParamType eDmaLogicChnParam = DMA_IP_CH_GET_CURRENT_ITER_COUNT; #endif pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); if (pBytesRemaining != NULL_PTR) { if (pUartState->bIsRxBusy) { /* Fill in the bytes transferred. */ if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* In interrupt-based communication, the remaining bytes are retrieved * from the state structure */ *pBytesRemaining = pUartState->u32RxSize; } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* In DMA-based communication, the remaining bytes are retrieved * from the current DMA major loop count */ Dma_Ip_GetLogicChannelParam(pUartUserCfg->u8RxDMAChannel, eDmaLogicChnParam, pBytesRemaining); } #endif } else { *pBytesRemaining = 0; } } return pUartState->eReceiveStatus; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_AbortReceivingData * Description : Terminates a non-blocking receive early. * * Implements : Lpuart_Uart_Ip_AbortReceivingData_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_AbortReceivingData_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_AbortReceivingData(uint32 u32Instance) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; LPUART_UART_DEV_ASSERT(pUartState != NULL_PTR); LPUART_UART_DEV_ASSERT(pUartUserCfg != NULL_PTR); boolean bIsReturn = FALSE; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_ERROR; /* Check if a transfer is running. */ if (!pUartState->bIsRxBusy) { retVal = LPUART_UART_IP_STATUS_SUCCESS; bIsReturn = TRUE; } if(!bIsReturn) { /* Update the rx status */ pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_ABORTED; /* Stop the running transfer. */ if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(u32Instance); } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* Release the DMA channel */ (void)Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8RxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST); Lpuart_Uart_Ip_CompleteReceiveUsingDma(u32Instance); } #endif /* Clear all the error flags */ LPUART_Uart_ClearErrorFlags(pBase); /* Flush the Rx Buffer */ LPUART_Uart_FlushRxBuffer(pBase); retVal = LPUART_UART_IP_STATUS_SUCCESS; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_SetBaudRate * Description : Configures the LPUART baud rate. * In some LPUART instances the user must disable the transmitter/receiver * before calling this function. * Generally, this may be applied to all LPUARTs to ensure safe operation. * * Implements : Lpuart_Uart_Ip_SetBaudRate_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_SetBaudRate_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetBaudRate(uint32 u32Instance, Lpuart_Uart_Ip_BaudrateType u32DesiredBaudrate, uint32 u32ClockFrequency) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); uint16 sbr, sbrTemp, i; uint32 osr, tempDiff, calculatedBaud, baudDiff, maxOsr; LPUART_Type * pBase = Lpuart_Uart_Ip_apBases[u32Instance]; Lpuart_Uart_Ip_StateStructureType * pUartState; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; boolean bIsReturn = FALSE; Lpuart_Uart_Ip_StatusType retVal = LPUART_UART_IP_STATUS_ERROR; if (pUartState != NULL_PTR) { /* Check if there is an ongoing transfer */ if (pUartState->bIsTxBusy == TRUE) { retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } if ((pUartState->bIsRxBusy == TRUE) && (bIsReturn == FALSE)) { retVal = LPUART_UART_IP_STATUS_BUSY; bIsReturn = TRUE; } } if(!bIsReturn) { /* Check if current instance is clock gated off. */ LPUART_UART_DEV_ASSERT(u32ClockFrequency > 0U); /* Check if the desired baud rate can be configured with the current protocol clock. */ LPUART_UART_DEV_ASSERT(u32ClockFrequency >= (u32DesiredBaudrate * 5U)); /* This lpuart instantiation uses a slightly different baud rate calculation * The idea is to use the best OSR (over-sampling rate) possible * Note, osr is typically hard-set to 16 in other lpuart instantiations * First calculate the baud rate using the minimum OSR possible (4) */ osr = 4; sbr = (uint16)(u32ClockFrequency / (u32DesiredBaudrate * osr)); calculatedBaud = (u32ClockFrequency / (osr * sbr)); if (calculatedBaud > u32DesiredBaudrate) { baudDiff = calculatedBaud - u32DesiredBaudrate; } else { baudDiff = u32DesiredBaudrate - calculatedBaud; } /* find maximum osr */ maxOsr = u32ClockFrequency / u32DesiredBaudrate; if (maxOsr > 32U) { maxOsr = 32U; } /* loop to find the best osr value possible, one that generates minimum baudDiff * iterate through the rest of the supported values of osr */ if (maxOsr >= 5U) { for (i = 5U; i <= maxOsr; i++) { /* calculate the temporary sbr value */ sbrTemp = (uint16)(u32ClockFrequency / (u32DesiredBaudrate * i)); /* calculate the baud rate based on the temporary osr and sbr values */ calculatedBaud = (u32ClockFrequency / (i * sbrTemp)); if (calculatedBaud > u32DesiredBaudrate) { tempDiff = calculatedBaud - u32DesiredBaudrate; } else { tempDiff = u32DesiredBaudrate - calculatedBaud; } if (tempDiff <= baudDiff) { baudDiff = tempDiff; osr = i; /* update and store the best osr value calculated */ sbr = sbrTemp; /* update store the best sbr value calculated */ } } } /* Check if osr is between 4x and 7x oversampling. * If so, then "BOTHEDGE" sampling must be turned on */ if (osr < 8U) { LPUART_Uart_EnableBothEdgeSamplingCmd(pBase); } /* program the osr value (bit value is one less than actual value) */ LPUART_Uart_SetOversamplingRatio(pBase, (osr - 1U)); /* write the sbr value to the BAUD registers */ LPUART_Uart_SetBaudRateDivisor(pBase, sbr); pUartState->u32BaudRate = calculatedBaud; retVal = LPUART_UART_IP_STATUS_SUCCESS; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_GetBaudRate * Description : Returns the LPUART configured baud rate. * * Implements : Lpuart_Uart_Ip_GetBaudRate_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_GetBaudRate_Activity*/ void Lpuart_Uart_Ip_GetBaudRate(uint32 u32Instance, uint32 * pConfiguredBaudRate) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pConfiguredBaudRate != NULL_PTR); Lpuart_Uart_Ip_StateStructureType * pUartState; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; *pConfiguredBaudRate = pUartState->u32BaudRate; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_SetTxBuffer * Description : Sets the driver internal reference to the tx buffer. * Can be called from the tx callback to provide a different * buffer for continuous transmission. * * Implements : Lpuart_Uart_Ip_SetTxBuffer_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_SetTxBuffer_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetTxBuffer(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pTxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32TxSize > 0U); Lpuart_Uart_Ip_StateStructureType * pUartState; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartState->pTxBuff = pTxBuff; pUartState->u32TxSize = u32TxSize; return LPUART_UART_IP_STATUS_SUCCESS; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_SetRxBuffer * Description : Sets the driver internal reference to the rx buffer. * Can be called from the rx callback to provide a different * buffer for continuous reception. * * Implements : Lpuart_Uart_Ip_SetRxBuffer_Activity *END**************************************************************************/ /* implements Lpuart_Uart_Ip_SetRxBuffer_Activity*/ Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_SetRxBuffer(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_UART_DEV_ASSERT(pRxBuff != NULL_PTR); LPUART_UART_DEV_ASSERT(u32RxSize > 0U); Lpuart_Uart_Ip_StateStructureType * pUartState; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartState->pRxBuff = pRxBuff; pUartState->u32RxSize = u32RxSize; return LPUART_UART_IP_STATUS_SUCCESS; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_IRQHandler * Description : Interrupt handler for LPUART. * This handler uses the buffers stored in the Lpuart_Uart_Ip_StateStructureType structs to transfer * data. This is not a public API as it is called by IRQ whenever an interrupt * occurs. * *END**************************************************************************/ /* implements Lpuart_Uart_Ip_IRQHandler_Activity*/ void Lpuart_Uart_Ip_IRQHandler(uint32 u32Instance) { LPUART_UART_DEV_ASSERT(u32Instance < LPUART_UART_IP_NUMBER_OF_INSTANCES); LPUART_Type * pBase; Lpuart_Uart_Ip_StateStructureType * pUartState; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; boolean bIsReturn = FALSE; /* Case of spurious interrupt when driver is not at all initialized or it is not in transmit/receive process*/ if (pUartState == NULL_PTR) { /* Read dummy to clear RDRF flag if it is set*/ (void)LPUART_Uart_Getchar(pBase); /* Clear all the error flags */ LPUART_Uart_ClearErrorFlags(pBase); /* Transmit flags can not be cleared, return to exit */ } else { Lpuart_Uart_Ip_ErrIrqHandler(u32Instance); /* Handle receive data full interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_DATA_REG_FULL)) { if (LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_RX_DATA_REG_FULL)) { Lpuart_Uart_Ip_RxIrqHandler(u32Instance); } /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */ else { /* Read dummy to clear RDRF flag */ (void)LPUART_Uart_Getchar(pBase); } bIsReturn = TRUE; } /* Handle transmitter data register empty interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_TX_DATA_REG_EMPTY) && (bIsReturn == FALSE)) { if (LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY)) { Lpuart_Uart_Ip_TxEmptyIrqHandler(u32Instance); bIsReturn = TRUE; } /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */ else { /* Do nothing, because TDRE can not clear without affecting to normal operation*/ } } /* Handle transmission complete interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_TX_COMPLETE) && (bIsReturn == FALSE)) { if (LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_TX_COMPLETE)) { Lpuart_Uart_Ip_TxCompleteIrqHandler(u32Instance); } /* Case of spurious interrupt when the interupt enable flag is not set and respective interrupt status flag is set */ else { /* Do nothing, because TC can not clear without affecting to normal operation*/ } } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_RxIrqHandler * Description : Rx Interrupt handler for LPUART. * This function treats the rx full interrupt. * *END**************************************************************************/ static void Lpuart_Uart_Ip_RxIrqHandler(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Get data and put in receive buffer */ Lpuart_Uart_Ip_GetData(u32Instance); /* Check if this was the last byte in the current buffer */ if (pUartState->u32RxSize == 0U) { /* Invoke callback if there is one (callback may reset the rx buffer for continuous reception) */ if (pUartUserCfg->pfRxCallback != NULL_PTR) { pUartUserCfg->pfRxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_RX_FULL, pUartUserCfg->pRxCallbackParam); } } /* Finish reception if this was the last byte received */ if (pUartState->u32RxSize == 0U) { /* Complete transfer (disable rx logic) */ Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(u32Instance); /* Invoke callback if there is one */ if (pUartUserCfg->pfRxCallback != NULL_PTR) { pUartUserCfg->pfRxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_END_TRANSFER, pUartUserCfg->pRxCallbackParam); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_TxEmptyIrqHandler * Description : Tx Empty Interrupt handler for LPUART. * This function treats the tx empty interrupt. * *END**************************************************************************/ static void Lpuart_Uart_Ip_TxEmptyIrqHandler(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Check if there are any more bytes to send */ if (pUartState->u32TxSize > 0U) { /* Transmit the data */ Lpuart_Uart_Ip_PutData(u32Instance); /* Check if this was the last byte in the current buffer */ if ((pUartState->u32TxSize == 0U) && (pUartUserCfg->pfTxCallback != NULL_PTR)) { /* Invoke callback if there is one (callback may reset the tx buffer for continuous transmission)*/ pUartUserCfg->pfTxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_TX_EMPTY, pUartUserCfg->pTxCallbackParam); } /* If there's no new data, disable tx empty interrupt and enable transmission complete interrupt */ if (pUartState->u32TxSize == 0U) { LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_COMPLETE, TRUE); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_TxCompleteIrqHandler * Description : Tx Complete Interrupt handler for LPUART. * This function treats the tx complete interrupt. * *END**************************************************************************/ static void Lpuart_Uart_Ip_TxCompleteIrqHandler(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; if (pUartState->u32TxSize == 0U) { if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* Complete the interrupt based transfer */ Lpuart_Uart_Ip_CompleteSendDataUsingInt(u32Instance); } /* Invoke callback if there is one */ if (pUartUserCfg->pfTxCallback != NULL_PTR) { pUartUserCfg->pfTxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_END_TRANSFER, pUartUserCfg->pTxCallbackParam); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_ErrIrqHandler * Description : Error Interrupt handler for LPUART. * This function treats the error interrupts. * *END**************************************************************************/ static void Lpuart_Uart_Ip_ErrIrqHandler(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; boolean bIsError = FALSE; boolean bIsReturn = FALSE; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Handle receive overrun interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_RX_OVERRUN)) { /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_RX_OVERRUN); /* Case of spurious interrupt when interrupt enable bit is not set*/ if (!LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN)) { bIsReturn = TRUE; } else { /* Update the status */ bIsError = TRUE; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_RX_OVERRUN; } } /* Handle framing error interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_FRAME_ERR) && (bIsReturn == FALSE)) { /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_FRAME_ERR); /* Case of spurious interrupt when interrupt enable bit is not set*/ if (!LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG)) { bIsReturn = TRUE; } else { /* Update the status */ bIsError = TRUE; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_FRAMING_ERROR; } } /* Handle parity error interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_PARITY_ERR) && (bIsReturn == FALSE)) { /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_PARITY_ERR); /* Case of spurious interrupt when interrupt enable bit is not set*/ if (!LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG)) { bIsReturn = TRUE; } else { /* Update the status */ bIsError = TRUE; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_PARITY_ERROR; } } /* Handle noise error interrupt */ if (LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_NOISE_DETECT) && (bIsReturn == FALSE)) { /* Clear the flag */ LPUART_Uart_ClearStatusFlag(pBase, LPUART_UART_IP_NOISE_DETECT); /* Case of spurious interrupt when interrupt enable bit is not set*/ if (!LPUART_Uart_GetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG)) { bIsReturn = TRUE; } else { /* Update the internal status */ bIsError = TRUE; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_NOISE_ERROR; } } if(bIsReturn == FALSE) { if (bIsError == TRUE) { if (pUartUserCfg->eTransferType == LPUART_UART_IP_USING_INTERRUPTS) { /* Complete the transfer (disable rx logic) */ Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(u32Instance); } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) else { /* Complete the transfer (stop DMA channel) */ (void)Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8RxDMAChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST); Lpuart_Uart_Ip_CompleteReceiveUsingDma(u32Instance); } #endif /* Invoke callback if there is one */ if (pUartUserCfg->pfErrorCallback != NULL_PTR) { pUartUserCfg->pfErrorCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_ERROR, pUartUserCfg->pErrorCallbackParam); } } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_StartSendDataUsingInt * Description : Initiate (start) a transmit by beginning the process of * sending data and enabling the interrupt. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingInt(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize) { LPUART_Type * pBase; Lpuart_Uart_Ip_StateStructureType * pUartState; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; /* initialize the module driver state structure */ pUartState->pTxBuff = pTxBuff; pUartState->u32TxSize = u32TxSize; pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_BUSY; /* Enable the LPUART transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, TRUE); /* Enable tx empty interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, TRUE); return LPUART_UART_IP_STATUS_SUCCESS; } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_StartSendDataUsingDma * Description : Initiate (start) a transmit by beginning the process of * sending data using DMA transfers. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartSendDataUsingDma(uint32 u32Instance, const uint8 * pTxBuff, uint32 u32TxSize) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; Dma_Ip_LogicChannelTransferListType dmaTransferList[LPUART_UART_DMA_CONFIG_LIST_DIMENSION]; Dma_Ip_ReturnType eDmaReturnStatus; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Set up parameters for Dma_Ip_LogicChannelTransferListType */ dmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS; dmaTransferList[0].Value = (uint32)pTxBuff; dmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS; dmaTransferList[1].Value = LPUART_UART_IP_LSBW_ADDR(pBase->DATA); dmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET; dmaTransferList[2].Value = 1; dmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET; dmaTransferList[3].Value = 0; dmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT; dmaTransferList[4].Value = u32TxSize; dmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE; dmaTransferList[5].Value = 1; dmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE; dmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; dmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE; dmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; dmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT; dmaTransferList[8].Value = 1; dmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST; dmaTransferList[9].Value = 1; /* Update state structure */ pUartState->pTxBuff = pTxBuff; pUartState->u32TxSize = 0U; pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_BUSY; /* Configure the transfer control descriptor for the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(pUartUserCfg->u8TxDMAChannel, dmaTransferList, LPUART_UART_DMA_CONFIG_LIST_DIMENSION); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Start the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8TxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Enable the LPUART transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, TRUE); /* Enable tx DMA requests for the current instance */ LPUART_Uart_SetTxDmaCmd(pBase, TRUE); return LPUART_UART_IP_STATUS_SUCCESS; } #endif /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_CompleteSendDataUsingInt * Description : Finish up a transmit by completing the process of sending * data and disabling the interrupt. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static void Lpuart_Uart_Ip_CompleteSendDataUsingInt(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; LPUART_Type * pBase; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; if (pUartState->eTransmitStatus == LPUART_UART_IP_STATUS_BUSY) { /* If the transfer is completed, update the transmit status */ pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_SUCCESS; } else { /* If the transfer is aborted or timed out, disable tx empty interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_DATA_REG_EMPTY, FALSE); } /* Disable transmission complete interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_TX_COMPLETE, FALSE); /* Disable transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, FALSE); /* Update the internal busy flag */ pUartState->bIsTxBusy = FALSE; } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_CompleteSendUsingDma * Description : Finish up a transmit by completing the process of sending * data and disabling the DMA requests. This is a callback for DMA major loop * completion, so it must match the DMA callback signature. * *END**************************************************************************/ void Lpuart_Uart_Ip_CompleteSendUsingDma(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; Dma_Ip_LogicChannelTransferListType dmaTransferList[LPUART_UART_DMA_CONFIG_LIST_DIMENSION]; Dma_Ip_ReturnType eDmaReturnStatus; Dma_Ip_LogicChannelStatusType dmaStatus; uint32 u32StartTime; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Get Dma Ip Logic Channel Status */ (void)Dma_Ip_GetLogicChannelStatus(pUartUserCfg->u8TxDMAChannel, &dmaStatus); if (dmaStatus.ChStateValue == DMA_IP_CH_ERROR_STATE) { /* Reset the Dma Channel Error status. */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8TxDMAChannel, DMA_IP_CH_CLEAR_ERROR); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Update transmit status */ pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_ERROR; /* Invoke callback if there is one */ if (pUartUserCfg->pfErrorCallback != NULL_PTR) { pUartUserCfg->pfErrorCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_ERROR, pUartUserCfg->pErrorCallbackParam); } } /* Invoke the callback when the buffer is finished; * Application can provide another buffer inside the callback by calling Lpuart_Uart_Ip_SetTxBuffer */ if (pUartState->eTransmitStatus == LPUART_UART_IP_STATUS_BUSY) { /* Invoke callback if there is one (callback may reset the tx buffer for continuous transmission)*/ if (pUartUserCfg->pfTxCallback != NULL_PTR) { pUartUserCfg->pfTxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_TX_EMPTY, pUartUserCfg->pTxCallbackParam); } } /* If the callback has updated the tx buffer, update the DMA descriptor to continue the transfer; * otherwise, stop the current transfer. */ if ((pUartState->u32TxSize > 0U) && (pUartState->eTransmitStatus != LPUART_UART_IP_STATUS_ERROR)) { /* Set up parameters for Dma_Ip_LogicChannelTransferListType */ dmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS; dmaTransferList[0].Value = (uint32)(pUartState->pTxBuff); /* Update tx size and major loop count parameters for Dma_Ip_LogicChannelTransferListType */ dmaTransferList[1].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT; dmaTransferList[1].Value = pUartState->u32TxSize; /* Re-configure the transfer control descriptor for the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(pUartUserCfg->u8TxDMAChannel, dmaTransferList, LPUART_UART_DMA_LEAST_CONFIG_LIST_DIMENSION); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Now that this tx is set up, clear remaining bytes count */ pUartState->u32TxSize = 0U; /* Re-start the channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8TxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); } else { /* In Abort case, the transmission need to stop instantly */ if (pUartState->eTransmitStatus != LPUART_UART_IP_STATUS_ABORTED) { /* Wait until the last transmission complete */ u32StartTime = OsIf_GetCounter(LPUART_UART_IP_TIMEOUT_TYPE); while (!LPUART_Uart_GetStatusFlag(pBase, LPUART_UART_IP_TX_COMPLETE) && \ !LPUART_Uart_CheckTimeout(u32StartTime, (uint32)LPUART_UART_IP_TIMEOUT_VALUE_US)) {} } /* Disable tx DMA requests for the current instance */ LPUART_Uart_SetTxDmaCmd(pBase, FALSE); /* Disable the transmitter */ LPUART_Uart_SetTransmitterCmd(pBase, FALSE); /* Update the busy flag */ pUartState->bIsTxBusy = FALSE; /* If the current reception hasn't been aborted, update the status */ if (pUartState->eTransmitStatus == LPUART_UART_IP_STATUS_BUSY) { pUartState->eTransmitStatus = LPUART_UART_IP_STATUS_SUCCESS; /* Invoke callback if there is one */ if (pUartUserCfg->pfTxCallback != NULL_PTR) { pUartUserCfg->pfTxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_END_TRANSFER, pUartUserCfg->pTxCallbackParam); } } } } #endif /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_StartReceiveDataUsingInt * Description : Initiate (start) a receive by beginning the process of * receiving data and enabling the interrupt. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingInt(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize) { LPUART_Type * pBase; Lpuart_Uart_Ip_StateStructureType * pUartState; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; /* Initialize the module driver state struct to indicate transfer in progress * and with the buffer and byte count data. */ pUartState->bIsRxBusy = TRUE; pUartState->pRxBuff = pRxBuff; pUartState->u32RxSize = u32RxSize; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_BUSY; /* Clear all the error flags */ LPUART_Uart_ClearErrorFlags(pBase); /* Flush the Tx Buffer */ LPUART_Uart_FlushRxBuffer(pBase); /* Enable the receiver */ LPUART_Uart_SetReceiverCmd(pBase, TRUE); /* Enable error interrupts */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG, TRUE); /* Enable receive data full interrupt */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_DATA_REG_FULL, TRUE); return LPUART_UART_IP_STATUS_SUCCESS; } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_StartReceiveDataUsingDma * Description : Initiate (start) a receive by beginning the process of * receiving data using DMA transfers. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingDma(uint32 u32Instance, uint8 * pRxBuff, uint32 u32RxSize) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; Dma_Ip_LogicChannelTransferListType dmaTransferList[LPUART_UART_DMA_CONFIG_LIST_DIMENSION]; Dma_Ip_ReturnType eDmaReturnStatus; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Clear all the error flags */ LPUART_Uart_ClearErrorFlags(pBase); /* Flush the Tx Buffer */ LPUART_Uart_FlushRxBuffer(pBase); /* Set up parameters for Dma_Ip_LogicChannelTransferListType */ dmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS; dmaTransferList[0].Value = LPUART_UART_IP_LSBW_ADDR(pBase->DATA); dmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS; dmaTransferList[1].Value = (uint32)pRxBuff; dmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET; dmaTransferList[2].Value = 0; dmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET; dmaTransferList[3].Value = 1; dmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT; dmaTransferList[4].Value = u32RxSize; dmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE; dmaTransferList[5].Value = 1; dmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE; dmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; dmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE; dmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; dmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT; dmaTransferList[8].Value = 1; dmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST; dmaTransferList[9].Value = 1; /* Update the state structure */ pUartState->pRxBuff = pRxBuff; pUartState->u32RxSize = 0U; pUartState->bIsRxBusy = TRUE; pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_BUSY; /* Configure the transfer control descriptor for the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(pUartUserCfg->u8RxDMAChannel, dmaTransferList, LPUART_UART_DMA_CONFIG_LIST_DIMENSION); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Start the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8RxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Enable the receiver */ LPUART_Uart_SetReceiverCmd(pBase, TRUE); /* Enable error interrupts */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG, TRUE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG, TRUE); /* Enable rx DMA requests for the current instance */ LPUART_Uart_SetRxDmaCmd(pBase, TRUE); return LPUART_UART_IP_STATUS_SUCCESS; } #endif /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_CompleteReceiveDataUsingInt * Description : Finish up a receive by completing the process of receiving data * and disabling the interrupt. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static void Lpuart_Uart_Ip_CompleteReceiveDataUsingInt(uint32 u32Instance) { LPUART_Type * pBase; Lpuart_Uart_Ip_StateStructureType * pUartState; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; /* Disable receiver */ LPUART_Uart_SetReceiverCmd(pBase, FALSE); /* Disable all error interrupts */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG, FALSE); /* Disable receive data full and rx overrun interrupt. */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_DATA_REG_FULL, FALSE); /* Read dummy to clear RDRF flag */ (void)LPUART_Uart_Getchar(pBase); /* Update the information of the module driver state */ pUartState->bIsRxBusy = FALSE; if (pUartState->eReceiveStatus == LPUART_UART_IP_STATUS_BUSY) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS; } } #if (LPUART_UART_IP_HAS_DMA_ENABLED == STD_ON) /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_CompleteReceiveUsingDma * Description : Finish up a receive by completing the process of receiving data * and disabling the DMA requests. This is a callback for DMA major loop * completion, so it must match the DMA callback signature. * *END**************************************************************************/ void Lpuart_Uart_Ip_CompleteReceiveUsingDma(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; Dma_Ip_LogicChannelTransferListType dmaTransferList[LPUART_UART_DMA_CONFIG_LIST_DIMENSION]; Dma_Ip_ReturnType eDmaReturnStatus; Dma_Ip_LogicChannelStatusType dmaStatus; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; /* Get Dma Ip Logic Channel Status */ (void)Dma_Ip_GetLogicChannelStatus(pUartUserCfg->u8RxDMAChannel, &dmaStatus); if (dmaStatus.ChStateValue == DMA_IP_CH_ERROR_STATE) { /* Reset the Dma Channel Error status. */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8RxDMAChannel, DMA_IP_CH_CLEAR_ERROR); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Update transmit status */ pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_ERROR; /* Invoke callback if there is one */ if (pUartUserCfg->pfErrorCallback != NULL_PTR) { pUartUserCfg->pfErrorCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_ERROR, pUartUserCfg->pErrorCallbackParam); } } /* Invoke the callback when the buffer is finished */ if (pUartState->eReceiveStatus == LPUART_UART_IP_STATUS_BUSY) { /* Application can provide another buffer inside the callback by calling Lpuart_Uart_Ip_SetRxBuffer */ if (pUartUserCfg->pfRxCallback != NULL_PTR) { pUartUserCfg->pfRxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_RX_FULL, pUartUserCfg->pRxCallbackParam); } } /* If the callback has updated the rx buffer, update the DMA descriptor to continue the transfer; * otherwise, stop the current transfer. */ if ((pUartState->u32RxSize > 0U) && (pUartState->eReceiveStatus != LPUART_UART_IP_STATUS_ERROR)) { /* Set up parameters for Dma_Ip_LogicChannelTransferListType */ dmaTransferList[0].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS; dmaTransferList[0].Value = (uint32)(pUartState->pRxBuff); dmaTransferList[1].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT; dmaTransferList[1].Value = pUartState->u32RxSize; /* Re-configure the transfer control descriptor for the DMA channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(pUartUserCfg->u8RxDMAChannel, dmaTransferList, LPUART_UART_DMA_LEAST_CONFIG_LIST_DIMENSION); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); /* Now that this rx is set up, clear remaining bytes count */ pUartState->u32RxSize = 0U; /* Re-start the channel */ eDmaReturnStatus = Dma_Ip_SetLogicChannelCommand(pUartUserCfg->u8RxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST); LPUART_UART_DEV_ASSERT(eDmaReturnStatus == DMA_IP_STATUS_SUCCESS); } else { /* Disable receiver */ LPUART_Uart_SetReceiverCmd(pBase, FALSE); /* Disable error interrupts */ LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_RX_OVERRUN, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_PARITY_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_NOISE_ERR_FLAG, FALSE); LPUART_Uart_SetIntMode(pBase, LPUART_UART_IP_INT_FRAME_ERR_FLAG, FALSE); /* Disable rx DMA requests for the current instance */ LPUART_Uart_SetRxDmaCmd(pBase, FALSE); /* Read dummy to clear RDRF flag */ (void)LPUART_Uart_Getchar(pBase); /* Update the information of the module driver state */ pUartState->bIsRxBusy = FALSE; /* If the current reception hasn't been aborted, update the status and call the callback */ if (pUartState->eReceiveStatus == LPUART_UART_IP_STATUS_BUSY) { pUartState->eReceiveStatus = LPUART_UART_IP_STATUS_SUCCESS; /* Call the callback to notify application that the transfer is complete */ if (pUartUserCfg->pfRxCallback != NULL_PTR) { pUartUserCfg->pfRxCallback(u32Instance, pUartState, LPUART_UART_IP_EVENT_END_TRANSFER, pUartUserCfg->pRxCallbackParam); } } } } #endif /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_PutData * Description : Write data to the buffer register, according to configured * word length. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static void Lpuart_Uart_Ip_PutData(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; uint16 u16Data; uint8 u8Data; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; if ((LPUART_UART_IP_7_BITS_PER_CHAR == pUartUserCfg->eBitCountPerChar) || (LPUART_UART_IP_8_BITS_PER_CHAR == pUartUserCfg->eBitCountPerChar)) { u8Data = *(pUartState->pTxBuff); /* Update the state structure */ ++pUartState->pTxBuff; --pUartState->u32TxSize; /* Transmit the data */ LPUART_Uart_Putchar(pBase, u8Data); } else { u16Data = (uint16)(*pUartState->pTxBuff); /* Update the state structure */ if(pUartState->u32TxSize == 1U) { ++pUartState->pTxBuff; --pUartState->u32TxSize; } else { ++pUartState->pTxBuff; u16Data |= (uint16)(((uint16)(*pUartState->pTxBuff)) << 8U); ++pUartState->pTxBuff; pUartState->u32TxSize -= 2U; } /* Transmit the data */ if (pUartUserCfg->eBitCountPerChar == LPUART_UART_IP_9_BITS_PER_CHAR) { LPUART_Uart_Putchar9(pBase, u16Data); } else { LPUART_Uart_Putchar10(pBase, u16Data); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Uart_Ip_GetData * Description : Read data from the buffer register, according to configured * word length. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static void Lpuart_Uart_Ip_GetData(uint32 u32Instance) { Lpuart_Uart_Ip_StateStructureType * pUartState; const Lpuart_Uart_Ip_UserConfigType *pUartUserCfg; LPUART_Type * pBase; uint16 u16Data; pBase = Lpuart_Uart_Ip_apBases[u32Instance]; pUartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[u32Instance]; pUartUserCfg = (Lpuart_Uart_Ip_UserConfigType*) Lpuart_Uart_Ip_apUserConfig[u32Instance]; if ((LPUART_UART_IP_7_BITS_PER_CHAR == pUartUserCfg->eBitCountPerChar) || (LPUART_UART_IP_8_BITS_PER_CHAR == pUartUserCfg->eBitCountPerChar)) { /* Receive the data */ *(pUartState->pRxBuff) = LPUART_Uart_Getchar(pBase); if (LPUART_UART_IP_7_BITS_PER_CHAR == pUartUserCfg->eBitCountPerChar) { *(pUartState->pRxBuff) &= 0x7FU; } /* Update the state structure */ ++pUartState->pRxBuff; --pUartState->u32RxSize; } else { if (pUartUserCfg->eBitCountPerChar == LPUART_UART_IP_9_BITS_PER_CHAR) { u16Data = LPUART_Uart_Getchar9(pBase); } else { u16Data = LPUART_Uart_Getchar10(pBase); } /* Get the data and update state structure */ if(pUartState->u32RxSize == 1U) { *(pUartState->pRxBuff) = (uint8)u16Data; ++pUartState->pRxBuff; --pUartState->u32RxSize; } else { /* Write the least significant bits to the receive buffer */ *(pUartState->pRxBuff) = (uint8)(u16Data & 0xFFU); ++pUartState->pRxBuff; /* Write the ninth bit to the subsequent byte in the rx buffer */ *pUartState->pRxBuff = (uint8)(u16Data >> 8U); ++pUartState->pRxBuff; pUartState->u32RxSize -= 2U; } } } #define UART_STOP_SEC_CODE /* @violates @ref Uart_c_REF_1 This violation is not fixed since the inclusion of Uart_MemMap.h is as per AUTOSAR requirement*/ #include "Uart_MemMap.h" #ifdef __cplusplus } /** @} */ #endif