S32 SDK
lin_lpuart_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
48 /*******************************************************************************
49  * Includes
50  ******************************************************************************/
51 #include "lin_lpuart_driver.h"
52 
53 /*******************************************************************************
54  * Variables
55  ******************************************************************************/
56 
57 /* Table of base addresses for LPUART instances. */
59 
60 /* Table to save LPUART IRQ enumeration numbers defined in the CMSIS header file */
62 
63 #ifdef LPUART_ERR_IRQS
64 /* Table to save LPUART_ERR IRQ enumeration numbers defined in the device header file */
65 const IRQn_Type g_linLpuartErrIrqId[LPUART_INSTANCE_COUNT] = LPUART_ERR_IRQS;
66 #endif
67 
68 /* Table to save LPUART state structure pointers */
70 
71 /* Table to save LIN user config structure pointers */
73 
74 /* Table to save ISR pointers for LPUART instances */
76 
77 #ifdef LPUART_ERR_IRQS
78 /* Table to save ERR ISR pointers for LPUART instances */
79 extern isr_t g_linLpuartErrIsrs[LPUART_INSTANCE_COUNT];
80 #endif
81 
82 /*******************************************************************************
83  * Static variables
84  ******************************************************************************/
86 static uint8_t s_wakeupSignal[LPUART_INSTANCE_COUNT] = {0U};
87 static uint8_t s_countMeasure[LPUART_INSTANCE_COUNT] = {0U};
88 static uint32_t s_timeMeasure[LPUART_INSTANCE_COUNT] = {0U};
89 
90 /*******************************************************************************
91  * Static function prototypes
92  ******************************************************************************/
93 
94 static status_t LIN_LPUART_DRV_WaitComplete(uint32_t instance,
95  uint32_t timeoutMSec);
96 
97 static void LIN_LPUART_DRV_ProcessBreakDetect(uint32_t instance);
98 
99 static void LIN_LPUART_DRV_CheckWakeupSignal(uint32_t instance);
100 
101 static void LIN_LPUART_DRV_ProcessFrame(uint32_t instance,
102  uint8_t tmpByte);
103 
104 static void LIN_LPUART_DRV_ProcessFrameHeader(uint32_t instance,
105  uint8_t tmpByte);
106 
107 static void LIN_LPUART_DRV_ProcessReceiveFrameData(uint32_t instance,
108  uint8_t tmpByte);
109 
110 static void LIN_LPUART_DRV_ProcessSendFrameData(uint32_t instance,
111  uint8_t tmpByte);
112 
113 static void LIN_LPUART_DRV_AutobaudTimerValEval(uint32_t instance,
114  uint32_t twoBitTimeLength);
115 
116 static void LIN_LPUART_DRV_EvalTwoBitTimeLength(uint32_t instance,
117  uint32_t twoBitTimeLength);
118 
119 /*******************************************************************************
120  * Code
121  ******************************************************************************/
122 /*FUNCTION**********************************************************************
123  *
124  * Function Name : LIN_LPUART_DRV_Init
125  * Description : This function initializes a LPUART instance for operation.
126  * This function will initialize the run-time state structure to keep track of
127  * the on-going transfers, initialize the module to user defined settings and
128  * default settings, set break field length to be 13 bit times minimum, enable
129  * the break detect interrupt, Rx complete interrupt, frame error detect interrupt,
130  * and enable the LPUART module transmitter and receiver.
131  *
132  * Implements : LIN_LPUART_DRV_Init_Activity
133  *END**************************************************************************/
134 status_t LIN_LPUART_DRV_Init(uint32_t instance,
135  lin_user_config_t * linUserConfig,
136  lin_state_t * linCurrentState)
137 {
138  /* Assert parameters. */
139  DEV_ASSERT(linUserConfig && linCurrentState);
140  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
141 
142  clock_names_t linLpuartClkName = LPUART0_CLK;
143  uint32_t linSourceClockFreq = 0U;
144  status_t retVal = STATUS_SUCCESS;
145 
146  /* Get base address of the LPUART instance. */
147  LPUART_Type * base = g_linLpuartBase[instance];
148 
149  switch (instance)
150  {
151  #if (LPUART_INSTANCE_COUNT > 1U)
152  case 1U:
153  linLpuartClkName = LPUART1_CLK;
154  break;
155  #endif
156  #if (LPUART_INSTANCE_COUNT > 2U)
157  case 2U:
158  linLpuartClkName = LPUART2_CLK;
159  break;
160  #endif
161  #if (LPUART_INSTANCE_COUNT > 3U)
162  case 3U:
163  linLpuartClkName = LPUART3_CLK;
164  break;
165  #endif
166  default:
167  /* statement or comment should appear in default case [MISRA 2012 Rule 16.1, required] */
168  break;
169  }
170 
171  /* Get the LPUART clock as configured in the clock manager */
172  (void)CLOCK_SYS_GetFreq(linLpuartClkName, &linSourceClockFreq);
173 
174  /* Check if current instance is clock gated off. */
175  DEV_ASSERT(linSourceClockFreq > 0U);
176 
177  /* Check if current instance is already initialized. */
178  DEV_ASSERT(g_linStatePtr[instance] == NULL);
179 
180  /* Save runtime structure pointer. */
181  g_linStatePtr[instance] = linCurrentState;
182 
183  /* Save LIN user config structure pointer. */
184  g_linUserconfigPtr[instance] = linUserConfig;
185 
186  /* Clear linSourceClockFreq value */
187  linCurrentState->linSourceClockFreq = linSourceClockFreq;
188 
189  /* Init LPUART */
190  LPUART_Init(base);
191 
192  /* Create txCompleted and rxCompleted semaphores as counting, with init value is 0 */
193  if (OSIF_SemaCreate(&linCurrentState->txCompleted, 0) != STATUS_SUCCESS)
194  {
195  retVal = STATUS_ERROR;
196  }
197  else if (OSIF_SemaCreate(&linCurrentState->rxCompleted, 0) != STATUS_SUCCESS)
198  {
199  retVal = STATUS_ERROR;
200  }
201  else
202  {
203  /* if autobaud is enabled */
204  if ((linUserConfig->autobaudEnable) && (linUserConfig->nodeFunction == (bool)SLAVE))
205  {
206  /* Setting Slave's baudrate to 19200 will help Slave node */
207  /* always detect LIN Break from Master */
208  linUserConfig->baudRate = 19200U;
209  linCurrentState->fallingEdgeInterruptCount = 0U;
210  linCurrentState->baudrateEvalEnable = true;
211  s_previousTwoBitTimeLength[instance] = 0U;
212  s_countMeasure[instance] = 0U;
213  s_timeMeasure[instance] = 0U;
214  }
215 
216  /* Set baud rate to User's value */
217  (void)LPUART_DRV_SetBaudRate(instance, linUserConfig->baudRate);
218 
219  /* Set 8 bit counts per char */
220  LPUART_SetBitCountPerChar(base, LPUART_8_BITS_PER_CHAR);
221 
222  /* Set no parity mode */
223  LPUART_SetParityMode(base, LPUART_PARITY_DISABLED);
224 
225  /* One stop bit */
226  LPUART_SetStopBitCount(base, LPUART_ONE_STOP_BIT);
227 
228  /* Check if the current node is MASTER */
229  if (linUserConfig->nodeFunction == (bool)MASTER)
230  {
231  /* Set Break char length as 13 bits minimum */
232  LPUART_SetBreakCharTransmitLength(base, LPUART_BREAK_CHAR_13_BIT_MINIMUM);
233  }
234 
235  /* Set Break char detect length as 13 bits minimum */
236  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_13_BIT_MINIMUM);
237 
238  /* Enable RX complete interrupt */
239  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
240 
241  /* Enable frame error interrupt */
242  LPUART_SetIntMode(base, LPUART_INT_FRAME_ERR_FLAG, true);
243 
244  /* Enable LIN break detect interrupt */
245  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, true);
246 
247  /* Install LIN_RxTx ISR for LPUART instance */
249  /* Enable LPUART interrupts. */
251 #ifdef LPUART_ERR_IRQS
252  /* Install LIN_ERR ISR for LPUART instance */
253  INT_SYS_InstallHandler(g_linLpuartErrIrqId[instance], g_linLpuartErrIsrs[instance], (isr_t *)0);
254  /* Enable LPUART error interrupts */
255  INT_SYS_EnableIRQ(g_linLpuartErrIrqId[instance]);
256 #endif
257  /* Change node's current state to IDLE */
258  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
259 
260  /* Clear flags in current LIN state structure */
261  linCurrentState->isTxBusy = false;
262  linCurrentState->isRxBusy = false;
263  linCurrentState->isBusBusy = false;
264  linCurrentState->isRxBlocking = false;
265  linCurrentState->isTxBlocking = false;
266  linCurrentState->timeoutCounterFlag = false;
267  linCurrentState->timeoutCounter = 0U;
268 
269  /* Assign wakeup signal to satisfy LIN Specifications specifies that
270  * wakeup signal shall be in range from 250us to 5 ms.
271  */
272  if (linUserConfig->baudRate > 10000U)
273  {
274  /* Wakeup signal will be range from 400us to 800us depend on baudrate */
275  s_wakeupSignal[instance] = 0x80U;
276  }
277  else
278  {
279  /* Wakeup signal will be range from 400us to 4ms depend on baudrate */
280  s_wakeupSignal[instance] = 0xF8U;
281  }
282 
283  if (!((linUserConfig->autobaudEnable) && (linUserConfig->nodeFunction == (bool)SLAVE)))
284  {
285  /* Enable the LPUART transmitter and receiver */
286  LPUART_SetTransmitterCmd(base, true);
287  LPUART_SetReceiverCmd(base, true);
288  }
289  }
290 
291  return retVal;
292 }
293 
294 /*FUNCTION**********************************************************************
295  *
296  * Function Name : LIN_LPUART_DRV_Deinit
297  * Description : This function shuts down the LPUART by disabling interrupts and
298  * transmitter/receiver.
299  *
300  * Implements : LIN_LPUART_DRV_Deinit_Activity
301  *END**************************************************************************/
302 status_t LIN_LPUART_DRV_Deinit(uint32_t instance)
303 {
304  /* Assert parameters. */
305  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
306 
307  status_t retVal = STATUS_SUCCESS;
308 
309  /* Get base address of the LPUART instance. */
310  LPUART_Type * base = g_linLpuartBase[instance];
311 
312  /* Get the current LIN state of this LPUART instance. */
313  lin_state_t * linCurrentState = g_linStatePtr[instance];
314 
315  /* Check if current instance is already de-initialized or is gated.*/
316  DEV_ASSERT(linCurrentState != NULL);
317  DEV_ASSERT(linCurrentState->linSourceClockFreq > 0U);
318 
319  /* Wait until the data is completely shifted out of shift register */
320  while (!LPUART_GetStatusFlag(base, LPUART_TX_COMPLETE))
321  {
322  /* Do nothing */
323  }
324 
325  /* Disable the LPUART transmitter and receiver */
326  LPUART_SetTransmitterCmd(base, false);
327  LPUART_SetReceiverCmd(base, false);
328 
329  /* Destroy TX and RX semaphores. */
330  if (OSIF_SemaDestroy(&linCurrentState->txCompleted) != STATUS_SUCCESS)
331  {
332  retVal = STATUS_ERROR;
333  }
334  else if (OSIF_SemaDestroy(&linCurrentState->rxCompleted) != STATUS_SUCCESS)
335  {
336  retVal = STATUS_ERROR;
337  }
338  else
339  {
340  /* Disable LPUART interrupts. */
342 #ifdef LPUART_ERR_IRQS
343  INT_SYS_DisableIRQ(g_linLpuartErrIrqId[instance]);
344 #endif
345 
346  /* Change node's current state to UNINIT */
347  linCurrentState->currentNodeState = LIN_NODE_STATE_UNINIT;
348 
349  /* Clear our saved pointer to the LIN state structure */
350  g_linStatePtr[instance] = NULL;
351  }
352 
353  return retVal;
354 }
355 
356 /*FUNCTION**********************************************************************
357  *
358  * Function Name : LIN_LPUART_DRV_InstallCallback
359  * Description : This function installs the callback function that is used for LIN_LPUART_DRV_IRQHandler.
360  * Pass in Null pointer as callback will uninstall.
361  *
362  * Implements : LIN_LPUART_DRV_InstallCallback_Activity
363  *END**************************************************************************/
365  lin_callback_t function)
366 {
367  /* Assert parameters. */
368  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
369 
370  /* Get the current LIN state of this LPUART instance. */
371  lin_state_t * linCurrentState = g_linStatePtr[instance];
372 
373  /* Get the current callback function. */
374  lin_callback_t currentCallback = linCurrentState->Callback;
375 
376  /* Install new callback function. */
377  linCurrentState->Callback = function;
378 
379  return currentCallback;
380 }
381 
382 /*FUNCTION**********************************************************************
383  *
384  * Function Name : LIN_LPUART_DRV_SendFrameDataBlocking
385  * Description : This function sends data out through the LPUART module using
386  * blocking method. This function checks if txSize is in range from 1 to 8.
387  * If not, it will return STATUS_ERROR. This function also returns STATUS_ERROR
388  * if node's current state is in SLEEP mode. This function checks if the
389  * isBusBusy is false, if not it will return STATUS_BUSY. The function does not
390  * return until the transmission is complete. If the transmission is successful,
391  * it will return STATUS_SUCCESS. If not, it will return STATUS_TIMEOUT.
392  *
393  * Implements : LIN_LPUART_DRV_SendFrameDataBlocking_Activity
394  *END**************************************************************************/
396  const uint8_t * txBuff,
397  uint8_t txSize,
398  uint32_t timeoutMSec)
399 {
400  /* Assert parameters. */
401  DEV_ASSERT(txBuff != NULL);
402  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
403 
404  /* Get base address of the LPUART instance. */
405  LPUART_Type * base = g_linLpuartBase[instance];
406 
407  /* Get the current LIN state of this LPUART instance. */
408  lin_state_t * linCurrentState = g_linStatePtr[instance];
409  status_t retVal = STATUS_SUCCESS;
410 
411  /* Check whether current mode is sleep mode */
412  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
413 
414  /* Check if txSize > 8 or equal to 0 or node's current state
415  * is in SLEEP mode then return STATUS_ERROR */
416  if ((8U < txSize) || (0U == txSize) || checkSleepMode)
417  {
418  retVal = STATUS_ERROR;
419  }
420  else
421  {
422  /* Check if the LIN Bus is busy */
423  if (linCurrentState->isBusBusy)
424  {
425  retVal = STATUS_BUSY;
426  }
427  else
428  {
429  /* Make the checksum byte. */
430  linCurrentState->checkSum = LIN_DRV_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
431 
432  /* Update the LIN state structure. */
433  linCurrentState->txBuff = txBuff;
434  /* Add a place for checksum byte */
435  linCurrentState->txSize = (uint8_t)(txSize + 1U);
436  linCurrentState->cntByte = 0U;
437  linCurrentState->currentEventId = LIN_NO_EVENT;
438  linCurrentState->isBusBusy = true;
439  linCurrentState->isTxBusy = true;
440  linCurrentState->isTxBlocking = true;
441 
442  /* Set Break char detect length as 10 bits minimum */
443  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
444 
445  /* Set node's current state to SEND_DATA */
446  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
447 
448  /* Start sending data */
449  LPUART_Putchar(base, *linCurrentState->txBuff);
450 
451  /* Wait until the transmission is complete. */
452  retVal = LIN_LPUART_DRV_WaitComplete(instance, timeoutMSec);
453 
454  /* Clear Tx Blocking flag */
455  linCurrentState->isTxBlocking = false;
456  /* Update Bus Busy flag. */
457  linCurrentState->isBusBusy = false;
458  linCurrentState->isTxBusy = false;
459 
460  /* Change node's current state to IDLE */
461  (void)LIN_LPUART_DRV_GotoIdleState(instance);
462  }
463  }
464 
465  return retVal;
466 }
467 
468 /*FUNCTION**********************************************************************
469  *
470  * Function Name : LIN_LPUART_DRV_SendFrameData
471  * Description : This function sends data out through the LPUART module using
472  * non-blocking method. This function will calculate the checksum byte and send
473  * it with the frame data. The function will return immediately after calling
474  * this function. If txSize is equal to 0 or greater than 8 or node's current
475  * state is in SLEEP mode then the function will return STATUS_ERROR. If
476  * isBusBusy is currently true then the function will return STATUS_BUSY.
477  *
478  * Implements : LIN_LPUART_DRV_SendFrameData_Activity
479  *END**************************************************************************/
481  const uint8_t * txBuff,
482  uint8_t txSize)
483 {
484  /* Assert parameters. */
485  DEV_ASSERT(txBuff != NULL);
486  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
487 
488  status_t retVal = STATUS_SUCCESS;
489 
490  /* Get base address of the LPUART instance. */
491  LPUART_Type * base = g_linLpuartBase[instance];
492 
493  /* Get the current LIN state of this LPUART instance. */
494  lin_state_t * linCurrentState = g_linStatePtr[instance];
495 
496  /* Check whether current mode is sleep mode */
497  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
498 
499  /* Check if txSize > 8 or equal to 0 or node's current state
500  * is in SLEEP mode then return STATUS_ERROR */
501  if ((8U < txSize) || (0U == txSize) || checkSleepMode)
502  {
503  retVal = STATUS_ERROR;
504  }
505  else
506  {
507  /* Check if the LIN Bus is busy */
508  if (linCurrentState->isBusBusy)
509  {
510  retVal = STATUS_BUSY;
511  }
512  else
513  {
514  /* Make the checksum byte. */
515  linCurrentState->checkSum = LIN_DRV_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
516 
517  /* Update the LIN state structure. */
518  linCurrentState->txBuff = txBuff;
519  /* Add a place for checksum byte */
520  linCurrentState->txSize = (uint8_t)(txSize + 1U);
521  linCurrentState->cntByte = 0U;
522  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
523  linCurrentState->currentEventId = LIN_NO_EVENT;
524  linCurrentState->isBusBusy = true;
525  linCurrentState->isTxBusy = true;
526 
527  /* Set Break char detect length as 10 bits minimum */
528  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
529 
530  /* Start sending data */
531  LPUART_Putchar(base, *linCurrentState->txBuff);
532  }
533  }
534 
535  return retVal;
536 }
537 
538 /*FUNCTION**********************************************************************
539  *
540  * Function Name : LIN_LPUART_DRV_GetTransmitStatus
541  * Description : This function returns whether the previous LPUART transmit has
542  * finished. When performing non-blocking transmit, the user can call this
543  * function to ascertain the state of the current transmission:
544  * in progress (or busy that is STATUS_BUSY) or timeout (if timeout has occurred that is
545  * STATUS_TIMEOUT) or complete (success that is STATUS_SUCCESS).
546  * In addition, if the transmission is still in progress, the user can obtain the number
547  * of bytes that still needed to transmit.
548  *
549  * Implements : LIN_LPUART_DRV_GetTransmitStatus_Activity
550  *END**************************************************************************/
552  uint8_t * bytesRemaining)
553 {
554  /* Assert parameters. */
555  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
556 
557  status_t retVal = STATUS_SUCCESS;
558 
559  /* Get the current LIN state of this LPUART instance. */
560  const lin_state_t * linCurrentState = g_linStatePtr[instance];
561 
562  /* Get the number of bytes that is still needed to transmit */
563  *bytesRemaining = (uint8_t)(linCurrentState->txSize - linCurrentState->cntByte);
564 
565  /* Return status of the on-going transmission */
566  if ((linCurrentState->currentEventId == LIN_NO_EVENT) && (*bytesRemaining != 0U))
567  {
568  if (linCurrentState->timeoutCounterFlag == false)
569  {
570  retVal = STATUS_BUSY;
571  }
572  else
573  {
574  retVal = STATUS_TIMEOUT;
575  }
576  }
577 
578  return retVal;
579 }
580 
581 /*FUNCTION**********************************************************************
582  *
583  * Function Name : LIN_LPUART_DRV_RecvFrmDataBlocking
584  * Description : This function receives data from LPUART module using blocking
585  * method, the function does not return until the receive is complete. The interrupt
586  * handler LIN_LPUART_DRV_IRQHandler will check the checksum byte. If the checksum
587  * is correct, it will receive the frame data. If the checksum is incorrect, this
588  * function will return STATUS_TIMEOUT and data in rxBuff might be wrong. This function
589  * also check if rxSize is in range from 1 to 8. If not, it will return STATUS_ERROR.
590  * This function also returns STATUS_ERROR if node's current state is in SLEEP mode.
591  * This function checks if the isBusBusy is false, if not it will return
592  * STATUS_BUSY.
593  *
594  * Implements : LIN_LPUART_DRV_RecvFrmDataBlocking_Activity
595  *END**************************************************************************/
597  uint8_t * rxBuff,
598  uint8_t rxSize,
599  uint32_t timeoutMSec)
600 {
601  /* Assert parameters. */
602  DEV_ASSERT(rxBuff != NULL);
603  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
604 
605  /* Get base address of the LPUART instance. */
606  LPUART_Type * base = g_linLpuartBase[instance];
607 
608  /* Get the current LIN state of this LPUART instance. */
609  lin_state_t * linCurrentState = g_linStatePtr[instance];
610  status_t retVal = STATUS_SUCCESS;
611 
612  /* Check whether current mode is sleep mode */
613  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
614 
615  /* Check if rxSize > 8 or equal to 0 or node's current state
616  * is in SLEEP mode then return STATUS_ERROR */
617  if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
618  {
619  retVal = STATUS_ERROR;
620  }
621  else
622  {
623  /* Check if the LIN Bus is busy */
624  if (linCurrentState->isBusBusy)
625  {
626  retVal = STATUS_BUSY;
627  }
628  else
629  {
630  /* Update the LIN state structure. */
631  linCurrentState->rxBuff = rxBuff;
632  /* Add a place for checksum byte */
633  linCurrentState->rxSize = (uint8_t)(rxSize + 1U);
634  linCurrentState->cntByte = 0U;
635 
636  /* Start receiving data */
637  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
638  linCurrentState->currentEventId = LIN_NO_EVENT;
639  linCurrentState->isBusBusy = true;
640  linCurrentState->isRxBusy = true;
641  linCurrentState->isRxBlocking = true;
642 
643  /* Set Break char detect length as 10 bits minimum */
644  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
645 
646  /* Wait until the reception is complete. */
647  retVal = LIN_LPUART_DRV_WaitComplete(instance, timeoutMSec);
648 
649  /* In case of receiving a go to sleep request, after callback, node is in SLEEP MODE */
650  /* In this case, node is in SLEEP MODE state */
651  if (linCurrentState->currentNodeState != LIN_NODE_STATE_SLEEP_MODE)
652  {
653  /* Update node's current state to IDLE. */
654  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
655  }
656 
657  /* Clear Rx Blocking flag. */
658  linCurrentState->isRxBlocking = false;
659 
660  /* Update Bus Busy flag. */
661  linCurrentState->isBusBusy = false;
662  linCurrentState->isRxBusy = false;
663  }
664  }
665 
666  return retVal;
667 }
668 
669 /*FUNCTION**********************************************************************
670  *
671  * Function Name : LIN_LPUART_DRV_RecvFrmData
672  * Description : This function receives data from LPUART module using
673  * non-blocking method. This function returns immediately after initiating the
674  * receive function. The application has to get the receive status to see when
675  * the receive is complete. In other words, after calling non-blocking get
676  * function, the application must get the receive status to check if receive
677  * is completed or not. The interrupt handler LIN_LPUART_DRV_IRQHandler will check
678  * the checksum byte. If the checksum is correct, it will receive the frame data.
679  * If the checksum is incorrect, this function will return STATUS_TIMEOUT and data in
680  * rxBuff might be wrong. This function also check if rxSize is in range from 1 to 8.
681  * If not, it will return STATUS_ERROR. This function also returns STATUS_ERROR if
682  * node's current state is in SLEEP mode. This function checks if the
683  * isBusBusy is false, if not it will return STATUS_BUSY.
684  *
685  * Implements : LIN_LPUART_DRV_RecvFrmData_Activity
686  *END**************************************************************************/
688  uint8_t * rxBuff,
689  uint8_t rxSize)
690 {
691  /* Assert parameters. */
692  DEV_ASSERT(rxBuff != NULL);
693  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
694 
695  status_t retVal = STATUS_SUCCESS;
696 
697  /* Get base address of the LPUART instance. */
698  LPUART_Type * base = g_linLpuartBase[instance];
699 
700  /* Get the current LIN state of this LPUART instance. */
701  lin_state_t * linCurrentState = g_linStatePtr[instance];
702 
703  /* Check whether current mode is sleep mode */
704  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
705 
706  /* Check if rxSize > 8 or equal to 0 or node's current state
707  * is in SLEEP mode then return STATUS_ERROR */
708  if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
709  {
710  retVal = STATUS_ERROR;
711  }
712  else
713  {
714  /* Check if the LIN Bus is busy */
715  if (linCurrentState->isBusBusy)
716  {
717  retVal = STATUS_BUSY;
718  }
719  else
720  {
721  /* Update the LIN state structure. */
722  linCurrentState->rxBuff = rxBuff;
723  /* Add a place for checksum byte */
724  linCurrentState->rxSize = (uint8_t)(rxSize + 1U);
725  linCurrentState->cntByte = 0U;
726 
727  /* Start receiving data */
728  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
729  linCurrentState->currentEventId = LIN_NO_EVENT;
730  linCurrentState->isBusBusy = true;
731  linCurrentState->isRxBusy = true;
732  linCurrentState->isRxBlocking = false;
733 
734  /* Set Break char detect length as 10 bits minimum */
735  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
736  }
737  }
738 
739  return retVal;
740 }
741 
742 /*FUNCTION**********************************************************************
743  *
744  * Function Name : LPUART_DRV_AbortTransferData
745  * Description : Aborts an on-going non-blocking transmission/reception.
746  * While performing a non-blocking transferring data, users can call this
747  * function to terminate immediately the transferring.
748  *
749  * Implements : LIN_LPUART_DRV_AbortTransferData_Activity
750  *END**************************************************************************/
752 {
753  /* Assert parameters. */
754  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
755 
756  status_t retVal = STATUS_SUCCESS;
757 
758  /* Get the current LIN state of this LPUART instance. */
759  lin_state_t * linCurrentState = g_linStatePtr[instance];
760 
761  /* Change node's current state to IDLE */
762  (void)LIN_LPUART_DRV_GotoIdleState(instance);
763 
764  /* Clear LIN Bus Busy flag */
765  linCurrentState->isTxBusy = false;
766  linCurrentState->isRxBusy = false;
767  linCurrentState->isBusBusy = false;
768 
769  return retVal;
770 }
771 
772 /*FUNCTION**********************************************************************
773  *
774  * Function Name : LIN_LPUART_DRV_GetReceiveStatus
775  * Description : This function returns whether the previous LPUART reception is
776  * complete. When performing a non-blocking receive, the user can call this
777  * function to ascertain the state of the current receive progress: in progress
778  * or complete. In addition, if the reception is still in progress, the user can
779  * obtain the number of words that is still needed to receive.
780  *
781  * Implements : LIN_LPUART_DRV_GetReceiveStatus_Activity
782  *END**************************************************************************/
784  uint8_t * bytesRemaining)
785 {
786  /* Assert parameters. */
787  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
788 
789  status_t retVal = STATUS_SUCCESS;
790 
791  /* Get the current LIN state of this LPUART instance. */
792  const lin_state_t * linCurrentState = g_linStatePtr[instance];
793 
794  /* Get the number of bytes that is still needed to receive */
795  *bytesRemaining = (uint8_t)(linCurrentState->rxSize - linCurrentState->cntByte);
796 
797  /* Return status of the on-going reception */
798  if ((linCurrentState->currentEventId == LIN_NO_EVENT) && (*bytesRemaining != 0U))
799  {
800  if (linCurrentState->timeoutCounterFlag == false)
801  {
802  retVal = STATUS_BUSY;
803  }
804  else
805  {
806  retVal = STATUS_TIMEOUT;
807  }
808  }
809 
810  return retVal;
811 }
812 
813 /*FUNCTION**********************************************************************
814  *
815  * Function Name : LIN_LPUART_DRV_GoToSleepMode
816  * Description : This function puts current LIN node to sleep mode.
817  * This function changes current node state to LIN_NODE_STATE_SLEEP_MODE.
818  *
819  * Implements : LIN_LPUART_DRV_GoToSleepMode_Activity
820  *END**************************************************************************/
822 {
823  /* Assert parameters. */
824  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
825 
826  /* Get base address of the LPUART instance. */
827  LPUART_Type * base = g_linLpuartBase[instance];
828 
829  /* Get the current LIN state of this LPUART instance. */
830  lin_state_t * linCurrentState = g_linStatePtr[instance];
831 
832  /* Update node's current state to SLEEP_MODE. */
833  linCurrentState->currentNodeState = LIN_NODE_STATE_SLEEP_MODE;
834 
835  /* Set Receive data not inverted */
836  LPUART_SetRxDataPolarity(base, false);
837 
838  /* Disable RX complete interrupt */
839  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, false);
840 
841  /* Enable RX Input Active Edge interrupt */
842  LPUART_SetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE, true);
843 
844  /* Disable frame error interrupt */
845  LPUART_SetIntMode(base, LPUART_INT_FRAME_ERR_FLAG, false);
846 
847  /* Disable LIN break detect interrupt */
848  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, false);
849 
850  return STATUS_SUCCESS;
851 }
852 
853 /*FUNCTION**********************************************************************
854  *
855  * Function Name : LIN_LPUART_DRV_SendWakeupSignal
856  * Description : This function sends a wakeup signal through the LPUART interface.
857  *
858  * Implements : LIN_LPUART_DRV_SendWakeupSignal_Activity
859  *END**************************************************************************/
861 {
862  /* DEV_ASSERT parameters. */
863  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
864 
865  /* Get base address of the LPUART instance. */
866  LPUART_Type * base = g_linLpuartBase[instance];
867  /* Get the current LIN state of this LPUART instance. */
868  const lin_state_t * linCurrentState = g_linStatePtr[instance];
869  status_t retVal = STATUS_SUCCESS;
870 
871  /* Check if bus is not busy */
872  if (linCurrentState->isBusBusy == false)
873  {
874  /* Send a wakeup signal */
875  LPUART_Putchar(base, s_wakeupSignal[instance]);
876  }
877  else
878  {
879  retVal = STATUS_BUSY;
880  }
881 
882  return retVal;
883 }
884 
885 /*FUNCTION**********************************************************************
886  *
887  * Function Name : LIN_LPUART_DRV_GetCurrentNodeState
888  * Description : This function gets the current LIN node state.
889  *
890  * Implements : LIN_LPUART_DRV_GetCurrentNodeState_Activity
891  *END**************************************************************************/
893 {
894  /* Assert parameters. */
895  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
896 
898  /* Get the current LIN state of this LPUART instance. */
899  const lin_state_t * linCurrentState = g_linStatePtr[instance];
900 
901  if (linCurrentState != NULL)
902  {
903  retVal = linCurrentState->currentNodeState;
904  }
905 
906  /* Return LIN node's current state */
907  return retVal;
908 }
909 
910 /*FUNCTION**********************************************************************
911  *
912  * Function Name : LIN_LPUART_DRV_TimeoutService
913  * Description : This is callback function for Timer Interrupt Handler.
914  * Users shall initialize a timer (for example FTM) in Output compare mode
915  * with period of about 500 micro seconds. In timer IRQ handler, call this function.
916  *
917  * Implements : LIN_LPUART_DRV_TimeoutService_Activity
918  *END**************************************************************************/
919 void LIN_LPUART_DRV_TimeoutService(uint32_t instance)
920 {
921  /* Assert parameters. */
922  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
923 
924  /* Get the current LIN state of this LPUART instance. */
925  lin_state_t * linCurrentState = g_linStatePtr[instance];
926 
927  /* Get LIN node's current state */
928  lin_node_state_t state = linCurrentState->currentNodeState;
929 
930  switch (state)
931  {
932  /* If the node is SENDING DATA */
934  /* Check if timeout Counter is 0 */
935  if (linCurrentState->timeoutCounter == 0U)
936  {
937  /* Set timeout Counter flag */
938  linCurrentState->timeoutCounterFlag = true;
939 
940  if (linCurrentState->isTxBlocking == false)
941  {
942  /* Callback to handle timeout Counter flag */
943  if (linCurrentState->Callback != NULL)
944  {
945  linCurrentState->Callback(instance, linCurrentState);
946  }
947 
948  /* Clear Bus busy flag */
949  linCurrentState->isBusBusy = false;
950  linCurrentState->isTxBusy = false;
951 
952  /* Change the node's current state to IDLE */
953  (void)LIN_LPUART_DRV_GotoIdleState(instance);
954  }
955  }
956  else /* If timeout Counter is not 0, then decrease timeout Counter by one */
957  {
958  linCurrentState->timeoutCounter--;
959  }
960 
961  break;
962  /* If the node is RECEIVING DATA */
964  /* Check if timeout Counter is 0 */
965  if (linCurrentState->timeoutCounter == 0U)
966  {
967  /* Set timeout Counter flag */
968  linCurrentState->timeoutCounterFlag = true;
969 
970  /* Check if the reception is non-blocking */
971  if (linCurrentState->isRxBlocking == false)
972  {
973  /* Callback to handle timeout Counter flag */
974  if (linCurrentState->Callback != NULL)
975  {
976  linCurrentState->Callback(instance, linCurrentState);
977  }
978 
979  /* Clear Bus busy flag */
980  linCurrentState->isBusBusy = false;
981  linCurrentState->isRxBusy = false;
982  /* Change the node's current state to IDLE */
983  (void)LIN_LPUART_DRV_GotoIdleState(instance);
984  }
985  }
986  /* If timeout Counter is not 0, then decrease timeout Counter by one */
987  else
988  {
989  linCurrentState->timeoutCounter--;
990  }
991 
992  break;
993  default:
994  /* The node state is not SENDING nor RECEIVING data */
995  break;
996  }
997 }
998 
999 /*FUNCTION**********************************************************************
1000  *
1001  * Function Name : LIN_LPUART_DRV_SetTimeoutCounter
1002  * Description : This function sets value for timeout counter that is used in
1003  * LIN_LPUART_DRV_TimeoutService
1004  *
1005  * Implements : LIN_LPUART_DRV_SetTimeoutCounter_Activity
1006  *END**************************************************************************/
1007 void LIN_LPUART_DRV_SetTimeoutCounter(uint32_t instance,
1008  uint32_t timeoutValue)
1009 {
1010  /* Assert parameters. */
1011  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1012 
1013  /* Get the current LIN state of this LPUART instance. */
1014  lin_state_t * linCurrentState = g_linStatePtr[instance];
1015 
1016  /* Clear Timeout Counter Flag */
1017  linCurrentState->timeoutCounterFlag = false;
1018 
1019  /* Set new value for Timeout Counter */
1020  linCurrentState->timeoutCounter = timeoutValue;
1021 }
1022 
1023 /*FUNCTION**********************************************************************
1024  *
1025  * Function Name : LIN_LPUART_DRV_MasterSendHeader
1026  * Description : This function sends frame header out through the LPUART module
1027  * using a non-blocking method. Non-blocking means that the function returns
1028  * immediately. This function sends LIN Break field, sync field then the ID with
1029  * correct parity. This function checks if the interface is Master, if not, it will
1030  * return STATUS_ERROR.This function checks if id is in range from 0 to 0x3F, if not
1031  * it will return STATUS_ERROR. This function also check node's current state is in
1032  * SLEEP mode then the function will return STATUS_ERROR. And check if isBusBusy is
1033  * currently true then the function will return STATUS_BUSY.
1034  *
1035  * Implements : LIN_LPUART_DRV_MasterSendHeader_Activity
1036  *END**************************************************************************/
1038  uint8_t id)
1039 {
1040  /* Assert parameters. */
1041  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1042 
1043  status_t retVal = STATUS_SUCCESS;
1044 
1045  /* Get the current LIN user config structure of this LPUART instance. */
1046  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1047 
1048  /* Get base address of the LPUART instance. */
1049  LPUART_Type * base = g_linLpuartBase[instance];
1050 
1051  /* Get the current LIN state of this LPUART instance. */
1052  lin_state_t * linCurrentState = g_linStatePtr[instance];
1053 
1054  /* Check whether current mode is sleep mode */
1055  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1056 
1057  /* Check if the current node is slave or id is invalid or node's current
1058  * state is in SLEEP state */
1059  if ((linUserConfig->nodeFunction == (bool)SLAVE) || (0x3FU < id) || checkSleepMode)
1060  {
1061  retVal = STATUS_ERROR;
1062  }
1063  else
1064  {
1065  /* Check if the LIN bus is busy */
1066  if (linCurrentState->isBusBusy)
1067  {
1068  retVal = STATUS_BUSY;
1069  }
1070  else
1071  {
1072  linCurrentState->currentId = id;
1073 
1074  /* Make parity for the current ID */
1075  linCurrentState->currentPid = LIN_DRV_ProcessParity(id, MAKE_PARITY);
1076 
1077  /* Set LIN current state to sending Break field */
1079  linCurrentState->currentEventId = LIN_NO_EVENT;
1080  linCurrentState->isBusBusy = true;
1081 
1082  /* Set Break char detect length as 13 bits minimum */
1083  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_13_BIT_MINIMUM);
1084  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, true);
1085 
1086  /* Send break char by using queue mode */
1087  LPUART_QueueBreakField(base);
1088  }
1089  }
1090 
1091  return retVal;
1092 }
1093 
1094 /*FUNCTION**********************************************************************
1095  *
1096  * Function Name : LIN_LPUART_DRV_EnableIRQ
1097  * Description : This function enables LPUART hardware interrupts.
1098  *
1099  * Implements : LIN_LPUART_DRV_EnableIRQ_Activity
1100  *END**************************************************************************/
1102 {
1103  /* Assert parameters. */
1104  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1105 
1106  status_t retVal = STATUS_SUCCESS;
1107 
1108  /* Get base address of the LPUART instance. */
1109  LPUART_Type * base = g_linLpuartBase[instance];
1110 
1111  /* Get the current LIN state of this LPUART instance. */
1112  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1113 
1114  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1115  {
1116  /* Enable RX Input Active Edge interrupt */
1117  LPUART_SetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE, true);
1118  }
1119  else
1120  {
1121  /* Enable RX complete interrupt */
1122  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
1123 
1124  /* Enable frame error interrupt */
1125  LPUART_SetIntMode(base, LPUART_INT_FRAME_ERR_FLAG, true);
1126 
1127  /* Enable LIN break detect interrupt */
1128  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, true);
1129  }
1130 
1131  /* Enable LPUART interrupts. */
1133 #ifdef LPUART_ERR_IRQS
1134  INT_SYS_EnableIRQ(g_linLpuartErrIrqId[instance]);
1135 #endif
1136 
1137  return retVal;
1138 }
1139 
1140 /*FUNCTION**********************************************************************
1141  *
1142  * Function Name : LIN_LPUART_DRV_DisableIRQ
1143  * Description : This function disables LPUART hardware interrupts.
1144  *
1145  * Implements : LIN_LPUART_DRV_DisableIRQ_Activity
1146  *END**************************************************************************/
1148 {
1149  /* Assert parameters. */
1150  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1151 
1152  status_t retVal = STATUS_SUCCESS;
1153 
1154  /* Get base address of the LPUART instance. */
1155  LPUART_Type * base = g_linLpuartBase[instance];
1156 
1157  /* Get the current LIN state of this LPUART instance. */
1158  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1159 
1160  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1161  {
1162  /* Disable RX Input Active Edge interrupt */
1163  LPUART_SetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE, false);
1164  }
1165  else
1166  {
1167  /* Disable RX complete interrupt */
1168  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, false);
1169 
1170  /* Disable frame error interrupt */
1171  LPUART_SetIntMode(base, LPUART_INT_FRAME_ERR_FLAG, false);
1172 
1173  /* Disable frame error interrupt */
1174  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, false);
1175  }
1176 
1177  /* Disable LPUART interrupts. */
1179 #ifdef LPUART_ERR_IRQS
1180  INT_SYS_DisableIRQ(g_linLpuartErrIrqId[instance]);
1181 #endif
1182 
1183  return retVal;
1184 }
1185 
1186 /*FUNCTION**********************************************************************
1187  *
1188  * Function Name : LIN_LPUART_DRV_GotoIdleState
1189  * Description : This function puts current node to Idle state.
1190  *
1191  * Implements : LIN_LPUART_DRV_GotoIdleState_Activity
1192  *END**************************************************************************/
1194 {
1195  /* Get base address of the LPUART instance. */
1196  LPUART_Type * base = g_linLpuartBase[instance];
1197 
1198  /* Get the current LIN state of this LPUART instance. */
1199  lin_state_t * linCurrentState = g_linStatePtr[instance];
1200 
1201  linCurrentState->currentEventId = LIN_NO_EVENT;
1202 
1203  /* Set Break char detect length as 13 bits minimum */
1204  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_13_BIT_MINIMUM);
1205 
1206  /* Set Receive data not inverted */
1207  LPUART_SetRxDataPolarity(base, false);
1208 
1209  /* Enable RX complete interrupt */
1210  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
1211 
1212  /* Disable RXEDG interrupt */
1213  LPUART_SetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE, false);
1214 
1215  /* Enable frame error interrupt */
1216  LPUART_SetIntMode(base, LPUART_INT_FRAME_ERR_FLAG, true);
1217 
1218  /* Enable LIN break detect interrupt */
1219  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, true);
1220 
1221  /* Change node's current state to IDLE */
1222  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1223 
1224  return STATUS_SUCCESS;
1225 }
1226 
1227 /*FUNCTION**********************************************************************
1228  *
1229  * Function Name : LIN_LPUART_DRV_WaitComplete
1230  * Description : This function waits until transmission/reception is complete and
1231  * returns status of the transaction.
1232  *
1233  * Implements : LIN_LPUART_DRV_WaitComplete_Activity
1234  *END**************************************************************************/
1235 static status_t LIN_LPUART_DRV_WaitComplete(uint32_t instance,
1236  uint32_t timeoutMSec)
1237 {
1238  /* Get the current LIN state of this LPUART instance. */
1239  lin_state_t * linCurrentState = g_linStatePtr[instance];
1240  status_t retVal = STATUS_SUCCESS;
1241 
1242  if (linCurrentState->isTxBusy == true)
1243  {
1244  if (OSIF_SemaWait(&linCurrentState->txCompleted, timeoutMSec) == STATUS_TIMEOUT)
1245  {
1246  retVal = STATUS_TIMEOUT;
1247  }
1248  }
1249 
1250  if (linCurrentState->isRxBusy == true)
1251  {
1252  if (OSIF_SemaWait(&linCurrentState->rxCompleted, timeoutMSec) == STATUS_TIMEOUT)
1253  {
1254  retVal = STATUS_TIMEOUT;
1255  }
1256  }
1257 
1258  return retVal;
1259 }
1260 
1261 /*FUNCTION**********************************************************************
1262  *
1263  * Function Name : LIN_LPUART_DRV_IRQHandler
1264  * Description : Interrupt handler for LPUART.
1265  * This handler uses the buffers stored in the lin_state_t struct to transfer
1266  * data. This is not a public API as it is called by IRQ whenever an interrupt
1267  * occurs.
1268  *
1269  * Implements : LIN_LPUART_DRV_IRQHandler_Activity
1270  *END**************************************************************************/
1271 void LIN_LPUART_DRV_IRQHandler(uint32_t instance)
1272 {
1273  /* Assert parameters. */
1274  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1275 
1276  uint8_t tmpByte = 0U;
1277 
1278  /* Get base address of the LPUART instance. */
1279  LPUART_Type * base = g_linLpuartBase[instance];
1280 
1281  /* Get the current LIN state of this LPUART instance. */
1282  lin_state_t * linCurrentState = g_linStatePtr[instance];
1283 
1284  /* Check RX Input Active Edge interrupt enable */
1285  bool activeEdgeIntState = LPUART_GetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE);
1286 
1287  /* If LIN break character has been detected. */
1288  if (LPUART_GetStatusFlag(base, LPUART_LIN_BREAK_DETECT))
1289  {
1291  }
1292  else
1293  {
1294  /* If LPUART_RX Pin Active Edge has been detected. */
1295  if (LPUART_GetStatusFlag(base, LPUART_RX_ACTIVE_EDGE_DETECT) && activeEdgeIntState)
1296  {
1297  /* Clear LPUART_RX Pin Active Edge Interrupt Flag. */
1298  (void)LPUART_ClearStatusFlag(base, LPUART_RX_ACTIVE_EDGE_DETECT);
1299 
1300  /* Check if a wakeup signal has been received */
1302  }
1303  else
1304  {
1305  /* If Framing Error has been detected */
1306  if (LPUART_GetStatusFlag(base, LPUART_FRAME_ERR))
1307  {
1308  /* Clear Framing Error Interrupt Flag */
1309  (void)LPUART_ClearStatusFlag(base, LPUART_FRAME_ERR);
1310 
1311  /* Read dummy to clear LPUART_RX_DATA_REG_FULL flag */
1312  LPUART_Getchar(base, &tmpByte);
1313 
1314  /* Set current event id to LIN_FRAME_ERROR */
1315  linCurrentState->currentEventId = LIN_FRAME_ERROR;
1316 
1317  /* Check if LIN current node state is LIN_NODE_STATE_SEND_DATA */
1318  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_DATA)
1319  {
1320  /* Callback function to handle Framing Error Event */
1321  if (linCurrentState->Callback != NULL)
1322  {
1323  linCurrentState->Callback(instance, linCurrentState);
1324  }
1325  }
1326  else
1327  {
1328  /* Check if LIN current node state is LIN_NODE_STATE_RECV_DATA */
1329  if (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_DATA)
1330  {
1331  /* Callback function to handle Framing Error Event */
1332  if (linCurrentState->Callback != NULL)
1333  {
1334  linCurrentState->Callback(instance, linCurrentState);
1335  }
1336  }
1337  }
1338 
1339  /* Clear Bus busy Flag */
1340  linCurrentState->isBusBusy = false;
1341  /* Change node's state to IDLE */
1342  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1343  }
1344  else
1345  {
1346  if (LPUART_GetStatusFlag(base, LPUART_RX_DATA_REG_FULL))
1347  {
1348  /* Get data from Data Register & Clear LPUART_RX_DATA_REG_FULL flag */
1349  LPUART_Getchar(base, &tmpByte);
1350 
1351  /* Process data in Data Register while receive, send data */
1352  LIN_LPUART_DRV_ProcessFrame(instance, tmpByte);
1353  }
1354  } /* End else: if (LPUART_GetStatusFlag(base, LPUART_FRAME_ERR) == 0) */
1355  } /* End else: if (LPUART_GetStatusFlag(base, LPUART_RX_ACTIVE_EDGE_DETECT) == 0) */
1356  } /* End else: if (LPUART_GetStatusFlag(base, LPUART_LIN_BREAK_DETECT) == 0) */
1357 
1358  /* Get status RX overrun flag */
1359  if (LPUART_GetStatusFlag(base, LPUART_RX_OVERRUN))
1360  {
1361  /* Clear overrun flag */
1362  (void)LPUART_ClearStatusFlag(base, LPUART_RX_OVERRUN);
1363  }
1364 } /* End void LIN_LPUART_DRV_IRQHandler(uint32_t instance) */
1365 
1366 /*FUNCTION**********************************************************************
1367  *
1368  * Function Name : LIN_LPUART_DRV_ProcessBreakDetect
1369  * Description : This function process break detect for LIN communication.
1370  *
1371  * Implements : LIN_LPUART_DRV_ProcessBreakDetect_Activity
1372  *END**************************************************************************/
1373 static void LIN_LPUART_DRV_ProcessBreakDetect(uint32_t instance)
1374 {
1375  /* Get the current LIN user configure structure of this LPUART instance. */
1376  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1377 
1378  /* Get base address of the LPUART instance. */
1379  LPUART_Type * base = g_linLpuartBase[instance];
1380 
1381  /* Get the current LIN state of this LPUART instance. */
1382  lin_state_t * linCurrentState = g_linStatePtr[instance];
1383 
1384  /* Clear LIN Break Detect Interrupt Flag */
1385  (void)LPUART_ClearStatusFlag(base, LPUART_LIN_BREAK_DETECT);
1386 
1387  /* Check if the current node is in SLEEP MODE */
1388  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1389  {
1390  /* Change the node's current state to IDLE */
1391  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1392  }
1393  else
1394  {
1395  /* Set Break char detect length as 10 bits minimum */
1396  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
1397  /* Disable LIN Break Detect Interrupt */
1398  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, false);
1399 
1400  /* Set flag LIN bus busy */
1401  linCurrentState->isBusBusy = true;
1402 
1403  /* Check if the current node is MASTER */
1404  if (linUserConfig->nodeFunction == (bool)MASTER)
1405  {
1406  /* Check if LIN current node state is LIN_NODE_STATE_SEND_BREAK_FIELD */
1407  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_BREAK_FIELD)
1408  {
1409  /* Change the node's current state to SENDING PID to send PID after send SYNC */
1410  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_PID;
1411  /* Send Sync Field 0x55 */
1412  LPUART_Putchar(base, 0x55);
1413  }
1414  }
1415  /* If the current node is SLAVE */
1416  else
1417  {
1418  /* Change the node's current state to RECEIVED BREAK FIELD */
1419  linCurrentState->currentEventId = LIN_RECV_BREAK_FIELD_OK;
1420 
1421  /* Callback function */
1422  if (linCurrentState->Callback != NULL)
1423  {
1424  linCurrentState->Callback(instance, linCurrentState);
1425  }
1426 
1427  /* Change the node's current state to RECEIVING SYNC FIELD */
1428  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_SYNC;
1429  }
1430  }
1431 }
1432 
1433 /*FUNCTION**********************************************************************
1434  *
1435  * Function Name : LIN_LPUART_DRV_CheckWakeupSignal
1436  * Description : This function check if a dominant signal received is a wakeup
1437  * signal.
1438  *
1439  * Implements : LIN_LPUART_DRV_CheckWakeupSignal_Activity
1440  *END**************************************************************************/
1441 static void LIN_LPUART_DRV_CheckWakeupSignal(uint32_t instance)
1442 {
1443  uint32_t wakeupSignalLength = 0U;
1444 
1445  /* Get the current LIN user config structure of this LPUART instance. */
1446  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1447 
1448  /* Get base address of the LPUART instance. */
1449  LPUART_Type * base = g_linLpuartBase[instance];
1450 
1451  /* Get the current LIN state of this LPUART instance. */
1452  lin_state_t * linCurrentState = g_linStatePtr[instance];
1453 
1454  /* if LPUART_GetRxDataPolarity is 0: Receive Data is not inverted */
1455  if (LPUART_GetRxDataPolarity(base) == false)
1456  {
1457  /* Start measure time */
1458  (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
1459 
1460  /* Set Receive Data Inverted */
1461  LPUART_SetRxDataPolarity(base, true);
1462  }
1463  else
1464  {
1465  /* Set Receive Data is Not Inverted */
1466  LPUART_SetRxDataPolarity(base, false);
1467 
1468  /* Calculate time interval between the falling and rising edge */
1469  (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
1470 
1471  /* If length of the dominant signal is from 150us to 5ms, it is a wakeup signal */
1472  if ((wakeupSignalLength >= 150000U) && (wakeupSignalLength <= 5000000U))
1473  {
1474  linCurrentState->currentEventId = LIN_WAKEUP_SIGNAL;
1475 
1476  /* Callback to handle event: Received a wakeup signal */
1477  if (linCurrentState->Callback != NULL)
1478  {
1479  linCurrentState->Callback(instance, linCurrentState);
1480  }
1481 
1482  /* Change node's state to IDLE */
1483  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1484  }
1485  }
1486 }
1487 
1488 /*FUNCTION**********************************************************************
1489  *
1490  * Function Name : LIN_LPUART_DRV_ProcessFrame
1491  * Description : Part of Interrupt handler for receiving and sending data.
1492  * Receive Header, Data and Send Data.
1493  *
1494  * Implements : LIN_LPUART_DRV_ProcessFrame_Activity
1495  *END**************************************************************************/
1496 static void LIN_LPUART_DRV_ProcessFrame(uint32_t instance,
1497  uint8_t tmpByte)
1498 {
1499  /* Get the current LIN state of this LPUART instance. */
1500  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1501 
1502  /* Check node's current state */
1503  switch (linCurrentState->currentNodeState)
1504  {
1505  /* if current state is RECEIVE SYNC FIELD */
1507 
1508  /* if current state is MASTER SENDING PID */
1510 
1511  /* if current state is RECEIVE PID */
1513  LIN_LPUART_DRV_ProcessFrameHeader(instance, tmpByte);
1514  break;
1515  /* if current state is RECEIVE DATA */
1517  LIN_LPUART_DRV_ProcessReceiveFrameData(instance, tmpByte);
1518  break;
1519  /* if current state is SENDING DATA */
1521  LIN_LPUART_DRV_ProcessSendFrameData(instance, tmpByte);
1522  break;
1523 
1524  default:
1525  /* Other node state */
1526  break;
1527  }
1528 }
1529 
1530 /*FUNCTION**********************************************************************
1531  *
1532  * Function Name : LIN_LPUART_DRV_ProcessFrameHeader
1533  * Description : Part of Interrupt handler for receiving and sending data.
1534  * Receive Sync byte, PID and Send PID.
1535  *
1536  * Implements : LIN_LPUART_DRV_ProcessFrameHeader_Activity
1537  *END**************************************************************************/
1538 static void LIN_LPUART_DRV_ProcessFrameHeader(uint32_t instance,
1539  uint8_t tmpByte)
1540 {
1541  /* Get base address of the LPUART instance. */
1542  LPUART_Type * base = g_linLpuartBase[instance];
1543 
1544  /* Get the current LIN user config structure of this LPUART instance. */
1545  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1546 
1547  /* Get the current LIN state of this LPUART instance. */
1548  lin_state_t * linCurrentState = g_linStatePtr[instance];
1549 
1550  /* Check node's current state */
1551  switch (linCurrentState->currentNodeState)
1552  {
1553  /* If current state is RECEIVE SYNC FIELD */
1555  if (tmpByte == 0x55U)
1556  {
1557  /* Set current event ID to Sync byte is correct */
1558  linCurrentState->currentEventId = LIN_SYNC_OK;
1559  /* Change node's current state to RECEIVE PID */
1560  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1561  }
1562  else
1563  {
1564  /* Set current event ID to Sync byte is incorrect */
1565  linCurrentState->currentEventId = LIN_SYNC_ERROR;
1566  /* Callback function to handle event RECEIVED SYNC FIELD ERROR */
1567  if (linCurrentState->Callback != NULL)
1568  {
1569  linCurrentState->Callback(instance, linCurrentState);
1570  }
1571 
1572  /* Clear Bus busy flag */
1573  linCurrentState->isBusBusy = false;
1574 
1575  /* Change node's current state to IDLE */
1576  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1577  }
1578 
1579  break;
1580  /* If current state is MASTER SENDING PID */
1582  /* Check if master node sent SYNC byte correctly before send PID */
1583  if (tmpByte == 0x55U)
1584  {
1585  /* Change node's current state to RECEIVING PID */
1586  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1587  /* Send the current PID byte */
1588  LPUART_Putchar(base, linCurrentState->currentPid);
1589  }
1590  /* In case of errors during header transmission, it is up to the implementer
1591  * how to handle these errors (stop/continue transmission) and to decide if the
1592  * corresponding response is valid or not.
1593  * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
1594  */
1595  else
1596  {
1597  /* Set current event ID to Sync byte is incorrect */
1598  linCurrentState->currentEventId = LIN_SYNC_ERROR;
1599  /* Clear Bus bus flag */
1600  linCurrentState->isBusBusy = false;
1601  /* Change node's current state to IDLE */
1602  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1603 
1604  /* Callback function to handle event SENT SYNC BYTE ERROR */
1605  if (linCurrentState->Callback != NULL)
1606  {
1607  linCurrentState->Callback(instance, linCurrentState);
1608  }
1609  }
1610 
1611  break;
1612  /* If current state is RECEIVE PID */
1614  /* If the node is MASTER */
1615  if (linUserConfig->nodeFunction == (bool)MASTER)
1616  {
1617  /* Check if master node sent PID correctly */
1618  if (tmpByte == linCurrentState->currentPid)
1619  {
1620  /* Set current event ID to PID correct */
1621  linCurrentState->currentEventId = LIN_PID_OK;
1622 
1623  /* Clear Bus bus flag */
1624  linCurrentState->isBusBusy = false;
1625 
1626  /* Callback function to handle correct PID */
1627  if (linCurrentState->Callback != NULL)
1628  {
1629  linCurrentState->Callback(instance, linCurrentState);
1630  }
1631  }
1632  /* In case of errors during header transmission, it is up to the implementer
1633  * how to handle these errors (stop/continue transmission) and to decide if the
1634  * corresponding response is valid or not.
1635  * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
1636  */
1637  else
1638  {
1639  /* Set current event ID to PID incorrect */
1640  linCurrentState->currentEventId = LIN_PID_ERROR;
1641  /* Clear bus busy flag */
1642  linCurrentState->isBusBusy = false;
1643  /* Change node's current state to IDLE */
1644  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1645  /* Callback function to handle event MASTER SENT PID ERROR */
1646  if (linCurrentState->Callback != NULL)
1647  {
1648  linCurrentState->Callback(instance, linCurrentState);
1649  }
1650  }
1651  }
1652  /* If the node is SLAVE */
1653  else
1654  {
1655  /* Check the received PID */
1656  linCurrentState->currentId = LIN_DRV_ProcessParity(tmpByte, CHECK_PARITY);
1657  linCurrentState->currentPid = tmpByte;
1658  if (linCurrentState->currentId != 0xFFU)
1659  {
1660  /* Set current event ID to PID correct */
1661  linCurrentState->currentEventId = LIN_PID_OK;
1662 
1663  /* Clear Bus bus flag */
1664  linCurrentState->isBusBusy = false;
1665 
1666  /* Callback function to handle event PID correct */
1667  if (linCurrentState->Callback != NULL)
1668  {
1669  linCurrentState->Callback(instance, linCurrentState);
1670  }
1671  }
1672  else
1673  {
1674  /* Set current event ID to PID ERROR */
1675  linCurrentState->currentEventId = LIN_PID_ERROR;
1676 
1677  /* Callback function to handle event PID incorrect */
1678  if (linCurrentState->Callback != NULL)
1679  {
1680  linCurrentState->Callback(instance, linCurrentState);
1681  }
1682 
1683  /* Clear bus busy flag */
1684  linCurrentState->isBusBusy = false;
1685 
1686  /* Change node's current state to IDLE */
1687  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1688  }
1689  }
1690 
1691  break;
1692  default:
1693  /* Other node state */
1694  break;
1695  }
1696 }
1697 
1698 /*FUNCTION**********************************************************************
1699  *
1700  * Function Name : LIN_LPUART_DRV_ProcessReceiveFrameData
1701  * Description : Part of Interrupt handler for receiving.
1702  *
1703  * Implements : LIN_LPUART_DRV_ProcessReceiveFrameData_Activity
1704  *END**************************************************************************/
1705 static void LIN_LPUART_DRV_ProcessReceiveFrameData(uint32_t instance,
1706  uint8_t tmpByte)
1707 {
1708  /* Get the current LIN state of this LPUART instance. */
1709  lin_state_t * linCurrentState = g_linStatePtr[instance];
1710 
1711  if (linCurrentState->rxSize > (linCurrentState->cntByte + 1U))
1712  {
1713  *(linCurrentState->rxBuff) = tmpByte;
1714  linCurrentState->rxBuff++;
1715  }
1716  else
1717  {
1718  if ((linCurrentState->rxSize - linCurrentState->cntByte) == 1U)
1719  {
1720  linCurrentState->checkSum = tmpByte;
1721  }
1722  }
1723 
1724  linCurrentState->cntByte++;
1725  if (linCurrentState->cntByte == linCurrentState->rxSize)
1726  {
1727  /* Restore rxBuffer pointer */
1728  linCurrentState->rxBuff -= linCurrentState->rxSize - 1U;
1729  if (LIN_DRV_MakeChecksumByte(linCurrentState->rxBuff, linCurrentState->rxSize - 1U, linCurrentState->currentPid) == linCurrentState->checkSum)
1730  {
1731  linCurrentState->currentEventId = LIN_RX_COMPLETED;
1733 
1734  /* callback function to handle RX COMPLETED */
1735  if (linCurrentState->Callback != NULL)
1736  {
1737  linCurrentState->Callback(instance, linCurrentState);
1738  }
1739 
1740  /* Check if the reception is non-blocking */
1741  if (linCurrentState->isRxBlocking == false)
1742  {
1743  /* Clear Bus busy flag */
1744  linCurrentState->isBusBusy = false;
1745  linCurrentState->isRxBusy = false;
1746 
1747  /* In case of receiving a go to sleep request, after callback, node is in SLEEP MODE */
1748  /* In this case, node is in SLEEP MODE state */
1749  if (linCurrentState->currentNodeState != LIN_NODE_STATE_SLEEP_MODE)
1750  {
1751  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1752  }
1753  }
1754  else
1755  {
1756  /* Post Semaphore to signal Rx Completed*/
1757  (void)OSIF_SemaPost(&linCurrentState->rxCompleted);
1758  }
1759  }
1760  else
1761  {
1762  linCurrentState->currentEventId = LIN_CHECKSUM_ERROR;
1763  /* callback function to handle checksum error */
1764  if (linCurrentState->Callback != NULL)
1765  {
1766  linCurrentState->Callback(instance, linCurrentState);
1767  }
1768 
1769  /* Clear bus busy flag */
1770  linCurrentState->isBusBusy = false;
1771  linCurrentState->isRxBusy = false;
1772  /* Change node's current state to IDLE */
1773  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1774  }
1775  }
1776 }
1777 
1778 /*FUNCTION**********************************************************************
1779  *
1780  * Function Name : LIN_LPUART_DRV_ProcessSendFrameData
1781  * Description : Part of Interrupt handler for sending data.
1782  *
1783  * Implements : LIN_LPUART_DRV_ProcessSendFrameData_Activity
1784  *END**************************************************************************/
1785 static void LIN_LPUART_DRV_ProcessSendFrameData(uint32_t instance,
1786  uint8_t tmpByte)
1787 {
1788  bool sendFlag = true;
1789  uint8_t tmpSize;
1790  bool tmpCheckSumAndSize;
1791  bool tmpBuffAndSize;
1792 
1793  /* Get base address of the LPUART instance. */
1794  LPUART_Type * base = g_linLpuartBase[instance];
1795 
1796  /* Get the current LIN state of this LPUART instance. */
1797  lin_state_t * linCurrentState = g_linStatePtr[instance];
1798 
1799  /* Check if Tx data register empty flag is false */
1800  if (LPUART_GetStatusFlag(base, LPUART_TX_DATA_REG_EMPTY) == false)
1801  {
1802  linCurrentState->currentEventId = LIN_READBACK_ERROR;
1803  /* callback function to handle Readback error */
1804  if (linCurrentState->Callback != NULL)
1805  {
1806  linCurrentState->Callback(instance, linCurrentState);
1807  }
1808 
1809  /* Check if the transmission is non-blocking */
1810  if (linCurrentState->isTxBlocking == false)
1811  {
1812  /* Clear bus busy flag */
1813  linCurrentState->isBusBusy = false;
1814  linCurrentState->isTxBusy = false;
1815  /* Change node's current state to IDLE */
1816  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1817  }
1818 
1819  sendFlag = false;
1820  }
1821  else
1822  {
1823  tmpSize = (uint8_t)(linCurrentState->txSize - linCurrentState->cntByte);
1824  tmpCheckSumAndSize = (tmpSize == 1U) && (linCurrentState->checkSum != tmpByte);
1825  tmpBuffAndSize = (*linCurrentState->txBuff != tmpByte) && (tmpSize != 1U);
1826  if (tmpBuffAndSize || tmpCheckSumAndSize)
1827  {
1828  linCurrentState->currentEventId = LIN_READBACK_ERROR;
1829 
1830  /* callback function to handle Readback error */
1831  if (linCurrentState->Callback != NULL)
1832  {
1833  linCurrentState->Callback(instance, linCurrentState);
1834  }
1835 
1836  /* Check if the transmission is non-blocking */
1837  if (linCurrentState->isTxBlocking == false)
1838  {
1839  /* Clear bus busy flag */
1840  linCurrentState->isBusBusy = false;
1841  linCurrentState->isTxBusy = false;
1842  /* Change node's current state to IDLE */
1843  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1844  }
1845 
1846  sendFlag = false;
1847  }
1848  else
1849  {
1850  linCurrentState->txBuff++;
1851  linCurrentState->cntByte++;
1852  }
1853  }
1854 
1855  if (sendFlag)
1856  {
1857  if (linCurrentState->cntByte < linCurrentState->txSize)
1858  {
1859  /* Send checksum byte */
1860  if ((linCurrentState->txSize - linCurrentState->cntByte) == 1U)
1861  {
1862  LPUART_Putchar(base, linCurrentState->checkSum);
1863  }
1864  /* Send data bytes */
1865  else
1866  {
1867  LPUART_Putchar(base, *linCurrentState->txBuff);
1868  }
1869  }
1870  else
1871  {
1872  linCurrentState->currentEventId = LIN_TX_COMPLETED;
1874 
1875  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, false);
1876  /* callback function to handle event TX COMPLETED */
1877  if (linCurrentState->Callback != NULL)
1878  {
1879  linCurrentState->Callback(instance, linCurrentState);
1880  }
1881 
1882  /* Check if the transmission is non-blocking */
1883  if (linCurrentState->isTxBlocking == false)
1884  {
1885  /* Clear bus busy flag */
1886  linCurrentState->isBusBusy = false;
1887  linCurrentState->isTxBusy = false;
1888  /* Change node's current state to IDLE */
1889  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1890  }
1891  else
1892  {
1893  /* Post Semaphore to signal Tx Completed*/
1894  (void)OSIF_SemaPost(&linCurrentState->txCompleted);
1895  }
1896  }
1897  }
1898 }
1899 
1900 /*FUNCTION**********************************************************************
1901  *
1902  * Function Name : LIN_LPUART_DRV_AutobaudTimerValEval
1903  * Description : This function calculate LIN bus baudrate and set slave's baudrate accordingly.
1904  * Autobaud process runs only once after reset. After setting slave's baudrate to LIN bus baudrate,
1905  * slave does not evaluate LIN bus baudrate anymore.
1906  * This is not a public API as it is called from other driver functions.
1907  *
1908  * Implements : LIN_LPUART_DRV_AutobaudTimerValEval_Activity
1909  *END**************************************************************************/
1910 static void LIN_LPUART_DRV_AutobaudTimerValEval(uint32_t instance,
1911  uint32_t twoBitTimeLength)
1912 {
1913  /* Assert parameters. */
1914  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1915 
1916  uint32_t MasterBaudRate = 0U;
1917 
1918  /* Get the current LIN user config structure of this LPUART instance. */
1919  lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1920 
1921  /* Get the current LIN state of this LPUART instance. */
1922  lin_state_t * linCurrentState = g_linStatePtr[instance];
1923 
1924  /* Check whether current node state is receive sync */
1925  bool checkNodeState = (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_SYNC);
1926 
1927  /* Evaluate average value against baudrate */
1928  LIN_LPUART_DRV_EvalTwoBitTimeLength(instance, twoBitTimeLength);
1929 
1930  if ((linCurrentState->fallingEdgeInterruptCount > 4U) && checkNodeState)
1931  {
1932  if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_19200) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_19200))
1933  {
1934  MasterBaudRate = 19200U;
1935  }
1936  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_14400) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_14400))
1937  {
1938  MasterBaudRate = 14400U;
1939  }
1940  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_9600) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_9600))
1941  {
1942  MasterBaudRate = 9600U;
1943  }
1944  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_4800) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_4800))
1945  {
1946  MasterBaudRate = 4800U;
1947  }
1948  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_2400) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_2400))
1949  {
1950  MasterBaudRate = 2400U;
1951  }
1952  else
1953  {
1954  /* Complete if-elseif-else block to avoid violating MISRA 2012 Rule 15.7 */
1955  }
1956 
1957  /* Check Master Baudrate against node's current baudrate */
1958  if ((MasterBaudRate != 0U) && (linUserConfig->baudRate != MasterBaudRate))
1959  {
1960  linUserConfig->baudRate = MasterBaudRate;
1961 
1962  /* Set new baud rate */
1963  (void)LPUART_DRV_SetBaudRate(instance, linUserConfig->baudRate);
1964 
1965  /* Assign wakeup signal to satisfy LIN Specifications specifies that
1966  * wakeup signal shall be in range from 250us to 5 ms.
1967  */
1968  if (linUserConfig->baudRate > 10000U)
1969  {
1970  /* Wakeup signal will be range from 400us to 800us depend on baudrate */
1971  s_wakeupSignal[instance] = 0x80U;
1972  }
1973  else
1974  {
1975  /* Wakeup signal will be range from 400us to 4ms depend on baudrate */
1976  s_wakeupSignal[instance] = 0xF8U;
1977  }
1978  }
1979 
1980  linCurrentState->currentEventId = LIN_BAUDRATE_ADJUSTED;
1981  /* Disable baudrate evaluation process */
1982  linCurrentState->baudrateEvalEnable = false;
1983  /* Callback function to handle this event */
1984  if (linCurrentState->Callback != NULL)
1985  {
1986  linCurrentState->Callback(instance, linCurrentState);
1987  }
1988 
1989  /* Update current state and current event */
1990  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1991  linCurrentState->currentEventId = LIN_SYNC_OK;
1992 
1993  }
1994 }
1995 
1996 /*FUNCTION**********************************************************************
1997  *
1998  * Function Name : LIN_LPUART_DRV_EvalTwoBitTimeLength
1999  * Description : This function check time of double bit in sync byte for support autobaud.
2000  * This is not a public API as it is called from other driver functions.
2001  *
2002  * Implements : LIN_LPUART_DRV_EvalTwoBitTimeLength_Activity
2003  *END**************************************************************************/
2004 static void LIN_LPUART_DRV_EvalTwoBitTimeLength(uint32_t instance,
2005  uint32_t twoBitTimeLength)
2006 {
2007  /* Assert parameters. */
2008  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
2009 
2010  /* Get the current LIN state of this LPUART instance. */
2011  lin_state_t * linCurrentState = g_linStatePtr[instance];
2012 
2013  if (linCurrentState->fallingEdgeInterruptCount < 5U)
2014  {
2015  if (linCurrentState->fallingEdgeInterruptCount > 0U)
2016  {
2017  if ((twoBitTimeLength < TWO_BIT_DURATION_MIN_19200) ||
2018  ((twoBitTimeLength > TWO_BIT_DURATION_MAX_19200) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_14400)) ||
2019  ((twoBitTimeLength > TWO_BIT_DURATION_MAX_14400) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_9600)) ||
2020  ((twoBitTimeLength > TWO_BIT_DURATION_MAX_9600) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_4800)) ||
2021  ((twoBitTimeLength > TWO_BIT_DURATION_MAX_4800) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_2400)) ||
2022  (twoBitTimeLength > TWO_BIT_DURATION_MAX_2400))
2023  {
2024  /* Change node's current state to IDLE */
2025  (void)LIN_LPUART_DRV_GotoIdleState(instance);
2026  linCurrentState->fallingEdgeInterruptCount = 0U;
2027  }
2028  else
2029  {
2030  if (linCurrentState->fallingEdgeInterruptCount > 1U)
2031  {
2032  if ((twoBitTimeLength < ((100U - BIT_RATE_TOLERANCE_UNSYNC) * s_previousTwoBitTimeLength[instance] / 100U)) ||
2033  (twoBitTimeLength > ((100U + BIT_RATE_TOLERANCE_UNSYNC) * s_previousTwoBitTimeLength[instance] / 100U)))
2034  {
2035  /* Change node's current state to IDLE */
2036  (void)LIN_LPUART_DRV_GotoIdleState(instance);
2037  linCurrentState->fallingEdgeInterruptCount = 0U;
2038  }
2039  }
2040  }
2041 
2042  s_previousTwoBitTimeLength[instance] = twoBitTimeLength;
2043  }
2044  }
2045 
2046  linCurrentState->fallingEdgeInterruptCount += 1U;
2047 }
2048 
2049 /*FUNCTION**********************************************************************
2050  *
2051  * Function Name : LIN_LPUART_DRV_AutoBaudCapture
2052  * Description : This function capture bits time to detect break char, calculate
2053  * baudrate from sync bits and enable transceiver if autobaud successful.
2054  * This function should only be used in Slave.
2055  *
2056  * Implements : LIN_LPUART_DRV_AutoBaudCapture_Activity
2057  *END**************************************************************************/
2059 {
2060  /* Assert parameters. */
2061  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
2062 
2063  /* Get base address of the LPUART instance. */
2064  LPUART_Type * base = g_linLpuartBase[instance];
2065  /* Get the current LIN user config structure of this LPUART instance. */
2066  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
2067  /* Get the current LIN state of this LPUART instance. */
2068  lin_state_t * linCurrentState = g_linStatePtr[instance];
2069  status_t retVal = STATUS_BUSY;
2070  uint32_t tmpTime = 0U;
2071 
2072  if (linCurrentState->baudrateEvalEnable)
2073  {
2074  /* Calculate time between two bit (for service autobaud) */
2075  (void)linUserConfig->timerGetTimeIntervalCallback(&tmpTime);
2076 
2077  /* Get two bits time length */
2078  s_timeMeasure[instance] += tmpTime;
2079  s_countMeasure[instance]++;
2080  if ((s_countMeasure[instance] > 1U))
2081  {
2082  switch (linCurrentState->currentNodeState)
2083  {
2084  /* If current state is SLEEP MODE */
2086  /* If length of the dominant signal is from 150us to 5ms, it is a wakeup signal */
2087  if ((tmpTime >= 150000U) && (tmpTime <= 5000000U))
2088  {
2089  linCurrentState->currentEventId = LIN_WAKEUP_SIGNAL;
2090 
2091  /* Callback to handle event: Received a wakeup signal */
2092  if (linCurrentState->Callback != NULL)
2093  {
2094  linCurrentState->Callback(instance, linCurrentState);
2095  }
2096 
2097  /* Change node's state to IDLE */
2098  (void)LIN_LPUART_DRV_GotoIdleState(instance);
2099  }
2100  else
2101  {
2102  retVal = STATUS_ERROR;
2103  }
2104  s_countMeasure[instance] = 0U;
2105 
2106  break;
2107  /* If current state is IDLE */
2108  case LIN_NODE_STATE_IDLE:
2109  /* Check break time minimum */
2110  if (tmpTime >= AUTOBAUD_BREAK_TIME_MIN)
2111  {
2112  /* Set Break char detect length as 10 bits minimum */
2113  LPUART_SetBreakCharDetectLength(base, LPUART_BREAK_CHAR_10_BIT_MINIMUM);
2114 
2115  /* Disable LIN Break Detect Interrupt */
2116  LPUART_SetIntMode(base, LPUART_INT_LIN_BREAK_DETECT, false);
2117 
2118  /* Set flag LIN bus busy */
2119  linCurrentState->isBusBusy = true;
2120 
2121  /* Change the node's current state to RECEIVED BREAK FIELD */
2122  linCurrentState->currentEventId = LIN_RECV_BREAK_FIELD_OK;
2123 
2124  /* Callback function */
2125  if (linCurrentState->Callback != NULL)
2126  {
2127  linCurrentState->Callback(instance, linCurrentState);
2128  }
2129 
2130  /* Change the node's current state to RECEIVING SYNC FIELD */
2131  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_SYNC;
2132 
2133  /* Start Autobaud Count(initialize number of measurements in sync byte) */
2134  linCurrentState->fallingEdgeInterruptCount = 0U;
2135 
2136  s_countMeasure[instance] = 1U;
2137  }
2138  else
2139  {
2140  s_countMeasure[instance] = 0U;
2141  retVal = STATUS_ERROR;
2142  }
2143 
2144  break;
2145  /* If current state is RECEIVE SYNC */
2146  default:
2147  /* Calculate baudrate */
2149 
2150  /* Reset to measure in next times */
2151  s_countMeasure[instance] = 0U;
2152  s_timeMeasure[instance] = 0U;
2153 
2154  if (linCurrentState->currentNodeState == LIN_NODE_STATE_IDLE)
2155  {
2156  retVal = STATUS_ERROR;
2157  }
2158 
2159  break;
2160  }
2161  }
2162  }
2163  else
2164  {
2165  if (linCurrentState->fallingEdgeInterruptCount > 4U)
2166  {
2167  /* Enable the LPUART transmitter and receiver */
2168  LPUART_SetTransmitterCmd(base, true);
2169  LPUART_SetReceiverCmd(base, true);
2170 
2171  linCurrentState->fallingEdgeInterruptCount = 0U;
2172  }
2173 
2174  retVal = STATUS_SUCCESS;
2175  }
2176 
2177  return retVal;
2178 }
2179 
2180 /*******************************************************************************
2181  * EOF
2182  ******************************************************************************/
lin_node_state_t
Define type for an enumerating LIN Node state. Implements : lin_node_state_t_Class.
Definition: lin_driver.h:97
LPUART_Type *const g_linLpuartBase[LPUART_INSTANCE_COUNT]
Table of base addresses for LPUART instances.
volatile bool timeoutCounterFlag
Definition: lin_driver.h:142
status_t LIN_LPUART_DRV_Init(uint32_t instance, lin_user_config_t *linUserConfig, lin_state_t *linCurrentState)
Initializes an LIN_LPUART instance for LIN Network.
volatile bool baudrateEvalEnable
Definition: lin_driver.h:143
#define LPUART_BASE_PTRS
Definition: S32K142.h:6630
status_t LIN_LPUART_DRV_SendWakeupSignal(uint32_t instance)
Sends a wakeup signal through the LIN_LPUART interface.
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
uint8_t checkSum
Definition: lin_driver.h:130
volatile bool isTxBusy
Definition: lin_driver.h:131
volatile lin_event_id_t currentEventId
Definition: lin_driver.h:139
status_t LIN_LPUART_DRV_SendFrameDataBlocking(uint32_t instance, const uint8_t *txBuff, uint8_t txSize, uint32_t timeoutMSec)
Sends Frame data out through the LIN_LPUART module using blocking method. This function will calculat...
uint8_t currentPid
Definition: lin_driver.h:138
static void LIN_LPUART_DRV_CheckWakeupSignal(uint32_t instance)
volatile uint32_t timeoutCounter
Definition: lin_driver.h:141
static void LIN_LPUART_DRV_ProcessFrameHeader(uint32_t instance, uint8_t tmpByte)
lin_user_config_t * g_linUserconfigPtr[LPUART_INSTANCE_COUNT]
Table to save LIN user config structure pointers.
status_t LIN_LPUART_DRV_SendFrameData(uint32_t instance, const uint8_t *txBuff, uint8_t txSize)
Sends frame data out through the LIN_LPUART module using non-blocking method. This enables an a-sync ...
void(* lin_callback_t)(uint32_t instance, void *linState)
LIN Driver callback function type Implements : lin_callback_t_Class.
Definition: lin_driver.h:115
uint32_t baudRate
Definition: lin_driver.h:67
#define SLAVE
Definition: lin_driver.h:50
status_t LIN_LPUART_DRV_GoToSleepMode(uint32_t instance)
This function puts current node to sleep mode This function changes current node state to LIN_NODE_ST...
#define MASTER
Definition: lin_driver.h:51
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
static void LIN_LPUART_DRV_EvalTwoBitTimeLength(uint32_t instance, uint32_t twoBitTimeLength)
status_t LIN_LPUART_DRV_GetTransmitStatus(uint32_t instance, uint8_t *bytesRemaining)
Get status of an on-going non-blocking transmission While sending frame data using non-blocking metho...
semaphore_t rxCompleted
Definition: lin_driver.h:147
uint8_t cntByte
Definition: lin_driver.h:127
static uint32_t s_timeMeasure[LPUART_INSTANCE_COUNT]
#define TWO_BIT_DURATION_MAX_4800
static uint8_t s_countMeasure[LPUART_INSTANCE_COUNT]
status_t LIN_LPUART_DRV_DisableIRQ(uint32_t instance)
Disables LIN_LPUART hardware interrupts.
volatile lin_node_state_t currentNodeState
Definition: lin_driver.h:140
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
#define TWO_BIT_DURATION_MAX_14400
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t LIN_LPUART_DRV_AutoBaudCapture(uint32_t instance)
LIN_LPUART capture time interval to set baudrate automatically when enable autobaud feature...
static void LIN_LPUART_DRV_ProcessReceiveFrameData(uint32_t instance, uint8_t tmpByte)
void LIN_LPUART_DRV_SetTimeoutCounter(uint32_t instance, uint32_t timeoutValue)
Set Value for Timeout Counter that is used in LIN_LPUART_DRV_TimeoutService.
clock_names_t
Clock names.
#define TWO_BIT_DURATION_MIN_9600
const IRQn_Type g_linLpuartRxTxIrqId[LPUART_INSTANCE_COUNT]
Table to save LPUART IRQ enumeration numbers defined in the device header file.
volatile bool isRxBusy
Definition: lin_driver.h:132
uint32_t linSourceClockFreq
Definition: lin_driver.h:145
#define TWO_BIT_DURATION_MIN_14400
volatile uint8_t fallingEdgeInterruptCount
Definition: lin_driver.h:144
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
volatile uint8_t rxSize
Definition: lin_driver.h:129
uint8_t currentId
Definition: lin_driver.h:137
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
#define TWO_BIT_DURATION_MAX_19200
lin_timer_get_time_interval_t timerGetTimeIntervalCallback
Definition: lin_driver.h:70
uint8_t LIN_DRV_ProcessParity(uint8_t PID, uint8_t typeAction)
Makes or checks parity bits. If action is checking parity, the function returns ID value if parity bi...
Definition: lin_common.c:58
status_t LPUART_DRV_SetBaudRate(uint32_t instance, uint32_t desiredBaudRate)
Configures the LPUART baud rate.
#define TWO_BIT_DURATION_MIN_2400
volatile uint8_t txSize
Definition: lin_driver.h:128
static status_t LIN_LPUART_DRV_WaitComplete(uint32_t instance, uint32_t timeoutMSec)
static void LIN_LPUART_DRV_ProcessFrame(uint32_t instance, uint8_t tmpByte)
static void LIN_LPUART_DRV_ProcessBreakDetect(uint32_t instance)
uint8_t * rxBuff
Definition: lin_driver.h:126
volatile bool isRxBlocking
Definition: lin_driver.h:135
void LIN_LPUART_DRV_TimeoutService(uint32_t instance)
Callback function for Timer Interrupt Handler Users shall initialize a timer (for example FTM) in Out...
static uint8_t s_wakeupSignal[LPUART_INSTANCE_COUNT]
status_t LIN_LPUART_DRV_GetReceiveStatus(uint32_t instance, uint8_t *bytesRemaining)
Get status of an on-going non-blocking reception While receiving frame data using non-blocking method...
Runtime state of the LIN driver.
Definition: lin_driver.h:124
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
#define TWO_BIT_DURATION_MIN_4800
LIN hardware configuration structure Implements : lin_user_config_t_Class.
Definition: lin_driver.h:66
volatile bool isTxBlocking
Definition: lin_driver.h:134
static void LIN_LPUART_DRV_ProcessSendFrameData(uint32_t instance, uint8_t tmpByte)
#define AUTOBAUD_BREAK_TIME_MIN
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
const uint8_t * txBuff
Definition: lin_driver.h:125
static uint32_t s_previousTwoBitTimeLength[LPUART_INSTANCE_COUNT]
status_t LIN_LPUART_DRV_RecvFrmData(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize)
Receives frame data through the LIN_LPUART module using non-blocking method. This function returns im...
#define LPUART_INSTANCE_COUNT
Definition: S32K142.h:6615
#define TWO_BIT_DURATION_MAX_2400
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
lin_node_state_t LIN_LPUART_DRV_GetCurrentNodeState(uint32_t instance)
Get the current LIN node state.
status_t LIN_LPUART_DRV_GotoIdleState(uint32_t instance)
Puts current LIN node to Idle state This function changes current node state to LIN_NODE_STATE_IDLE.
status_t LIN_LPUART_DRV_AbortTransferData(uint32_t instance)
Aborts an on-going non-blocking transmission/reception. While performing a non-blocking transferring ...
#define TWO_BIT_DURATION_MIN_19200
status_t LIN_LPUART_DRV_MasterSendHeader(uint32_t instance, uint8_t id)
Sends frame header out through the LIN_LPUART module using a non-blocking method. This function sends...
isr_t g_linLpuartIsrs[LPUART_INSTANCE_COUNT]
Definition: lin_irq.c:86
#define TWO_BIT_DURATION_MAX_9600
static void LIN_LPUART_DRV_AutobaudTimerValEval(uint32_t instance, uint32_t twoBitTimeLength)
void LIN_LPUART_DRV_IRQHandler(uint32_t instance)
LIN_LPUART interrupt handler for RX_TX and Error interrupts.
lin_callback_t Callback
Definition: lin_driver.h:136
uint8_t LIN_DRV_MakeChecksumByte(const uint8_t *buffer, uint8_t sizeBuffer, uint8_t PID)
Makes the checksum byte for a frame.
Definition: lin_common.c:102
lin_state_t * g_linStatePtr[LPUART_INSTANCE_COUNT]
Table to save LPUART state structure pointers.
semaphore_t txCompleted
Definition: lin_driver.h:146
status_t LIN_LPUART_DRV_EnableIRQ(uint32_t instance)
Enables LIN_LPUART hardware interrupts.
status_t LIN_LPUART_DRV_Deinit(uint32_t instance)
Shuts down the LIN_LPUART by disabling interrupts and transmitter/receiver.
void(* isr_t)(void)
Interrupt handler type.
#define BIT_RATE_TOLERANCE_UNSYNC
#define CHECK_PARITY
Definition: lin_driver.h:53
status_t LIN_LPUART_DRV_RecvFrmDataBlocking(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize, uint32_t timeoutMSec)
Receives frame data through the LIN_LPUART module using blocking method. The function does not return...
#define MAKE_PARITY
Definition: lin_driver.h:52
#define LPUART_RX_TX_IRQS
Definition: S32K142.h:6636
lin_callback_t LIN_LPUART_DRV_InstallCallback(uint32_t instance, lin_callback_t function)
Installs callback function that is used for LIN_LPUART_DRV_IRQHandler.
volatile bool isBusBusy
Definition: lin_driver.h:133
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192
void INT_SYS_InstallHandler(IRQn_Type irqNumber, const isr_t newHandler, isr_t *const oldHandler)
Installs an interrupt handler routine for a given IRQ number.