ADM/GW/RTD/src/Lpuart_Lin_Ip.c
2024-08-08 10:00:15 +09:00

2305 lines
95 KiB
C

/*==================================================================================================
* 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(&currentTick, 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
/** @} */