/*================================================================================================== * Project : RTD AUTOSAR 4.4 * Platform : CORTEXM * Peripheral : LPUART * Dependencies : none * * 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_Lin_Ip.c * * @addtogroup LPUART_LIN_IP * @{ */ #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_Lin_Ip.h" /*================================================================================================== * SOURCE FILE VERSION INFORMATION ==================================================================================================*/ #define LPUART_LIN_IP_VENDOR_ID_C 43 #define LPUART_LIN_IP_AR_RELEASE_MAJOR_VERSION_C 4 #define LPUART_LIN_IP_AR_RELEASE_MINOR_VERSION_C 4 #define LPUART_LIN_IP_AR_RELEASE_REVISION_VERSION_C 0 #define LPUART_LIN_IP_SW_MAJOR_VERSION_C 0 #define LPUART_LIN_IP_SW_MINOR_VERSION_C 9 #define LPUART_LIN_IP_SW_PATCH_VERSION_C 0 /*================================================================================================== * FILE VERSION CHECKS ==================================================================================================*/ #if (LPUART_LIN_IP_VENDOR_ID_C != LPUART_LIN_IP_VENDOR_ID) #error "Lpuart_Lin_Ip.c and Lpuart_Lin_Ip.h have different vendor ids" #endif /* Check if current file and Lpuart_Lin_Ip header file are of the same Autosar version */ #if ((LPUART_LIN_IP_AR_RELEASE_MAJOR_VERSION_C != LPUART_LIN_IP_AR_RELEASE_MAJOR_VERSION) || \ (LPUART_LIN_IP_AR_RELEASE_MINOR_VERSION_C != LPUART_LIN_IP_AR_RELEASE_MINOR_VERSION) || \ (LPUART_LIN_IP_AR_RELEASE_REVISION_VERSION_C != LPUART_LIN_IP_AR_RELEASE_REVISION_VERSION)) #error "AutoSar Version Numbers of Lpuart_Lin_Ip.c and Lpuart_Lin_Ip.h are different" #endif /* Check if current file and Lpuart_Lin_Ip header file are of the same Software version */ #if ((LPUART_LIN_IP_SW_MAJOR_VERSION_C != LPUART_LIN_IP_SW_MAJOR_VERSION) || \ (LPUART_LIN_IP_SW_MINOR_VERSION_C != LPUART_LIN_IP_SW_MINOR_VERSION) || \ (LPUART_LIN_IP_SW_PATCH_VERSION_C != LPUART_LIN_IP_SW_PATCH_VERSION) ) #error "Software Version Numbers of Lpuart_Lin_Ip.c and Lpuart_Lin_Ip.h are different" #endif /*================================================================================================== * LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS) ==================================================================================================*/ /*================================================================================================== * LOCAL MACROS ==================================================================================================*/ /*================================================================================================== * LOCAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * LOCAL VARIABLES ==================================================================================================*/ #define LIN_START_SEC_VAR_NO_INIT_8 #include "Lin_MemMap.h" static uint8 Lpuart_Lin_Ip_au8WakeupSignal[LPUART_INSTANCE_COUNT]; #define LIN_STOP_SEC_VAR_NO_INIT_8 #include "Lin_MemMap.h" /*================================================================================================== * GLOBAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * GLOBAL VARIABLES ==================================================================================================*/ /* Table of base addresses for LPUART instances. */ #define LIN_START_SEC_CONST_UNSPECIFIED #include "Lin_MemMap.h" static LPUART_Type * const Lpuart_Lin_Ip_apxBases[LPUART_INSTANCE_COUNT] = LPUART_BASE_PTRS; #define LIN_STOP_SEC_CONST_UNSPECIFIED #include "Lin_MemMap.h" #define LIN_START_SEC_VAR_NO_INIT_UNSPECIFIED #include "Lin_MemMap.h" Lpuart_Lin_Ip_StateStructType Lpuart_Lin_Ip_axStateStructure[LPUART_LIN_IP_NUMBER_OF_INSTANCES]; /* Table to save LIN user config structure pointers */ static const Lpuart_Lin_Ip_UserConfigType * Lpuart_Lin_Ip_apxUserConfigs[LPUART_INSTANCE_COUNT]; static Lpuart_Lin_Ip_StateStructType *Lpuart_Lin_Ip_apxStateStructureArray[LPUART_INSTANCE_COUNT]; #define LIN_STOP_SEC_VAR_NO_INIT_UNSPECIFIED #include "Lin_MemMap.h" /*================================================================================================== * LOCAL FUNCTION PROTOTYPES ==================================================================================================*/ #define LIN_START_SEC_CODE #include "Lin_MemMap.h" static void Lpuart_Lin_Ip_ProcessBreakDetect(const uint32 u32Instance); static void Lpuart_Lin_Ip_CheckWakeupSignal(const uint32 u32Instance); static void Lpuart_Lin_Ip_FrameIrqHandler(const uint32 u32Instance); static void Lpuart_Lin_Ip_ProcessFrameHeader(const uint32 u32Instance, const uint8 tmpByte); static void Lpuart_Lin_Ip_ProcessReceiveFrameData(const uint32 u32Instance); static void Lpuart_Lin_Ip_ProcessSendFrameData(const uint32 u32Instance, const uint8 tmpByte); static uint8 Lpuart_Lin_Ip_MakeChecksumByte(const uint32 u32Instance, \ const uint8 * buffer, \ const uint8 sizeBuffer, \ const uint8 PID \ ); static void Lpuart_Lin_Ip_AutoBaudCapture(const uint32 u32Instance); static void Lpuart_Lin_Ip_ProcessWakeupDetect(const uint32 u32Instance); static void Lpuart_Lin_Ip_FrameErrorIrqHandler(const uint32 u32Instance); static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_StatusBeforeTransfer(const uint8 u8Size, const Lpuart_Lin_Ip_StateStructType *linCurrentState); static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_GetBytetoBuffer(const uint8 byteCnt, \ const uint8 u8BuffSize, \ uint8 * pBuff, \ const uint32 u32Instance \ ); static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_CheckReadbackByte(const uint8 readbackByte, const uint8 sendByte); /*================================================================================================== * LOCAL FUNCTIONS ==================================================================================================*/ /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_CheckReadbackByte * Description : This function checks read-back byte and updates status. * *END**************************************************************************/ static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_CheckReadbackByte(const uint8 readbackByte, const uint8 sendByte) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; if (sendByte != readbackByte) { retVal = LPUART_LIN_IP_STATUS_ERROR; } else { /* Do nothing */ } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_GetBytetoBuffer * Description : This function get received byte then stored to up and also update instance state. * *END**************************************************************************/ static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_GetBytetoBuffer(const uint8 byteCnt, \ const uint8 u8BuffSize, \ uint8 * pBuff, \ const uint32 u32Instance \ ) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; const LPUART_Type *base = Lpuart_Lin_Ip_apxBases[u32Instance]; Lpuart_Lin_Ip_StateStructType *linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; uint8 checkSum; if (byteCnt < u8BuffSize) { /* No error happened, get data bytes */ Lpuart_Lin_Ip_HwGetchar(base, &pBuff[byteCnt]); } else { /* Get checksum byte */ Lpuart_Lin_Ip_HwGetchar(base, &checkSum); if (checkSum != Lpuart_Lin_Ip_MakeChecksumByte(u32Instance, pBuff, u8BuffSize, linCurrentState->currentPid)) { linCurrentState->currentEventId = LPUART_LIN_IP_CHECKSUM_ERROR_EVENT; retVal = LPUART_LIN_IP_STATUS_ERROR; } else { linCurrentState->currentEventId = LPUART_LIN_IP_RX_COMPLETED; linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_DATA_COMPLETED; retVal = LPUART_LIN_IP_STATUS_SUCCESS; } } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_StatusBeforeTransfer * Description : This function checks input parameters of transmission/reception operation. * *END**************************************************************************/ static Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_StatusBeforeTransfer(const uint8 u8Size, const Lpuart_Lin_Ip_StateStructType *linCurrentState) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; boolean checkSleepMode = (LPUART_LIN_IP_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState); if ((8U < u8Size) || (0U == u8Size) || checkSleepMode) { retVal = LPUART_LIN_IP_STATUS_ERROR; } else { /* Check if the LIN Bus is busy */ if (linCurrentState->isBusBusy) { retVal = LPUART_LIN_IP_STATUS_BUSY; } } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_FrameErrorIrqHandler * Description : This function handles frame error when it occurs * *END**************************************************************************/ static void Lpuart_Lin_Ip_FrameErrorIrqHandler(const uint32 u32Instance) { LPUART_Type *base = Lpuart_Lin_Ip_apxBases[u32Instance]; Lpuart_Lin_Ip_StateStructType *linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; const Lpuart_Lin_Ip_UserConfigType *pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; uint8 tmpByte; /* Clear Framing Error Interrupt Flag */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_FRAME_ERR); /* Read dummy to clear LPUART_LIN_IP_RX_DATA_REG_FULL flag */ Lpuart_Lin_Ip_HwGetchar(base, &tmpByte); /* Set current event id to LIN_FRAME_ERROR */ linCurrentState->currentEventId = LPUART_LIN_IP_FRAME_ERROR; /* Check if LIN current node state is LPUART_LIN_IP_NODE_STATE_SEND_DATA */ if (LPUART_LIN_IP_NODE_STATE_SEND_DATA == linCurrentState->currentNodeState) { /* Callback function to handle Framing Error Event */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } else { /* Check if LIN current node state is LPUART_LIN_IP_NODE_STATE_RECV_DATA */ if (LPUART_LIN_IP_NODE_STATE_RECV_DATA == linCurrentState->currentNodeState) { /* Callback function to handle Framing Error Event */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_MakeChecksumByte * Description : This function calculate checksum for a frame. This function * will return classic or enhanced checksum base on data in * Lpuart_Lin_Ip_apxUserConfigs[u32Instance] and input parameter. * *END**************************************************************************/ static uint8 Lpuart_Lin_Ip_MakeChecksumByte(const uint32 u32Instance, const uint8 * buffer, const uint8 sizeBuffer, const uint8 PID) { uint8 checkSum = PID; const uint8 *classicPID; uint8 retVal = 0U; const Lpuart_Lin_Ip_StateStructType *linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; const uint8 numOfClassicPID = linCurrentState->numOfClassicPID; /* Get list of PIDs use classic checksum. */ classicPID = linCurrentState->classicPID; if (255U == numOfClassicPID) { /*all frame use enhanced checksum */ checkSum = 0U; } else { if(NULL_PTR != classicPID) { for (retVal = 0U; retVal < numOfClassicPID; retVal++) { if(checkSum == classicPID[retVal]) { checkSum = 0U; break; } } } } retVal = Lin_Ip_MakeChecksumByte(buffer, sizeBuffer, checkSum); return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_AutoBaudCapture * Description : This function capture bits time to detect break char, calculate * baudrate from sync bits and enable transceiver if autobaud successful. * This function should only be used in Slave. * *END**************************************************************************/ static void Lpuart_Lin_Ip_AutoBaudCapture(const uint32 u32Instance) { static uint32 currentTick; static uint8 fallingEgdeCount; uint32 u32ElapsedTicks; uint32 tickPerMicros; uint32 masterBaudrateDivisor = 0UL; uint8 wakeupByte = 0xF8u; /* wakeup byte for baudrate smaller than 10000 bps */ const Lpuart_Lin_Ip_UserConfigType *pUserConfig; Lpuart_Lin_Ip_StateStructType *linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; LPUART_Type *base = Lpuart_Lin_Ip_apxBases[u32Instance]; pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; if (fallingEgdeCount++ > 0u) { /* Time between two time falling edge */ u32ElapsedTicks = OsIf_GetElapsed(¤tTick, LPUART_LIN_IP_TIMEOUT_TYPE); /* Get number of tick per a micro second */ tickPerMicros = OsIf_MicrosToTicks(1000000, LPUART_LIN_IP_TIMEOUT_TYPE); if ((u32ElapsedTicks >= (tickPerMicros * BIT_DURATION_MIN_19200)) && (u32ElapsedTicks <= (tickPerMicros * BIT_DURATION_MAX_19200))) { masterBaudrateDivisor = 19200UL; wakeupByte = 0x80u; } if ((u32ElapsedTicks >= (tickPerMicros * BIT_DURATION_MIN_14400)) && (u32ElapsedTicks <= (tickPerMicros * BIT_DURATION_MAX_14400))) { masterBaudrateDivisor = 14400UL; wakeupByte = 0x80u; } if ((u32ElapsedTicks >= (tickPerMicros * BIT_DURATION_MIN_9600)) && (u32ElapsedTicks <= (tickPerMicros * BIT_DURATION_MAX_9600))) { masterBaudrateDivisor = 9600UL; } if ((u32ElapsedTicks >= (tickPerMicros * BIT_DURATION_MIN_4800)) && (u32ElapsedTicks <= (tickPerMicros * BIT_DURATION_MAX_4800))) { masterBaudrateDivisor = 4800UL; } if ((u32ElapsedTicks >= (tickPerMicros * BIT_DURATION_MIN_2400)) && (u32ElapsedTicks <= (tickPerMicros * BIT_DURATION_MAX_2400))) { masterBaudrateDivisor = 2400UL; } if (0UL != masterBaudrateDivisor) { masterBaudrateDivisor = pUserConfig->u32ChannelClock / (pUserConfig->u32OverSamplingRatio * masterBaudrateDivisor); } if ((0UL != masterBaudrateDivisor) && (pUserConfig->u32BaudRateDivisor != masterBaudrateDivisor)) { /* set the new baudrate */ Lpuart_Lin_Ip_HwSetBaudRateDivisor(base, masterBaudrateDivisor); /* configure wakeup byte because it depends on baudrate */ Lpuart_Lin_Ip_au8WakeupSignal[u32Instance] = wakeupByte; linCurrentState->currentEventId = LPUART_LIN_IP_BAUDRATE_ADJUSTED; /* Disable baudrate evaluation process */ linCurrentState->baudrateEvalEnable = (boolean)FALSE; if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* disable Rx active edge */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_ACTIVE_EDGE, (boolean)FALSE); /* Update current state and current event */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_PID; linCurrentState->currentEventId = LPUART_LIN_IP_SYNC_OK; } } else { currentTick = OsIf_GetCounter(LPUART_LIN_IP_TIMEOUT_TYPE); } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessWakeupDetect * Description : This function process wake-up signal detect for LIN communication. * *END**************************************************************************/ static void Lpuart_Lin_Ip_ProcessWakeupDetect(const uint32 u32Instance) { const Lpuart_Lin_Ip_StateStructType * linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; LPUART_Type * base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Clear LPUART_RX Pin Active Edge Interrupt Flag. */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_RX_ACTIVE_EDGE_DETECT); switch(linCurrentState->currentNodeState) { case LPUART_LIN_IP_NODE_STATE_SLEEP_MODE: /* Check if a wakeup signal has been received */ Lpuart_Lin_Ip_CheckWakeupSignal(u32Instance); break; case LPUART_LIN_IP_NODE_STATE_RECV_SYNC: if (linCurrentState->baudrateEvalEnable) { /* Count falling edge of sync byte */ Lpuart_Lin_Ip_AutoBaudCapture(u32Instance); } break; default: /* Other case, do nothing */ break; } } /*================================================================================================== * GLOBAL FUNCTIONS ==================================================================================================*/ /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_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, initialize the module to user defined settings and * default settings, set break field length to be 13 bit times minimum, enable * the break detect interrupt, Rx complete interrupt, frame error detect interrupt, * and enable the LPUART module transmitter and receiver. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_Init_Activity */ void Lpuart_Lin_Ip_Init(const uint32 u32Instance, const Lpuart_Lin_Ip_UserConfigType * pUserConfig) { LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *pCrtStateStruct; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != pUserConfig); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if current instance is already initialized. */ #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) LPUART_LIN_IP_DEV_ASSERT(NULL_PTR == Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the pointer of the state structure */ pCrtStateStruct = pUserConfig->pStateStruct; /* Save LIN user config structure pointer. */ Lpuart_Lin_Ip_apxUserConfigs[u32Instance] = pUserConfig; /* Init LPUART */ Lpuart_Lin_Ip_HwInit(base); /* if autobaud is enabled */ if ((pUserConfig->autobaudEnable) && ((boolean)LPUART_LIN_IP_SLAVE == pUserConfig->nodeFunction)) { /* Setting Slave's baudrate to 19200 will help Slave node */ /* always detect LIN Break from Master */ pCrtStateStruct->fallingEdgeInterruptCount = 0U; pCrtStateStruct->baudrateEvalEnable = (boolean)TRUE; } /* Check if osr is between 4x and 7x oversampling. * If so, then "BOTHEDGE" sampling must be turned on */ if (pUserConfig->u32OverSamplingRatio < 8U) { Lpuart_Lin_Ip_HwEnableBothEdgeSamplingCmd(base); } /* program the osr value (bit value is one less than actual value) */ Lpuart_Lin_Ip_HwSetOversamplingRatio(base, (pUserConfig->u32OverSamplingRatio - 1U)); /* write the sbr value to the BAUD registers */ Lpuart_Lin_Ip_HwSetBaudRateDivisor(base, pUserConfig->u32BaudRateDivisor); /* Set 8 bit counts per char */ Lpuart_Lin_Ip_HwSetBitCountPerChar(base, LPUART_LIN_IP_8_BITS_PER_CHAR, (boolean)FALSE); /* Set no parity mode */ Lpuart_Lin_Ip_HwSetParityMode(base, LPUART_LIN_IP_PARITY_DISABLED); /* One stop bit */ Lpuart_Lin_Ip_HwSetStopBitCount(base, LPUART_LIN_IP_ONE_STOP_BIT); /* Check if the current node is MASTER */ if ((boolean)LPUART_LIN_IP_MASTER == pUserConfig->nodeFunction) { /* Set Break char length as 13 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharTransmitLength(base, pUserConfig->u8BreakLength); /* Set Break char detect length as 11 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, pUserConfig->u8BreakLengthDetect); } else { /* Set Break char detect length as 11 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, pUserConfig->u8BreakLengthDetect); /* Enable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)TRUE); } /* Clear interupt lag for guarantee */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_ALL_INT_FLAGS); /* Disable RX complete interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* Enable frame error interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_FRAME_ERR_FLAG, (boolean)TRUE); /* Change node's current state to IDLE */ pCrtStateStruct->currentNodeState = LPUART_LIN_IP_NODE_STATE_IDLE; /* Clear flags in current LIN state structure */ pCrtStateStruct->isTxBusy = (boolean)FALSE; pCrtStateStruct->isRxBusy = (boolean)FALSE; pCrtStateStruct->isBusBusy = (boolean)FALSE; pCrtStateStruct->timeoutCounterFlag = (boolean)FALSE; pCrtStateStruct->timeoutCounter = 0U; pCrtStateStruct->classicPID = pUserConfig->classicPID; pCrtStateStruct->numOfClassicPID = pUserConfig->numOfClassicPID; /* Assign wakeup signal to satisfy LIN Specifications specifies that * wakeup signal shall be in range from 250us to 5 ms. */ Lpuart_Lin_Ip_au8WakeupSignal[u32Instance] = pUserConfig->u8WakeupByte; if (!((pUserConfig->autobaudEnable) && ((boolean)LPUART_LIN_IP_SLAVE == pUserConfig->nodeFunction))) { /* Enable the LPUART transmitter and receiver */ Lpuart_Lin_Ip_HwSetTransmitterCmd(base, (boolean)TRUE); Lpuart_Lin_Ip_HwSetReceiverCmd(base, (boolean)TRUE); } /* Save runtime structure pointer. */ Lpuart_Lin_Ip_apxStateStructureArray[u32Instance] = pUserConfig->pStateStruct; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_Deinit * Description : This function shuts down the LPUART by disabling interrupts and * transmitter/receiver. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_Deinit_Activity */ void Lpuart_Lin_Ip_Deinit(const uint32 u32Instance) { LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; uint32 startTime; uint32 timeoutTicks; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Check if current instance is already de-initialized or is gated.*/ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ Lpuart_Lin_Ip_StartTimeout(&startTime, &timeoutTicks, LPUART_LIN_IP_TIMEOUT_VALUE_US, LPUART_LIN_IP_TIMEOUT_TYPE); do { /* Wait until the data is completely shifted out of shift register */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_TX_COMPLETE)) { break; } } while (!Lpuart_Lin_Ip_TimeoutExpired(startTime, timeoutTicks, LPUART_LIN_IP_TIMEOUT_TYPE)); /* Disable the LPUART transmitter and receiver */ Lpuart_Lin_Ip_HwSetTransmitterCmd(base, (boolean)FALSE); Lpuart_Lin_Ip_HwSetReceiverCmd(base, (boolean)FALSE); /* Change node's current state to UNINIT */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_UNINIT; /* Clear our saved pointer to the LIN state structure */ Lpuart_Lin_Ip_apxStateStructureArray[u32Instance] = NULL_PTR; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_AsyncSendFrameData * Description : This function sends data out through the LPUART module using * non-blocking method. This function will calculate the checksum byte and send * it with the frame data. The function will return immediately after calling * this function. If txSize is equal to 0 or greater than 8 or node's current * state is in SLEEP mode then the function will return LPUART_LIN_IP_STATUS_ERROR. If * isBusBusy is currently TRUE then the function will return LPUART_LIN_IP_STATUS_BUSY. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_AsyncSendFrameData_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_AsyncSendFrameData(const uint32 u32Instance, const uint8 * pTxBuff, const uint8 u8TxSize) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) const Lpuart_Lin_Ip_UserConfigType *pUserConfig; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != pTxBuff); LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if txSize > 8 or equal to 0 or node's current state * is in SLEEP mode then return LPUART_LIN_IP_STATUS_ERROR. Or * return LPUART_LIN_IP_STATUS_BUSY if bus is busy */ retVal = Lpuart_Lin_Ip_StatusBeforeTransfer(u8TxSize, linCurrentState); if (LPUART_LIN_IP_STATUS_SUCCESS != retVal) { /* Do nothing */ } else { /* Make the checksum byte. */ linCurrentState->checkSum = Lpuart_Lin_Ip_MakeChecksumByte(u32Instance, pTxBuff, u8TxSize, linCurrentState->currentPid); SchM_Enter_Lin_LIN_EXCLUSIVE_AREA_00(); { /* Update the LIN state structure. */ linCurrentState->txBuff = pTxBuff; /* Add a place for checksum byte */ linCurrentState->txSize = (uint8)(u8TxSize + 1U); linCurrentState->cntByte = 0U; linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_SEND_DATA; linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; linCurrentState->isBusBusy = (boolean)TRUE; linCurrentState->isTxBusy = (boolean)TRUE; } SchM_Exit_Lin_LIN_EXCLUSIVE_AREA_00(); /* Set Break char detect length as 10 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, LPUART_LIN_IP_BREAK_CHAR_10_BIT_MINIMUM_U8); #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Set timeout counter for processing in TimeoutService funtion */ /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to timeout each data byte multi length of data frame plus checksum byte and div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32ResponseTimeoutValue * ((uint32)u8TxSize + 1UL) / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ /* Start sending data */ Lpuart_Lin_Ip_HwPutchar(base, *linCurrentState->txBuff); } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_SyncSendFrameData * Description : This function shall send frame data out through * the LIN Hardware Interface module using a blocking method. * The function does not return until the transmission is completed. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_SyncSendFrameData_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_SyncSendFrameData(const uint32 u32Instance, const uint8 * pTxBuff, const uint8 u8TxSize) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_ERROR; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; uint8 byteCnt = 0; uint8 sendByte; uint8 readbackByte; uint32 startTime; uint32 timeoutTicks; #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) const Lpuart_Lin_Ip_UserConfigType *pUserConfig; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != pTxBuff); LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if rxSize > 8, equal to 0 or node's current state * is in SLEEP mode then return LPUART_LIN_IP_STATUS_ERROR. Or instance is Busy */ retVal = Lpuart_Lin_Ip_StatusBeforeTransfer(u8TxSize, linCurrentState); if (LPUART_LIN_IP_STATUS_SUCCESS != retVal) { /* Do nothing */ } else { /* Disable interrupt Rx data full */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* Disable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)FALSE); linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; /* Make the checksum byte. */ linCurrentState->checkSum = Lpuart_Lin_Ip_MakeChecksumByte(u32Instance, pTxBuff, u8TxSize, linCurrentState->currentPid); #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Set timeout counter for processing in TimeoutService funtion */ /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to timeout each data byte multi length of data frame plus checksum byte and div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32ResponseTimeoutValue * ((uint32)u8TxSize + 1UL) / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ do { /* Check no error occurred or not */ if ( (LPUART_LIN_IP_NO_EVENT != linCurrentState->currentEventId) || (byteCnt > u8TxSize) ) { /* At least an error occurred */ retVal = LPUART_LIN_IP_STATUS_ERROR; break; } else { if (byteCnt < u8TxSize) { sendByte = pTxBuff[byteCnt]; } else { sendByte = linCurrentState->checkSum; } /* Push data to buffer */ Lpuart_Lin_Ip_HwPutchar(base, sendByte); /* Prepare state to fit code flow */ retVal = LPUART_LIN_IP_STATUS_TIMEOUT; } /* Set time for waiting loop */ Lpuart_Lin_Ip_StartTimeout(&startTime, &timeoutTicks, LPUART_LIN_IP_TIMEOUT_VALUE_US, LPUART_LIN_IP_TIMEOUT_TYPE); /* Check status of byte transmission and read back value */ do { /* Check read back status of buffer */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_DATA_REG_FULL)) { Lpuart_Lin_Ip_HwGetchar(base, &readbackByte); retVal = Lpuart_Lin_Ip_CheckReadbackByte(readbackByte, sendByte); break; } } while (!Lpuart_Lin_Ip_TimeoutExpired(startTime, timeoutTicks, LPUART_LIN_IP_TIMEOUT_TYPE)); } /* Check the last of data frame and move to next byte */ while ((byteCnt++ < u8TxSize) && (LPUART_LIN_IP_STATUS_SUCCESS == retVal)); /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_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 that is LPUART_LIN_IP_STATUS_BUSY) or timeout (if timeout has occurred that is * LPUART_LIN_IP_STATUS_TIMEOUT) or complete (success that is LPUART_LIN_IP_STATUS_SUCCESS). * In addition, if the transmission is still in progress, the user can obtain the number * of bytes that still needed to transmit. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_GetTransmitStatus_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_GetTransmitStatus(const uint32 u32Instance, uint8 * const pBytesRemaining) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; const Lpuart_Lin_Ip_StateStructType *linCurrentState; boolean bBytesCountReturn = (NULL_PTR == pBytesRemaining) ? (boolean)FALSE : (boolean)TRUE; uint8 u8LocalBytesRemaining = 0u; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the number of bytes that is still needed to transmit */ u8LocalBytesRemaining = (uint8)(linCurrentState->txSize - linCurrentState->cntByte); /* Return status of the on-going transmission */ if ( (LPUART_LIN_IP_NO_EVENT == linCurrentState->currentEventId) && (0U != u8LocalBytesRemaining) ) { if ((boolean)TRUE != linCurrentState->timeoutCounterFlag) { retVal = LPUART_LIN_IP_STATUS_BUSY; } else { retVal = LPUART_LIN_IP_STATUS_TIMEOUT; } } if (bBytesCountReturn) { *pBytesRemaining = u8LocalBytesRemaining; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_AsyncReceiveFrameData * 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. The interrupt handler function will check * the checksum byte. If the checksum is correct, it will receive the frame data. * If the checksum is incorrect, this function will return LPUART_LIN_IP_STATUS_TIMEOUT and data in * rxBuff might be wrong. This function also check if rxSize is in range from 1 to 8. * If not, it will return LPUART_LIN_IP_STATUS_ERROR. This function also returns LPUART_LIN_IP_STATUS_ERROR if * node's current state is in SLEEP mode. This function checks if the * isBusBusy is (boolean)FALSE, if not it will return LPUART_LIN_IP_STATUS_BUSY. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_AsyncReceiveFrameData_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_AsyncReceiveFrameData(const uint32 u32Instance, uint8 * pRxBuff, const uint8 u8RxSize) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) const Lpuart_Lin_Ip_UserConfigType *pUserConfig; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != pRxBuff); LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if txSize > 8 or equal to 0 or node's current state * is in SLEEP mode then return LPUART_LIN_IP_STATUS_ERROR. Or * return LPUART_LIN_IP_STATUS_BUSY if bus is busy */ retVal = Lpuart_Lin_Ip_StatusBeforeTransfer(u8RxSize, linCurrentState); if (LPUART_LIN_IP_STATUS_SUCCESS != retVal) { /* Do nothing */ } else { SchM_Enter_Lin_LIN_EXCLUSIVE_AREA_01(); { /* Update the LIN state structure. */ linCurrentState->rxBuff = pRxBuff; /* Add a place for checksum byte */ linCurrentState->rxSize = (uint8)(u8RxSize + 1U); linCurrentState->cntByte = 0U; /* Start receiving data */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_DATA; linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; linCurrentState->isBusBusy = (boolean)TRUE; linCurrentState->isRxBusy = (boolean)TRUE; } SchM_Exit_Lin_LIN_EXCLUSIVE_AREA_01(); #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Set timeout counter for processing in TimeoutService funtion */ /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to timeout each data byte multi length of data frame plus checksum byte and div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32ResponseTimeoutValue * ((uint32)u8RxSize + 1UL) / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ /* Set Break char detect length as 10 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, LPUART_LIN_IP_BREAK_CHAR_10_BIT_MINIMUM_U8); } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_SyncReceiveFrameData * 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. The interrupt handler function will check * the checksum byte. If the checksum is correct, it will receive the frame data. * If the checksum is incorrect, this function will return LPUART_LIN_IP_STATUS_TIMEOUT and data in * rxBuff might be wrong. This function also check if rxSize is in range from 1 to 8. * If not, it will return LPUART_LIN_IP_STATUS_ERROR. This function also returns LPUART_LIN_IP_STATUS_ERROR if * node's current state is in SLEEP mode. This function checks if the * isBusBusy is (boolean)FALSE, if not it will return LPUART_LIN_IP_STATUS_BUSY. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_SyncReceiveFrameData_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_SyncReceiveFrameData(const uint32 u32Instance, uint8 * pRxBuff, const uint8 u8RxSize) { volatile Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; uint8 byteCnt = 0; uint32 timeoutTicks; uint32 startTime; #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) const Lpuart_Lin_Ip_UserConfigType *pUserConfig; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != pRxBuff); LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if rxSize > 8 or equal to 0 or node's current state * is in SLEEP mode then return LPUART_LIN_IP_STATUS_ERROR */ retVal = Lpuart_Lin_Ip_StatusBeforeTransfer(u8RxSize, linCurrentState); if (LPUART_LIN_IP_STATUS_SUCCESS != retVal) { /* Do nothing */ } else { /* Disable interrupt Rx data full */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* Disable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)FALSE); /* Start receiving data */ linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; do { #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Set timeout counter for processing in TimeoutService funtion */ /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to timeout each data byte multi length of data frame plus checksum byte and div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32ResponseTimeoutValue * ((uint32)u8RxSize + 1UL) / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ retVal = LPUART_LIN_IP_STATUS_TIMEOUT; /* Set time for waiting loop */ Lpuart_Lin_Ip_StartTimeout(&startTime, &timeoutTicks, LPUART_LIN_IP_TIMEOUT_VALUE_US, LPUART_LIN_IP_TIMEOUT_TYPE); while (!Lpuart_Lin_Ip_TimeoutExpired(startTime, timeoutTicks, LPUART_LIN_IP_TIMEOUT_TYPE)) { if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_DATA_REG_FULL)) { retVal = LPUART_LIN_IP_STATUS_SUCCESS; break; } } if (LPUART_LIN_IP_NO_EVENT != linCurrentState->currentEventId) { /* An error occurred in reception */ retVal = LPUART_LIN_IP_STATUS_ERROR; } else if (LPUART_LIN_IP_STATUS_SUCCESS == retVal) { /* Get char to Rx buffer, check check sum byte to update event id */ retVal = Lpuart_Lin_Ip_GetBytetoBuffer(byteCnt, u8RxSize, pRxBuff, u32Instance); } else { retVal = LPUART_LIN_IP_STATUS_TIMEOUT; } if (LPUART_LIN_IP_STATUS_SUCCESS != retVal) { /* Error in receiving previous byte */ break; } } while (u8RxSize > byteCnt++); /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_AbortTransferData * Description : Aborts an on-going non-blocking transmission/reception. * While performing a non-blocking transferring data, users can call this * function to terminate immediately the transferring. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_AbortTransferData_Activity */ void Lpuart_Lin_Ip_AbortTransferData(const uint32 u32Instance) { Lpuart_Lin_Ip_StateStructType *linCurrentState; LPUART_Type * base; uint32 startTime; uint32 timeoutTicks; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Disable RX complete interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* Disable frame error interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_FRAME_ERR_FLAG, (boolean)FALSE); /* Disable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)FALSE); MCAL_FAULT_INJECTION_POINT(LPUART_FIP_1_T_TIME_OUT_1); /* Wait until the data is completely shifted out of shift register */ Lpuart_Lin_Ip_StartTimeout(&startTime, &timeoutTicks, LPUART_LIN_IP_TIMEOUT_VALUE_US, LPUART_LIN_IP_TIMEOUT_TYPE); do { if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_TX_COMPLETE)) { break; } } while (!Lpuart_Lin_Ip_TimeoutExpired(startTime, timeoutTicks, LPUART_LIN_IP_TIMEOUT_TYPE)); /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); /* Clear LIN Tx and Rx Busy flag */ linCurrentState->isTxBusy = (boolean)FALSE; linCurrentState->isRxBusy = (boolean)FALSE; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_GetReceiveStatus * Description : This function returns whether the previous LPUART reception 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 reception is still in progress, the user can * obtain the number of words that is still needed to receive. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_GetReceiveStatus_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_GetReceiveStatus(const uint32 u32Instance, uint8 * const pBytesRemaining) { const Lpuart_Lin_Ip_StateStructType *linCurrentState; Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the number of bytes that is still needed to receive */ *pBytesRemaining = (uint8)(linCurrentState->rxSize - linCurrentState->cntByte); /* Return status of the on-going reception */ if ((LPUART_LIN_IP_NO_EVENT == linCurrentState->currentEventId) && (0U != *pBytesRemaining)) { if ((boolean)TRUE != linCurrentState->timeoutCounterFlag) { retVal = LPUART_LIN_IP_STATUS_BUSY; } else { retVal = LPUART_LIN_IP_STATUS_TIMEOUT; } } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_GoToSleepMode * Description : This function puts current LIN node to sleep mode. * This function changes current node state to LPUART_LIN_IP_NODE_STATE_SLEEP_MODE. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_GoToSleepMode_Activity */ void Lpuart_Lin_Ip_GoToSleepMode(const uint32 u32Instance) { LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Update node's current state to SLEEP_MODE. */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_SLEEP_MODE; /* Clear txBusy, rxBusy, busBusy flags */ linCurrentState->isTxBusy = (boolean)FALSE; linCurrentState->isRxBusy = (boolean)FALSE; linCurrentState->isBusBusy = (boolean)FALSE; /* Clear LPUART_RX Pin Active Edge Interrupt Flag. */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_RX_ACTIVE_EDGE_DETECT); /* Set Receive data not inverted */ Lpuart_Lin_Ip_HwSetRxDataPolarity(base, (boolean)FALSE); /* Disable RX complete interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* Enable RX Input Active Edge interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_ACTIVE_EDGE, (boolean)TRUE); /* Disable frame error interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_FRAME_ERR_FLAG, (boolean)FALSE); /* Disable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)FALSE); } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_SendWakeupSignal * Description : This function sends a wakeup signal through the LPUART interface. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_SendWakeupSignal_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_SendWakeupSignal(const uint32 u32Instance) { LPUART_Type *base; const Lpuart_Lin_Ip_StateStructType *linCurrentState; Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Check if bus is not busy */ if ((boolean)TRUE != linCurrentState->isBusBusy) { /* Send a wakeup signal */ Lpuart_Lin_Ip_HwPutchar(base, Lpuart_Lin_Ip_au8WakeupSignal[u32Instance]); } else { retVal = LPUART_LIN_IP_STATUS_BUSY; } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_GetCurrentNodeState * Description : This function gets the current LIN node state. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_GetCurrentNodeState_Activity */ Lpuart_Lin_Ip_NodeStateType Lpuart_Lin_Ip_GetCurrentNodeState(const uint32 u32Instance) { Lpuart_Lin_Ip_NodeStateType retVal = LPUART_LIN_IP_NODE_STATE_UNINIT; const Lpuart_Lin_Ip_StateStructType *linCurrentState; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; if (NULL_PTR != linCurrentState) { retVal = linCurrentState->currentNodeState; } /* Return LIN node's current state */ return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_TimeoutService * Description : This is callback function for Timer Interrupt Handler. * Users shall initialize a timer (for example FTM) in Output compare mode * with period of about 500 micro seconds. In timer IRQ handler, call this function. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_TimeoutService_Activity */ void Lpuart_Lin_Ip_TimeoutService(const uint32 u32Instance) { #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) const Lpuart_Lin_Ip_UserConfigType *pUserConfig; Lpuart_Lin_Ip_StateStructType *linCurrentState; Lpuart_Lin_Ip_NodeStateType state; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get LIN node's current state */ state = linCurrentState->currentNodeState; switch(state) { /* If the node is SENDING DATA */ case LPUART_LIN_IP_NODE_STATE_SEND_DATA: /* If the node is RECEIVING DATA */ case LPUART_LIN_IP_NODE_STATE_RECV_DATA: /* If the node is RECEIVING HEADER */ case LPUART_LIN_IP_NODE_STATE_RECV_SYNC: case LPUART_LIN_IP_NODE_STATE_RECV_PID: /* Timeout error in sending header */ case LPUART_LIN_IP_NODE_STATE_SEND_PID: /* Check if timeout Counter is 0 */ if (0U == linCurrentState->timeoutCounter) { /* Set timeout Counter flag */ linCurrentState->timeoutCounterFlag = (boolean)TRUE; /* Clear Tx busy flag */ linCurrentState->isTxBusy = (boolean)FALSE; /* Set current event to timeout error */ linCurrentState->currentEventId = LPUART_LIN_IP_TIMEOUT_ERROR; #ifdef LPUART_LIN_IP_END_TIMEOUT_NOTIFICATION /* Call the notification to stop timer */ LPUART_LIN_IP_END_TIMEOUT_NOTIFICATION(u32Instance); #endif /* Callback to handle timeout Counter flag to further processing */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } else /* If timeout Counter is not 0, then decrease timeout Counter by one */ { linCurrentState->timeoutCounter--; } break; default: /* The node state is not SENDING nor RECEIVING data */ break; } if ((boolean)FALSE != linCurrentState->timeoutCounterFlag) { } #else /* Casting to void to avoid compiler warning */ (void)u32Instance; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_SetTimeoutCounter * Description : This function sets value for timeout counter that is used in * Lpuart_Lin_Ip_TimeoutService * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_SetTimeoutCounter_Activity */ void Lpuart_Lin_Ip_SetTimeoutCounter(const uint32 u32Instance, const uint32 u32TimeoutValue) { #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) Lpuart_Lin_Ip_StateStructType *linCurrentState; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Clear Timeout Counter Flag */ linCurrentState->timeoutCounterFlag = (boolean)FALSE; /* Set new value for Timeout Counter */ linCurrentState->timeoutCounter = u32TimeoutValue; #else /* Casting to void to avoid compiler warning */ (void)u32Instance; (void)u32TimeoutValue; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_MasterSendHeader * Description : This function sends frame header out through the LPUART module * using a non-blocking method. Non-blocking means that the function returns * immediately. This function sends LIN Break field, sync field then the ID with * correct parity. This function checks if the interface is Master, if not, it will * return LPUART_LIN_IP_STATUS_ERROR.This function checks if id is in range from 0 to 0x3F, if not * it will return LPUART_LIN_IP_STATUS_ERROR. This function also check node's current state is in * SLEEP mode then the function will return LPUART_LIN_IP_STATUS_ERROR. And check if isBusBusy is * currently TRUE then the function will return LPUART_LIN_IP_STATUS_BUSY. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_MasterSendHeader_Activity */ Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_MasterSendHeader(const uint32 u32Instance, const uint8 u8Id) { Lpuart_Lin_Ip_StatusType retVal = LPUART_LIN_IP_STATUS_SUCCESS; const Lpuart_Lin_Ip_UserConfigType *pUserConfig; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; boolean checkSleepMode; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN user config structure of this LPUART instance. */ pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* Check whether current mode is sleep mode */ checkSleepMode = (LPUART_LIN_IP_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState); /* Check if the current node is slave or id is invalid or node's current * state is in SLEEP state */ if (((boolean)LPUART_LIN_IP_MASTER != pUserConfig->nodeFunction) || (0x3FU < u8Id) || checkSleepMode) { retVal = LPUART_LIN_IP_STATUS_ERROR; } else { /* Check if the LIN bus is busy */ if (linCurrentState->isBusBusy) { retVal = LPUART_LIN_IP_STATUS_BUSY; } else { linCurrentState->currentId = u8Id; /* Make parity for the current ID */ linCurrentState->currentPid = Lin_Ip_ProcessParity(u8Id, LIN_MAKE_PARITY); /* Set LIN current state to sending Break field */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_SEND_BREAK_FIELD; linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; linCurrentState->isBusBusy = (boolean)TRUE; /* Set Break char detect length as 13 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, LPUART_LIN_IP_BREAK_CHAR_13_BIT_MINIMUM_U8); Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)TRUE); /* Send break char by using queue mode */ Lpuart_Lin_Ip_HwQueueBreakField(base); } } return retVal; } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_GotoIdleState * Description : This function puts current node to Idle state. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_GotoIdleState_Activity */ void Lpuart_Lin_Ip_GotoIdleState(const uint32 u32Instance) { LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; const Lpuart_Lin_Ip_UserConfigType *pUserConfig; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(NULL_PTR != linCurrentState); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get user configuration */ pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; linCurrentState->currentEventId = LPUART_LIN_IP_NO_EVENT; /* Set Receive data not inverted */ Lpuart_Lin_Ip_HwSetRxDataPolarity(base, (boolean)FALSE); /* Disable RXEDG interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_ACTIVE_EDGE, (boolean)FALSE); /* Enable frame error interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_FRAME_ERR_FLAG, (boolean)TRUE); /* Disable Rx buffer full interurpt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); if ((boolean)LPUART_LIN_IP_MASTER != pUserConfig->nodeFunction) { /* Set Break char detect length as configuration */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, pUserConfig->u8BreakLengthDetect); /* Only in slave mode, break detection interrupt should be enabled to know new frame. Be side that, the interrupt of master is enable when start transmit a new frame */ /* Enable LIN break detect interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)TRUE); } SchM_Enter_Lin_LIN_EXCLUSIVE_AREA_02(); { /* Change node's current state to IDLE */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_IDLE; /* Clear Bus busy Flag */ linCurrentState->isBusBusy = (boolean)FALSE; linCurrentState->isTxBusy = (boolean)FALSE; linCurrentState->isRxBusy = (boolean)FALSE; #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) /* Clear timeout flag */ linCurrentState->timeoutCounterFlag = (boolean)FALSE; #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ } SchM_Exit_Lin_LIN_EXCLUSIVE_AREA_02(); } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_IRQHandler * Description : Interrupt handler for LPUART. * This handler uses the buffers stored in the Lpuart_Lin_Ip_StateStructType struct to transfer * data. This is not a public API as it is called by IRQ whenever an interrupt * occurs. * *END**************************************************************************/ /** * @implements Lpuart_Lin_Ip_IRQHandler_Activity */ void Lpuart_Lin_Ip_IRQHandler(const uint32 u32Instance) { const Lpuart_Lin_Ip_UserConfigType *pUserConfig; LPUART_Type *base; Lpuart_Lin_Ip_StateStructType *linCurrentState; boolean activeEdgeIntState; boolean bSpuriousIntAvailable = (boolean)FALSE; #if (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) /* Assert parameters. */ LPUART_LIN_IP_DEV_ASSERT(LPUART_INSTANCE_COUNT > u32Instance); #endif /* (LPUART_LIN_IP_DEV_ERROR_DETECT == STD_ON) */ pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get base address of the LPUART instance. */ base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* Check RX Input Active Edge interrupt enable */ activeEdgeIntState = Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_RX_ACTIVE_EDGE); /* Check instance was initialized or not */ if (NULL_PTR == linCurrentState) { /* Clear all interrupt flag */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_ALL_INT_FLAGS); } else { /* If LIN break character has been detected. */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_BREAK_DETECT) && Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT)) { Lpuart_Lin_Ip_ProcessBreakDetect(u32Instance); } else { /* If LPUART_RX Pin Active Edge has been detected. */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_ACTIVE_EDGE_DETECT) && activeEdgeIntState) { Lpuart_Lin_Ip_ProcessWakeupDetect(u32Instance); } else { /* If Framing Error has been detected */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_FRAME_ERR) && Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_FRAME_ERR_FLAG)) { Lpuart_Lin_Ip_FrameErrorIrqHandler(u32Instance); /* Change node's state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } else { bSpuriousIntAvailable = (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_DATA_REG_FULL) && Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL)); /* Check full received register flag and handler */ Lpuart_Lin_Ip_FrameIrqHandler(u32Instance); } /* End else: if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_FRAME_ERR) == 0) */ } /* End else: if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_ACTIVE_EDGE_DETECT) == 0) */ } /* End else: if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_BREAK_DETECT) == 0) */ /* Get status RX overrun flag */ if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_OVERRUN) && Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_RX_OVERRUN)) { /* Clear overrun flag */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_RX_OVERRUN); /* Set current event id to LIN_RX_OVERRUN */ linCurrentState->currentEventId = LPUART_LIN_IP_RX_OVERRUN_ERROR; /* Callback function to handle RX Overrun Event */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } else { if ((boolean)FALSE != bSpuriousIntAvailable) { /* Clear all interrupt flag */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_ALL_INT_FLAGS); } } } } /* End void Lpuart_Lin_Ip_IRQHandler(uint32 u32Instance) */ /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessBreakDetect * Description : This function process break detect for LIN communication. * *END**************************************************************************/ static void Lpuart_Lin_Ip_ProcessBreakDetect(const uint32 u32Instance) { /* Get the current LIN user configure structure of this LPUART instance. */ const Lpuart_Lin_Ip_UserConfigType * pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; uint8 discardData; /* Get base address of the LPUART instance. */ LPUART_Type * base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ Lpuart_Lin_Ip_StateStructType * linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* Clear LIN Break Detect Interrupt Flag */ (void)Lpuart_Lin_Ip_HwClearStatusFlag(base, LPUART_LIN_IP_BREAK_DETECT); /* Set Break char detect length as 10 bits minimum */ Lpuart_Lin_Ip_HwSetBreakCharDetectLength(base, LPUART_LIN_IP_BREAK_CHAR_10_BIT_MINIMUM_U8); /* Disable LIN Break Detect Interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_BREAK_DETECT, (boolean)FALSE); /* Clear Rx complete interrupt flag */ Lpuart_Lin_Ip_HwGetchar(base, &discardData); (void)discardData; /* Enable RX complete interrupt */ Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)TRUE); /* Check if the current node is MASTER */ if ((boolean)LPUART_LIN_IP_SLAVE != pUserConfig->nodeFunction) { /* Check if LIN current node state is LPUART_LIN_IP_NODE_STATE_SEND_BREAK_FIELD */ if (LPUART_LIN_IP_NODE_STATE_SEND_BREAK_FIELD == linCurrentState->currentNodeState) { #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to header timeout div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32HeaderTimeoutValue / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ /* Change the node's current state to SENDING PID to send PID after send SYNC */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_SEND_PID; /* Send Sync Field 0x55 */ Lpuart_Lin_Ip_HwPutchar(base, 0x55); } } /* If the current node is SLAVE */ else { /* Set flag LIN bus busy */ linCurrentState->isBusBusy = (boolean)TRUE; /* Change the node's current state to RECEIVED BREAK FIELD */ linCurrentState->currentEventId = LPUART_LIN_IP_RECV_BREAK_FIELD_OK; /* Change the node's current state to RECEIVING SYNC FIELD */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_SYNC; /* If auto baudrate detection is enabled, the driver will count falling edge in sync byte */ if ((boolean)FALSE != linCurrentState->baudrateEvalEnable) { Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_ACTIVE_EDGE, (boolean)TRUE); linCurrentState->fallingEdgeInterruptCount = 0u; /* Enable the LPUART transmitter and receiver */ Lpuart_Lin_Ip_HwSetTransmitterCmd(base, (boolean)TRUE); Lpuart_Lin_Ip_HwSetReceiverCmd(base, (boolean)TRUE); } #if (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) /* * The TimeoutService function is call each 500 microsecond regularly, * so timeout counter equal to header timeout div 500. * At the end, plus 1 for surplus. */ Lpuart_Lin_Ip_SetTimeoutCounter(u32Instance, pUserConfig->u32HeaderTimeoutValue / 500UL + 1UL); #ifdef LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION /* Call notification to start timer */ LPUART_LIN_IP_START_TIMEOUT_NOTIFICATION(u32Instance); #endif #endif /* (LPUART_LIN_IP_FRAME_TIMEOUT_DISABLE == STD_OFF) */ } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_CheckWakeupSignal * Description : This function check if a dominant signal received is a wakeup * signal. * *END**************************************************************************/ static void Lpuart_Lin_Ip_CheckWakeupSignal(const uint32 u32Instance) { uint32 wakeupSignalLength = 0U; /* Get the current LIN user config structure of this LPUART instance. */ const Lpuart_Lin_Ip_UserConfigType * pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get base address of the LPUART instance. */ LPUART_Type * base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ Lpuart_Lin_Ip_StateStructType * linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* if Lpuart_Lin_Ip_HwGetRxDataPolarity is 0: Receive Data is not inverted */ if ((boolean)TRUE != Lpuart_Lin_Ip_HwGetRxDataPolarity(base)) { /* Start measure time */ (void)pUserConfig->timerGetTimeIntervalCallback(u32Instance, &wakeupSignalLength); /* Set Receive Data Inverted */ Lpuart_Lin_Ip_HwSetRxDataPolarity(base, (boolean)TRUE); } else { /* Set Receive Data is Not Inverted */ Lpuart_Lin_Ip_HwSetRxDataPolarity(base, (boolean)FALSE); /* Calculate time interval between the falling and rising edge */ (void)pUserConfig->timerGetTimeIntervalCallback(u32Instance, &wakeupSignalLength); /* If length of the dominant signal is longer than 150us, it is a wakeup signal */ if (wakeupSignalLength >= 150000U) { linCurrentState->currentEventId = LPUART_LIN_IP_WAKEUP_SIGNAL; /* Callback to handle event: Received a wakeup signal */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Change node's state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessFrame * Description : Part of Interrupt handler for receiving and sending data. * Receive Header, Data and Send Data. * *END**************************************************************************/ static void Lpuart_Lin_Ip_FrameIrqHandler(const uint32 u32Instance) { uint8 tmpByte; const LPUART_Type *base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN state of this LPUART instance. */ const Lpuart_Lin_Ip_StateStructType * linCurrentState = (const Lpuart_Lin_Ip_StateStructType *)Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; if (Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_RX_DATA_REG_FULL) && Lpuart_Lin_Ip_HwGetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL)) { /* Check node's current state */ switch (linCurrentState->currentNodeState) { /* if current state is RECEIVE SYNC FIELD */ case LPUART_LIN_IP_NODE_STATE_RECV_SYNC: /* if current state is MASTER SENDING PID */ case LPUART_LIN_IP_NODE_STATE_SEND_PID: /* if current state is RECEIVE PID */ case LPUART_LIN_IP_NODE_STATE_RECV_PID: /* Get data from Data Register & Clear LPUART_LIN_IP_RX_DATA_REG_FULL flag */ Lpuart_Lin_Ip_HwGetchar(base, &tmpByte); Lpuart_Lin_Ip_ProcessFrameHeader(u32Instance, tmpByte); break; /* if current state is RECEIVE DATA */ case LPUART_LIN_IP_NODE_STATE_RECV_DATA: Lpuart_Lin_Ip_ProcessReceiveFrameData(u32Instance); break; /* if current state is SENDING DATA */ case LPUART_LIN_IP_NODE_STATE_SEND_DATA: /* Get data from Data Register & Clear LPUART_LIN_IP_RX_DATA_REG_FULL flag */ Lpuart_Lin_Ip_HwGetchar(base, &tmpByte); Lpuart_Lin_Ip_ProcessSendFrameData(u32Instance, tmpByte); break; default: /* Other node state */ /* Get data from Data Register to Clear LPUART_LIN_IP_RX_DATA_REG_FULL flag */ Lpuart_Lin_Ip_HwGetchar(base, &tmpByte); break; } } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessFrameHeader * Description : Part of Interrupt handler for receiving and sending data. * Receive Sync byte, PID and Send PID. * *END**************************************************************************/ static void Lpuart_Lin_Ip_ProcessFrameHeader(const uint32 u32Instance, const uint8 tmpByte) { /* Get base address of the LPUART instance. */ LPUART_Type * base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN user config structure of this LPUART instance. */ const Lpuart_Lin_Ip_UserConfigType * pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get the current LIN state of this LPUART instance. */ Lpuart_Lin_Ip_StateStructType * linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* Check node's current state */ switch (linCurrentState->currentNodeState) { /* If current state is RECEIVE SYNC FIELD */ case LPUART_LIN_IP_NODE_STATE_RECV_SYNC: if (0x55U == tmpByte) { /* Set current event ID to Sync byte is correct */ linCurrentState->currentEventId = LPUART_LIN_IP_SYNC_OK; /* Change node's current state to RECEIVE PID */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_PID; } else { /* Set current event ID to Sync byte is incorrect */ linCurrentState->currentEventId = LPUART_LIN_IP_SYNC_ERROR; /* Callback function to handle event RECEIVED SYNC FIELD ERROR */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } break; /* If current state is MASTER SENDING PID */ case LPUART_LIN_IP_NODE_STATE_SEND_PID: /* Check if master node sent SYNC byte correctly before send PID */ if (0x55U == tmpByte) { /* Change node's current state to RECEIVING PID */ linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_RECV_PID; /* Send the current PID byte */ Lpuart_Lin_Ip_HwPutchar(base, linCurrentState->currentPid); } /* In case of errors during header transmission, it is up to the implementer * how to handle these errors (stop/continue transmission) and to decide if the * corresponding response is valid or not. * By default, LIN Driver set isBusBusy to (boolean)FALSE, and change node's state to IDLE. */ else { /* Set current event ID to read-back error */ linCurrentState->currentEventId = LPUART_LIN_IP_READBACK_ERROR; /* Clear Bus bus flag */ linCurrentState->isBusBusy = (boolean)FALSE; /* Callback function to handle event SENT SYNC BYTE ERROR */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } break; /* If current state is RECEIVE PID */ case LPUART_LIN_IP_NODE_STATE_RECV_PID: /* If the node is MASTER */ if ((boolean)LPUART_LIN_IP_SLAVE != pUserConfig->nodeFunction) { /* Check if master node sent PID correctly */ if (tmpByte == linCurrentState->currentPid) { /* Set current event ID to PID correct */ linCurrentState->currentEventId = LPUART_LIN_IP_PID_OK; /* Clear Bus bus flag */ linCurrentState->isBusBusy = (boolean)FALSE; /* Callback function to handle correct PID */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } /* In case of errors during header transmission, it is up to the implementer * how to handle these errors (stop/continue transmission) and to decide if the * corresponding response is valid or not. * By default, LIN Driver set isBusBusy to (boolean)FALSE, and change node's state to IDLE. */ else { /* Set current event ID to read-back incorrect */ linCurrentState->currentEventId = LPUART_LIN_IP_READBACK_ERROR; /* Clear bus busy flag */ linCurrentState->isBusBusy = (boolean)FALSE; /* Callback function to handle event MASTER SENT PID ERROR */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } } /* If the node is SLAVE */ else { /* Check the received PID */ linCurrentState->currentId = Lin_Ip_ProcessParity(tmpByte, LIN_CHECK_PARITY); linCurrentState->currentPid = tmpByte; if (0xFFU != linCurrentState->currentId) { /* Set current event ID to PID correct */ linCurrentState->currentEventId = LPUART_LIN_IP_PID_OK; /* Clear Bus bus flag */ linCurrentState->isBusBusy = (boolean)FALSE; /* Callback function to handle event PID correct */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } else { /* Set current event ID to PID ERROR */ linCurrentState->currentEventId = LPUART_LIN_IP_PID_ERROR; /* Callback function to handle event PID incorrect */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } } break; default: /* Other node state */ break; } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessReceiveFrameData * Description : Part of Interrupt handler for receiving. * *END**************************************************************************/ static void Lpuart_Lin_Ip_ProcessReceiveFrameData(const uint32 u32Instance) { /* Get the current LIN state of this LPUART instance. */ Lpuart_Lin_Ip_StateStructType * linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; Lpuart_Lin_Ip_StatusType retVal; /* Get the current LIN user config structure of this LPUART instance. */ const Lpuart_Lin_Ip_UserConfigType * pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* RxSize plused checksum byte to it, so must to decrease 1 in if condition */ retVal = Lpuart_Lin_Ip_GetBytetoBuffer(linCurrentState->cntByte, \ linCurrentState->rxSize - 1U, \ linCurrentState->rxBuff, \ u32Instance \ ); /* Increase index to receive next byte */ if(linCurrentState->cntByte < linCurrentState->rxSize) { linCurrentState->cntByte++; } if (LPUART_LIN_IP_STATUS_SUCCESS == retVal) { if (linCurrentState->rxSize == linCurrentState->cntByte) { /* Received checksum byte is correct */ /* callback function to handle RX COMPLETED */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } } else { /* Nothing to do */ } } /* Checksum error occurred */ else { /* callback function to handle checksum error */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Clear Rx busy flag */ linCurrentState->isRxBusy = (boolean)FALSE; /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } } /*FUNCTION********************************************************************** * * Function Name : Lpuart_Lin_Ip_ProcessSendFrameData * Description : Part of Interrupt handler for sending data. * *END**************************************************************************/ static void Lpuart_Lin_Ip_ProcessSendFrameData(const uint32 u32Instance, const uint8 tmpByte) { boolean sendFlag = (boolean)TRUE; uint8 tmpSize; boolean tmpCheckSumAndSize; boolean tmpBuffAndSize; /* Get base address of the LPUART instance. */ LPUART_Type * base = Lpuart_Lin_Ip_apxBases[u32Instance]; /* Get the current LIN user config structure of this LPUART instance. */ const Lpuart_Lin_Ip_UserConfigType * pUserConfig = Lpuart_Lin_Ip_apxUserConfigs[u32Instance]; /* Get the current LIN state of this LPUART instance. */ Lpuart_Lin_Ip_StateStructType * linCurrentState = Lpuart_Lin_Ip_apxStateStructureArray[u32Instance]; /* Check if Tx data register empty flag is (boolean)FALSE */ if ((boolean)TRUE != Lpuart_Lin_Ip_HwGetStatusFlag(base, LPUART_LIN_IP_TX_DATA_REG_EMPTY)) { linCurrentState->currentEventId = LPUART_LIN_IP_READBACK_ERROR; /* callback function to handle Readback error */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Clear Tx busy flag */ linCurrentState->isTxBusy = (boolean)FALSE; /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); sendFlag = (boolean)FALSE; } else { tmpSize = (uint8)(linCurrentState->txSize - linCurrentState->cntByte); tmpCheckSumAndSize = (1U == tmpSize) && (linCurrentState->checkSum != tmpByte); tmpBuffAndSize = (tmpByte != *linCurrentState->txBuff) && (1U != tmpSize); if (tmpBuffAndSize || tmpCheckSumAndSize) { linCurrentState->currentEventId = LPUART_LIN_IP_READBACK_ERROR; /* callback function to handle Readback error */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Clear Tx busy flag */ linCurrentState->isTxBusy = (boolean)FALSE; /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); sendFlag = (boolean)FALSE; } else { linCurrentState->txBuff++; linCurrentState->cntByte++; } } if (sendFlag) { if (linCurrentState->cntByte < linCurrentState->txSize) { /* Send checksum byte */ if (1U == (linCurrentState->txSize - linCurrentState->cntByte)) { Lpuart_Lin_Ip_HwPutchar(base, linCurrentState->checkSum); } /* Send data bytes */ else { Lpuart_Lin_Ip_HwPutchar(base, *linCurrentState->txBuff); } } else { linCurrentState->currentEventId = LPUART_LIN_IP_TX_COMPLETED; linCurrentState->currentNodeState = LPUART_LIN_IP_NODE_STATE_SEND_DATA_COMPLETED; Lpuart_Lin_Ip_HwSetIntMode(base, LPUART_LIN_IP_INT_RX_DATA_REG_FULL, (boolean)FALSE); /* callback function to handle event TX COMPLETED */ if (NULL_PTR != pUserConfig->Callback) { pUserConfig->Callback(u32Instance, linCurrentState); } /* Clear Tx busy flag */ linCurrentState->isTxBusy = (boolean)FALSE; /* In this case, node is in SLEEP MODE state */ if (linCurrentState->currentNodeState != LPUART_LIN_IP_NODE_STATE_SLEEP_MODE) { /* Change node's current state to IDLE */ Lpuart_Lin_Ip_GotoIdleState(u32Instance); } } } } #define LIN_STOP_SEC_CODE #include "Lin_MemMap.h" #ifdef __cplusplus } #endif /** @} */