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