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