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 = PCC_LPUART0_CLOCK;
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 = PCC_LPUART1_CLOCK;
154  break;
155  #endif
156  #if (LPUART_INSTANCE_COUNT > 2U)
157  case 2U:
158  linLpuartClkName = PCC_LPUART2_CLOCK;
159  break;
160  #endif
161  #if (LPUART_INSTANCE_COUNT > 3U)
162  case 3U:
163  linLpuartClkName = PCC_LPUART3_CLOCK;
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_HAL_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 baudrate to User's value */
217  if (LPUART_HAL_SetBaudRate(base, linCurrentState->linSourceClockFreq, linUserConfig->baudRate) != STATUS_SUCCESS)
218  {
219  retVal = STATUS_ERROR;
220  }
221  else
222  {
223  /* Set 8 bit counts per char */
225 
226  /* Set no parity mode */
228 
229  /* 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 */
237  }
238 
239  /* Set Break char detect length as 13 bits minimum */
241 
242  /* Enable RX complete interrupt */
244 
245  /* Enable frame error interrupt */
247 
248  /* Enable LIN break detect interrupt */
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_HAL_SetTransmitterCmd(base, true);
291  LPUART_HAL_SetReceiverCmd(base, true);
292  }
293  }
294  }
295 
296  return retVal;
297 }
298 
299 /*FUNCTION**********************************************************************
300  *
301  * Function Name : LIN_LPUART_DRV_Deinit
302  * Description : This function shuts down the LPUART by disabling interrupts and
303  * transmitter/receiver.
304  *
305  * Implements : LIN_LPUART_DRV_Deinit_Activity
306  *END**************************************************************************/
307 status_t LIN_LPUART_DRV_Deinit(uint32_t instance)
308 {
309  /* Assert parameters. */
310  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
311 
312  status_t retVal = STATUS_SUCCESS;
313 
314  /* Get base address of the LPUART instance. */
315  LPUART_Type * base = g_linLpuartBase[instance];
316 
317  /* Get the current LIN state of this LPUART instance. */
318  lin_state_t * linCurrentState = g_linStatePtr[instance];
319 
320  /* Check if current instance is already de-initialized or is gated.*/
321  DEV_ASSERT(linCurrentState != NULL);
322  DEV_ASSERT(linCurrentState->linSourceClockFreq > 0U);
323 
324  /* Wait until the data is completely shifted out of shift register */
326  {
327  /* Do nothing */
328  }
329 
330  /* Disable the LPUART transmitter and receiver */
331  LPUART_HAL_SetTransmitterCmd(base, false);
332  LPUART_HAL_SetReceiverCmd(base, false);
333 
334  /* Destroy TX and RX semaphores. */
335  if (OSIF_SemaDestroy(&linCurrentState->txCompleted) != STATUS_SUCCESS)
336  {
337  retVal = STATUS_ERROR;
338  }
339  else if (OSIF_SemaDestroy(&linCurrentState->rxCompleted) != STATUS_SUCCESS)
340  {
341  retVal = STATUS_ERROR;
342  }
343  else
344  {
345  /* Disable LPUART interrupts. */
347 #ifdef LPUART_ERR_IRQS
348  INT_SYS_DisableIRQ(g_linLpuartErrIrqId[instance]);
349 #endif
350 
351  /* Change node's current state to UNINIT */
352  linCurrentState->currentNodeState = LIN_NODE_STATE_UNINIT;
353 
354  /* Clear our saved pointer to the LIN state structure */
355  g_linStatePtr[instance] = NULL;
356  }
357 
358  return retVal;
359 }
360 
361 /*FUNCTION**********************************************************************
362  *
363  * Function Name : LIN_LPUART_DRV_InstallCallback
364  * Description : This function installs the callback function that is used for LIN_LPUART_DRV_IRQHandler.
365  * Pass in Null pointer as callback will uninstall.
366  *
367  * Implements : LIN_LPUART_DRV_InstallCallback_Activity
368  *END**************************************************************************/
370  lin_callback_t function)
371 {
372  /* Assert parameters. */
373  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
374 
375  /* Get the current LIN state of this LPUART instance. */
376  lin_state_t * linCurrentState = g_linStatePtr[instance];
377 
378  /* Get the current callback function. */
379  lin_callback_t currentCallback = linCurrentState->Callback;
380 
381  /* Install new callback function. */
382  linCurrentState->Callback = function;
383 
384  return currentCallback;
385 }
386 
387 /*FUNCTION**********************************************************************
388  *
389  * Function Name : LIN_LPUART_DRV_SendFrameDataBlocking
390  * Description : This function sends data out through the LPUART module using
391  * blocking method. This function checks if txSize is in range from 1 to 8.
392  * If not, it will return STATUS_ERROR. This function also returns STATUS_ERROR
393  * if node's current state is in SLEEP mode. This function checks if the
394  * isBusBusy is false, if not it will return STATUS_BUSY. The function does not
395  * return until the transmission is complete. If the transmission is successful,
396  * it will return STATUS_SUCCESS. If not, it will return STATUS_TIMEOUT.
397  *
398  * Implements : LIN_LPUART_DRV_SendFrameDataBlocking_Activity
399  *END**************************************************************************/
401  const uint8_t * txBuff,
402  uint8_t txSize,
403  uint32_t timeoutMSec)
404 {
405  /* Assert parameters. */
406  DEV_ASSERT(txBuff != NULL);
407  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
408 
409  /* Get base address of the LPUART instance. */
410  LPUART_Type * base = g_linLpuartBase[instance];
411 
412  /* Get the current LIN state of this LPUART instance. */
413  lin_state_t * linCurrentState = g_linStatePtr[instance];
414  status_t retVal = STATUS_SUCCESS;
415 
416  /* Check whether current mode is sleep mode */
417  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
418 
419  /* Check if txSize > 8 or equal to 0 or node's current state
420  * is in SLEEP mode then return STATUS_ERROR */
421  if ((8U < txSize) || (0U == txSize) || checkSleepMode)
422  {
423  retVal = STATUS_ERROR;
424  }
425  else
426  {
427  /* Check if the LIN Bus is busy */
428  if (linCurrentState->isBusBusy)
429  {
430  retVal = STATUS_BUSY;
431  }
432  else
433  {
434  /* Make the checksum byte. */
435  linCurrentState->checkSum = LIN_DRV_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
436 
437  /* Update the LIN state structure. */
438  linCurrentState->txBuff = txBuff;
439  /* Add a place for checksum byte */
440  linCurrentState->txSize = (uint8_t)(txSize + 1U);
441  linCurrentState->cntByte = 0U;
442  linCurrentState->currentEventId = LIN_NO_EVENT;
443  linCurrentState->isBusBusy = true;
444  linCurrentState->isTxBusy = true;
445  linCurrentState->isTxBlocking = true;
446 
447  /* Set Break char detect length as 10 bits minimum */
449 
450  /* Set node's current state to SEND_DATA */
451  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
452 
453  /* Start sending data */
454  LPUART_HAL_Putchar(base, *linCurrentState->txBuff);
455 
456  /* Wait until the transmission is complete. */
457  retVal = LIN_LPUART_DRV_WaitComplete(instance, timeoutMSec);
458 
459  /* Clear Tx Blocking flag */
460  linCurrentState->isTxBlocking = false;
461  /* Update Bus Busy flag. */
462  linCurrentState->isBusBusy = false;
463  linCurrentState->isTxBusy = false;
464 
465  /* Change node's current state to IDLE */
466  (void)LIN_LPUART_DRV_GotoIdleState(instance);
467  }
468  }
469 
470  return retVal;
471 }
472 
473 /*FUNCTION**********************************************************************
474  *
475  * Function Name : LIN_LPUART_DRV_SendFrameData
476  * Description : This function sends data out through the LPUART module using
477  * non-blocking method. This function will calculate the checksum byte and send
478  * it with the frame data. The function will return immediately after calling
479  * this function. If txSize is equal to 0 or greater than 8 or node's current
480  * state is in SLEEP mode then the function will return STATUS_ERROR. If
481  * isBusBusy is currently true then the function will return STATUS_BUSY.
482  *
483  * Implements : LIN_LPUART_DRV_SendFrameData_Activity
484  *END**************************************************************************/
486  const uint8_t * txBuff,
487  uint8_t txSize)
488 {
489  /* Assert parameters. */
490  DEV_ASSERT(txBuff != NULL);
491  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
492 
493  status_t retVal = STATUS_SUCCESS;
494 
495  /* Get base address of the LPUART instance. */
496  LPUART_Type * base = g_linLpuartBase[instance];
497 
498  /* Get the current LIN state of this LPUART instance. */
499  lin_state_t * linCurrentState = g_linStatePtr[instance];
500 
501  /* Check whether current mode is sleep mode */
502  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
503 
504  /* Check if txSize > 8 or equal to 0 or node's current state
505  * is in SLEEP mode then return STATUS_ERROR */
506  if ((8U < txSize) || (0U == txSize) || checkSleepMode)
507  {
508  retVal = STATUS_ERROR;
509  }
510  else
511  {
512  /* Check if the LIN Bus is busy */
513  if (linCurrentState->isBusBusy)
514  {
515  retVal = STATUS_BUSY;
516  }
517  else
518  {
519  /* Make the checksum byte. */
520  linCurrentState->checkSum = LIN_DRV_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
521 
522  /* Update the LIN state structure. */
523  linCurrentState->txBuff = txBuff;
524  /* Add a place for checksum byte */
525  linCurrentState->txSize = (uint8_t)(txSize + 1U);
526  linCurrentState->cntByte = 0U;
527  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
528  linCurrentState->currentEventId = LIN_NO_EVENT;
529  linCurrentState->isBusBusy = true;
530  linCurrentState->isTxBusy = true;
531 
532  /* Set Break char detect length as 10 bits minimum */
534 
535  /* Start sending data */
536  LPUART_HAL_Putchar(base, *linCurrentState->txBuff);
537  }
538  }
539 
540  return retVal;
541 }
542 
543 /*FUNCTION**********************************************************************
544  *
545  * Function Name : LIN_LPUART_DRV_GetTransmitStatus
546  * Description : This function returns whether the previous LPUART transmit has
547  * finished. When performing non-blocking transmit, the user can call this
548  * function to ascertain the state of the current transmission:
549  * in progress (or busy that is STATUS_BUSY) or timeout (if timeout has occurred that is
550  * STATUS_TIMEOUT) or complete (success that is STATUS_SUCCESS).
551  * In addition, if the transmission is still in progress, the user can obtain the number
552  * of bytes that still needed to transmit.
553  *
554  * Implements : LIN_LPUART_DRV_GetTransmitStatus_Activity
555  *END**************************************************************************/
557  uint8_t * bytesRemaining)
558 {
559  /* Assert parameters. */
560  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
561 
562  status_t retVal = STATUS_SUCCESS;
563 
564  /* Get the current LIN state of this LPUART instance. */
565  const lin_state_t * linCurrentState = g_linStatePtr[instance];
566 
567  /* Get the number of bytes that is still needed to transmit */
568  *bytesRemaining = (uint8_t)(linCurrentState->txSize - linCurrentState->cntByte);
569 
570  /* Return status of the on-going transmission */
571  if ((linCurrentState->currentEventId == LIN_NO_EVENT) && (*bytesRemaining != 0U))
572  {
573  if (linCurrentState->timeoutCounterFlag == false)
574  {
575  retVal = STATUS_BUSY;
576  }
577  else
578  {
579  retVal = STATUS_TIMEOUT;
580  }
581  }
582 
583  return retVal;
584 }
585 
586 /*FUNCTION**********************************************************************
587  *
588  * Function Name : LIN_LPUART_DRV_RecvFrmDataBlocking
589  * Description : This function receives data from LPUART module using blocking
590  * method, the function does not return until the receive is complete. The interrupt
591  * handler LIN_LPUART_DRV_IRQHandler will check the checksum byte. If the checksum
592  * is correct, it will receive the frame data. If the checksum is incorrect, this
593  * function will return STATUS_TIMEOUT and data in rxBuff might be wrong. This function
594  * also check if rxSize is in range from 1 to 8. If not, it will return STATUS_ERROR.
595  * This function also returns STATUS_ERROR if node's current state is in SLEEP mode.
596  * This function checks if the isBusBusy is false, if not it will return
597  * STATUS_BUSY.
598  *
599  * Implements : LIN_LPUART_DRV_RecvFrmDataBlocking_Activity
600  *END**************************************************************************/
602  uint8_t * rxBuff,
603  uint8_t rxSize,
604  uint32_t timeoutMSec)
605 {
606  /* Assert parameters. */
607  DEV_ASSERT(rxBuff != NULL);
608  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
609 
610  /* Get base address of the LPUART instance. */
611  LPUART_Type * base = g_linLpuartBase[instance];
612 
613  /* Get the current LIN state of this LPUART instance. */
614  lin_state_t * linCurrentState = g_linStatePtr[instance];
615  status_t retVal = STATUS_SUCCESS;
616 
617  /* Check whether current mode is sleep mode */
618  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
619 
620  /* Check if rxSize > 8 or equal to 0 or node's current state
621  * is in SLEEP mode then return STATUS_ERROR */
622  if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
623  {
624  retVal = STATUS_ERROR;
625  }
626  else
627  {
628  /* Check if the LIN Bus is busy */
629  if (linCurrentState->isBusBusy)
630  {
631  retVal = STATUS_BUSY;
632  }
633  else
634  {
635  /* Update the LIN state structure. */
636  linCurrentState->rxBuff = rxBuff;
637  /* Add a place for checksum byte */
638  linCurrentState->rxSize = (uint8_t)(rxSize + 1U);
639  linCurrentState->cntByte = 0U;
640 
641  /* Start receiving data */
642  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
643  linCurrentState->currentEventId = LIN_NO_EVENT;
644  linCurrentState->isBusBusy = true;
645  linCurrentState->isRxBusy = true;
646  linCurrentState->isRxBlocking = true;
647 
648  /* Set Break char detect length as 10 bits minimum */
650 
651  /* Wait until the reception is complete. */
652  retVal = LIN_LPUART_DRV_WaitComplete(instance, timeoutMSec);
653 
654  /* In case of receiving a go to sleep request, after callback, node is in SLEEP MODE */
655  /* In this case, node is in SLEEP MODE state */
656  if (linCurrentState->currentNodeState != LIN_NODE_STATE_SLEEP_MODE)
657  {
658  /* Update node's current state to IDLE. */
659  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
660  }
661 
662  /* Clear Rx Blocking flag. */
663  linCurrentState->isRxBlocking = false;
664 
665  /* Update Bus Busy flag. */
666  linCurrentState->isBusBusy = false;
667  linCurrentState->isRxBusy = false;
668  }
669  }
670 
671  return retVal;
672 }
673 
674 /*FUNCTION**********************************************************************
675  *
676  * Function Name : LIN_LPUART_DRV_RecvFrmData
677  * Description : This function receives data from LPUART module using
678  * non-blocking method. This function returns immediately after initiating the
679  * receive function. The application has to get the receive status to see when
680  * the receive is complete. In other words, after calling non-blocking get
681  * function, the application must get the receive status to check if receive
682  * is completed or not. The interrupt handler LIN_LPUART_DRV_IRQHandler will check
683  * the checksum byte. If the checksum is correct, it will receive the frame data.
684  * If the checksum is incorrect, this function will return STATUS_TIMEOUT and data in
685  * rxBuff might be wrong. This function also check if rxSize is in range from 1 to 8.
686  * If not, it will return STATUS_ERROR. This function also returns STATUS_ERROR if
687  * node's current state is in SLEEP mode. This function checks if the
688  * isBusBusy is false, if not it will return STATUS_BUSY.
689  *
690  * Implements : LIN_LPUART_DRV_RecvFrmData_Activity
691  *END**************************************************************************/
693  uint8_t * rxBuff,
694  uint8_t rxSize)
695 {
696  /* Assert parameters. */
697  DEV_ASSERT(rxBuff != NULL);
698  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
699 
700  status_t retVal = STATUS_SUCCESS;
701 
702  /* Get base address of the LPUART instance. */
703  LPUART_Type * base = g_linLpuartBase[instance];
704 
705  /* Get the current LIN state of this LPUART instance. */
706  lin_state_t * linCurrentState = g_linStatePtr[instance];
707 
708  /* Check whether current mode is sleep mode */
709  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
710 
711  /* Check if rxSize > 8 or equal to 0 or node's current state
712  * is in SLEEP mode then return STATUS_ERROR */
713  if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
714  {
715  retVal = STATUS_ERROR;
716  }
717  else
718  {
719  /* Check if the LIN Bus is busy */
720  if (linCurrentState->isBusBusy)
721  {
722  retVal = STATUS_BUSY;
723  }
724  else
725  {
726  /* Update the LIN state structure. */
727  linCurrentState->rxBuff = rxBuff;
728  /* Add a place for checksum byte */
729  linCurrentState->rxSize = (uint8_t)(rxSize + 1U);
730  linCurrentState->cntByte = 0U;
731 
732  /* Start receiving data */
733  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
734  linCurrentState->currentEventId = LIN_NO_EVENT;
735  linCurrentState->isBusBusy = true;
736  linCurrentState->isRxBusy = true;
737  linCurrentState->isRxBlocking = false;
738 
739  /* Set Break char detect length as 10 bits minimum */
741  }
742  }
743 
744  return retVal;
745 }
746 
747 /*FUNCTION**********************************************************************
748  *
749  * Function Name : LPUART_DRV_AbortTransferData
750  * Description : Aborts an on-going non-blocking transmission/reception.
751  * While performing a non-blocking transferring data, users can call this
752  * function to terminate immediately the transferring.
753  *
754  * Implements : LIN_LPUART_DRV_AbortTransferData_Activity
755  *END**************************************************************************/
757 {
758  /* Assert parameters. */
759  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
760 
761  status_t retVal = STATUS_SUCCESS;
762 
763  /* Get the current LIN state of this LPUART instance. */
764  lin_state_t * linCurrentState = g_linStatePtr[instance];
765 
766  /* Change node's current state to IDLE */
767  (void)LIN_LPUART_DRV_GotoIdleState(instance);
768 
769  /* Clear LIN Bus Busy flag */
770  linCurrentState->isTxBusy = false;
771  linCurrentState->isRxBusy = false;
772  linCurrentState->isBusBusy = false;
773 
774  return retVal;
775 }
776 
777 /*FUNCTION**********************************************************************
778  *
779  * Function Name : LIN_LPUART_DRV_GetReceiveStatus
780  * Description : This function returns whether the previous LPUART reception is
781  * complete. When performing a non-blocking receive, the user can call this
782  * function to ascertain the state of the current receive progress: in progress
783  * or complete. In addition, if the reception is still in progress, the user can
784  * obtain the number of words that is still needed to receive.
785  *
786  * Implements : LIN_LPUART_DRV_GetReceiveStatus_Activity
787  *END**************************************************************************/
789  uint8_t * bytesRemaining)
790 {
791  /* Assert parameters. */
792  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
793 
794  status_t retVal = STATUS_SUCCESS;
795 
796  /* Get the current LIN state of this LPUART instance. */
797  const lin_state_t * linCurrentState = g_linStatePtr[instance];
798 
799  /* Get the number of bytes that is still needed to receive */
800  *bytesRemaining = (uint8_t)(linCurrentState->rxSize - linCurrentState->cntByte);
801 
802  /* Return status of the on-going reception */
803  if ((linCurrentState->currentEventId == LIN_NO_EVENT) && (*bytesRemaining != 0U))
804  {
805  if (linCurrentState->timeoutCounterFlag == false)
806  {
807  retVal = STATUS_BUSY;
808  }
809  else
810  {
811  retVal = STATUS_TIMEOUT;
812  }
813  }
814 
815  return retVal;
816 }
817 
818 /*FUNCTION**********************************************************************
819  *
820  * Function Name : LIN_LPUART_DRV_GoToSleepMode
821  * Description : This function puts current LIN node to sleep mode.
822  * This function changes current node state to LIN_NODE_STATE_SLEEP_MODE.
823  *
824  * Implements : LIN_LPUART_DRV_GoToSleepMode_Activity
825  *END**************************************************************************/
827 {
828  /* Assert parameters. */
829  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
830 
831  /* Get base address of the LPUART instance. */
832  LPUART_Type * base = g_linLpuartBase[instance];
833 
834  /* Get the current LIN state of this LPUART instance. */
835  lin_state_t * linCurrentState = g_linStatePtr[instance];
836 
837  /* Update node's current state to SLEEP_MODE. */
838  linCurrentState->currentNodeState = LIN_NODE_STATE_SLEEP_MODE;
839 
840  /* Set Receive data not inverted */
841  LPUART_HAL_SetRxDataPolarity(base, false);
842 
843  /* Disable RX complete interrupt */
845 
846  /* Enable RX Input Active Edge interrupt */
848 
849  /* Disable frame error interrupt */
851 
852  /* Disable LIN break detect interrupt */
854 
855  return STATUS_SUCCESS;
856 }
857 
858 /*FUNCTION**********************************************************************
859  *
860  * Function Name : LIN_LPUART_DRV_SendWakeupSignal
861  * Description : This function sends a wakeup signal through the LPUART interface.
862  *
863  * Implements : LIN_LPUART_DRV_SendWakeupSignal_Activity
864  *END**************************************************************************/
866 {
867  /* DEV_ASSERT parameters. */
868  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
869 
870  /* Get base address of the LPUART instance. */
871  LPUART_Type * base = g_linLpuartBase[instance];
872  /* Get the current LIN state of this LPUART instance. */
873  const lin_state_t * linCurrentState = g_linStatePtr[instance];
874  status_t retVal = STATUS_SUCCESS;
875 
876  /* Check if bus is not busy */
877  if (linCurrentState->isBusBusy == false)
878  {
879  /* Send a wakeup signal */
880  LPUART_HAL_Putchar(base, s_wakeupSignal[instance]);
881  }
882  else
883  {
884  retVal = STATUS_BUSY;
885  }
886 
887  return retVal;
888 }
889 
890 /*FUNCTION**********************************************************************
891  *
892  * Function Name : LIN_LPUART_DRV_GetCurrentNodeState
893  * Description : This function gets the current LIN node state.
894  *
895  * Implements : LIN_LPUART_DRV_GetCurrentNodeState_Activity
896  *END**************************************************************************/
898 {
899  /* Assert parameters. */
900  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
901 
903  /* Get the current LIN state of this LPUART instance. */
904  const lin_state_t * linCurrentState = g_linStatePtr[instance];
905 
906  if (linCurrentState != NULL)
907  {
908  retVal = linCurrentState->currentNodeState;
909  }
910 
911  /* Return LIN node's current state */
912  return retVal;
913 }
914 
915 /*FUNCTION**********************************************************************
916  *
917  * Function Name : LIN_LPUART_DRV_TimeoutService
918  * Description : This is callback function for Timer Interrupt Handler.
919  * Users shall initialize a timer (for example FTM) in Output compare mode
920  * with period of about 500 micro seconds. In timer IRQ handler, call this function.
921  *
922  * Implements : LIN_LPUART_DRV_TimeoutService_Activity
923  *END**************************************************************************/
924 void LIN_LPUART_DRV_TimeoutService(uint32_t instance)
925 {
926  /* Assert parameters. */
927  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
928 
929  /* Get the current LIN state of this LPUART instance. */
930  lin_state_t * linCurrentState = g_linStatePtr[instance];
931 
932  /* Get LIN node's current state */
933  lin_node_state_t state = linCurrentState->currentNodeState;
934 
935  switch (state)
936  {
937  /* If the node is SENDING DATA */
939  /* Check if timeout Counter is 0 */
940  if (linCurrentState->timeoutCounter == 0U)
941  {
942  /* Set timeout Counter flag */
943  linCurrentState->timeoutCounterFlag = true;
944 
945  if (linCurrentState->isTxBlocking == false)
946  {
947  /* Callback to handle timeout Counter flag */
948  if (linCurrentState->Callback != NULL)
949  {
950  linCurrentState->Callback(instance, linCurrentState);
951  }
952 
953  /* Clear Bus busy flag */
954  linCurrentState->isBusBusy = false;
955  linCurrentState->isTxBusy = false;
956 
957  /* Change the node's current state to IDLE */
958  (void)LIN_LPUART_DRV_GotoIdleState(instance);
959  }
960  }
961  else /* If timeout Counter is not 0, then decrease timeout Counter by one */
962  {
963  linCurrentState->timeoutCounter--;
964  }
965 
966  break;
967  /* If the node is RECEIVING DATA */
969  /* Check if timeout Counter is 0 */
970  if (linCurrentState->timeoutCounter == 0U)
971  {
972  /* Set timeout Counter flag */
973  linCurrentState->timeoutCounterFlag = true;
974 
975  /* Check if the reception is non-blocking */
976  if (linCurrentState->isRxBlocking == false)
977  {
978  /* Callback to handle timeout Counter flag */
979  if (linCurrentState->Callback != NULL)
980  {
981  linCurrentState->Callback(instance, linCurrentState);
982  }
983 
984  /* Clear Bus busy flag */
985  linCurrentState->isBusBusy = false;
986  linCurrentState->isRxBusy = false;
987  /* Change the node's current state to IDLE */
988  (void)LIN_LPUART_DRV_GotoIdleState(instance);
989  }
990  }
991  /* If timeout Counter is not 0, then decrease timeout Counter by one */
992  else
993  {
994  linCurrentState->timeoutCounter--;
995  }
996 
997  break;
998  default:
999  /* The node state is not SENDING nor RECEIVING data */
1000  break;
1001  }
1002 }
1003 
1004 /*FUNCTION**********************************************************************
1005  *
1006  * Function Name : LIN_LPUART_DRV_SetTimeoutCounter
1007  * Description : This function sets value for timeout counter that is used in
1008  * LIN_LPUART_DRV_TimeoutService
1009  *
1010  * Implements : LIN_LPUART_DRV_SetTimeoutCounter_Activity
1011  *END**************************************************************************/
1012 void LIN_LPUART_DRV_SetTimeoutCounter(uint32_t instance,
1013  uint32_t timeoutValue)
1014 {
1015  /* Assert parameters. */
1016  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1017 
1018  /* Get the current LIN state of this LPUART instance. */
1019  lin_state_t * linCurrentState = g_linStatePtr[instance];
1020 
1021  /* Clear Timeout Counter Flag */
1022  linCurrentState->timeoutCounterFlag = false;
1023 
1024  /* Set new value for Timeout Counter */
1025  linCurrentState->timeoutCounter = timeoutValue;
1026 }
1027 
1028 /*FUNCTION**********************************************************************
1029  *
1030  * Function Name : LIN_LPUART_DRV_MasterSendHeader
1031  * Description : This function sends frame header out through the LPUART module
1032  * using a non-blocking method. Non-blocking means that the function returns
1033  * immediately. This function sends LIN Break field, sync field then the ID with
1034  * correct parity. This function checks if the interface is Master, if not, it will
1035  * return STATUS_ERROR.This function checks if id is in range from 0 to 0x3F, if not
1036  * it will return STATUS_ERROR. This function also check node's current state is in
1037  * SLEEP mode then the function will return STATUS_ERROR. And check if isBusBusy is
1038  * currently true then the function will return STATUS_BUSY.
1039  *
1040  * Implements : LIN_LPUART_DRV_MasterSendHeader_Activity
1041  *END**************************************************************************/
1043  uint8_t id)
1044 {
1045  /* Assert parameters. */
1046  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1047 
1048  status_t retVal = STATUS_SUCCESS;
1049 
1050  /* Get the current LIN user config structure of this LPUART instance. */
1051  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1052 
1053  /* Get base address of the LPUART instance. */
1054  LPUART_Type * base = g_linLpuartBase[instance];
1055 
1056  /* Get the current LIN state of this LPUART instance. */
1057  lin_state_t * linCurrentState = g_linStatePtr[instance];
1058 
1059  /* Check whether current mode is sleep mode */
1060  bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1061 
1062  /* Check if the current node is slave or id is invalid or node's current
1063  * state is in SLEEP state */
1064  if ((linUserConfig->nodeFunction == (bool)SLAVE) || (0x3FU < id) || checkSleepMode)
1065  {
1066  retVal = STATUS_ERROR;
1067  }
1068  else
1069  {
1070  /* Check if the LIN bus is busy */
1071  if (linCurrentState->isBusBusy)
1072  {
1073  retVal = STATUS_BUSY;
1074  }
1075  else
1076  {
1077  linCurrentState->currentId = id;
1078 
1079  /* Make parity for the current ID */
1080  linCurrentState->currentPid = LIN_DRV_ProcessParity(id, MAKE_PARITY);
1081 
1082  /* Set LIN current state to sending Break field */
1084  linCurrentState->currentEventId = LIN_NO_EVENT;
1085  linCurrentState->isBusBusy = true;
1086 
1087  /* Set Break char detect length as 13 bits minimum */
1090 
1091  /* Send break char by using queue mode */
1093  }
1094  }
1095 
1096  return retVal;
1097 }
1098 
1099 /*FUNCTION**********************************************************************
1100  *
1101  * Function Name : LIN_LPUART_DRV_EnableIRQ
1102  * Description : This function enables LPUART hardware interrupts.
1103  *
1104  * Implements : LIN_LPUART_DRV_EnableIRQ_Activity
1105  *END**************************************************************************/
1107 {
1108  /* Assert parameters. */
1109  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1110 
1111  status_t retVal = STATUS_SUCCESS;
1112 
1113  /* Get base address of the LPUART instance. */
1114  LPUART_Type * base = g_linLpuartBase[instance];
1115 
1116  /* Get the current LIN state of this LPUART instance. */
1117  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1118 
1119  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1120  {
1121  /* Enable RX Input Active Edge interrupt */
1123  }
1124  else
1125  {
1126  /* Enable RX complete interrupt */
1128 
1129  /* Enable frame error interrupt */
1131 
1132  /* Enable LIN break detect interrupt */
1134  }
1135 
1136  /* Enable LPUART interrupts. */
1138 #ifdef LPUART_ERR_IRQS
1139  INT_SYS_EnableIRQ(g_linLpuartErrIrqId[instance]);
1140 #endif
1141 
1142  return retVal;
1143 }
1144 
1145 /*FUNCTION**********************************************************************
1146  *
1147  * Function Name : LIN_LPUART_DRV_DisableIRQ
1148  * Description : This function disables LPUART hardware interrupts.
1149  *
1150  * Implements : LIN_LPUART_DRV_DisableIRQ_Activity
1151  *END**************************************************************************/
1153 {
1154  /* Assert parameters. */
1155  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1156 
1157  status_t retVal = STATUS_SUCCESS;
1158 
1159  /* Get base address of the LPUART instance. */
1160  LPUART_Type * base = g_linLpuartBase[instance];
1161 
1162  /* Get the current LIN state of this LPUART instance. */
1163  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1164 
1165  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1166  {
1167  /* Disable RX Input Active Edge interrupt */
1169  }
1170  else
1171  {
1172  /* Disable RX complete interrupt */
1174 
1175  /* Disable frame error interrupt */
1177 
1178  /* Disable frame error interrupt */
1180  }
1181 
1182  /* Disable LPUART interrupts. */
1184 #ifdef LPUART_ERR_IRQS
1185  INT_SYS_DisableIRQ(g_linLpuartErrIrqId[instance]);
1186 #endif
1187 
1188  return retVal;
1189 }
1190 
1191 /*FUNCTION**********************************************************************
1192  *
1193  * Function Name : LIN_LPUART_DRV_GotoIdleState
1194  * Description : This function puts current node to Idle state.
1195  *
1196  * Implements : LIN_LPUART_DRV_GotoIdleState_Activity
1197  *END**************************************************************************/
1199 {
1200  /* Get base address of the LPUART instance. */
1201  LPUART_Type * base = g_linLpuartBase[instance];
1202 
1203  /* Get the current LIN state of this LPUART instance. */
1204  lin_state_t * linCurrentState = g_linStatePtr[instance];
1205 
1206  linCurrentState->currentEventId = LIN_NO_EVENT;
1207 
1208  /* Set Break char detect length as 13 bits minimum */
1210 
1211  /* Set Receive data not inverted */
1212  LPUART_HAL_SetRxDataPolarity(base, false);
1213 
1214  /* Enable RX complete interrupt */
1216 
1217  /* Disable RXEDG interrupt */
1219 
1220  /* Enable frame error interrupt */
1222 
1223  /* Enable LIN break detect interrupt */
1225 
1226  /* Change node's current state to IDLE */
1227  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1228 
1229  return STATUS_SUCCESS;
1230 }
1231 
1232 /*FUNCTION**********************************************************************
1233  *
1234  * Function Name : LIN_LPUART_DRV_WaitComplete
1235  * Description : This function waits until transmission/reception is complete and
1236  * returns status of the transaction.
1237  *
1238  * Implements : LIN_LPUART_DRV_WaitComplete_Activity
1239  *END**************************************************************************/
1240 static status_t LIN_LPUART_DRV_WaitComplete(uint32_t instance,
1241  uint32_t timeoutMSec)
1242 {
1243  /* Get the current LIN state of this LPUART instance. */
1244  lin_state_t * linCurrentState = g_linStatePtr[instance];
1245  status_t retVal = STATUS_SUCCESS;
1246 
1247  if (linCurrentState->isTxBusy == true)
1248  {
1249  if (OSIF_SemaWait(&linCurrentState->txCompleted, timeoutMSec) == STATUS_TIMEOUT)
1250  {
1251  retVal = STATUS_TIMEOUT;
1252  }
1253  }
1254 
1255  if (linCurrentState->isRxBusy == true)
1256  {
1257  if (OSIF_SemaWait(&linCurrentState->rxCompleted, timeoutMSec) == STATUS_TIMEOUT)
1258  {
1259  retVal = STATUS_TIMEOUT;
1260  }
1261  }
1262 
1263  return retVal;
1264 }
1265 
1266 /*FUNCTION**********************************************************************
1267  *
1268  * Function Name : LIN_LPUART_DRV_IRQHandler
1269  * Description : Interrupt handler for LPUART.
1270  * This handler uses the buffers stored in the lin_state_t struct to transfer
1271  * data. This is not a public API as it is called by IRQ whenever an interrupt
1272  * occurs.
1273  *
1274  * Implements : LIN_LPUART_DRV_IRQHandler_Activity
1275  *END**************************************************************************/
1276 void LIN_LPUART_DRV_IRQHandler(uint32_t instance)
1277 {
1278  /* Assert parameters. */
1279  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1280 
1281  uint8_t tmpByte = 0U;
1282 
1283  /* Get base address of the LPUART instance. */
1284  LPUART_Type * base = g_linLpuartBase[instance];
1285 
1286  /* Get the current LIN state of this LPUART instance. */
1287  lin_state_t * linCurrentState = g_linStatePtr[instance];
1288 
1289  /* Check RX Input Active Edge interrupt enable */
1290  bool activeEdgeIntState = LPUART_HAL_GetIntMode(base, LPUART_INT_RX_ACTIVE_EDGE);
1291 
1292  /* If LIN break character has been detected. */
1294  {
1296  }
1297  else
1298  {
1299  /* If LPUART_RX Pin Active Edge has been detected. */
1300  if (LPUART_HAL_GetStatusFlag(base, LPUART_RX_ACTIVE_EDGE_DETECT) && activeEdgeIntState)
1301  {
1302  /* Clear LPUART_RX Pin Active Edge Interrupt Flag. */
1304 
1305  /* Check if a wakeup signal has been received */
1307  }
1308  else
1309  {
1310  /* If Framing Error has been detected */
1312  {
1313  /* Clear Framing Error Interrupt Flag */
1315 
1316  /* Read dummy to clear LPUART_RX_DATA_REG_FULL flag */
1317  LPUART_HAL_Getchar(base, &tmpByte);
1318 
1319  /* Set current event id to LIN_FRAME_ERROR */
1320  linCurrentState->currentEventId = LIN_FRAME_ERROR;
1321 
1322  /* Check if LIN current node state is LIN_NODE_STATE_SEND_DATA */
1323  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_DATA)
1324  {
1325  /* Callback function to handle Framing Error Event */
1326  if (linCurrentState->Callback != NULL)
1327  {
1328  linCurrentState->Callback(instance, linCurrentState);
1329  }
1330  }
1331  else
1332  {
1333  /* Check if LIN current node state is LIN_NODE_STATE_RECV_DATA */
1334  if (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_DATA)
1335  {
1336  /* Callback function to handle Framing Error Event */
1337  if (linCurrentState->Callback != NULL)
1338  {
1339  linCurrentState->Callback(instance, linCurrentState);
1340  }
1341  }
1342  }
1343 
1344  /* Clear Bus busy Flag */
1345  linCurrentState->isBusBusy = false;
1346  /* Change node's state to IDLE */
1347  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1348  }
1349  else
1350  {
1352  {
1353  /* Get data from Data Register & Clear LPUART_RX_DATA_REG_FULL flag */
1354  LPUART_HAL_Getchar(base, &tmpByte);
1355 
1356  /* Process data in Data Register while receive, send data */
1357  LIN_LPUART_DRV_ProcessFrame(instance, tmpByte);
1358  }
1359  } /* End else: if (LPUART_HAL_GetStatusFlag(base, LPUART_FRAME_ERR) == 0) */
1360  } /* End else: if (LPUART_HAL_GetStatusFlag(base, LPUART_RX_ACTIVE_EDGE_DETECT) == 0) */
1361  } /* End else: if (LPUART_HAL_GetStatusFlag(base, LPUART_LIN_BREAK_DETECT) == 0) */
1362 
1363  /* Get status RX overrun flag */
1365  {
1366  /* Clear overrun flag */
1368  }
1369 } /* End void LIN_LPUART_DRV_IRQHandler(uint32_t instance) */
1370 
1371 /*FUNCTION**********************************************************************
1372  *
1373  * Function Name : LIN_LPUART_DRV_ProcessBreakDetect
1374  * Description : This function process break detect for LIN communication.
1375  *
1376  * Implements : LIN_LPUART_DRV_ProcessBreakDetect_Activity
1377  *END**************************************************************************/
1378 static void LIN_LPUART_DRV_ProcessBreakDetect(uint32_t instance)
1379 {
1380  /* Get the current LIN user configure structure of this LPUART instance. */
1381  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1382 
1383  /* Get base address of the LPUART instance. */
1384  LPUART_Type * base = g_linLpuartBase[instance];
1385 
1386  /* Get the current LIN state of this LPUART instance. */
1387  lin_state_t * linCurrentState = g_linStatePtr[instance];
1388 
1389  /* Clear LIN Break Detect Interrupt Flag */
1391 
1392  /* Check if the current node is in SLEEP MODE */
1393  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1394  {
1395  /* Change the node's current state to IDLE */
1396  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1397  }
1398  else
1399  {
1400  /* Set Break char detect length as 10 bits minimum */
1402  /* Disable LIN Break Detect Interrupt */
1404 
1405  /* Set flag LIN bus busy */
1406  linCurrentState->isBusBusy = true;
1407 
1408  /* Check if the current node is MASTER */
1409  if (linUserConfig->nodeFunction == (bool)MASTER)
1410  {
1411  /* Check if LIN current node state is LIN_NODE_STATE_SEND_BREAK_FIELD */
1412  if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_BREAK_FIELD)
1413  {
1414  /* Change the node's current state to SENDING PID to send PID after send SYNC */
1415  linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_PID;
1416  /* Send Sync Field 0x55 */
1417  LPUART_HAL_Putchar(base, 0x55);
1418  }
1419  }
1420  /* If the current node is SLAVE */
1421  else
1422  {
1423  /* Change the node's current state to RECEIVED BREAK FIELD */
1424  linCurrentState->currentEventId = LIN_RECV_BREAK_FIELD_OK;
1425 
1426  /* Callback function */
1427  if (linCurrentState->Callback != NULL)
1428  {
1429  linCurrentState->Callback(instance, linCurrentState);
1430  }
1431 
1432  /* Change the node's current state to RECEIVING SYNC FIELD */
1433  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_SYNC;
1434  }
1435  }
1436 }
1437 
1438 /*FUNCTION**********************************************************************
1439  *
1440  * Function Name : LIN_LPUART_DRV_CheckWakeupSignal
1441  * Description : This function check if a dominant signal received is a wakeup
1442  * signal.
1443  *
1444  * Implements : LIN_LPUART_DRV_CheckWakeupSignal_Activity
1445  *END**************************************************************************/
1446 static void LIN_LPUART_DRV_CheckWakeupSignal(uint32_t instance)
1447 {
1448  uint32_t wakeupSignalLength = 0U;
1449 
1450  /* Get the current LIN user config structure of this LPUART instance. */
1451  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1452 
1453  /* Get base address of the LPUART instance. */
1454  LPUART_Type * base = g_linLpuartBase[instance];
1455 
1456  /* Get the current LIN state of this LPUART instance. */
1457  lin_state_t * linCurrentState = g_linStatePtr[instance];
1458 
1459  /* if LPUART_HAL_GetRxDataPolarity is 0: Receive Data is not inverted */
1460  if (LPUART_HAL_GetRxDataPolarity(base) == false)
1461  {
1462  /* Start measure time */
1463  (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
1464 
1465  /* Set Receive Data Inverted */
1466  LPUART_HAL_SetRxDataPolarity(base, true);
1467  }
1468  else
1469  {
1470  /* Set Receive Data is Not Inverted */
1471  LPUART_HAL_SetRxDataPolarity(base, false);
1472 
1473  /* Calculate time interval between the falling and rising edge */
1474  (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
1475 
1476  /* If length of the dominant signal is from 150us to 5ms, it is a wakeup signal */
1477  if ((wakeupSignalLength >= 150000U) && (wakeupSignalLength <= 5000000U))
1478  {
1479  linCurrentState->currentEventId = LIN_WAKEUP_SIGNAL;
1480 
1481  /* Callback to handle event: Received a wakeup signal */
1482  if (linCurrentState->Callback != NULL)
1483  {
1484  linCurrentState->Callback(instance, linCurrentState);
1485  }
1486 
1487  /* Change node's state to IDLE */
1488  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1489  }
1490  }
1491 }
1492 
1493 /*FUNCTION**********************************************************************
1494  *
1495  * Function Name : LIN_LPUART_DRV_ProcessFrame
1496  * Description : Part of Interrupt handler for receiving and sending data.
1497  * Receive Header, Data and Send Data.
1498  *
1499  * Implements : LIN_LPUART_DRV_ProcessFrame_Activity
1500  *END**************************************************************************/
1501 static void LIN_LPUART_DRV_ProcessFrame(uint32_t instance,
1502  uint8_t tmpByte)
1503 {
1504  /* Get the current LIN state of this LPUART instance. */
1505  const lin_state_t * linCurrentState = g_linStatePtr[instance];
1506 
1507  /* Check node's current state */
1508  switch (linCurrentState->currentNodeState)
1509  {
1510  /* if current state is RECEIVE SYNC FIELD */
1512 
1513  /* if current state is MASTER SENDING PID */
1515 
1516  /* if current state is RECEIVE PID */
1518  LIN_LPUART_DRV_ProcessFrameHeader(instance, tmpByte);
1519  break;
1520  /* if current state is RECEIVE DATA */
1522  LIN_LPUART_DRV_ProcessReceiveFrameData(instance, tmpByte);
1523  break;
1524  /* if current state is SENDING DATA */
1526  LIN_LPUART_DRV_ProcessSendFrameData(instance, tmpByte);
1527  break;
1528 
1529  default:
1530  /* Other node state */
1531  break;
1532  }
1533 }
1534 
1535 /*FUNCTION**********************************************************************
1536  *
1537  * Function Name : LIN_LPUART_DRV_ProcessFrameHeader
1538  * Description : Part of Interrupt handler for receiving and sending data.
1539  * Receive Sync byte, PID and Send PID.
1540  *
1541  * Implements : LIN_LPUART_DRV_ProcessFrameHeader_Activity
1542  *END**************************************************************************/
1543 static void LIN_LPUART_DRV_ProcessFrameHeader(uint32_t instance,
1544  uint8_t tmpByte)
1545 {
1546  /* Get base address of the LPUART instance. */
1547  LPUART_Type * base = g_linLpuartBase[instance];
1548 
1549  /* Get the current LIN user config structure of this LPUART instance. */
1550  const lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1551 
1552  /* Get the current LIN state of this LPUART instance. */
1553  lin_state_t * linCurrentState = g_linStatePtr[instance];
1554 
1555  /* Check node's current state */
1556  switch (linCurrentState->currentNodeState)
1557  {
1558  /* If current state is RECEIVE SYNC FIELD */
1560  if (tmpByte == 0x55U)
1561  {
1562  /* Set current event ID to Sync byte is correct */
1563  linCurrentState->currentEventId = LIN_SYNC_OK;
1564  /* Change node's current state to RECEIVE PID */
1565  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1566  }
1567  else
1568  {
1569  /* Set current event ID to Sync byte is incorrect */
1570  linCurrentState->currentEventId = LIN_SYNC_ERROR;
1571  /* Callback function to handle event RECEIVED SYNC FIELD ERROR */
1572  if (linCurrentState->Callback != NULL)
1573  {
1574  linCurrentState->Callback(instance, linCurrentState);
1575  }
1576 
1577  /* Clear Bus busy flag */
1578  linCurrentState->isBusBusy = false;
1579 
1580  /* Change node's current state to IDLE */
1581  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1582  }
1583 
1584  break;
1585  /* If current state is MASTER SENDING PID */
1587  /* Check if master node sent SYNC byte correctly before send PID */
1588  if (tmpByte == 0x55U)
1589  {
1590  /* Change node's current state to RECEIVING PID */
1591  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1592  /* Send the current PID byte */
1593  LPUART_HAL_Putchar(base, linCurrentState->currentPid);
1594  }
1595  /* In case of errors during header transmission, it is up to the implementer
1596  * how to handle these errors (stop/continue transmission) and to decide if the
1597  * corresponding response is valid or not.
1598  * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
1599  */
1600  else
1601  {
1602  /* Set current event ID to Sync byte is incorrect */
1603  linCurrentState->currentEventId = LIN_SYNC_ERROR;
1604  /* Clear Bus bus flag */
1605  linCurrentState->isBusBusy = false;
1606  /* Change node's current state to IDLE */
1607  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1608 
1609  /* Callback function to handle event SENT SYNC BYTE ERROR */
1610  if (linCurrentState->Callback != NULL)
1611  {
1612  linCurrentState->Callback(instance, linCurrentState);
1613  }
1614  }
1615 
1616  break;
1617  /* If current state is RECEIVE PID */
1619  /* If the node is MASTER */
1620  if (linUserConfig->nodeFunction == (bool)MASTER)
1621  {
1622  /* Check if master node sent PID correctly */
1623  if (tmpByte == linCurrentState->currentPid)
1624  {
1625  /* Set current event ID to PID correct */
1626  linCurrentState->currentEventId = LIN_PID_OK;
1627 
1628  /* Clear Bus bus flag */
1629  linCurrentState->isBusBusy = false;
1630 
1631  /* Callback function to handle correct PID */
1632  if (linCurrentState->Callback != NULL)
1633  {
1634  linCurrentState->Callback(instance, linCurrentState);
1635  }
1636  }
1637  /* In case of errors during header transmission, it is up to the implementer
1638  * how to handle these errors (stop/continue transmission) and to decide if the
1639  * corresponding response is valid or not.
1640  * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
1641  */
1642  else
1643  {
1644  /* Set current event ID to PID incorrect */
1645  linCurrentState->currentEventId = LIN_PID_ERROR;
1646  /* Clear bus busy flag */
1647  linCurrentState->isBusBusy = false;
1648  /* Change node's current state to IDLE */
1649  linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1650  /* Callback function to handle event MASTER SENT PID ERROR */
1651  if (linCurrentState->Callback != NULL)
1652  {
1653  linCurrentState->Callback(instance, linCurrentState);
1654  }
1655  }
1656  }
1657  /* If the node is SLAVE */
1658  else
1659  {
1660  /* Check the received PID */
1661  linCurrentState->currentId = LIN_DRV_ProcessParity(tmpByte, CHECK_PARITY);
1662  linCurrentState->currentPid = tmpByte;
1663  if (linCurrentState->currentId != 0xFFU)
1664  {
1665  /* Set current event ID to PID correct */
1666  linCurrentState->currentEventId = LIN_PID_OK;
1667 
1668  /* Clear Bus bus flag */
1669  linCurrentState->isBusBusy = false;
1670 
1671  /* Callback function to handle event PID correct */
1672  if (linCurrentState->Callback != NULL)
1673  {
1674  linCurrentState->Callback(instance, linCurrentState);
1675  }
1676  }
1677  else
1678  {
1679  /* Set current event ID to PID ERROR */
1680  linCurrentState->currentEventId = LIN_PID_ERROR;
1681 
1682  /* Callback function to handle event PID incorrect */
1683  if (linCurrentState->Callback != NULL)
1684  {
1685  linCurrentState->Callback(instance, linCurrentState);
1686  }
1687 
1688  /* Clear bus busy flag */
1689  linCurrentState->isBusBusy = false;
1690 
1691  /* Change node's current state to IDLE */
1692  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1693  }
1694  }
1695 
1696  break;
1697  default:
1698  /* Other node state */
1699  break;
1700  }
1701 }
1702 
1703 /*FUNCTION**********************************************************************
1704  *
1705  * Function Name : LIN_LPUART_DRV_ProcessReceiveFrameData
1706  * Description : Part of Interrupt handler for receiving.
1707  *
1708  * Implements : LIN_LPUART_DRV_ProcessReceiveFrameData_Activity
1709  *END**************************************************************************/
1710 static void LIN_LPUART_DRV_ProcessReceiveFrameData(uint32_t instance,
1711  uint8_t tmpByte)
1712 {
1713  /* Get the current LIN state of this LPUART instance. */
1714  lin_state_t * linCurrentState = g_linStatePtr[instance];
1715 
1716  if (linCurrentState->rxSize > (linCurrentState->cntByte + 1U))
1717  {
1718  *(linCurrentState->rxBuff) = tmpByte;
1719  linCurrentState->rxBuff++;
1720  }
1721  else
1722  {
1723  if ((linCurrentState->rxSize - linCurrentState->cntByte) == 1U)
1724  {
1725  linCurrentState->checkSum = tmpByte;
1726  }
1727  }
1728 
1729  linCurrentState->cntByte++;
1730  if (linCurrentState->cntByte == linCurrentState->rxSize)
1731  {
1732  /* Restore rxBuffer pointer */
1733  linCurrentState->rxBuff -= linCurrentState->rxSize - 1U;
1734  if (LIN_DRV_MakeChecksumByte(linCurrentState->rxBuff, linCurrentState->rxSize - 1U, linCurrentState->currentPid) == linCurrentState->checkSum)
1735  {
1736  linCurrentState->currentEventId = LIN_RX_COMPLETED;
1738 
1739  /* callback function to handle RX COMPLETED */
1740  if (linCurrentState->Callback != NULL)
1741  {
1742  linCurrentState->Callback(instance, linCurrentState);
1743  }
1744 
1745  /* Check if the reception is non-blocking */
1746  if (linCurrentState->isRxBlocking == false)
1747  {
1748  /* Clear Bus busy flag */
1749  linCurrentState->isBusBusy = false;
1750  linCurrentState->isRxBusy = false;
1751 
1752  /* In case of receiving a go to sleep request, after callback, node is in SLEEP MODE */
1753  /* In this case, node is in SLEEP MODE state */
1754  if (linCurrentState->currentNodeState != LIN_NODE_STATE_SLEEP_MODE)
1755  {
1756  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1757  }
1758  }
1759  else
1760  {
1761  /* Post Semaphore to signal Rx Completed*/
1762  (void)OSIF_SemaPost(&linCurrentState->rxCompleted);
1763  }
1764  }
1765  else
1766  {
1767  linCurrentState->currentEventId = LIN_CHECKSUM_ERROR;
1768  /* callback function to handle checksum error */
1769  if (linCurrentState->Callback != NULL)
1770  {
1771  linCurrentState->Callback(instance, linCurrentState);
1772  }
1773 
1774  /* Clear bus busy flag */
1775  linCurrentState->isBusBusy = false;
1776  linCurrentState->isRxBusy = false;
1777  /* Change node's current state to IDLE */
1778  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1779  }
1780  }
1781 }
1782 
1783 /*FUNCTION**********************************************************************
1784  *
1785  * Function Name : LIN_LPUART_DRV_ProcessSendFrameData
1786  * Description : Part of Interrupt handler for sending data.
1787  *
1788  * Implements : LIN_LPUART_DRV_ProcessSendFrameData_Activity
1789  *END**************************************************************************/
1790 static void LIN_LPUART_DRV_ProcessSendFrameData(uint32_t instance,
1791  uint8_t tmpByte)
1792 {
1793  bool sendFlag = true;
1794  uint8_t tmpSize;
1795  bool tmpCheckSumAndSize;
1796  bool tmpBuffAndSize;
1797 
1798  /* Get base address of the LPUART instance. */
1799  LPUART_Type * base = g_linLpuartBase[instance];
1800 
1801  /* Get the current LIN state of this LPUART instance. */
1802  lin_state_t * linCurrentState = g_linStatePtr[instance];
1803 
1804  /* Check if Tx data register empty flag is false */
1806  {
1807  linCurrentState->currentEventId = LIN_READBACK_ERROR;
1808  /* callback function to handle Readback error */
1809  if (linCurrentState->Callback != NULL)
1810  {
1811  linCurrentState->Callback(instance, linCurrentState);
1812  }
1813 
1814  /* Check if the transmission is non-blocking */
1815  if (linCurrentState->isTxBlocking == false)
1816  {
1817  /* Clear bus busy flag */
1818  linCurrentState->isBusBusy = false;
1819  linCurrentState->isTxBusy = false;
1820  /* Change node's current state to IDLE */
1821  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1822  }
1823 
1824  sendFlag = false;
1825  }
1826  else
1827  {
1828  tmpSize = (uint8_t)(linCurrentState->txSize - linCurrentState->cntByte);
1829  tmpCheckSumAndSize = (tmpSize == 1U) && (linCurrentState->checkSum != tmpByte);
1830  tmpBuffAndSize = (*linCurrentState->txBuff != tmpByte) && (tmpSize != 1U);
1831  if (tmpBuffAndSize || tmpCheckSumAndSize)
1832  {
1833  linCurrentState->currentEventId = LIN_READBACK_ERROR;
1834 
1835  /* callback function to handle Readback error */
1836  if (linCurrentState->Callback != NULL)
1837  {
1838  linCurrentState->Callback(instance, linCurrentState);
1839  }
1840 
1841  /* Check if the transmission is non-blocking */
1842  if (linCurrentState->isTxBlocking == false)
1843  {
1844  /* Clear bus busy flag */
1845  linCurrentState->isBusBusy = false;
1846  linCurrentState->isTxBusy = false;
1847  /* Change node's current state to IDLE */
1848  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1849  }
1850 
1851  sendFlag = false;
1852  }
1853  else
1854  {
1855  linCurrentState->txBuff++;
1856  linCurrentState->cntByte++;
1857  }
1858  }
1859 
1860  if (sendFlag)
1861  {
1862  if (linCurrentState->cntByte < linCurrentState->txSize)
1863  {
1864  /* Send checksum byte */
1865  if ((linCurrentState->txSize - linCurrentState->cntByte) == 1U)
1866  {
1867  LPUART_HAL_Putchar(base, linCurrentState->checkSum);
1868  }
1869  /* Send data bytes */
1870  else
1871  {
1872  LPUART_HAL_Putchar(base, *linCurrentState->txBuff);
1873  }
1874  }
1875  else
1876  {
1877  linCurrentState->currentEventId = LIN_TX_COMPLETED;
1879 
1881  /* callback function to handle event TX COMPLETED */
1882  if (linCurrentState->Callback != NULL)
1883  {
1884  linCurrentState->Callback(instance, linCurrentState);
1885  }
1886 
1887  /* Check if the transmission is non-blocking */
1888  if (linCurrentState->isTxBlocking == false)
1889  {
1890  /* Clear bus busy flag */
1891  linCurrentState->isBusBusy = false;
1892  linCurrentState->isTxBusy = false;
1893  /* Change node's current state to IDLE */
1894  (void)LIN_LPUART_DRV_GotoIdleState(instance);
1895  }
1896  else
1897  {
1898  /* Post Semaphore to signal Tx Completed*/
1899  (void)OSIF_SemaPost(&linCurrentState->txCompleted);
1900  }
1901  }
1902  }
1903 }
1904 
1905 /*FUNCTION**********************************************************************
1906  *
1907  * Function Name : LIN_LPUART_DRV_AutobaudTimerValEval
1908  * Description : This function calculate LIN bus baudrate and set slave's baudrate accordingly.
1909  * Autobaud process runs only once after reset. After setting slave's baudrate to LIN bus baudrate,
1910  * slave does not evaluate LIN bus baudrate anymore.
1911  * This is not a public API as it is called from other driver functions.
1912  *
1913  * Implements : LIN_LPUART_DRV_AutobaudTimerValEval_Activity
1914  *END**************************************************************************/
1915 static void LIN_LPUART_DRV_AutobaudTimerValEval(uint32_t instance,
1916  uint32_t twoBitTimeLength)
1917 {
1918  uint32_t MasterBaudrate = 0U;
1919 
1920  /* Get base address of the LPUART instance. */
1921  LPUART_Type * base = g_linLpuartBase[instance];
1922 
1923  /* Get the current LIN user config structure of this LPUART instance. */
1924  lin_user_config_t * linUserConfig = g_linUserconfigPtr[instance];
1925 
1926  /* Get the current LIN state of this LPUART instance. */
1927  lin_state_t * linCurrentState = g_linStatePtr[instance];
1928 
1929  /* Check whether current node state is receive sync */
1930  bool checkNodeState = (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_SYNC);
1931 
1932  /* Evaluate average value against baudrate */
1933  LIN_LPUART_DRV_EvalTwoBitTimeLength(instance, twoBitTimeLength);
1934 
1935  if ((linCurrentState->fallingEdgeInterruptCount > 4U) && checkNodeState)
1936  {
1937  if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_19200) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_19200))
1938  {
1939  MasterBaudrate = 19200U;
1940  }
1941  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_14400) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_14400))
1942  {
1943  MasterBaudrate = 14400U;
1944  }
1945  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_9600) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_9600))
1946  {
1947  MasterBaudrate = 9600U;
1948  }
1949  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_4800) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_4800))
1950  {
1951  MasterBaudrate = 4800U;
1952  }
1953  else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_2400) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_2400))
1954  {
1955  MasterBaudrate = 2400U;
1956  }
1957  else
1958  {
1959  /* Complete if-elseif-else block to avoid violating MISRA 2012 Rule 15.7 */
1960  }
1961 
1962  /* Check Master Baudrate against node's current baudrate */
1963  if ((MasterBaudrate != 0U) && (linUserConfig->baudRate != MasterBaudrate))
1964  {
1965  linUserConfig->baudRate = MasterBaudrate;
1966  /* Set new baudrate */
1967  (void)LPUART_HAL_SetBaudRate(base, linCurrentState->linSourceClockFreq, linUserConfig->baudRate);
1968 
1969  /* Assign wakeup signal to satisfy LIN Specifications specifies that
1970  * wakeup signal shall be in range from 250us to 5 ms.
1971  */
1972  if (linUserConfig->baudRate > 10000U)
1973  {
1974  /* Wakeup signal will be range from 400us to 800us depend on baudrate */
1975  s_wakeupSignal[instance] = 0x80U;
1976  }
1977  else
1978  {
1979  /* Wakeup signal will be range from 400us to 4ms depend on baudrate */
1980  s_wakeupSignal[instance] = 0xF8U;
1981  }
1982  }
1983 
1984  linCurrentState->currentEventId = LIN_BAUDRATE_ADJUSTED;
1985  /* Disable baudrate evaluation process */
1986  linCurrentState->baudrateEvalEnable = false;
1987  /* Callback function to handle this event */
1988  if (linCurrentState->Callback != NULL)
1989  {
1990  linCurrentState->Callback(instance, linCurrentState);
1991  }
1992 
1993  /* Update current state and current event */
1994  linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
1995  linCurrentState->currentEventId = LIN_SYNC_OK;
1996  }
1997 }
1998 
1999 /*FUNCTION**********************************************************************
2000  *
2001  * Function Name : LIN_LPUART_DRV_EvalTwoBitTimeLength
2002  * Description : This function check time of double bit in sync byte for support autobaud.
2003  * This is not a public API as it is called from other driver functions.
2004  *
2005  * Implements : LIN_LPUART_DRV_EvalTwoBitTimeLength_Activity
2006  *END**************************************************************************/
2007 static void LIN_LPUART_DRV_EvalTwoBitTimeLength(uint32_t instance,
2008  uint32_t twoBitTimeLength)
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 */
2114 
2115  /* Disable LIN Break Detect Interrupt */
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_HAL_SetTransmitterCmd(base, true);
2169  LPUART_HAL_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: S32K144.h:6702
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)
static void LPUART_HAL_QueueBreakField(LPUART_Type *base)
LPUART transmit sends break character configuration.
Definition: lpuart_hal.h:1213
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
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K144.h:269
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
void LPUART_HAL_SetParityMode(LPUART_Type *base, lpuart_parity_mode_t parityModeType)
Configures parity mode in the LPUART controller.
Definition: lpuart_hal.c:213
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:78
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
static void LPUART_HAL_SetBreakCharTransmitLength(LPUART_Type *base, lpuart_break_char_length_t length)
LPUART break character transmit length configuration.
Definition: lpuart_hal.h:1179
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
bool LPUART_HAL_GetIntMode(const LPUART_Type *base, lpuart_interrupt_t intSrc)
Returns LPUART module interrupts state.
Definition: lpuart_hal.c:418
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
static void LPUART_HAL_SetBreakCharDetectLength(LPUART_Type *base, lpuart_break_char_length_t length)
LPUART break character detect length configuration.
Definition: lpuart_hal.h:1197
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:31
#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
#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 bool LPUART_HAL_GetRxDataPolarity(const LPUART_Type *base)
Returns whether the receive data is inverted or not.
Definition: lpuart_hal.h:521
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.
clock_names_t
Clock names.
static void LPUART_HAL_SetTransmitterCmd(LPUART_Type *base, bool enable)
Enable/Disable the LPUART transmitter.
Definition: lpuart_hal.h:363
#define TWO_BIT_DURATION_MIN_4800
static void LPUART_HAL_Putchar(LPUART_Type *base, uint8_t data)
Sends the LPUART 8-bit character.
Definition: lpuart_hal.h:710
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.
status_t LPUART_HAL_ClearStatusFlag(LPUART_Type *base, lpuart_status_flag_t statusFlag)
LPUART clears an individual status flag.
Definition: lpuart_hal.c:684
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: S32K144.h:6683
#define TWO_BIT_DURATION_MAX_2400
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
status_t LPUART_HAL_SetBaudRate(LPUART_Type *base, uint32_t sourceClockInHz, uint32_t desiredBaudRate)
Configures the LPUART baud rate.
Definition: lpuart_hal.c:95
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 LPUART_HAL_SetReceiverCmd(LPUART_Type *base, bool enable)
Enable/Disable the LPUART receiver.
Definition: lpuart_hal.h:397
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
void LPUART_HAL_SetBitCountPerChar(LPUART_Type *base, lpuart_bit_count_per_char_t bitCountPerChar)
Configures the number of bits per character in the LPUART controller.
Definition: lpuart_hal.c:187
status_t LIN_LPUART_DRV_EnableIRQ(uint32_t instance)
Enables LIN_LPUART hardware interrupts.
void LPUART_HAL_SetIntMode(LPUART_Type *base, lpuart_interrupt_t intSrc, bool enable)
Configures the LPUART module interrupts.
Definition: lpuart_hal.c:371
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.
bool LPUART_HAL_GetStatusFlag(const LPUART_Type *base, lpuart_status_flag_t statusFlag)
LPUART get status flag.
Definition: lpuart_hal.c:636
#define BIT_RATE_TOLERANCE_UNSYNC
static void LPUART_HAL_SetStopBitCount(LPUART_Type *base, lpuart_stop_bit_count_t stopBitCount)
Configures the number of stop bits in the LPUART controller.
Definition: lpuart_hal.h:579
#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: S32K144.h:6708
void LPUART_HAL_Init(LPUART_Type *base)
Initializes the LPUART controller.
Definition: lpuart_hal.c:62
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
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.
static void LPUART_HAL_SetRxDataPolarity(LPUART_Type *base, bool polarity)
Sets whether the recevie data is inverted or not.
Definition: lpuart_hal.h:535
static void LPUART_HAL_Getchar(const LPUART_Type *base, uint8_t *readData)
Gets the LPUART 8-bit character.
Definition: lpuart_hal.h:748