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