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