1 /*
2  * Copyright  2016-2019 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /*******************************************************************************
10  * Includes
11  ******************************************************************************/
12 #include "fsl_lin_lpuart.h"
13 
14 /*
15  * $Coverage Justification Reference$
16  *
17  * $Justification lin_lpuart_c_ref_1$
18  * For SoC that only has 2 LPUART instances, the instance that is used as debug
19  * console cannot be tested using current test cases.
20  *
21  * $Justification lin_lpuart_c_ref_2$
22  * The situation that the lin break is detected by master while the master did not
23  * send it, can only be caused by intereference on bus.
24  *
25  * $Justification lin_lpuart_c_ref_3$
26  * The LIN user callback function shall always be installed for normal state
27  * handling and shall configured by user during lin initialization.
28  *
29  * $Justification lin_lpuart_c_ref_4$
30  * The LIN timerGetTimeInterval callback function shall always be installed for
31  * buadrate calculation if user wants to use autobad function, and shall configured
32  * by user during lin initialization.
33  *
34  * $Justification lin_lpuart_c_ref_5$
35  * Normally the node state shall only be LIN_NODE_STATE_RECV_SYNC in
36  * LIN_LPUART_AutobaudTimerValEval, the false branch can only be covered when the state
37  * is corrupted in user application.
38  *
39  * $Justification lin_lpuart_c_ref_6$
40  * The baudrate capture and calculation is done by timer, sometimes the captured and
41  * calculated value is not ideal and cannot meet all the possible baudrate range.
42  *
43  * $Justification lin_lpuart_c_ref_7$
44  * The false branch can only be covered when the sync byte on bus has different
45  * baudrates from LSB to MSB in the same byte, which may caused by intereference on bus.
46  *
47  * $Justification lin_lpuart_c_ref_8$
48  * Normally the falling edge count of the LIN state shall be smaller than 5 at
49  * this point, the false branch can only be covered when the state is corrupted
50  * in user application such as different thread updating the falling edge count the same time.
51  *
52  * $Justification lin_lpuart_c_ref_9$
53  * The readback error can only be caused by signal interference on bus which
54  * is hard to simulated.
55  *
56  * $Justification lin_lpuart_c_ref_10$
57  * The node state is covered by all the conditions and will not hit the default
58  * condition, the default branch is only added to avoid MISRA violation.
59  *
60  * $Justification lin_lpuart_c_ref_11$
61  * The branch can only be false if the detection of the go-to-sleep command is
62  * executed in another thread and slave node has just received the go-to-sleep
63  * command right after the last rx byte is read and before this line.
64  *
65  * $Justification lin_lpuart_c_ref_12$
66  * Normally the falling edge count of the LIN state shall be larger than 4 at this
67  * point, the false branch can only be covered when the state is corrupted in user
68  * application such as different thread updating the falling edge count the same time.
69  *
70  * $Justification lin_lpuart_c_ref_13$
71  * The LIN driver test cases are run in bare metal environment and can only be usd
72  * in non-blocking interrupt way.
73  */
74 
75 /*******************************************************************************
76  * Variables
77  ******************************************************************************/
78 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
79 /* Array of LPUART clock name. */
80 static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS;
81 
82 #if defined(LPUART_PERIPH_CLOCKS)
83 /* Array of LPUART functional clock name. */
84 static const clock_ip_name_t s_lpuartPeriphClocks[] = LPUART_PERIPH_CLOCKS;
85 #endif
86 #endif
87 
88 LPUART_Type *const g_linLpuartBase[FSL_FEATURE_SOC_LPUART_COUNT] = LPUART_BASE_PTRS;
89 
90 const IRQn_Type g_linLpuartRxTxIrqId[FSL_FEATURE_SOC_LPUART_COUNT] = LPUART_RX_TX_IRQS;
91 
92 #ifdef LPUART_ERR_IRQS
93 const IRQn_Type g_linLpuartErrIrqId[FSL_FEATURE_SOC_LPUART_COUNT] = LPUART_ERR_IRQS;
94 #endif
95 
96 /*******************************************************************************
97  * Static variables
98  ******************************************************************************/
99 static uint32_t s_previousTwoBitTimeLength[FSL_FEATURE_SOC_LPUART_COUNT] = {0U};
100 static uint8_t s_wakeupSignal[FSL_FEATURE_SOC_LPUART_COUNT]              = {0U};
101 static uint8_t s_countMeasure[FSL_FEATURE_SOC_LPUART_COUNT]              = {0U};
102 static uint32_t s_timeMeasure[FSL_FEATURE_SOC_LPUART_COUNT]              = {0U};
103 
104 /*******************************************************************************
105  * Static function prototypes
106  ******************************************************************************/
107 
108 static void LIN_LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask);
109 static void LIN_LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask);
110 static uint32_t LIN_LPUART_GetInstance(LPUART_Type *base);
111 static status_t LIN_LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask);
112 static uint32_t LIN_LPUART_GetStatusFlags(LPUART_Type *base);
113 static void LIN_LPUART_ProcessBreakDetect(uint32_t instance);
114 static void LIN_LPUART_CheckWakeupSignal(uint32_t instance);
115 static void LIN_LPUART_AutobaudTimerValEval(uint32_t instance, uint32_t twoBitTimeLength);
116 static void LIN_LPUART_EvalTwoBitTimeLength(uint32_t instance, uint32_t twoBitTimeLength);
117 static void LIN_LPUART_ProcessFrame(uint32_t instance, uint8_t tmpByte);
118 static void LIN_LPUART_ProcessFrameHeader(uint32_t instance, uint8_t tmpByte);
119 static void LIN_LPUART_ProcessReceiveFrameData(uint32_t instance, uint8_t tmpByte);
120 static void LIN_LPUART_ProcessSendFrameData(uint32_t instance, uint8_t tmpByte);
121 
122 /*******************************************************************************
123  * Code
124  ******************************************************************************/
LIN_LPUART_EnableInterrupts(LPUART_Type * base,uint32_t mask)125 static void LIN_LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
126 {
127     base->BAUD |= ((mask << 8U) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
128 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
129     base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) |
130                  ((mask << 8U) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
131 #endif
132     mask &= 0xFFFFFF00U;
133     base->CTRL |= mask;
134 }
135 
LIN_LPUART_DisableInterrupts(LPUART_Type * base,uint32_t mask)136 static void LIN_LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask)
137 {
138     base->BAUD &= ~((mask << 8U) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
139 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
140     base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) &
141                  ~((mask << 8U) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
142 #endif
143     mask &= 0xFFFFFF00U;
144     base->CTRL &= ~mask;
145 }
146 
LIN_LPUART_CalculateBaudRate(LPUART_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * osr,uint16_t * sbr)147 status_t LIN_LPUART_CalculateBaudRate(
148     LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz, uint32_t *osr, uint16_t *sbr)
149 {
150     assert(0U != baudRate_Bps);
151     status_t status = kStatus_Success;
152 
153     uint16_t sbrTemp;
154     uint32_t osrTemp, tempDiff, calculatedBaud, baudDiff;
155 
156     /* This LPUART instantiation uses a slightly different baud rate calculation
157      * The idea is to use the best OSR (over-sampling rate) possible
158      * Note, OSR is typically hard-set to 16 in other LPUART instantiations
159      * loop to find the best OSR value possible, one that generates minimum baudDiff
160      * iterate through the rest of the supported values of OSR */
161 
162     baudDiff = baudRate_Bps;
163     for (osrTemp = 4U; osrTemp <= 32U; osrTemp++)
164     {
165         /* calculate the temporary sbr value   */
166         sbrTemp = (uint16_t)(srcClock_Hz / (baudRate_Bps * osrTemp));
167         /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
168         if (sbrTemp == 0U)
169         {
170             sbrTemp = 1U;
171         }
172         /* Calculate the baud rate based on the temporary OSR and SBR values */
173         calculatedBaud = (srcClock_Hz / (osrTemp * sbrTemp));
174 
175         tempDiff = calculatedBaud - baudRate_Bps;
176 
177         /* Select the better value between srb and (sbr + 1) */
178         if (tempDiff > (baudRate_Bps - (srcClock_Hz / (osrTemp * ((uint32_t)sbrTemp + 1U)))))
179         {
180             tempDiff = baudRate_Bps - (srcClock_Hz / (osrTemp * ((uint32_t)sbrTemp + 1U)));
181             sbrTemp++;
182         }
183 
184         if (tempDiff <= baudDiff)
185         {
186             baudDiff = tempDiff;
187             *osr     = osrTemp; /* update and store the best OSR value calculated */
188             *sbr     = sbrTemp; /* update store the best SBR value calculated */
189         }
190     }
191 
192     if (baudDiff >= ((baudRate_Bps / 100U) * 3U))
193     {
194         status = kStatus_Fail;
195     }
196     return status;
197 }
198 
LIN_LPUART_SetBaudRate(LPUART_Type * base,uint32_t * osr,uint16_t * sbr)199 void LIN_LPUART_SetBaudRate(LPUART_Type *base, uint32_t *osr, uint16_t *sbr)
200 {
201     uint32_t temp, oldCtrl;
202     /* Store CTRL before disable Tx and Rx */
203     oldCtrl = base->CTRL;
204 
205     /* Disable LPUART TX RX before setting. */
206     base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
207 
208     temp = base->BAUD;
209 
210     /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
211      * If so, then "BOTHEDGE" sampling must be turned on */
212     if ((*osr > 3U) && (*osr < 8U))
213     {
214         temp |= LPUART_BAUD_BOTHEDGE_MASK;
215     }
216 
217     /* program the osr value (bit value is one less than actual value) */
218     temp &= ~LPUART_BAUD_OSR_MASK;
219     temp |= LPUART_BAUD_OSR(*osr - 1U);
220 
221     /* write the sbr value to the BAUD registers */
222     temp &= ~LPUART_BAUD_SBR_MASK;
223     base->BAUD = temp | LPUART_BAUD_SBR(*sbr);
224 
225     /* Restore CTRL. */
226     base->CTRL = oldCtrl;
227 }
228 
LIN_LPUART_SetBitCountPerChar(LPUART_Type * base)229 static void LIN_LPUART_SetBitCountPerChar(LPUART_Type *base)
230 {
231     /* config 8-bit (M=0) or 9-bits (M=1) */
232     base->CTRL = (base->CTRL & ~LPUART_CTRL_M_MASK);
233     /* clear M10 to make sure not 10-bit mode */
234     base->BAUD &= ~LPUART_BAUD_M10_MASK;
235 }
236 
LIN_LPUART_ClearStatusFlags(LPUART_Type * base,uint32_t mask)237 static status_t LIN_LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask)
238 {
239     uint32_t temp;
240     status_t status;
241 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
242     temp = (uint32_t)base->FIFO;
243     temp &= (uint32_t)(~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK));
244     temp |= (mask << 16U) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK);
245     base->FIFO = temp;
246 #endif
247     temp = (uint32_t)base->STAT;
248 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
249     temp &= (uint32_t)(~(LPUART_STAT_LBKDIF_MASK));
250     temp |= mask & LPUART_STAT_LBKDIF_MASK;
251 #endif
252     temp &= (uint32_t)(~(LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
253                          LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK));
254     temp |= mask & (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
255                     LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
256 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
257     temp &= (~((uint32_t)LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK));
258     temp |= mask & (LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK);
259 #endif
260     base->STAT = temp;
261     /* If some flags still pending. */
262     if (0U != (mask & LIN_LPUART_GetStatusFlags(base)))
263     {
264         /* Some flags can only clear or set by the hardware itself, these flags are: kLPUART_TxDataRegEmptyFlag,
265         kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, kLPUART_RxActiveFlag,
266         kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
267         kLPUART_TxFifoEmptyFlag, kLPUART_RxFifoEmptyFlag. */
268         status = (status_t)kStatus_LPUART_FlagCannotClearManually; /* flags can not clear manually */
269     }
270     else
271     {
272         status = kStatus_Success;
273     }
274 
275     return status;
276 }
277 
LIN_LPUART_GetStatusFlags(LPUART_Type * base)278 static uint32_t LIN_LPUART_GetStatusFlags(LPUART_Type *base)
279 {
280     uint32_t temp;
281     temp = base->STAT;
282 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
283     temp |= (base->FIFO &
284              (LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >>
285             16U;
286 #endif
287     return temp;
288 }
289 
LIN_LPUART_GetInstance(LPUART_Type * base)290 static uint32_t LIN_LPUART_GetInstance(LPUART_Type *base)
291 {
292     uint32_t instance;
293 
294     /* Find the instance index from base address mappings. */
295     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_1$ */
296     for (instance = 0; instance <= ((uint32_t)FSL_FEATURE_SOC_LPUART_COUNT - 1UL); instance++)
297     {
298         if (g_linLpuartBase[instance] == base)
299         {
300             break;
301         }
302     }
303 
304     assert(instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT);
305 
306     return instance;
307 }
308 
LIN_LPUART_QueueBreakChar(LPUART_Type * base)309 static lin_status_t LIN_LPUART_QueueBreakChar(LPUART_Type *base)
310 {
311     /* mask T0-T9 bits from data register */
312     base->DATA = LPUART_DATA_FRETSC(1U);
313 
314     return LIN_SUCCESS;
315 }
316 
LIN_LPUART_ProcessBreakDetect(uint32_t instance)317 static void LIN_LPUART_ProcessBreakDetect(uint32_t instance)
318 {
319     LPUART_Type *base = g_linLpuartBase[instance];
320     /* Get the current LIN user configure structure of this LPUART instance. */
321     const lin_user_config_t *linUserConfig = (const lin_user_config_t *)(uint32_t)g_linUserconfigPtr[instance];
322 
323     /* Get the current LIN state of this LPUART instance. */
324     lin_state_t *linCurrentState = g_linStatePtr[instance];
325 
326     /* Clear LIN Break Detect Interrupt Flag */
327     (void)LIN_LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_LinBreakFlag);
328 
329     /* Check if the current node is in SLEEP MODE */
330     if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
331     {
332         /* Change the node's current state to IDLE */
333         (void)LIN_LPUART_GotoIdleState(base);
334     }
335     else
336     {
337 /* Set Break char detect length as 10 bits minimum */
338 /* Disable LIN Break Detect Interrupt */
339 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
340         /* Set Break char detect length as 10 bits minimum and interrupt */
341         base->STAT &= ~LPUART_STAT_LBKDE_MASK;
342         LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
343 #endif
344         /* Set flag LIN bus busy */
345         linCurrentState->isBusBusy = true;
346 
347         /* Check if the current node is MASTER */
348         if (linUserConfig->nodeFunction == (bool)LIN_MASTER) /* Master */
349         {
350             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_2$ */
351             if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_BREAK_FIELD)
352             {
353                 /* Change the node's current state to SENDING PID */
354                 linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_PID;
355 
356                 LIN_LPUART_WriteByte(base, 0x55);
357             }
358         }
359         /* If the current node is SLAVE */
360         else
361         {
362             /* If the current node state is still receive/send data when break detected, this indicate the lst frame's
363                response is not complete */
364             if ((linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_DATA) ||
365                 (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_DATA))
366             {
367                 /* Change the node's current event to LAST RESPONSE TOO SHORT */
368                 linCurrentState->currentEventId = LIN_LAST_RESPONSE_SHORT_ERROR;
369 
370                 /* Callback function */
371                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
372                 if (linCurrentState->Callback != NULL)
373                 {
374                     linCurrentState->Callback(instance, linCurrentState);
375                 }
376             }
377             /* Change the node's current event to RECEIVED BREAK FIELD */
378             linCurrentState->currentEventId = LIN_RECV_BREAK_FIELD_OK;
379 
380             /* Callback function */
381             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
382             if (linCurrentState->Callback != NULL)
383             {
384                 linCurrentState->Callback(instance, linCurrentState);
385             }
386 
387             /* Change the node's current state to RECEIVING SYNC FIELD */
388             linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_SYNC;
389         }
390     }
391 }
392 
LIN_LPUART_CheckWakeupSignal(uint32_t instance)393 static void LIN_LPUART_CheckWakeupSignal(uint32_t instance)
394 {
395     uint32_t wakeupSignalLength = 0U;
396 
397     LPUART_Type *base = g_linLpuartBase[instance];
398     /* Get the current LIN user config structure of this LPUART instance. */
399     const lin_user_config_t *linUserConfig = (const lin_user_config_t *)(uint32_t)g_linUserconfigPtr[instance];
400 
401     /* Get the current LIN state of this LPUART instance. */
402     lin_state_t *linCurrentState = g_linStatePtr[instance];
403 
404     /* if LPUART_HAL_GetRxDataPolarity is 0: Receive Data is not inverted */
405     if (LIN_LPUART_GetRxDataPolarity((const LPUART_Type *)(uint32_t)base) == false)
406     {
407         /* Start measure time */
408         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_4 $ */
409         if (linUserConfig->timerGetTimeIntervalCallback == NULL)
410         {
411             return;
412         }
413         (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
414 
415         /* Set Receive Data Inverted */
416         LIN_LPUART_SetRxDataPolarity(base, true);
417     }
418     else
419     {
420         /* Set Receive Data is Not Inverted */
421         LIN_LPUART_SetRxDataPolarity(base, false);
422 
423         /* Calculate time interval between the falling and rising edge */
424         (void)linUserConfig->timerGetTimeIntervalCallback(&wakeupSignalLength);
425 
426         /* If length of the dominant signal is from 150us to 5ms, it is a wakeup signal */
427         if (wakeupSignalLength >= 150000U)
428         {
429             if (wakeupSignalLength <= 5000000U)
430             {
431                 linCurrentState->currentEventId = LIN_WAKEUP_SIGNAL;
432 
433                 /* Callback to handle event: Received a wakeup signal */
434                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
435                 if (linCurrentState->Callback != NULL)
436                 {
437                     linCurrentState->Callback(instance, linCurrentState);
438                 }
439 
440                 /* Change node's state to IDLE */
441                 (void)LIN_LPUART_GotoIdleState(base);
442             }
443         }
444     }
445 }
446 
LIN_LPUART_AutobaudTimerValEval(uint32_t instance,uint32_t twoBitTimeLength)447 static void LIN_LPUART_AutobaudTimerValEval(uint32_t instance, uint32_t twoBitTimeLength)
448 {
449     uint32_t MasterBaudrate = 0U;
450 
451     /* Get the current LIN user config structure of this LPUART instance. */
452     lin_user_config_t *linUserConfig = g_linUserconfigPtr[instance];
453 
454     /* Get the current LIN state of this LPUART instance. */
455     lin_state_t *linCurrentState = g_linStatePtr[instance];
456     /* If LIN Stack enabled. */
457 #if defined(FSL_SDK_LIN_STACK_ENABLE) && (FSL_SDK_LIN_STACK_ENABLE)
458     uint32_t osrValue = 0U;
459     uint16_t sbrValue = 0U;
460 #endif
461     LPUART_Type *base = g_linLpuartBase[instance];
462 
463     /* Check whether current node state is receive sync */
464     bool checkNodeState = (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_SYNC);
465 
466     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_5 $ */
467     if (checkNodeState)
468     {
469         /* Evaluate average value against baudrate */
470         LIN_LPUART_EvalTwoBitTimeLength(instance, twoBitTimeLength);
471 
472         if (linCurrentState->fallingEdgeInterruptCount > 4U)
473         {
474             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
475             if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_19200) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_19200))
476             {
477                 MasterBaudrate = 19200U;
478             }
479             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
480             else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_14400) &&
481                      (twoBitTimeLength <= TWO_BIT_DURATION_MAX_14400))
482             {
483                 MasterBaudrate = 14400U;
484             }
485             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
486             else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_9600) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_9600))
487             {
488                 MasterBaudrate = 9600U;
489             }
490             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
491             else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_4800) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_4800))
492             {
493                 MasterBaudrate = 4800U;
494             }
495             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
496             else if ((twoBitTimeLength >= TWO_BIT_DURATION_MIN_2400) && (twoBitTimeLength <= TWO_BIT_DURATION_MAX_2400))
497             {
498                 MasterBaudrate = 2400U;
499             }
500             else
501             {
502                 /* Complete if-elseif-else block to avoid violating MISRA 2012 Rule 15.7 */
503             }
504 
505             /* Check Master Baudrate against node's current baudrate */
506             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_7 $ */
507             if (MasterBaudrate != 0U)
508             {
509                 if (linUserConfig->baudRate != MasterBaudrate)
510                 {
511                     linUserConfig->baudRate = MasterBaudrate;
512 
513 #if defined(FSL_SDK_LIN_STACK_ENABLE) && (FSL_SDK_LIN_STACK_ENABLE)
514                     if (LIN_LPUART_CalculateBaudRate(base, linUserConfig->baudRate, LIN_LPUART_CLOCK_FREQ, &osrValue,
515                                                      &sbrValue) == kStatus_Success)
516                     {
517                         /* Set baudrate to User's value */
518                         LIN_LPUART_SetBaudRate(base, &osrValue, &sbrValue);
519                     }
520 #endif
521                     /* Assign wakeup signal to satisfy LIN Specifications specifies that
522                      * wakeup signal shall be in range from 250us to 5 ms.
523                      */
524                     if (linUserConfig->baudRate > 10000U)
525                     {
526                         /* Wakeup signal will be range from 400us to 800us depend on baudrate */
527                         s_wakeupSignal[instance] = 0x80U;
528                     }
529                     else
530                     {
531                         /* Wakeup signal will be range from 400us to 4ms depend on baudrate */
532                         s_wakeupSignal[instance] = 0xF8U;
533                     }
534                 }
535                 linCurrentState->currentEventId = LIN_BAUDRATE_ADJUSTED;
536                 /* Disable baudrate evaluation process */
537                 linCurrentState->baudrateEvalEnable = false;
538                 /* Callback function to handle this event */
539                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
540                 if (linCurrentState->Callback != NULL)
541                 {
542                     linCurrentState->Callback(instance, linCurrentState);
543                 }
544                 /* Interrupt in rising edge */
545 
546                 linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
547                 linCurrentState->currentEventId   = LIN_SYNC_OK;
548             }
549             else
550             {
551                 /* cancel capturing if baudrate not supported. */
552                 (void)LIN_LPUART_GotoIdleState(base);
553                 linCurrentState->fallingEdgeInterruptCount = 0U;
554             }
555         }
556     }
557 }
558 
LIN_LPUART_EvalTwoBitTimeLength(uint32_t instance,uint32_t twoBitTimeLength)559 static void LIN_LPUART_EvalTwoBitTimeLength(uint32_t instance, uint32_t twoBitTimeLength)
560 {
561     LPUART_Type *base = g_linLpuartBase[instance];
562     /* Get the current LIN state of this LPUART instance. */
563     lin_state_t *linCurrentState = g_linStatePtr[instance];
564 
565     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_8 $ */
566     if (linCurrentState->fallingEdgeInterruptCount < 5U)
567     {
568         if (linCurrentState->fallingEdgeInterruptCount > 0U)
569         {
570             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
571             if ((twoBitTimeLength < TWO_BIT_DURATION_MIN_19200) ||
572                 ((twoBitTimeLength > TWO_BIT_DURATION_MAX_19200) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_14400)) ||
573                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
574                 ((twoBitTimeLength > TWO_BIT_DURATION_MAX_14400) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_9600)) ||
575                 ((twoBitTimeLength > TWO_BIT_DURATION_MAX_9600) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_4800)) ||
576                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_6 $ */
577                 ((twoBitTimeLength > TWO_BIT_DURATION_MAX_4800) && (twoBitTimeLength < TWO_BIT_DURATION_MIN_2400)) ||
578                 (twoBitTimeLength > TWO_BIT_DURATION_MAX_2400))
579             {
580                 /* cancel capturing */
581                 (void)LIN_LPUART_GotoIdleState(base);
582                 linCurrentState->fallingEdgeInterruptCount = 0U;
583             }
584             else
585             {
586                 if (linCurrentState->fallingEdgeInterruptCount > 1U)
587                 {
588                     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_7 $ */
589                     if ((twoBitTimeLength <
590                          ((100U - BIT_RATE_TOLERANCE_UNSYNC) * s_previousTwoBitTimeLength[instance] / 100U)) ||
591                         (twoBitTimeLength >
592                          ((100U + BIT_RATE_TOLERANCE_UNSYNC) * s_previousTwoBitTimeLength[instance] / 100U)))
593                     {
594                         /* cancel capturing */
595                         (void)LIN_LPUART_GotoIdleState(base);
596                         linCurrentState->fallingEdgeInterruptCount = 0U;
597                     }
598                 }
599             }
600             s_previousTwoBitTimeLength[instance] = twoBitTimeLength;
601         }
602     }
603     linCurrentState->fallingEdgeInterruptCount += 1U;
604 }
605 
LIN_LPUART_ProcessFrame(uint32_t instance,uint8_t tmpByte)606 static void LIN_LPUART_ProcessFrame(uint32_t instance, uint8_t tmpByte)
607 {
608     /* Get the current LIN state of this LPUART instance. */
609     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
610 
611     /* Check node's current state */
612     switch (linCurrentState->currentNodeState)
613     {
614         /* if current state is RECEIVE SYNC FIELD */
615         case LIN_NODE_STATE_RECV_SYNC:
616 
617         /* if current state is MASTER SENDING PID */
618         case LIN_NODE_STATE_SEND_PID:
619 
620         /* if current state is RECEIVE PID */
621         case LIN_NODE_STATE_RECV_PID:
622             LIN_LPUART_ProcessFrameHeader(instance, tmpByte);
623             break;
624         /* if current state is RECEIVE DATA */
625         case LIN_NODE_STATE_RECV_DATA:
626             LIN_LPUART_ProcessReceiveFrameData(instance, tmpByte);
627             break;
628         /* if current state is SENDING DATA */
629         case LIN_NODE_STATE_SEND_DATA:
630             LIN_LPUART_ProcessSendFrameData(instance, tmpByte);
631             break;
632 
633         default:
634             /* Other node state */
635             break;
636     }
637 }
638 
LIN_LPUART_ProcessFrameHeader(uint32_t instance,uint8_t tmpByte)639 static void LIN_LPUART_ProcessFrameHeader(uint32_t instance, uint8_t tmpByte)
640 {
641     LPUART_Type *base = g_linLpuartBase[instance];
642     /* Get the current LIN user config structure of this LPUART instance. */
643     const lin_user_config_t *linUserConfig = (const lin_user_config_t *)(uint32_t)g_linUserconfigPtr[instance];
644 
645     /* Get the current LIN state of this LPUART instance. */
646     lin_state_t *linCurrentState = g_linStatePtr[instance];
647 
648     /* Check node's current state */
649     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_10 $ */
650     switch (linCurrentState->currentNodeState)
651     {
652         /* if current state is RECEIVE SYNC FIELD */
653         case LIN_NODE_STATE_RECV_SYNC:
654             if (tmpByte == 0x55U)
655             {
656                 linCurrentState->currentEventId = LIN_SYNC_OK;
657 
658                 /* Change node's current state to RECEIVE PID */
659                 linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
660             }
661             else
662             {
663                 linCurrentState->currentEventId = LIN_SYNC_ERROR;
664 
665                 /* Callback function to handle event RECEIVED SYNC FIELD ERROR */
666                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
667                 if (linCurrentState->Callback != NULL)
668                 {
669                     linCurrentState->Callback(instance, linCurrentState);
670                 }
671 
672                 /* Clear Bus busy flag */
673                 linCurrentState->isBusBusy = false;
674 
675                 /* Change node's current state to IDLE */
676                 (void)LIN_LPUART_GotoIdleState(base);
677             }
678             break;
679         /* if current state is MASTER SENDING PID */
680         case LIN_NODE_STATE_SEND_PID:
681             /* Check if master node sent SYNC byte correctly before send PID */
682             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
683             if (tmpByte == 0x55U)
684             {
685                 /* Change node's current state to RECEIVING PID */
686                 linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_PID;
687                 /* Send the current PID byte */
688                 LIN_LPUART_WriteByte(base, linCurrentState->currentPid);
689             }
690             /* In case of errors during header transmission, it is up to the implementer
691              * how to handle these errors (stop/continue transmission) and to decide if the
692              * corresponding response is valid or not.
693              * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
694              */
695             else
696             {
697                 linCurrentState->currentEventId = LIN_SYNC_ERROR;
698                 /* Clear Bus busy flag */
699                 linCurrentState->isBusBusy = false;
700                 /* Change node's current state to IDLE */
701                 linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
702                 /* Callback function to handle event RECEIVED SYNC FIELD ERROR */
703                 if (linCurrentState->Callback != NULL)
704                 {
705                     linCurrentState->Callback(instance, linCurrentState);
706                 }
707             }
708             break;
709         /* if current state is RECEIVE PID */
710         case LIN_NODE_STATE_RECV_PID:
711             /* if the node is MASTER */
712             if (linUserConfig->nodeFunction == (bool)LIN_MASTER)
713             {
714                 /* Check if master node sent PID correctly */
715                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
716                 if (tmpByte == linCurrentState->currentPid)
717                 {
718                     /* Set current event ID to PID correct */
719                     linCurrentState->currentEventId = LIN_PID_OK;
720 
721                     /* Clear Bus busy flag */
722                     linCurrentState->isBusBusy = false;
723 
724                     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
725                     if (linCurrentState->Callback != NULL)
726                     {
727                         linCurrentState->Callback(instance, linCurrentState);
728                     }
729                 }
730                 /* In case of errors during header transmission, it is up to the implementer
731                  * how to handle these errors (stop/continue transmission) and to decide if the
732                  * corresponding response is valid or not.
733                  * By default, LIN Driver set isBusBusy to false, and change node's state to IDLE.
734                  */
735                 else
736                 {
737                     /* Set current event ID to PID incorrect */
738                     linCurrentState->currentEventId = LIN_PID_ERROR;
739                     /* Clear bus busy flag */
740                     linCurrentState->isBusBusy = false;
741                     /* Change node's current state to IDLE */
742                     linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
743                     /* Callback function to handle event MASTER SENT PID ERROR */
744                     if (linCurrentState->Callback != NULL)
745                     {
746                         linCurrentState->Callback(instance, linCurrentState);
747                     }
748                 }
749             }
750             /* If the node is SLAVE */
751             else
752             {
753                 /* Check the received PID */
754                 linCurrentState->currentId  = LIN_ProcessParity(tmpByte, CHECK_PARITY);
755                 linCurrentState->currentPid = tmpByte;
756                 if (linCurrentState->currentId != 0xFFU)
757                 {
758                     /* Set current event PID correct */
759                     linCurrentState->currentEventId = LIN_PID_OK;
760 
761                     /* Clear Bus bus flag */
762                     linCurrentState->isBusBusy = false;
763 
764                     /* Callback function to handle correct PID */
765                     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
766                     if (linCurrentState->Callback != NULL)
767                     {
768                         linCurrentState->Callback(instance, linCurrentState);
769                     }
770                 }
771                 else
772                 {
773                     /* Set current event PID incorrect */
774                     linCurrentState->currentEventId = LIN_PID_ERROR;
775 
776                     /* Callback function to handle correct PID */
777                     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
778                     if (linCurrentState->Callback != NULL)
779                     {
780                         linCurrentState->Callback(instance, linCurrentState);
781                     }
782 
783                     /* Clear Bus bus flag */
784                     linCurrentState->isBusBusy = false;
785 
786                     /* Change node's current state to IDLE */
787                     (void)LIN_LPUART_GotoIdleState(base);
788                 }
789             }
790             break;
791         default:
792             /* Other node state */
793             break;
794     }
795 }
796 
LIN_LPUART_ProcessReceiveFrameData(uint32_t instance,uint8_t tmpByte)797 static void LIN_LPUART_ProcessReceiveFrameData(uint32_t instance, uint8_t tmpByte)
798 {
799     LPUART_Type *base = g_linLpuartBase[instance];
800     /* Get the current LIN state of this LPUART instance. */
801     lin_state_t *linCurrentState = g_linStatePtr[instance];
802 
803     if (linCurrentState->rxSize > (linCurrentState->cntByte + 1U))
804     {
805         *(linCurrentState->rxBuff) = tmpByte;
806         linCurrentState->rxBuff++;
807     }
808     else
809     {
810         linCurrentState->checkSum = tmpByte;
811     }
812 
813     linCurrentState->cntByte++;
814     if (linCurrentState->cntByte == linCurrentState->rxSize)
815     {
816         /* Restore rxBuffer pointer */
817         linCurrentState->rxBuff -= linCurrentState->rxSize - 1U;
818         /* Regardless of the check sum calculation, the node state should be changed to receive data complete. */
819         linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA_COMPLETED;
820         if (LIN_MakeChecksumByte(linCurrentState->rxBuff, linCurrentState->rxSize - 1U, linCurrentState->currentPid) ==
821             linCurrentState->checkSum)
822         {
823             linCurrentState->currentEventId = LIN_RX_COMPLETED;
824 
825             /* callback function to handle RX COMPLETED */
826             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
827             if (linCurrentState->Callback != NULL)
828             {
829                 linCurrentState->Callback(instance, linCurrentState);
830             }
831             if (linCurrentState->isRxBlocking == true)
832             {
833                 /* Post Semaphore to signal Rx Completed*/
834                 linCurrentState->rxCompleted = true;
835             }
836             /* Clear Bus bus flag */
837             linCurrentState->isBusBusy = false;
838             linCurrentState->isRxBusy  = false;
839 
840             /* In case of receiving a go to sleep request, after callback, node is in SLEEP MODE */
841             /* In this case, node is in SLEEP MODE state */
842             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_11 $ */
843             if (linCurrentState->currentNodeState != LIN_NODE_STATE_SLEEP_MODE)
844             {
845                 (void)LIN_LPUART_GotoIdleState(base);
846             }
847         }
848         else
849         {
850             linCurrentState->currentEventId = LIN_CHECKSUM_ERROR;
851 
852             /* callback function to handle checksum error */
853             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
854             if (linCurrentState->Callback != NULL)
855             {
856                 linCurrentState->Callback(instance, linCurrentState);
857             }
858             /* Clear Bus bus flag */
859             linCurrentState->isBusBusy = false;
860             linCurrentState->isRxBusy  = false;
861             /* Change node's current state to IDLE */
862             (void)LIN_LPUART_GotoIdleState(base);
863         }
864     }
865 }
866 
LIN_LPUART_ProcessSendFrameData(uint32_t instance,uint8_t tmpByte)867 static void LIN_LPUART_ProcessSendFrameData(uint32_t instance, uint8_t tmpByte)
868 {
869     bool sendFlag = true;
870     uint8_t tmpSize;
871     bool tmpCheckSumAndSize;
872     bool tmpBuffAndSize;
873 
874     LPUART_Type *base = g_linLpuartBase[instance];
875 
876     /* Get the current LIN state of this LPUART instance. */
877     lin_state_t *linCurrentState = g_linStatePtr[instance];
878 
879     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
880     if (0U == (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_TxDataRegEmptyFlag))
881     {
882         linCurrentState->currentEventId = LIN_READBACK_ERROR;
883 
884         /* callback function to handle Readback error */
885         if (linCurrentState->Callback != NULL)
886         {
887             linCurrentState->Callback(instance, linCurrentState);
888         }
889         if (linCurrentState->isTxBlocking == false)
890         {
891             /* Clear Bus bus flag */
892             linCurrentState->isBusBusy = false;
893             linCurrentState->isTxBusy  = false;
894             /* Change node's current state to IDLE */
895             (void)LIN_LPUART_GotoIdleState(base);
896         }
897         sendFlag = false;
898     }
899     else
900     {
901         /* Remaining tx count. */
902         tmpSize = linCurrentState->txSize - linCurrentState->cntByte;
903         /* In send checksum state but the readback data is not equal to checksum */
904         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
905         tmpCheckSumAndSize = (tmpSize == 1U) && (linCurrentState->checkSum != tmpByte);
906         /* In send data state but the readback data is not equal to data to send */
907         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
908         tmpBuffAndSize = (*linCurrentState->txBuff != tmpByte) && (tmpSize != 1U);
909         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
910         if (tmpBuffAndSize || tmpCheckSumAndSize)
911         {
912             linCurrentState->currentEventId = LIN_READBACK_ERROR;
913 
914             /* callback function to handle Readback error */
915             if (linCurrentState->Callback != NULL)
916             {
917                 linCurrentState->Callback(instance, linCurrentState);
918             }
919             if (linCurrentState->isTxBlocking == false)
920             {
921                 /* Clear Bus bus flag */
922                 linCurrentState->isBusBusy = false;
923                 linCurrentState->isTxBusy  = false;
924                 /* Change node's current state to IDLE */
925                 (void)LIN_LPUART_GotoIdleState(base);
926             }
927             sendFlag = false;
928         }
929         else
930         {
931             linCurrentState->txBuff++;
932             linCurrentState->cntByte++;
933         }
934     }
935 
936     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_9 $ */
937     if (sendFlag == true)
938     {
939         if (linCurrentState->cntByte < linCurrentState->txSize)
940         {
941             /* Send checksum byte */
942             if ((linCurrentState->txSize - linCurrentState->cntByte) == 1U)
943             {
944                 LIN_LPUART_WriteByte(base, linCurrentState->checkSum);
945             }
946             /* Send data bytes */
947             else
948             {
949                 LIN_LPUART_WriteByte(base, *linCurrentState->txBuff);
950             }
951         }
952         else
953         {
954             linCurrentState->currentEventId   = LIN_TX_COMPLETED;
955             linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA_COMPLETED;
956 
957             LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_RxDataRegFullFlag);
958             /* callback function to handle event TX COMPLETED */
959             /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
960             if (linCurrentState->Callback != NULL)
961             {
962                 linCurrentState->Callback(instance, linCurrentState);
963             }
964             /* Check if the transmission is non-blocking */
965             if (linCurrentState->isTxBlocking == true)
966             {
967                 linCurrentState->txCompleted = true;
968             }
969             /* Clear Bus bus flag */
970             linCurrentState->isBusBusy = false;
971             linCurrentState->isTxBusy  = false;
972             /* Change node's current state to IDLE */
973             (void)LIN_LPUART_GotoIdleState(base);
974         }
975     }
976 }
977 
LIN_LPUART_Init(LPUART_Type * base,lin_user_config_t * linUserConfig,lin_state_t * linCurrentState,uint32_t linSourceClockFreq)978 lin_status_t LIN_LPUART_Init(LPUART_Type *base,
979                              lin_user_config_t *linUserConfig,
980                              lin_state_t *linCurrentState,
981                              uint32_t linSourceClockFreq)
982 {
983     uint32_t temp;
984     uint32_t osrValue   = 0U;
985     uint16_t sbrValue   = 0U;
986     lin_status_t retVal = LIN_SUCCESS;
987 
988     /* Assert parameters. */
989     assert(NULL != linUserConfig);
990     assert(0U != linUserConfig->baudRate);
991 
992     uint32_t instance = LIN_LPUART_GetInstance(base);
993 
994     if (linSourceClockFreq == 0U)
995     {
996         retVal = LIN_LPUART_STAT_CLOCK_GATED_OFF;
997     }
998     else
999     {
1000         /* if autobaud is enabled */
1001         if ((true == linUserConfig->autobaudEnable) && (linUserConfig->nodeFunction == (bool)LIN_SLAVE))
1002         {
1003             /* Setting Slave's baudrate to 19200 will help Slave node always detect LIN Break from Master */
1004             linUserConfig->baudRate                    = 19200U;
1005             linCurrentState->fallingEdgeInterruptCount = 0U;
1006             linCurrentState->baudrateEvalEnable        = true;
1007             s_previousTwoBitTimeLength[instance]       = 0U;
1008             s_countMeasure[instance]                   = 0U;
1009             s_timeMeasure[instance]                    = 0U;
1010         }
1011 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1012         /* LPUART init */
1013         CLOCK_EnableClock(s_lpuartClock[instance]);
1014 #if defined(LPUART_PERIPH_CLOCKS)
1015         CLOCK_EnableClock(s_lpuartPeriphClocks[instance]);
1016 #endif
1017 #endif
1018         /* Reset values */
1019         base->CTRL = 0x00000000;
1020         /* Reset match addresses */
1021         base->MATCH = 0x00000000;
1022 #if FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
1023         /* Reset IrDA modem features */
1024         base->MODIR = 0x00000000;
1025 #endif
1026 #if FSL_FEATURE_LPUART_FIFO_SIZEn(instance) > 0U
1027         /* Reset FIFO feature */
1028         base->FIFO = (LPUART_FIFO_RXUF_MASK | LPUART_FIFO_TXOF_MASK);
1029         /* Reset FIFO Watermark values */
1030         base->WATER = 0x00000000;
1031 #endif
1032 
1033         if (LIN_LPUART_CalculateBaudRate(base, linUserConfig->baudRate, linSourceClockFreq, &osrValue, &sbrValue) ==
1034             kStatus_Success)
1035         {
1036             /* Set baudrate to User's value */
1037             LIN_LPUART_SetBaudRate(base, &osrValue, &sbrValue);
1038 
1039             /* config 8-bit (M=0) */
1040             LIN_LPUART_SetBitCountPerChar(base);
1041 
1042             /* Set no parity mode */
1043             base->CTRL &= ~LPUART_CTRL_PE_MASK;
1044             base->CTRL &= ~LPUART_CTRL_PT_MASK;
1045 
1046             /* config 1 stop bit  */
1047             temp       = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
1048             base->BAUD = temp | LPUART_BAUD_SBNS(kLPUART_OneStopBit);
1049 
1050             /* Set Break char transmit length as 13 bits minimum */
1051             if (linUserConfig->nodeFunction == (bool)LIN_MASTER)
1052             {
1053                 base->STAT |= LPUART_STAT_BRK13_MASK;
1054             }
1055 
1056             (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1057 #ifdef LPUART_ERR_IRQS
1058             (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1059 #endif
1060 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1061             /* Set Break char detect length as 13 bits minimum and interrupt */
1062             base->STAT |= LPUART_STAT_LBKDE_MASK;
1063             LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1064 #endif
1065 
1066             LIN_LPUART_EnableInterrupts(
1067                 base, ((uint32_t)kLPUART_FramingErrorInterruptEnable | (uint32_t)kLPUART_RxDataRegFullInterruptEnable));
1068             (void)EnableIRQ(g_linLpuartRxTxIrqId[instance]);
1069 #ifdef LPUART_ERR_IRQS
1070             (void)EnableIRQ(g_linLpuartErrIrqId[instance]);
1071 #endif
1072 
1073             /* Change node's current state to IDLE */
1074             linCurrentState->currentNodeState   = LIN_NODE_STATE_IDLE;
1075             linCurrentState->linSourceClockFreq = linSourceClockFreq;
1076             /* Clear flags in current LIN state structure */
1077             linCurrentState->isTxBusy           = false;
1078             linCurrentState->isRxBusy           = false;
1079             linCurrentState->isBusBusy          = false;
1080             linCurrentState->isRxBlocking       = false;
1081             linCurrentState->isTxBlocking       = false;
1082             linCurrentState->timeoutCounterFlag = false;
1083             linCurrentState->timeoutCounter     = 0U;
1084             linCurrentState->txCompleted        = false;
1085             linCurrentState->rxCompleted        = false;
1086             linCurrentState->frame_index        = 0U;
1087 
1088             /* Assign wakeup signal to satisfy LIN Specifications specifies that
1089              * wakeup signal shall be in range from 250us to 5 ms.
1090              */
1091             if (linUserConfig->baudRate > 10000U)
1092             {
1093                 /* Wakeup signal will be range from 400us to 800us depend on baudrate */
1094                 s_wakeupSignal[instance] = 0x80U;
1095             }
1096             else
1097             {
1098                 /* Wakeup signal will be range from 400us to 4ms depend on baudrate */
1099                 s_wakeupSignal[instance] = 0xF8U;
1100             }
1101             if (!((true == linUserConfig->autobaudEnable) && (linUserConfig->nodeFunction == (bool)LIN_SLAVE)))
1102             {
1103                 /* Enable the LPUART transmitter and receiver */
1104                 base->CTRL |= (LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
1105             }
1106         }
1107         else
1108         {
1109             retVal = LIN_ERROR;
1110         }
1111     } /* End of if (linSourceClockFreq == 0U) */
1112 
1113     return retVal;
1114 }
1115 
1116 /*!
1117  * brief Shuts down the LIN_LPUART by disabling interrupts and transmitter/receiver.
1118  *
1119  * param instance LIN_LPUART instance number
1120  * return An error code or lin_status_t
1121  */
LIN_LPUART_Deinit(LPUART_Type * base)1122 lin_status_t LIN_LPUART_Deinit(LPUART_Type *base)
1123 {
1124     lin_status_t retVal          = LIN_SUCCESS;
1125     uint32_t instance            = LIN_LPUART_GetInstance(base);
1126     lin_state_t *linCurrentState = g_linStatePtr[instance];
1127     if (linCurrentState == NULL)
1128     {
1129         retVal = LIN_ERROR;
1130     }
1131     else
1132     {
1133         /* Wait until the data is completely shifted out of shift register */
1134         while (0U == (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_TransmissionCompleteFlag))
1135         {
1136             /* Do nothing */
1137         }
1138 
1139         /* Disable the LPUART transmitter and receiver */
1140         base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
1141 
1142         /* Disable LPUART interrupt. */
1143         (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1144 #ifdef LPUART_ERR_IRQS
1145         (void)DisableIRQ(g_linLpuartErrIrqId[instance]);
1146 #endif
1147 
1148 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1149         /* Disable LPUART clock */
1150         CLOCK_DisableClock(s_lpuartClock[instance]);
1151 #if defined(LPUART_PERIPH_CLOCKS)
1152         CLOCK_DisableClock(s_lpuartPeriphClocks[instance]);
1153 #endif
1154 #endif
1155         /* Change node's current state to UNINIT */
1156         linCurrentState->currentNodeState = LIN_NODE_STATE_UNINIT;
1157 
1158         /* Clear our saved pointer to the LIN state structure */
1159         g_linStatePtr[instance] = NULL;
1160     }
1161 
1162     return retVal;
1163 }
1164 
1165 /*!
1166  * brief Sends Frame data out through the LIN_LPUART module using blocking method.
1167  *
1168  * This function calculates the checksum byte and send it after the frame data.
1169  * Blocking means that the function does not return until the transmission is complete.
1170  *
1171  * param base LPUART peripheral base address
1172  * param txBuff source buffer containing 8-bit data chars to send
1173  * param txSize the number of bytes to send
1174  * param timeoutMSec timeout value in milli seconds
1175  * return An error code or lin_status_t
1176  */
LIN_LPUART_SendFrameDataBlocking(LPUART_Type * base,const uint8_t * txBuff,uint8_t txSize,uint32_t timeoutMSec)1177 lin_status_t LIN_LPUART_SendFrameDataBlocking(LPUART_Type *base,
1178                                               const uint8_t *txBuff,
1179                                               uint8_t txSize,
1180                                               uint32_t timeoutMSec)
1181 {
1182     /* Assert parameters. */
1183     assert(NULL != txBuff);
1184 
1185     uint32_t instance = LIN_LPUART_GetInstance(base);
1186     /* Get the current LIN state of this LPUART instance. */
1187     lin_state_t *linCurrentState = g_linStatePtr[instance];
1188     lin_status_t retVal          = LIN_SUCCESS;
1189     /* Check whether current mode is sleep mode */
1190     bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1191 
1192     /* Check if txSize > 8 or equal to 0 or node's current state
1193      * is in SLEEP mode then return STATUS_ERROR */
1194     if ((8U < txSize) || (0U == txSize) || checkSleepMode)
1195     {
1196         retVal = LIN_ERROR;
1197     }
1198     else
1199     {
1200         /* Check if the LIN Bus is busy */
1201         if (true == linCurrentState->isBusBusy)
1202         {
1203             retVal = LIN_BUS_BUSY;
1204         }
1205         else
1206         {
1207             /* Make the checksum byte. */
1208             linCurrentState->checkSum = LIN_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
1209 
1210             /* Update the LIN state structure. */
1211             linCurrentState->txBuff = txBuff;
1212             /* Add a place for checksum byte */
1213             linCurrentState->txSize         = txSize + 1U;
1214             linCurrentState->cntByte        = 0U;
1215             linCurrentState->currentEventId = LIN_NO_EVENT;
1216             linCurrentState->isBusBusy      = true;
1217             linCurrentState->isTxBusy       = true;
1218             linCurrentState->isTxBlocking   = true;
1219             linCurrentState->txCompleted    = false;
1220 
1221 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1222             /* Set Break char detect length as 10 bits minimum */
1223             base->STAT &= ~LPUART_STAT_LBKDE_MASK;
1224 #endif
1225 
1226             LIN_SetTimeoutCounter(instance, timeoutMSec);
1227             /* Set node's current state to SEND_DATA */
1228             linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
1229 
1230             /* Start sending data */
1231             LIN_LPUART_WriteByte(base, *linCurrentState->txBuff);
1232         }
1233     }
1234     return retVal;
1235 }
1236 
1237 /*!
1238  * brief Sends frame data out through the LIN_LPUART module using non-blocking method.
1239  *
1240  * This enables an a sync method for transmitting data. Non-blocking means that the function returns immediately.
1241  * The application has to get the transmit status to know when the transmit is complete.
1242  * This function will calculate the checksum byte and send it with the frame data.
1243  *
1244  * param base LPUART peripheral base address
1245  * param txBuff source buffer containing 8-bit data chars to send
1246  * param txSize the number of bytes to send
1247  * return An error code or lin_status_t
1248  */
LIN_LPUART_SendFrameData(LPUART_Type * base,const uint8_t * txBuff,uint8_t txSize)1249 lin_status_t LIN_LPUART_SendFrameData(LPUART_Type *base, const uint8_t *txBuff, uint8_t txSize)
1250 {
1251     /* Assert parameters. */
1252     assert(NULL != txBuff);
1253 
1254     uint32_t instance            = LIN_LPUART_GetInstance(base);
1255     lin_state_t *linCurrentState = g_linStatePtr[instance];
1256     lin_status_t retVal          = LIN_SUCCESS;
1257     bool checkSleepMode          = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1258 
1259     /* Check if txSize > 8 or equal to 0 or node's current state
1260      * is in SLEEP mode then return STATUS_ERROR */
1261     if ((8U < txSize) || (0U == txSize) || checkSleepMode)
1262     {
1263         retVal = LIN_ERROR;
1264     }
1265     /* If txSixe is in range from 1 to 8 */
1266     else
1267     {
1268         /* Check if the LIN Bus is busy */
1269         if (true == linCurrentState->isBusBusy)
1270         {
1271             retVal = LIN_BUS_BUSY;
1272         }
1273         else
1274         {
1275             /* Make the checksum byte. */
1276             linCurrentState->checkSum = LIN_MakeChecksumByte(txBuff, txSize, linCurrentState->currentPid);
1277 
1278             /* Update the LIN state structure. */
1279             linCurrentState->txBuff = txBuff;
1280             /* Add a place for checksum byte */
1281             linCurrentState->txSize           = txSize + 1U;
1282             linCurrentState->cntByte          = 0U;
1283             linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_DATA;
1284             linCurrentState->currentEventId   = LIN_NO_EVENT;
1285             linCurrentState->isBusBusy        = true;
1286             linCurrentState->isTxBusy         = true;
1287 
1288 /* Set Break char detect length as 10 bits minimum */
1289 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1290             /* Set Break char detect length as 10 bits minimum */
1291             base->STAT &= ~LPUART_STAT_LBKDE_MASK;
1292 #endif
1293             /* Start sending data */
1294             LIN_LPUART_WriteByte(base, *linCurrentState->txBuff);
1295         }
1296     }
1297     return retVal;
1298 }
1299 
1300 /*!
1301  * brief Get status of an on-going non-blocking transmission
1302  *  While sending frame data using non-blocking method, users can
1303  *  use this function to get status of that transmission.
1304  *  This function return LIN_TX_BUSY while sending, or LIN_TIMEOUT
1305  *  if timeout has occurred, or return LIN_SUCCESS when the transmission is complete.
1306  *  The bytesRemaining shows number of bytes that still needed to transmit.
1307  *
1308  * param base LPUART peripheral base address
1309  * param bytesRemaining  Number of bytes still needed to transmit
1310  * return lin_status_t LIN_TX_BUSY, LIN_SUCCESS or LIN_TIMEOUT
1311  */
LIN_LPUART_GetTransmitStatus(LPUART_Type * base,uint8_t * bytesRemaining)1312 lin_status_t LIN_LPUART_GetTransmitStatus(LPUART_Type *base, uint8_t *bytesRemaining)
1313 {
1314     lin_status_t retVal = LIN_SUCCESS;
1315 
1316     uint32_t instance = LIN_LPUART_GetInstance(base);
1317     /* Get the current LIN state of this LPUART instance. */
1318     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
1319 
1320     /* Get the number of bytes that is still needed to transmit */
1321     *bytesRemaining = linCurrentState->txSize - linCurrentState->cntByte;
1322 
1323     /* Return status of the on-going transmission */
1324     if (linCurrentState->currentEventId == LIN_NO_EVENT)
1325     {
1326         if (*bytesRemaining != 0U)
1327         {
1328             if (linCurrentState->timeoutCounterFlag == false)
1329             {
1330                 retVal = LIN_TX_BUSY;
1331             }
1332             else
1333             {
1334                 retVal = LIN_TIMEOUT;
1335             }
1336         }
1337     }
1338 #if !(defined(FSL_SDK_LIN_STACK_ENABLE) && (FSL_SDK_LIN_STACK_ENABLE))
1339     else if (linCurrentState->currentEventId == LIN_TIMEOUT_ERROR)
1340     {
1341         retVal = LIN_TIMEOUT;
1342     }
1343 #endif
1344     else
1345     {
1346         /* Nothing. */
1347     }
1348 
1349     return retVal;
1350 }
1351 
1352 /*!
1353  * brief Receives frame data through the LIN_LPUART module using blocking method.
1354  *  This function will check the checksum byte. If the checksum is correct, it
1355  *  will receive the frame data. Blocking means that the function does
1356  *  not return until the reception is complete.
1357  *
1358  * param base LPUART peripheral base address
1359  * param rxBuff  buffer containing 8-bit received data
1360  * param rxSize the number of bytes to receive
1361  * param timeoutMSec timeout value in milli seconds
1362  * return An error code or lin_status_t
1363  */
LIN_LPUART_RecvFrmDataBlocking(LPUART_Type * base,uint8_t * rxBuff,uint8_t rxSize,uint32_t timeoutMSec)1364 lin_status_t LIN_LPUART_RecvFrmDataBlocking(LPUART_Type *base, uint8_t *rxBuff, uint8_t rxSize, uint32_t timeoutMSec)
1365 {
1366     assert(NULL != rxBuff);
1367 
1368     uint32_t instance = LIN_LPUART_GetInstance(base);
1369 
1370     /* Get the current LIN state of this LPUART instance. */
1371     lin_state_t *linCurrentState = g_linStatePtr[instance];
1372     lin_status_t retVal          = LIN_SUCCESS;
1373     /* Check whether current mode is sleep mode */
1374     bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1375 
1376     /* Check if rxSize > 8 or equal to 0 or node's current state
1377      * is in SLEEP mode then return STATUS_ERROR */
1378     if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
1379     {
1380         retVal = LIN_ERROR;
1381     }
1382     /* if rxSize is from 1 to 8 */
1383     else
1384     {
1385         /* Check if the LIN Bus is busy */
1386         if (true == linCurrentState->isBusBusy)
1387         {
1388             retVal = LIN_BUS_BUSY;
1389         }
1390         else
1391         {
1392             /* Update the LIN state structure. */
1393             linCurrentState->rxBuff = rxBuff;
1394             /* Add a place for checksum byte */
1395             linCurrentState->rxSize  = rxSize + 1U;
1396             linCurrentState->cntByte = 0U;
1397 
1398             /* Start receiving data */
1399             linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
1400             linCurrentState->currentEventId   = LIN_NO_EVENT;
1401             linCurrentState->isBusBusy        = true;
1402             linCurrentState->isRxBusy         = true;
1403             linCurrentState->isRxBlocking     = true;
1404             linCurrentState->rxCompleted      = false;
1405 
1406 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1407             /* Set Break char detect length as 10 bits minimum */
1408             base->STAT &= ~LPUART_STAT_LBKDE_MASK;
1409 #endif
1410 
1411             LIN_SetTimeoutCounter(instance, timeoutMSec);
1412         }
1413     }
1414 
1415     return retVal;
1416 }
1417 
1418 /*!
1419  * brief Receives frame data through the LIN_LPUART module using blocking method.
1420  *  This function will check the checksum byte. If the checksum is correct, it
1421  *  will receive the frame data. Blocking means that the function does
1422  *  not return until the reception is complete.
1423  *
1424  * param base LPUART peripheral base address
1425  * param rxBuff  buffer containing 8-bit received data
1426  * param rxSize the number of bytes to receive
1427  * param timeoutMSec timeout value in milli seconds
1428  * return An error code or lin_status_t
1429  */
LIN_LPUART_RecvFrmData(LPUART_Type * base,uint8_t * rxBuff,uint8_t rxSize)1430 lin_status_t LIN_LPUART_RecvFrmData(LPUART_Type *base, uint8_t *rxBuff, uint8_t rxSize)
1431 {
1432     assert(NULL != rxBuff);
1433 
1434     lin_status_t retVal = LIN_SUCCESS;
1435 
1436     uint32_t instance = LIN_LPUART_GetInstance(base);
1437 
1438     /* Get the current LIN state of this LPUART instance. */
1439     lin_state_t *linCurrentState = g_linStatePtr[instance];
1440 
1441     /* Check whether current mode is sleep mode */
1442     bool checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1443 
1444     /* Check if rxSize > 8 or equal to 0 or node's current state
1445      * is in SLEEP mode then return STATUS_ERROR */
1446     if ((8U < rxSize) || (0U == rxSize) || checkSleepMode)
1447     {
1448         retVal = LIN_ERROR;
1449     }
1450     /* if rxSize is from 1 to 8 */
1451     else
1452     {
1453         /* Check if the LIN Bus is busy */
1454         if (true == linCurrentState->isBusBusy)
1455         {
1456             retVal = LIN_BUS_BUSY;
1457         }
1458         else
1459         {
1460             /* Update the LIN state structure. */
1461             linCurrentState->rxBuff = rxBuff;
1462             /* Add a place for checksum byte */
1463             linCurrentState->rxSize  = rxSize + 1U;
1464             linCurrentState->cntByte = 0U;
1465 
1466             /* Start receiving data */
1467             linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_DATA;
1468             linCurrentState->currentEventId   = LIN_NO_EVENT;
1469             linCurrentState->isBusBusy        = true;
1470             linCurrentState->isRxBusy         = true;
1471             linCurrentState->isRxBlocking     = false;
1472 
1473 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1474             /* Set Break char detect length as 10 bits minimum */
1475             base->STAT &= ~LPUART_STAT_LBKDE_MASK;
1476 #endif
1477         }
1478     }
1479 
1480     return retVal;
1481 }
1482 
1483 /*!
1484  * brief Aborts an on-going non-blocking transmission/reception.
1485  *  While performing a non-blocking transferring data, users can call this function
1486  *  to terminate immediately the transferring.
1487  *
1488  * param base LPUART peripheral base address
1489  * return An error code or lin_status_t
1490  */
LIN_LPUART_AbortTransferData(LPUART_Type * base)1491 lin_status_t LIN_LPUART_AbortTransferData(LPUART_Type *base)
1492 {
1493     lin_status_t retVal = LIN_SUCCESS;
1494 
1495     uint32_t instance = LIN_LPUART_GetInstance(base);
1496     /* Get the current LIN state of this LPUART instance. */
1497     lin_state_t *linCurrentState = g_linStatePtr[instance];
1498 
1499     /* Check if no transfer is running. */
1500     if (true == linCurrentState->isBusBusy)
1501     {
1502         /* Change node's current state to IDLE */
1503         (void)LIN_LPUART_GotoIdleState(base);
1504 
1505         /* Clear LIN Bus Busy flag */
1506         linCurrentState->isTxBusy  = false;
1507         linCurrentState->isRxBusy  = false;
1508         linCurrentState->isBusBusy = false;
1509     }
1510 
1511     return retVal;
1512 }
1513 
1514 /*!
1515  * brief Get status of an on-going non-blocking reception
1516  *  While receiving frame data using non-blocking method, users can
1517  *  use this function to get status of that receiving.
1518  *  This function return the current event ID, LIN_RX_BUSY while receiving
1519  *  and return LIN_SUCCESS, or timeout (LIN_TIMEOUT) when the reception is complete.
1520  *  The bytesRemaining shows number of bytes that still needed to receive.
1521  *
1522  * param base LPUART peripheral base address
1523  * param bytesRemaining  Number of bytes still needed to receive
1524  * return lin_status_t LIN_RX_BUSY, LIN_TIMEOUT or LIN_SUCCESS
1525  */
LIN_LPUART_GetReceiveStatus(LPUART_Type * base,uint8_t * bytesRemaining)1526 lin_status_t LIN_LPUART_GetReceiveStatus(LPUART_Type *base, uint8_t *bytesRemaining)
1527 {
1528     lin_status_t retVal = LIN_SUCCESS;
1529 
1530     uint32_t instance = LIN_LPUART_GetInstance(base);
1531     /* Get the current LIN state of this LPUART instance. */
1532     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
1533 
1534     /* Get the number of bytes that is still needed to receive */
1535     *bytesRemaining = linCurrentState->rxSize - linCurrentState->cntByte;
1536 
1537     /* Return status of the on-going reception */
1538     if (linCurrentState->currentEventId == LIN_NO_EVENT)
1539     {
1540         if (*bytesRemaining != 0U)
1541         {
1542             if (linCurrentState->timeoutCounterFlag == false)
1543             {
1544                 retVal = LIN_RX_BUSY;
1545             }
1546             else
1547             {
1548                 retVal = LIN_TIMEOUT;
1549             }
1550         }
1551     }
1552 #if !(defined(FSL_SDK_LIN_STACK_ENABLE) && (FSL_SDK_LIN_STACK_ENABLE))
1553     else if (linCurrentState->currentEventId == LIN_TIMEOUT_ERROR)
1554     {
1555         retVal = LIN_TIMEOUT;
1556     }
1557 #endif
1558     else
1559     {
1560         /* Nothing. */
1561     }
1562 
1563     return retVal;
1564 }
1565 
1566 /*!
1567  * brief This function puts current node to sleep mode
1568  * This function changes current node state to LIN_NODE_STATE_SLEEP_MODE
1569  *
1570  * param base LPUART peripheral base address
1571  * return An error code or lin_status_t
1572  */
LIN_LPUART_GoToSleepMode(LPUART_Type * base)1573 lin_status_t LIN_LPUART_GoToSleepMode(LPUART_Type *base)
1574 {
1575     lin_status_t retVal = LIN_SUCCESS;
1576 
1577     uint32_t instance = LIN_LPUART_GetInstance(base);
1578 
1579     /* Get the current LIN state of this LPUART instance. */
1580     lin_state_t *linCurrentState = g_linStatePtr[instance];
1581 
1582     /* Update node's current state to SLEEP_MODE. */
1583     linCurrentState->currentNodeState = LIN_NODE_STATE_SLEEP_MODE;
1584 
1585     /* Set Receive data not inverted */
1586     LIN_LPUART_SetRxDataPolarity(base, false);
1587 
1588     (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1589 #ifdef LPUART_ERR_IRQS
1590     (void)DisableIRQ(g_linLpuartErrIrqId[instance]);
1591 #endif
1592 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1593     LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1594 #endif
1595 
1596     LIN_LPUART_DisableInterrupts(
1597         base, ((uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_FramingErrorInterruptEnable));
1598     LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_RxActiveEdgeInterruptEnable);
1599     (void)EnableIRQ(g_linLpuartRxTxIrqId[instance]);
1600 #ifdef LPUART_ERR_IRQS
1601     (void)EnableIRQ(g_linLpuartErrIrqId[instance]);
1602 #endif
1603 
1604     return retVal;
1605 }
1606 
1607 /*!
1608  * brief Puts current LIN node to Idle state
1609  * This function changes current node state to LIN_NODE_STATE_IDLE
1610  *
1611  * param base LPUART peripheral base address
1612  * return An error code or lin_status_t
1613  */
LIN_LPUART_GotoIdleState(LPUART_Type * base)1614 lin_status_t LIN_LPUART_GotoIdleState(LPUART_Type *base)
1615 {
1616     uint32_t instance = LIN_LPUART_GetInstance(base);
1617     /* Get the current LIN state of this LPUART instance. */
1618     lin_state_t *linCurrentState = g_linStatePtr[instance];
1619 
1620     /* Set Receive data not inverted */
1621     LIN_LPUART_SetRxDataPolarity(base, false);
1622 
1623     (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1624 #ifdef LPUART_ERR_IRQS
1625     (void)DisableIRQ(g_linLpuartErrIrqId[instance]);
1626 #endif
1627 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1628     /* Set Break char detect length as 13 bits minimum */
1629     base->STAT |= LPUART_STAT_LBKDE_MASK;
1630     LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1631 #endif
1632 
1633     LIN_LPUART_EnableInterrupts(
1634         base, ((uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_FramingErrorInterruptEnable));
1635 
1636     LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_RxActiveEdgeInterruptEnable);
1637 
1638     (void)EnableIRQ(g_linLpuartRxTxIrqId[instance]);
1639 #ifdef LPUART_ERR_IRQS
1640     (void)EnableIRQ(g_linLpuartErrIrqId[instance]);
1641 #endif
1642     /* Change node's current state to IDLE */
1643     linCurrentState->currentNodeState = LIN_NODE_STATE_IDLE;
1644 
1645     return LIN_SUCCESS;
1646 }
1647 
1648 /*!
1649  * brief Sends a wakeup signal through the LIN_LPUART interface
1650  *
1651  * param base LPUART peripheral base address
1652  * return An error code or lin_status_t
1653  */
LIN_LPUART_SendWakeupSignal(LPUART_Type * base)1654 lin_status_t LIN_LPUART_SendWakeupSignal(LPUART_Type *base)
1655 {
1656     uint32_t instance = LIN_LPUART_GetInstance(base);
1657 
1658     /* Get the current LIN state of this LPUART instance. */
1659     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
1660     lin_status_t retVal                = LIN_SUCCESS;
1661 
1662     if (linCurrentState->isBusBusy == false)
1663     {
1664         /* Send a wakeup signal */
1665         LIN_LPUART_WriteByte(base, s_wakeupSignal[instance]);
1666     }
1667     else
1668     {
1669         retVal = LIN_BUS_BUSY;
1670     }
1671 
1672     return retVal;
1673 }
1674 
1675 /*!
1676  * brief Sends frame header out through the LIN_LPUART module using a non-blocking method.
1677  *  This function sends LIN Break field, sync field then the ID with
1678  *  correct parity.
1679  *
1680  * param base LPUART peripheral base address
1681  * param id Frame Identifier
1682  * return An error code or lin_status_t
1683  */
LIN_LPUART_MasterSendHeader(LPUART_Type * base,uint8_t id)1684 lin_status_t LIN_LPUART_MasterSendHeader(LPUART_Type *base, uint8_t id)
1685 {
1686     lin_status_t retVal = LIN_SUCCESS;
1687     bool checkSleepMode = false;
1688 
1689     uint32_t instance = LIN_LPUART_GetInstance(base);
1690     /* Get the current LIN user config structure of this LPUART instance. */
1691     const lin_user_config_t *linUserConfig = (const lin_user_config_t *)(uint32_t)g_linUserconfigPtr[instance];
1692 
1693     /* Get the current LIN state of this LPUART instance. */
1694     lin_state_t *linCurrentState = g_linStatePtr[instance];
1695 
1696     /* Check whether current mode is sleep mode */
1697     checkSleepMode = (LIN_NODE_STATE_SLEEP_MODE == linCurrentState->currentNodeState);
1698     /* Check if the current node is slave */
1699     if ((linUserConfig->nodeFunction == (bool)LIN_SLAVE) || (0x3FU < id) || checkSleepMode)
1700     {
1701         retVal = LIN_ERROR;
1702     }
1703     else
1704     {
1705         /* Check if the LIN bus is busy */
1706         if (true == linCurrentState->isBusBusy)
1707         {
1708             retVal = LIN_BUS_BUSY;
1709         }
1710         else
1711         {
1712             linCurrentState->currentId = id;
1713 
1714             /* Make parity for the current ID */
1715             linCurrentState->currentPid = LIN_ProcessParity(id, MAKE_PARITY);
1716 
1717             /* Send Break field */
1718             linCurrentState->currentNodeState = LIN_NODE_STATE_SEND_BREAK_FIELD;
1719             linCurrentState->currentEventId   = LIN_NO_EVENT;
1720             linCurrentState->isBusBusy        = true;
1721 
1722 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1723             /* Set Break char detect length as 13 bits minimum */
1724             base->STAT |= LPUART_STAT_LBKDE_MASK;
1725             LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1726 #endif
1727             (void)LIN_LPUART_QueueBreakChar(base);
1728         }
1729     }
1730 
1731     return retVal;
1732 }
1733 
1734 /*!
1735  * brief Enables LIN_LPUART hardware interrupts.
1736  *
1737  * param base LPUART peripheral base address
1738  * return An error code or lin_status_t
1739  */
LIN_LPUART_EnableIRQ(LPUART_Type * base)1740 lin_status_t LIN_LPUART_EnableIRQ(LPUART_Type *base)
1741 {
1742     lin_status_t retVal = LIN_SUCCESS;
1743     uint32_t instance   = LIN_LPUART_GetInstance(base);
1744     /* Get the current LIN state of this LPUART instance. */
1745     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
1746 
1747     (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1748 
1749     if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1750     {
1751         /* Enable RX Input Active Edge interrupt */
1752         LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_RxActiveEdgeInterruptEnable);
1753     }
1754     else
1755     {
1756 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1757         LIN_LPUART_EnableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1758 #endif
1759         LIN_LPUART_EnableInterrupts(
1760             base, ((uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_FramingErrorInterruptEnable));
1761     }
1762 
1763     (void)EnableIRQ(g_linLpuartRxTxIrqId[instance]);
1764 #ifdef LPUART_ERR_IRQS
1765     (void)EnableIRQ(g_linLpuartErrIrqId[instance]);
1766 #endif
1767 
1768     return retVal;
1769 }
1770 
1771 /*!
1772  * brief Disables LIN_LPUART hardware interrupts.
1773  *
1774  * param base LPUART peripheral base address
1775  * return An error code or lin_status_t
1776  */
LIN_LPUART_DisableIRQ(LPUART_Type * base)1777 lin_status_t LIN_LPUART_DisableIRQ(LPUART_Type *base)
1778 {
1779     lin_status_t retVal = LIN_SUCCESS;
1780 
1781     uint32_t instance = LIN_LPUART_GetInstance(base);
1782 
1783     /* Get the current LIN state of this LPUART instance. */
1784     const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
1785 
1786     if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1787     {
1788         /* Disable RX Input Active Edge interrupt */
1789         LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_RxActiveEdgeInterruptEnable);
1790     }
1791     else
1792     {
1793 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1794         LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1795 #endif
1796         LIN_LPUART_DisableInterrupts(
1797             base, ((uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_FramingErrorInterruptEnable));
1798     }
1799 
1800     (void)DisableIRQ(g_linLpuartRxTxIrqId[instance]);
1801 #ifdef LPUART_ERR_IRQS
1802     (void)DisableIRQ(g_linLpuartErrIrqId[instance]);
1803 #endif
1804 
1805     /* Disable LPUART interrupt. */
1806     return retVal;
1807 }
1808 
1809 /*!
1810  * brief This function capture bits time to detect break char, calculate
1811  * baudrate from sync bits and enable transceiver if autobaud successful.
1812  * This function should only be used in Slave.
1813  * The timer should be in mode input capture of both rising and falling edges.
1814  * The timer input capture pin should be externally connected to RXD pin.
1815  *
1816  * param instance LPUART instance
1817  * return lin_status_t
1818  */
LIN_LPUART_AutoBaudCapture(uint32_t instance)1819 lin_status_t LIN_LPUART_AutoBaudCapture(uint32_t instance)
1820 {
1821     /* Get base address of the LPUART instance. */
1822     LPUART_Type *base = g_linLpuartBase[instance];
1823     /* Get the current LIN user config structure of this LPUART instance. */
1824     const lin_user_config_t *linUserConfig = (const lin_user_config_t *)(uint32_t)g_linUserconfigPtr[instance];
1825     /* Get the current LIN state of this LPUART instance. */
1826     lin_state_t *linCurrentState = g_linStatePtr[instance];
1827     lin_status_t retVal          = LIN_BUS_BUSY;
1828     uint32_t tmpTime             = 0U;
1829 
1830     if (true == linCurrentState->baudrateEvalEnable)
1831     {
1832         /* Calculate time between two bit (for service autobaud) */
1833         (void)linUserConfig->timerGetTimeIntervalCallback(&tmpTime);
1834 
1835         /* Get two bits time length */
1836         s_timeMeasure[instance] += tmpTime;
1837         s_countMeasure[instance]++;
1838         if ((s_countMeasure[instance] > 1U))
1839         {
1840             switch (linCurrentState->currentNodeState)
1841             {
1842                 /* If current state is SLEEP MODE */
1843                 case LIN_NODE_STATE_SLEEP_MODE:
1844                     /* If length of the dominant signal is from 150us to 5ms, it is a wakeup signal */
1845                     if ((tmpTime >= 150000U) && (tmpTime <= 5000000U))
1846                     {
1847                         linCurrentState->currentEventId = LIN_WAKEUP_SIGNAL;
1848 
1849                         /* Callback to handle event: Received a wakeup signal */
1850                         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
1851                         if (linCurrentState->Callback != NULL)
1852                         {
1853                             linCurrentState->Callback(instance, linCurrentState);
1854                         }
1855 
1856                         /* Change node's state to IDLE */
1857                         (void)LIN_LPUART_GotoIdleState(base);
1858                     }
1859                     else
1860                     {
1861                         retVal = LIN_ERROR;
1862                     }
1863                     s_countMeasure[instance] = 0U;
1864 
1865                     break;
1866                 /* If current state is IDLE */
1867                 case LIN_NODE_STATE_IDLE:
1868                     /* Check break time minimum */
1869                     if (tmpTime >= AUTOBAUD_BREAK_TIME_MIN)
1870                     {
1871 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
1872                         /* Set Break char detect length as 13 bits minimum and interrupt */
1873                         base->STAT &= ~LPUART_STAT_LBKDE_MASK;
1874                         LIN_LPUART_DisableInterrupts(base, (uint32_t)kLPUART_LinBreakInterruptEnable);
1875 #endif
1876 
1877                         /* Set flag LIN bus busy */
1878                         linCurrentState->isBusBusy = true;
1879 
1880                         /* Change the node's current state to RECEIVED BREAK FIELD */
1881                         linCurrentState->currentEventId = LIN_RECV_BREAK_FIELD_OK;
1882 
1883                         /* Callback function */
1884                         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
1885                         if (linCurrentState->Callback != NULL)
1886                         {
1887                             linCurrentState->Callback(instance, linCurrentState);
1888                         }
1889 
1890                         /* Change the node's current state to RECEIVING SYNC FIELD */
1891                         linCurrentState->currentNodeState = LIN_NODE_STATE_RECV_SYNC;
1892 
1893                         /* Start Autobaud Count(initialize number of measurements in sync byte) */
1894                         linCurrentState->fallingEdgeInterruptCount = 0U;
1895 
1896                         s_countMeasure[instance] = 1U;
1897                     }
1898                     else
1899                     {
1900                         s_countMeasure[instance] = 0U;
1901                         retVal                   = LIN_ERROR;
1902                     }
1903 
1904                     break;
1905                 /* If current state is RECEIVE SYNC */
1906                 default:
1907                     /* Calculate baudrate */
1908                     LIN_LPUART_AutobaudTimerValEval(instance, s_timeMeasure[instance]);
1909 
1910                     /* Reset to measure in next times */
1911                     s_countMeasure[instance] = 0U;
1912                     s_timeMeasure[instance]  = 0U;
1913 
1914                     if (linCurrentState->currentNodeState == LIN_NODE_STATE_IDLE)
1915                     {
1916                         retVal = LIN_ERROR;
1917                     }
1918 
1919                     break;
1920             }
1921         }
1922     }
1923     else
1924     {
1925         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_12 $ */
1926         if (linCurrentState->fallingEdgeInterruptCount > 4U)
1927         {
1928             /* Enable the LPUART transmitter and receiver */
1929             base->CTRL |= (LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
1930 
1931             linCurrentState->fallingEdgeInterruptCount = 0U;
1932         }
1933 
1934         retVal = LIN_SUCCESS;
1935     }
1936 
1937     return retVal;
1938 }
1939 
1940 /*!
1941  * brief LIN_LPUART RX TX interrupt handler
1942  *
1943  * param base LPUART peripheral base address
1944  * return void
1945  */
LIN_LPUART_IRQHandler(LPUART_Type * base)1946 void LIN_LPUART_IRQHandler(LPUART_Type *base)
1947 {
1948     uint8_t tmpByte = 0xFFU;
1949 
1950     uint32_t instance = LIN_LPUART_GetInstance(base);
1951 
1952     /* Get the current LIN state of this LPUART instance. */
1953     lin_state_t *linCurrentState = g_linStatePtr[instance];
1954 
1955     /* Check RX Input Active Edge interrupt enable */
1956     bool activeEdgeIntState = (0U != (base->BAUD & ((uint32_t)1 << LPUART_BAUD_RXEDGIE_SHIFT))) ? true : false;
1957 
1958     /* If LIN break character has been detected. */
1959     if (0U != (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_LinBreakFlag))
1960     {
1961         LIN_LPUART_ProcessBreakDetect(instance);
1962     }
1963     else
1964     {
1965         /* If LPUART_RX Pin Active Edge has been detected. */
1966         if (((uint32_t)kLPUART_RxActiveEdgeFlag ==
1967              (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_RxActiveEdgeFlag)) &&
1968             activeEdgeIntState)
1969         {
1970             /* Clear LPUART_RX Pin Active Edge Interrupt Flag. Write 1 to clear */
1971             (void)LIN_LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxActiveEdgeFlag);
1972 
1973             /* Check if the node is in SLEEP MODE */
1974             /* If yes, then check if a wakeup signal has been received */
1975             if (linCurrentState->currentNodeState == LIN_NODE_STATE_SLEEP_MODE)
1976             {
1977                 LIN_LPUART_CheckWakeupSignal(instance);
1978             }
1979         }
1980         else
1981         {
1982             /* If Framing Error has been detected Write 1 to clear */
1983             if (0U != (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_FramingErrorFlag))
1984             {
1985                 /* Clear Framing Error Interrupt Flag */
1986                 (void)LIN_LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_FramingErrorFlag);
1987 
1988                 /* Read dummy to clear LPUART_RX_DATA_REG_FULL flag */
1989                 LIN_LPUART_ReadByte((const LPUART_Type *)(uint32_t)base, &tmpByte);
1990                 /* Set current event id to LIN_FRAME_ERROR */
1991                 linCurrentState->currentEventId = LIN_FRAME_ERROR;
1992 
1993                 if (linCurrentState->currentNodeState == LIN_NODE_STATE_SEND_DATA)
1994                 {
1995                     /* Callback function to handle Framing Error Event */
1996                     /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
1997                     if (linCurrentState->Callback != NULL)
1998                     {
1999                         linCurrentState->Callback(instance, linCurrentState);
2000                     }
2001                 }
2002 
2003                 /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_13 $ */
2004                 if (linCurrentState->isRxBlocking == false)
2005                 {
2006                     if (linCurrentState->currentNodeState == LIN_NODE_STATE_RECV_DATA)
2007                     {
2008                         /* Callback function to handle Framing Error Event */
2009                         /* $Branch Coverage Justification$ $ref lin_lpuart_c_ref_3$ */
2010                         if (linCurrentState->Callback != NULL)
2011                         {
2012                             linCurrentState->Callback(instance, linCurrentState);
2013                         }
2014                     }
2015                 }
2016 
2017                 /* Clear Bus busy Flag */
2018                 linCurrentState->isBusBusy = false;
2019                 /* Change node's state to IDLE */
2020                 (void)LIN_LPUART_GotoIdleState(base);
2021             }
2022             else
2023             {
2024                 if (0U != (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_RxDataRegFullFlag))
2025                 {
2026                     (void)LIN_LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxDataRegFullFlag);
2027                     /* Get data from Data Register & Clear LPUART_RX_DATA_REG_FULL flag */
2028                     LIN_LPUART_ReadByte((const LPUART_Type *)(uint32_t)base, &tmpByte);
2029                     /* Process data in Data Register while receive, send data */
2030                     LIN_LPUART_ProcessFrame(instance, tmpByte);
2031                 }
2032             } /* End else: if (LIN_LPUART_GetStatusFlags(base) & kLPUART_FramingErrorFlag) */
2033         }     /* End else: if ((LIN_LPUART_GetStatusFlags(base) & kLPUART_RxActiveEdgeFlag) && activeEdgeIntState) */
2034     }         /* End else: if (LIN_LPUART_GetStatusFlags(base) & kLPUART_LinBreakFlag) */
2035 
2036     /* Get status RX overrun flag */
2037     if ((uint32_t)kLPUART_RxOverrunFlag == (LIN_LPUART_GetStatusFlags(base) & (uint32_t)kLPUART_RxOverrunFlag))
2038     {
2039         /* Clear overrun flag */
2040         (void)LIN_LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxOverrunFlag);
2041     }
2042     SDK_ISR_EXIT_BARRIER;
2043 } /* End void LIN_LPUART_DRV_IRQHandler(uint32_t instance) */
2044