1 /*
2  * Copyright  2016-2019 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lin.h"
10 #if (FSL_FEATURE_SOC_LPUART_COUNT > 0U)
11 #include "fsl_lin_lpuart.h"
12 #endif
13 
14 /*
15  * $Coverage Justification Reference$
16  *
17  * $Justification lin_c_ref_1$
18  * The LIN user callback function should always be installed for normal state
19  * handling and configured by user during lin initialization.
20  *
21  * $Justification lin_c_ref_2$
22  * The LIN driver test cases are run in bare metal environment and can only be
23  * using in non-blocking interrupt way.
24  *
25  */
26 
27 /*******************************************************************************
28  * Definitions
29  ******************************************************************************/
30 
31 /* Component ID definition, used by tools. */
32 #ifndef FSL_COMPONENT_ID
33 #define FSL_COMPONENT_ID "platform.drivers.lin"
34 #endif
35 
36 /*******************************************************************************
37  * Prototypes
38  ******************************************************************************/
39 
40 /*! @brief Table to save LIN user config buadrate values */
41 lin_baudrate_values_t g_linConfigBaudrates[LIN_NUM_OF_SUPP_BAUDRATES];
42 /*! @brief Pointers to LPUART bases for each instance. */
43 
44 /*! @brief Table to save LPUART state structure pointers */
45 lin_state_t *g_linStatePtr[FSL_FEATURE_SOC_LPUART_COUNT];
46 
47 /*! @brief Table to save LIN user config structure pointers */
48 lin_user_config_t *g_linUserconfigPtr[FSL_FEATURE_SOC_LPUART_COUNT];
49 
50 /*******************************************************************************
51  * Code
52  ******************************************************************************/
53 
BIT(const uint8_t A,uint8_t B)54 static inline uint8_t BIT(const uint8_t A, uint8_t B)
55 {
56     uint8_t tmp = A;
57 
58     tmp = (uint8_t)(((uint8_t)((uint8_t)(tmp) >> (uint8_t)(B))) & 0x01U);
59     return tmp;
60 }
61 
62 /*!
63  * brief Calculates maximal header time lenght
64  *
65  *  Theader_Maximum = 1.4 * THeader_Nominal, THeader_Nominal = 34 * TBit,
66  * ( 13 nominal bits of breack;   1 nominal bit of break delimiter; 10 bits for SYNC and 10 bits of PID)
67  * The function is not include time for conveying break and break delimiter
68  * TIME_OUT_UNIT is in micro second
69  * param baudRate baudrate
70  *
71  */
LIN_CalcMaxHeaderTimeoutCnt(uint32_t baudRate)72 uint32_t LIN_CalcMaxHeaderTimeoutCnt(uint32_t baudRate)
73 {
74     return (uint32_t)((14U * 2U * 1000000U / (LIN_TIME_OUT_UNIT_US * baudRate)) + 1U);
75 }
76 
77 /*!
78  * brief Calculates maximal header time length
79  *
80  *  TResponse_Maximum = 1.4 * TResponse_Nominal, TResponse_Nominal = 10 * (NData+ 1) * TBit
81  *
82  * param baudRate Baudrate
83  * param size Frame size
84  *
85  */
LIN_CalcMaxResTimeoutCnt(uint32_t baudRate,uint8_t size)86 uint32_t LIN_CalcMaxResTimeoutCnt(uint32_t baudRate, uint8_t size)
87 {
88     return (uint32_t)((14U * (1U + (uint32_t)size) * 1000000U / (LIN_TIME_OUT_UNIT_US * baudRate)) + 1U);
89 }
90 
91 /*!
92  * brief Initializes linUserConfig variable for a slave node
93  *
94  * param linUserConfig Pointer to LIN user config structure
95  */
LIN_GetSlaveDefaultConfig(lin_user_config_t * linUserConfig)96 void LIN_GetSlaveDefaultConfig(lin_user_config_t *linUserConfig)
97 {
98     /* Initializes the configure structure to zero. */
99     (void)memset(linUserConfig, 0, sizeof(*linUserConfig));
100 
101     linUserConfig->autobaudEnable               = true;
102     linUserConfig->baudRate                     = 19200U;
103     linUserConfig->nodeFunction                 = (bool)LIN_SLAVE;
104     linUserConfig->timerGetTimeIntervalCallback = NULL;
105 }
106 
107 /*!
108  * brief Initializes linUserConfig variable for a master node
109  *
110  * param linUserConfig Pointer to LIN user config structure
111  */
LIN_GetMasterDefaultConfig(lin_user_config_t * linUserConfig)112 void LIN_GetMasterDefaultConfig(lin_user_config_t *linUserConfig)
113 {
114     /* Initializes the configure structure to zero. */
115     (void)memset(linUserConfig, 0, sizeof(*linUserConfig));
116 
117     linUserConfig->autobaudEnable               = false;
118     linUserConfig->baudRate                     = 19200U;
119     linUserConfig->nodeFunction                 = (bool)LIN_MASTER;
120     linUserConfig->timerGetTimeIntervalCallback = NULL;
121 }
122 
123 /*!
124  * brief Calculates baudrate registers values for given baudrate
125  *
126  * param instance LPUART instance
127  * param instance baudRate_Bps LPUART baudrate
128  * param instance srcClock_Hz LPUART clock frequency
129  * param instance osr LPUART baudrate OSR value, return value
130  * param instance sbr LPUART baudrate SBR value, return value
131  *
132  */
LIN_CalculateBaudrate(uint32_t instance,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * osr,uint16_t * sbr)133 void LIN_CalculateBaudrate(uint32_t instance, uint32_t baudRate_Bps, uint32_t srcClock_Hz, uint32_t *osr, uint16_t *sbr)
134 {
135     /* calculates baudrate registers values for required baudrate */
136     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
137     {
138         LPUART_Type *base = g_linLpuartBase[instance];
139         (void)LIN_LPUART_CalculateBaudRate(base, baudRate_Bps, srcClock_Hz, osr, sbr);
140     }
141 }
142 
143 /*!
144  * brief Set baudrate registers values
145  *
146  * param instance LPUART instance
147  * param instance osr LPUART baudrate OSR value
148  * param instance sbr LPUART baudrate SBR value
149  *
150  */
LIN_SetBaudrate(uint32_t instance,uint32_t osr,uint16_t sbr)151 void LIN_SetBaudrate(uint32_t instance, uint32_t osr, uint16_t sbr)
152 {
153     /* sets baudrate registers values for LPUART instance */
154     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
155     {
156         LPUART_Type *base = g_linLpuartBase[instance];
157         LIN_LPUART_SetBaudRate(base, &osr, &sbr);
158     }
159 }
160 
161 /*!
162  * brief Initializes an instance LIN Hardware Interface for LIN Network.
163  *
164  * The caller provides memory for the driver state structures during initialization.
165  * The user must select the LIN Hardware Interface clock source in the application to initialize the LIN Hardware
166  * Interface.
167  *
168  * param instance LPUART instance
169  * param linUserConfig user configuration structure of type #lin_user_config_t
170  * param linCurrentState pointer to the LIN Hardware Interface driver state structure
171  * return An error code or lin_status_t
172  */
LIN_Init(uint32_t instance,lin_user_config_t * linUserConfig,lin_state_t * linCurrentState,uint32_t clockSource)173 lin_status_t LIN_Init(uint32_t instance,
174                       lin_user_config_t *linUserConfig,
175                       lin_state_t *linCurrentState,
176                       uint32_t clockSource)
177 {
178     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
179 
180     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
181     {
182         LPUART_Type *base = g_linLpuartBase[instance];
183         /* Call lower level function */
184         retVal = LIN_LPUART_Init(base, linUserConfig, linCurrentState, clockSource);
185 
186         /* Save runtime structure pointer. */
187         g_linStatePtr[instance] = linCurrentState;
188         /* Save LIN user config structure pointer. */
189         g_linUserconfigPtr[instance] = linUserConfig;
190     }
191 
192     return retVal;
193 }
194 
195 /*!
196  * brief Shuts down the LIN Hardware Interface by disabling interrupts and transmitter/receiver.
197  *
198  * param instance LPUART instance
199  * return An error code or lin_status_t
200  */
LIN_Deinit(uint32_t instance)201 lin_status_t LIN_Deinit(uint32_t instance)
202 {
203     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
204 
205     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
206     {
207         LPUART_Type *base = g_linLpuartBase[instance];
208 
209         /* Call lower level function */
210         retVal = LIN_LPUART_Deinit(base);
211 
212         /* Clear runtime structure pointer. */
213         g_linStatePtr[instance] = NULL;
214         /* Clear LIN user config structure pointer. */
215         g_linUserconfigPtr[instance] = NULL;
216     }
217 
218     return retVal;
219 }
220 
221 /*!
222  * brief Installs callback function that is used for LIN_DRV_IRQHandler.
223  *
224  * note After a callback is installed, it bypasses part of the LIN Hardware Interface IRQHandler logic.
225  * Therefore, the callback needs to handle the indexes of txBuff and txSize.
226  *
227  * param instance LPUART instance.
228  * param function the LIN receive callback function.
229  * return Former LIN callback function pointer.
230  */
LIN_InstallCallback(uint32_t instance,lin_callback_t function)231 lin_callback_t LIN_InstallCallback(uint32_t instance, lin_callback_t function)
232 {
233     lin_callback_t currentCallback = NULL;
234 
235     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
236     {
237         lin_state_t *linCurrentState = g_linStatePtr[instance];
238 
239         /* Get the current callback function. */
240         currentCallback = linCurrentState->Callback;
241 
242         /* Install new callback function. */
243         linCurrentState->Callback = function;
244     }
245 
246     return currentCallback;
247 }
248 
249 /*!
250  * brief Sends Frame data out through the LIN Hardware Interface using blocking method.
251  *  This function will calculate the checksum byte and send it with the frame data.
252  *  Blocking means that the function does not return until the transmission is complete.
253  *
254  * param instance LPUART instance
255  * param txBuff source buffer containing 8-bit data chars to send
256  * param txSize the number of bytes to send
257  * param timeoutMSec timeout value in milli seconds
258  * return An error code or lin_status_t LIN_BUS_BUSY if the bus is currently busy, transmission
259  * cannot be started.
260  */
LIN_SendFrameDataBlocking(uint32_t instance,const uint8_t * txBuff,uint8_t txSize,uint32_t timeoutMSec)261 lin_status_t LIN_SendFrameDataBlocking(uint32_t instance, const uint8_t *txBuff, uint8_t txSize, uint32_t timeoutMSec)
262 {
263     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
264 
265     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
266     {
267         LPUART_Type *base = g_linLpuartBase[instance];
268         /* Call lower level function */
269         retVal = LIN_LPUART_SendFrameDataBlocking(base, txBuff, txSize, timeoutMSec);
270     }
271 
272     return retVal;
273 }
274 
275 /*!
276  * brief Sends frame data out through the LIN Hardware Interface using non-blocking method.
277  *  This enables an a-sync method for transmitting data.
278  *  Non-blocking  means that the function returns immediately.
279  *  The application has to get the transmit status to know when the transmit is complete.
280  *  This function will calculate the checksum byte and send it with the frame data.
281  * note If users use LIN_TimeoutService in a timer interrupt handler, then before using this function,
282  * users have to set timeout counter to an appropriate value by using LIN_SetTimeoutCounter(instance, timeoutValue).
283  * The timeout value should be big enough to complete the transmission. Timeout in real time is (timeoutValue) * (time
284  * period that LIN_TimeoutService is called). For example, if LIN_TimeoutService is called in an timer
285  * interrupt with period of 500 micro seconds, then timeout in real time is
286  * timeoutValue * 500 micro seconds.
287  * param instance LPUART instance
288  * param txBuff  source buffer containing 8-bit data chars to send
289  * param txSize  the number of bytes to send
290  * return An error code or lin_status_t LIN_BUS_BUSY if the bus is currently busy, transmission
291  * cannot be started. LIN_SUCCESS if the transmission was completed.
292  */
LIN_SendFrameData(uint32_t instance,const uint8_t * txBuff,uint8_t txSize)293 lin_status_t LIN_SendFrameData(uint32_t instance, const uint8_t *txBuff, uint8_t txSize)
294 {
295     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
296 
297     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
298     {
299         LPUART_Type *base = g_linLpuartBase[instance];
300         /* Call lower level function */
301         retVal = LIN_LPUART_SendFrameData(base, txBuff, txSize);
302     }
303 
304     return retVal;
305 }
306 
307 /*!
308  * brief Get status of an on-going non-blocking transmission
309  *  While sending frame data using non-blocking method, users can
310  *  use this function to get status of that transmission.
311  *  The bytesRemaining shows number of bytes that still needed to transmit.
312  *
313  * param instance LPUART instance
314  * param bytesRemaining Number of bytes still needed to transmit
315  * return lin_status_t LIN_TX_BUSY if the transmission is still in progress.
316  * LIN_TIMEOUT if timeout occurred and transmission was not completed.
317  * LIN_SUCCESS if the transmission was successful.
318  */
LIN_GetTransmitStatus(uint32_t instance,uint8_t * bytesRemaining)319 lin_status_t LIN_GetTransmitStatus(uint32_t instance, uint8_t *bytesRemaining)
320 {
321     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
322 
323     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
324     {
325         LPUART_Type *base = g_linLpuartBase[instance];
326         /* Call lower level function */
327         retVal = LIN_LPUART_GetTransmitStatus(base, bytesRemaining);
328     }
329 
330     return retVal;
331 }
332 
333 /*!
334  * brief Receives frame data through the LIN Hardware Interface using blocking method.
335  *  This function will check the checksum byte. If the checksum is correct, it
336  *  will receive the frame data. Blocking means that the function does
337  *  not return until the reception is complete.
338  *
339  * param instance LPUART instance
340  * param rxBuff  buffer containing 8-bit received data
341  * param rxSize the number of bytes to receive
342  * param timeoutMSec timeout value in milli seconds
343  * return An error code or lin_status_t
344  */
LIN_ReceiveFrameDataBlocking(uint32_t instance,uint8_t * rxBuff,uint8_t rxSize,uint32_t timeoutMSec)345 lin_status_t LIN_ReceiveFrameDataBlocking(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize, uint32_t timeoutMSec)
346 {
347     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
348 
349     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
350     {
351         LPUART_Type *base = g_linLpuartBase[instance];
352         /* Call lower level function */
353         retVal = LIN_LPUART_RecvFrmDataBlocking(base, rxBuff, rxSize, timeoutMSec);
354     }
355 
356     return retVal;
357 }
358 
359 /*!
360  * brief Receives frame data through the LIN Hardware Interface using non- blocking method.
361  *  This function will check the checksum byte. If the checksum is correct, it
362  *  will receive it with the frame data.
363  *  Non-blocking  means that the function returns immediately.
364  *  The application has to get the receive status to know when the reception is complete.
365  * note If users use LIN_TimeoutService in a timer interrupt handler, then before using this function,
366  * users have to set timeout counter to an appropriate value by using LIN_SetTimeoutCounter(instance, timeoutValue).
367  * The timeout value should be big enough to complete the reception. Timeout in real time is (timeoutValue) * (time
368  * period
369  * that LIN_TimeoutService is called). For example, if LIN_TimeoutService is called in an timer
370  * interrupt with period of 500 micro seconds, then timeout in real time is
371  * timeoutValue * 500 micro seconds.
372  *
373  * param instance LPUART instance
374  * param rxBuff  buffer containing 8-bit received data
375  * param rxSize the number of bytes to receive
376  * return An error code or lin_status_t
377  */
LIN_ReceiveFrameData(uint32_t instance,uint8_t * rxBuff,uint8_t rxSize)378 lin_status_t LIN_ReceiveFrameData(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize)
379 {
380     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
381 
382     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
383     {
384         LPUART_Type *base = g_linLpuartBase[instance];
385         /* Call lower level function */
386         retVal = LIN_LPUART_RecvFrmData(base, rxBuff, rxSize);
387     }
388 
389     return retVal;
390 }
391 
392 /*!
393  * brief Aborts an on-going non-blocking transmission/reception.
394  *  While performing a non-blocking transferring data, users can call this function
395  *  to terminate immediately the transferring.
396  *
397  * param instance LPUART instance
398  * return An error code or lin_status_t
399  */
LIN_AbortTransferData(uint32_t instance)400 lin_status_t LIN_AbortTransferData(uint32_t instance)
401 {
402     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
403 
404     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
405     {
406         LPUART_Type *base = g_linLpuartBase[instance];
407         /* Call lower level function */
408         retVal = LIN_LPUART_AbortTransferData(base);
409     }
410 
411     return retVal;
412 }
413 
414 /*!
415  * brief Get status of an on-going non-blocking reception
416  *  While receiving frame data using non-blocking method, users can
417  *  use this function to get status of that receiving.
418  *  This function return the current event ID, LIN_RX_BUSY while receiving
419  *  and return LIN_SUCCESS, or timeout (LIN_TIMEOUT) when the reception is complete.
420  *  The bytesRemaining shows number of bytes that still needed to receive.
421  *
422  * param instance LPUART instance
423  * param bytesRemaining Number of bytes still needed to receive
424  * return lin_status_t LIN_RX_BUSY, LIN_TIMEOUT or LIN_SUCCESS
425  */
LIN_GetReceiveStatus(uint32_t instance,uint8_t * bytesRemaining)426 lin_status_t LIN_GetReceiveStatus(uint32_t instance, uint8_t *bytesRemaining)
427 {
428     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
429 
430     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
431     {
432         LPUART_Type *base = g_linLpuartBase[instance];
433         /* Call lower level function */
434         retVal = LIN_LPUART_GetReceiveStatus(base, bytesRemaining);
435     }
436 
437     return retVal;
438 }
439 
440 /*!
441  * brief Puts current LIN node to sleep mode
442  * This function changes current node state to LIN_NODE_STATE_SLEEP_MODE
443  *
444  * param instance LPUART instance
445  * return An error code or lin_status_t
446  */
LIN_GoToSleepMode(uint32_t instance)447 lin_status_t LIN_GoToSleepMode(uint32_t instance)
448 {
449     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
450 
451     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
452     {
453         LPUART_Type *base = g_linLpuartBase[instance];
454         /* Call lower level function */
455         retVal = LIN_LPUART_GoToSleepMode(base);
456     }
457 
458     return retVal;
459 }
460 
461 /*!
462  * brief Puts current LIN node to Idle state
463  * This function changes current node state to LIN_NODE_STATE_IDLE
464  *
465  * param instance LPUART instance
466  * return An error code or lin_status_t
467  */
LIN_GotoIdleState(uint32_t instance)468 lin_status_t LIN_GotoIdleState(uint32_t instance)
469 {
470     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
471 
472     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
473     {
474         LPUART_Type *base = g_linLpuartBase[instance];
475         /* Call lower level function */
476         retVal = LIN_LPUART_GotoIdleState(base);
477     }
478 
479     return retVal;
480 }
481 
482 /*!
483  * brief Sends a wakeup signal through the LIN Hardware Interface
484  *
485  * param instance LPUART instance
486  * return An error code or lin_status_t
487  */
LIN_SendWakeupSignal(uint32_t instance)488 lin_status_t LIN_SendWakeupSignal(uint32_t instance)
489 {
490     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
491 
492     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
493     {
494         LPUART_Type *base = g_linLpuartBase[instance];
495         /* Call lower level function */
496         retVal = LIN_LPUART_SendWakeupSignal(base);
497     }
498 
499     return retVal;
500 }
501 
LIN_GetCurrentNodeState(uint32_t instance)502 lin_node_state_t LIN_GetCurrentNodeState(uint32_t instance)
503 {
504     lin_node_state_t retVal = LIN_NODE_STATE_UNINIT;
505 
506     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
507     {
508         const lin_state_t *linCurrentState = (const lin_state_t *)(uint32_t)g_linStatePtr[instance];
509 
510         if (linCurrentState != NULL)
511         {
512             /* return current state of node */
513             retVal = linCurrentState->currentNodeState;
514         }
515     }
516 
517     return retVal;
518 }
519 
520 /*!
521  * brief Callback function for Timer Interrupt Handler
522  * Users may use (optional, not required) LIN_TimeoutService to check if timeout has occurred during non-blocking frame
523  * data
524  * transmission and reception. User may initialize a timer (for example FTM) in Output Compare Mode
525  * with period of 500 micro seconds (recommended). In timer IRQ handler, call this function.
526  *
527  * param instance LPUART instance
528  * return void
529  */
LIN_TimeoutService(uint32_t instance)530 void LIN_TimeoutService(uint32_t instance)
531 {
532     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
533     {
534         /* Get the current LIN state of this LPUART instance. */
535         lin_state_t *linCurrentState = g_linStatePtr[instance];
536 
537         /* Get LIN node's current state */
538         lin_node_state_t state = linCurrentState->currentNodeState;
539 
540         switch (state)
541         {
542             /* If the node is SENDING DATA */
543             case LIN_NODE_STATE_SEND_DATA:
544                 /* Check if timeout Counter is 0 */
545                 if (linCurrentState->timeoutCounter == 0U)
546                 {
547                     /* Set timeout Counter flag */
548                     linCurrentState->timeoutCounterFlag = true;
549                     /* Callback to handle timeout Counter flag */
550                     /* $Branch Coverage Justification$ $ref lin_c_ref_1$ */
551                     if (linCurrentState->Callback != NULL)
552                     {
553                         linCurrentState->Callback(instance, linCurrentState);
554                     }
555 
556                     /* Check if the transmission is non-blocking */
557                     /* $Branch Coverage Justification$ $ref lin_c_ref_2$ */
558                     if (linCurrentState->isTxBlocking == false)
559                     {
560                         /* Clear Bus busy flag */
561                         linCurrentState->isBusBusy   = false;
562                         linCurrentState->isTxBusy    = false;
563                         linCurrentState->txCompleted = true;
564                     }
565                     /* Change the node's current state to IDLE */
566                     (void)LIN_GotoIdleState(instance);
567                 }
568                 /* If timeout Counter is not 0, then decrease timeout Counter by one */
569                 else
570                 {
571                     linCurrentState->timeoutCounter--;
572                 }
573                 break;
574             /* If the node is RECEIVING DATA */
575             case LIN_NODE_STATE_RECV_DATA:
576 
577                 /* Check if timeout Counter is 0 */
578                 if (linCurrentState->timeoutCounter == 0U)
579                 {
580                     /* Set timeout Counter flag */
581                     linCurrentState->timeoutCounterFlag = true;
582 
583                     /* Callback to handle timeout Counter flag */
584                     /* $Branch Coverage Justification$ $ref lin_c_ref_1$ */
585                     if (linCurrentState->Callback != NULL)
586                     {
587                         linCurrentState->Callback(instance, linCurrentState);
588                     }
589 
590                     /* Check if the reception is non-blocking */
591                     /* $Branch Coverage Justification$ $ref lin_c_ref_2$ */
592                     if (linCurrentState->isRxBlocking == false)
593                     {
594                         /* Clear Bus busy flag */
595                         linCurrentState->isBusBusy   = false;
596                         linCurrentState->isRxBusy    = false;
597                         linCurrentState->rxCompleted = true;
598                     }
599                     /* Change the node's current state to IDLE */
600                     (void)LIN_GotoIdleState(instance);
601                 }
602                 /* If timeout Counter is not 0, then decrease timeout Counter by one */
603                 else
604                 {
605                     linCurrentState->timeoutCounter--;
606                 }
607                 break;
608             default:
609                 /* The node state is not SENDING nor RECEIVING data */
610                 break;
611         }
612     }
613 }
614 
615 /*!
616  * brief Set Value for Timeout Counter that is used in LIN_TimeoutService
617  *
618  * param instance LPUART instance
619  * param timeoutValue  Timeout Value to be set
620  * return void
621  */
LIN_SetTimeoutCounter(uint32_t instance,uint32_t timeoutValue)622 void LIN_SetTimeoutCounter(uint32_t instance, uint32_t timeoutValue)
623 {
624     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
625     {
626         /* Get the current LIN state of this LPUART instance. */
627         lin_state_t *linCurrentState = g_linStatePtr[instance];
628 
629         /* Clear Timeout Counter Flag */
630         linCurrentState->timeoutCounterFlag = false;
631 
632         /* Set new value for Timeout Counter */
633         linCurrentState->timeoutCounter = timeoutValue;
634     }
635 }
636 
637 /*!
638  * brief Sends frame header out through the LIN Hardware Interface using a non-blocking method.
639  *  This function sends LIN Break field, sync field then the ID with
640  *  correct parity.
641  *
642  * param instance LPUART instance
643  * param id  Frame Identifier
644  * return An error code or lin_status_t
645  */
LIN_MasterSendHeader(uint32_t instance,uint8_t id)646 lin_status_t LIN_MasterSendHeader(uint32_t instance, uint8_t id)
647 {
648     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
649 
650     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
651     {
652         LPUART_Type *base = g_linLpuartBase[instance];
653         /* Call lower level function */
654         retVal = LIN_LPUART_MasterSendHeader(base, id);
655     }
656 
657     return retVal;
658 }
659 
660 /*!
661  * brief Enables LIN hardware interrupts.
662  *
663  * param instance LPUART instance
664  * return An error code or lin_status_t
665  */
LIN_EnableIRQ(uint32_t instance)666 lin_status_t LIN_EnableIRQ(uint32_t instance)
667 {
668     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
669 
670     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
671     {
672         LPUART_Type *base = g_linLpuartBase[instance];
673         /* Call lower level function */
674         retVal = LIN_LPUART_EnableIRQ(base);
675     }
676 
677     return retVal;
678 }
679 
680 /*!
681  * brief Disables LIN hardware interrupts.
682  *
683  * param instance LPUART instance
684  * return An error code or lin_status_t
685  */
LIN_DisableIRQ(uint32_t instance)686 lin_status_t LIN_DisableIRQ(uint32_t instance)
687 {
688     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
689 
690     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
691     {
692         LPUART_Type *base = g_linLpuartBase[instance];
693         /* Call lower level function */
694         retVal = LIN_LPUART_DisableIRQ(base);
695     }
696 
697     return retVal;
698 }
699 
700 /*!
701  * brief Interrupt handler for LIN Hardware Interface.
702  *
703  * param instance LPUART instance
704  * return void
705  */
LIN_IRQHandler(uint8_t instance)706 void LIN_IRQHandler(uint8_t instance)
707 {
708     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
709     {
710         LPUART_Type *base = g_linLpuartBase[instance];
711         /* Call lower level function */
712         LIN_LPUART_IRQHandler(base);
713     }
714     SDK_ISR_EXIT_BARRIER;
715 }
716 
717 /*!
718  * brief This function capture bits time to detect break char, calculate
719  * baudrate from sync bits and enable transceiver if autobaud successful.
720  * This function should only be used in Slave.
721  * The timer should be in mode input capture of both rising and falling edges.
722  * The timer input capture pin should be externally connected to RXD pin.
723  *
724  * param instance LPUART instance
725  * return lin_status_t
726  */
LIN_AutoBaudCapture(uint32_t instance)727 lin_status_t LIN_AutoBaudCapture(uint32_t instance)
728 {
729     lin_status_t retVal = LIN_IFC_NOT_SUPPORT;
730 
731     if (instance < (uint32_t)FSL_FEATURE_SOC_LPUART_COUNT)
732     {
733         retVal = LIN_LPUART_AutoBaudCapture(instance);
734     }
735 
736     return retVal;
737 }
738 
739 /*!
740  * brief Makes the checksum byte for a frame
741  *
742  * param buffer Pointer to Tx buffer
743  * param sizeBuffer Number of bytes that are contained in the buffer.
744  * param PID Protected Identifier byte.
745  * return the checksum byte.
746  */
LIN_MakeChecksumByte(const uint8_t * buffer,uint8_t sizeBuffer,uint8_t PID)747 uint8_t LIN_MakeChecksumByte(const uint8_t *buffer, uint8_t sizeBuffer, uint8_t PID)
748 {
749     uint8_t length;
750     uint16_t checksum;
751 
752     assert(0U != PID);
753     /* Frame identifier(ID) 0x3C(PID 0x3C) is reserved for the Master Request frame and
754        ID 0x3D(PID 0x7D) is reserved for the Slave Response frame, they should be applied with
755        classic checksum which PID value is not included in the calculation; for other PID values
756        enhanced checksum should be applied which PID value is included. */
757     if ((0x3CU != PID) && (0x7DU != PID))
758     {
759         /* For PID other than 0x3c and 0x7D: Add PID in checksum calculation */
760         checksum = PID;
761     }
762     else
763     {
764         /* For 0x3C and 0x7D: Do not add PID in checksum calculation */
765         checksum = 0U;
766     }
767 
768     for (length = sizeBuffer; 0U < length; length--)
769     {
770         checksum += *(buffer);
771         buffer++;
772         /* Deal with the carry */
773         if (checksum > 0xFFU)
774         {
775             checksum -= 0xFFU;
776         }
777     }
778 
779     /* Return reversed checksum */
780     return (~(uint8_t)checksum);
781 }
782 
783 /*!
784  * brief Makes or checks parity bits. If action is checking parity, the function
785  * returns ID value if parity bits are correct or 0xFF if parity bits are incorrect. If action
786  * is making parity bits, then from input value of ID, the function returns PID.
787  * This is not a public API as it is called by other API functions.
788  *
789  * param PID PID byte in case of checking parity bits or ID byte in case of making parity bits.
790  * param typeAction: 1 for Checking parity bits, 0 for making parity bits
791  * return 0xFF if parity bits are incorrect, ID in case of checking parity bits and
792  * they are correct. Function returns PID in case of making parity bits.
793  */
LIN_ProcessParity(uint8_t PID,uint8_t typeAction)794 uint8_t LIN_ProcessParity(uint8_t PID, uint8_t typeAction)
795 {
796     uint8_t parity;
797     uint8_t retVal;
798 
799     parity =
800         ((uint8_t)((uint8_t)((uint8_t)((uint8_t)(BIT(PID, 0U) ^ BIT(PID, 1U)) ^ BIT(PID, 2U)) ^ BIT(PID, 4U)) << 6U) |
801          (uint8_t)(
802              ((uint8_t)(~(uint8_t)((uint8_t)((uint8_t)(BIT(PID, 1U) ^ BIT(PID, 3U)) ^ BIT(PID, 4U)) ^ BIT(PID, 5U))))
803              << 7U));
804 
805     /* Check if action is checking parity bits */
806     if (CHECK_PARITY == typeAction)
807     {
808         /* If parity bits are incorrect */
809         if ((PID & 0xC0U) != parity)
810         {
811             /* Return 0xFF if parity bits are incorrect */
812             retVal = 0xFFU;
813         }
814         /* If parity bits are correct */
815         else
816         {
817             /* Return ID if parity bits are correct */
818             retVal = (uint8_t)(PID & 0x3FU);
819         }
820     }
821     /* If action is making parity bits */
822     else
823     {
824         /* Return PID in case of making parity bits */
825         retVal = (uint8_t)(PID | parity);
826     }
827 
828     return retVal;
829 }
830 
831 /*!
832  * brief Forwards a response to a lower level
833  *
834  * param instance LPUART instance
835  * param response_buff response message
836  * param response_length length of response
837  * param max_frame_res_timeout maximal timeout duration for message
838  * return An error code or lin_status_t
839  */
LIN_SetResponse(uint8_t instance,uint8_t * response_buff,uint8_t response_length,uint8_t max_frame_res_timeout)840 lin_status_t LIN_SetResponse(uint8_t instance,
841                              uint8_t *response_buff,
842                              uint8_t response_length,
843                              uint8_t max_frame_res_timeout)
844 {
845     lin_status_t retVal = LIN_ERROR;
846     /* Set correct timeout value */
847     LIN_SetTimeoutCounter(instance, max_frame_res_timeout);
848     /* Start sending data from the buffer */
849     retVal = LIN_SendFrameData(instance, response_buff, response_length);
850 
851     return retVal;
852 }
853 
854 /*!
855  * brief Forwards a response to a higher level
856  *
857  * param instance LPUART instance
858  * param response_buff response message
859  * param response_length length of response
860  * param max_frame_res_timeout maximal timeout duration for message
861  * return An error code or lin_status_t
862  */
LIN_RxResponse(uint8_t instance,uint8_t * response_buff,uint8_t response_length,uint8_t max_frame_res_timeout)863 lin_status_t LIN_RxResponse(uint8_t instance,
864                             uint8_t *response_buff,
865                             uint8_t response_length,
866                             uint8_t max_frame_res_timeout)
867 {
868     lin_status_t retVal = LIN_ERROR;
869     /* Set correct timeout value */
870     LIN_SetTimeoutCounter(instance, max_frame_res_timeout);
871     /* Start receiving frame data into input buffer */
872     retVal = LIN_ReceiveFrameData(instance, response_buff, response_length);
873 
874     return retVal;
875 }
876 
877 /*!
878  * brief Put a node into idle state
879  *
880  * param instance LPUART instance
881  * return An error code or lin_status_t
882  */
LIN_IgnoreResponse(uint8_t instance)883 lin_status_t LIN_IgnoreResponse(uint8_t instance)
884 {
885     lin_status_t retVal = LIN_ERROR;
886 
887     /* Abort frame data transferring */
888     retVal = LIN_GotoIdleState(instance);
889 
890     return retVal;
891 }
892