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