1 /*
2 * Copyright 2019,2021 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #ifndef _LIN_DRIVER_H_
10 #define _LIN_DRIVER_H_
11
12 /*******************************************************************************
13 * Includes
14 ******************************************************************************/
15 #include "fsl_common.h"
16
17 /*!
18 * @addtogroup lin_driver
19 * @{
20 */
21
22 /*******************************************************************************
23 * Definitions
24 ******************************************************************************/
25 #define MAKE_PARITY 0U
26 #define CHECK_PARITY 1U
27
28 /*! @name Driver version */
29 /*! @{ */
30
31 /*! @brief LIN stack driver version */
32 #define FSL_LIN_DRIVER_VERSION (MAKE_VERSION(2, 2, 1))
33
34 /* One time unit is 500 us */
35 #define LIN_TIME_OUT_UNIT_US 500U
36
37 /*!
38 * @brief Callback function to get time interval in nano seconds
39 */
40 typedef void (*lin_timer_get_time_interval_t)(uint32_t *nanoSeconds);
41
42 /*!
43 * @brief LIN Driver callback function type
44 */
45 typedef void (*lin_callback_t)(uint32_t instance, void *linState);
46
47 /*!
48 * @brief LIN hardware configuration structure
49 */
50 typedef struct
51 {
52 uint32_t baudRate; /*!< baudrate of LIN Hardware Interface to configure */
53 bool nodeFunction; /*!< Node function as Master or Slave */
54 bool autobaudEnable; /*!< Enable Autobaud feature */
55 lin_timer_get_time_interval_t
56 timerGetTimeIntervalCallback; /*!< Callback function to get time interval in nano seconds */
57 } lin_user_config_t;
58
59 /*!
60 * @brief Defines types for an enumerating event related to an Identifier.
61 */
62 typedef enum
63 {
64 LIN_NO_EVENT = 0x00U, /*!< No event yet */
65 LIN_WAKEUP_SIGNAL = 0x01U, /*!< Received a wakeup signal */
66 LIN_BAUDRATE_ADJUSTED = 0x02U, /*!< Indicate that baudrate was adjusted to Master's baudrate */
67 LIN_RECV_BREAK_FIELD_OK = 0x03U, /*!< Indicate that correct Break Field was received */
68 LIN_SYNC_OK = 0x04U, /*!< Sync byte is correct */
69 LIN_SYNC_ERROR = 0x05U, /*!< Sync byte is incorrect */
70 LIN_PID_OK = 0x06U, /*!< PID correct */
71 LIN_PID_ERROR = 0x07U, /*!< PID incorrect */
72 LIN_FRAME_ERROR = 0x08U, /*!< Framing Error */
73 LIN_READBACK_ERROR = 0x09U, /*!< Readback data is incorrect */
74 LIN_CHECKSUM_ERROR = 0x0AU, /*!< Checksum byte is incorrect */
75 LIN_TX_COMPLETED = 0x0BU, /*!< Sending data completed */
76 LIN_RX_COMPLETED = 0x0CU, /*!< Receiving data completed */
77 LIN_RX_OVERRUN = 0x0DU, /*!< Rx overrun flag. */
78 LIN_LAST_RESPONSE_SHORT_ERROR = 0x0EU /*!< Indicate that the last frame was too short */
79 } lin_event_id_t;
80
81 /*!
82 * @brief Defines Error codes of the LIN driver.
83 */
84 typedef enum
85 {
86 LIN_IFC_NOT_SUPPORT = 0x00U, /*!< This interface is not supported */
87 LIN_INITIALIZED = 0x01U, /*!< LIN Hardware has been initialized */
88 LIN_SUCCESS = 0x02U, /*!< Successfully done */
89 LIN_ERROR = 0x03U, /*!< Error */
90 LIN_TX_BUSY = 0x04U, /*!< Transmitter is busy */
91 LIN_RX_BUSY = 0x05U, /*!< Receiver is busy */
92 LIN_BUS_BUSY = 0x06U, /*!< Bus is busy */
93 LIN_NO_TRANSFER_IN_PROGRESS = 0x07U, /*!< No data transfer is in progress */
94 LIN_TIMEOUT = 0x08U, /*!< Timeout */
95 LIN_LPUART_STAT_CLOCK_GATED_OFF = 0x09U /*!< LPUART is gated from clock manager */
96 } lin_status_t;
97
98 /*!
99 * @brief Define type for an enumerating LIN Node state.
100 */
101 typedef enum
102 {
103 LIN_NODE_STATE_UNINIT = 0x00U, /*!< Uninitialized state */
104 LIN_NODE_STATE_SLEEP_MODE = 0x01U, /*!< Sleep mode state */
105 LIN_NODE_STATE_IDLE = 0x02U, /*!< Idle state */
106 LIN_NODE_STATE_SEND_BREAK_FIELD = 0x03U, /*!< Send break field state */
107 LIN_NODE_STATE_RECV_SYNC = 0x04U, /*!< Receive the synchronization byte state */
108 LIN_NODE_STATE_SEND_PID = 0x05U, /*!< Send PID state */
109 LIN_NODE_STATE_RECV_PID = 0x06U, /*!< Receive PID state */
110 LIN_NODE_STATE_RECV_DATA = 0x07U, /*!< Receive data state */
111 LIN_NODE_STATE_RECV_DATA_COMPLETED = 0x08U, /*!< Receive data completed state */
112 LIN_NODE_STATE_SEND_DATA = 0x09U, /*!< Send data state */
113 LIN_NODE_STATE_SEND_DATA_COMPLETED = 0x0AU /*!< Send data completed state */
114 } lin_node_state_t;
115
116 /*!
117 * @brief Runtime state of the LIN driver.
118 *
119 * Note that the caller provides memory for the driver state structures during
120 * initialization because the driver does not statically allocate memory.
121 */
122 typedef struct
123 {
124 const uint8_t *txBuff; /*!< The buffer of data being sent. */
125 uint8_t *rxBuff; /*!< The buffer of received data. */
126 uint8_t frame_index;
127 uint8_t cntByte; /*!< To count number of bytes already transmitted or received. */
128 volatile uint8_t txSize; /*!< The remaining number of bytes to be received. */
129 volatile uint8_t rxSize; /*!< The remaining number of bytes to be received. */
130 uint8_t checkSum; /*!< Checksum byte. */
131 volatile bool isTxBusy; /*!< True if the LIN interface is transmitting frame data. */
132 volatile bool isRxBusy; /*!< True if the LIN interface is receiving frame data. */
133 volatile bool isBusBusy; /*!< True if there are data, frame headers being transferred on bus */
134 volatile bool isTxBlocking; /*!< True if transmit is blocking transaction. */
135 volatile bool isRxBlocking; /*!< True if receive is blocking transaction. */
136 lin_callback_t Callback; /*!< Callback function to invoke after receiving a byte or transmitting a byte. */
137 uint8_t currentId; /*!< Current ID */
138 uint8_t currentPid; /*!< Current PID */
139 volatile lin_event_id_t currentEventId; /*!< Current ID Event */
140 volatile lin_node_state_t currentNodeState; /*!< Current Node state */
141 volatile uint32_t timeoutCounter; /*!< Value of the timeout counter */
142 volatile bool timeoutCounterFlag; /*!< Timeout counter flag */
143 volatile bool baudrateEvalEnable; /*!< Baudrate Evaluation Process Enable */
144 volatile uint8_t fallingEdgeInterruptCount; /*!< Falling Edge count of a sync byte */
145 uint32_t linSourceClockFreq; /*!< Frequency of the source clock for LIN */
146 volatile bool txCompleted; /*!< Used to wait for LIN interface ISR to complete transmission.*/
147 volatile bool rxCompleted; /*!< Used to wait for LIN interface ISR to complete reception*/
148 } lin_state_t;
149
150 /*! @brief Table of base addresses for LPUART instances. */
151 extern LPUART_Type *const g_linLpuartBase[FSL_FEATURE_SOC_LPUART_COUNT];
152
153 /*! @brief Table to save LPUART IRQ enumeration numbers defined in the CMSIS header file */
154 extern const IRQn_Type g_linLpuartRxTxIrqId[FSL_FEATURE_SOC_LPUART_COUNT];
155
156 #ifdef LPUART_ERR_IRQS
157 extern const IRQn_Type g_linLpuartErrIrqId[FSL_FEATURE_SOC_LPUART_COUNT];
158 #endif
159
160 /*! @brief Table to save LPUART state structure pointers */
161 extern lin_state_t *g_linStatePtr[FSL_FEATURE_SOC_LPUART_COUNT];
162
163 /*! @brief Table to save LIN user config structure pointers */
164 extern lin_user_config_t *g_linUserconfigPtr[FSL_FEATURE_SOC_LPUART_COUNT];
165
166 /*******************************************************************************
167 * API
168 ******************************************************************************/
169 #if defined(__cplusplus)
170 extern "C" {
171 #endif
172
173 /*!
174 * @name LIN DRIVER
175 * @{
176 */
177
178 /*!
179 * @brief Forwards a response to a lower level
180 *
181 * @param instance LPUART instance
182 * @param response_buff response message
183 * @param response_length length of response
184 * @param max_frame_res_timeout maximal timeout duration for message
185 * @return An error code or lin_status_t
186 */
187 lin_status_t LIN_DRV_SetResponse(uint8_t instance,
188 uint8_t *response_buff,
189 uint8_t response_length,
190 uint8_t max_frame_res_timeout);
191 /*!
192 * @brief Forwards a response to a higher level
193 *
194 * @param instance LPUART instance
195 * @param response_buff response message
196 * @param response_length length of response
197 * @param max_frame_res_timeout maximal timeout duration for message
198 * @return An error code or lin_status_t
199 */
200 lin_status_t LIN_DRV_RxResponse(uint8_t instance,
201 uint8_t *response_buff,
202 uint8_t response_length,
203 uint8_t max_frame_res_timeout);
204 /*!
205 * @brief Put a node into idle state
206 *
207 * @param instance LPUART instance
208 * @return An error code or lin_status_t
209 */
210 lin_status_t LIN_DRV_IgnoreResponse(uint8_t instance);
211
212 /*!
213 * @brief Calculates baudrate registers values for given baudrate
214 *
215 * @param instance LPUART instance
216 * @param instance baudRate_Bps LPUART baudrate
217 * @param instance srcClock_Hz LPUART clock frequency
218 * @param instance osr LPUART baudrate OSR value, return value
219 * @param instance sbr LPUART baudrate SBR value, return value
220 *
221 */
222 void LIN_DRV_CalculateBaudrate(
223 uint32_t instance, uint32_t baudRate_Bps, uint32_t srcClock_Hz, uint32_t *osr, uint16_t *sbr);
224 /*!
225 * @brief Set baudrate registers values
226 *
227 * @param instance LPUART instance
228 * @param instance osr LPUART baudrate OSR value
229 * @param instance sbr LPUART baudrate SBR value
230 *
231 */
232 void LIN_DRV_SetBaudrate(uint32_t instance, uint32_t osr, uint16_t sbr);
233 /*!
234 * @brief Initializes an instance LIN Hardware Interface for LIN Network.
235 *
236 * The caller provides memory for the driver state structures during initialization.
237 * The user must select the LIN Hardware Interface clock source in the application to initialize the LIN Hardware
238 * Interface.
239 *
240 * @param instance LPUART instance
241 * @param linUserConfig user configuration structure of type #lin_user_config_t
242 * @param linCurrentState pointer to the LIN Hardware Interface driver state structure
243 * @return operation status:
244 * - kStatus_Success : Operation was successful.
245 * - kStatus_Fail : Operation failed due to the initialization not complete.
246 */
247 lin_status_t LIN_DRV_Init(uint32_t instance, lin_user_config_t *linUserConfig, lin_state_t *linCurrentState);
248
249 /*!
250 * @brief Shuts down the LIN Hardware Interface by disabling interrupts and transmitter/receiver.
251 *
252 * @param instance LPUART instance
253 * @return Operation status.
254 */
255 lin_status_t LIN_DRV_Deinit(uint32_t instance);
256
257 /*!
258 * @brief Installs callback function that is used for LIN_DRV_IRQHandler.
259 *
260 * @note After a callback is installed, it bypasses part of the LIN Hardware Interface IRQHandler logic.
261 * Therefore, the callback needs to handle the indexes of txBuff and txSize.
262 *
263 * @param instance LPUART instance.
264 * @param function the LIN receive callback function.
265 * @return Former LIN callback function pointer.
266 */
267 lin_callback_t LIN_DRV_InstallCallback(uint32_t instance, lin_callback_t function);
268
269 /*!
270 * @brief Sends Frame data out through the LIN Hardware Interface using blocking method.
271 * This function will calculate the checksum byte and send it with the frame data.
272 * Blocking means that the function does not return until the transmission is complete.
273 *
274 * @param instance LIN instance
275 * @param txBuff source buffer containing 8-bit data chars to send
276 * @param txSize the number of bytes to send
277 * @param timeoutMSec timeout value in milli seconds
278 * @return Operation status.
279 */
280 lin_status_t LIN_DRV_SendFrameDataBlocking(uint32_t instance,
281 const uint8_t *txBuff,
282 uint8_t txSize,
283 uint32_t timeoutMSec);
284
285 /*!
286 * @brief Sends frame data out through the LIN Hardware Interface using non-blocking method.
287 * This enables an a-sync method for transmitting data.
288 * Non-blocking means that the function returns immediately.
289 * The application has to get the transmit status to know when the transmit is complete.
290 * This function will calculate the checksum byte and send it with the frame data.
291 * @note If users use LIN_TimeoutService in a timer interrupt handler, then before using this function,
292 * users have to set timeout counter to an appropriate value by using LIN_SetTimeoutCounter(instance, timeoutValue).
293 * The timeout value should be big enough to complete the transmission. Timeout in real time is (timeoutValue) * (time
294 * period that LIN_TimeoutService is called). For example, if LIN_TimeoutService is called in an timer
295 * interrupt with period of 500 micro seconds, then timeout in real time is
296 * timeoutValue * 500 micro seconds.
297 * @param instance LPUART instance
298 * @param txBuff source buffer containing 8-bit data chars to send
299 * @param txSize the number of bytes to send
300 * @return Operation status.
301 */
302 lin_status_t LIN_DRV_SendFrameData(uint32_t instance, const uint8_t *txBuff, uint8_t txSize);
303
304 /*!
305 * @brief Get status of an on-going non-blocking transmission
306 * While sending frame data using non-blocking method, users can
307 * use this function to get status of that transmission.
308 * The bytesRemaining shows number of bytes that still needed to transmit.
309 *
310 * @param instance LIN instance
311 * @param bytesRemaining Number of bytes still needed to transmit
312 * @return Operation status.
313 */
314 lin_status_t LIN_DRV_GetTransmitStatus(uint32_t instance, uint8_t *bytesRemaining);
315
316 /*!
317 * @brief Receives frame data through the LIN Hardware Interface using blocking method.
318 * This function will check the checksum byte. If the checksum is correct, it
319 * will receive the frame data. Blocking means that the function does
320 * not return until the reception is complete.
321 *
322 * @param instance LPUART instance
323 * @param rxBuff buffer containing 8-bit received data
324 * @param rxSize the number of bytes to receive
325 * @param timeoutMSec timeout value in milli seconds
326 * @return Operation status.
327 */
328 lin_status_t LIN_DRV_ReceiveFrameDataBlocking(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize, uint32_t timeoutMSec);
329
330 /*!
331 * @brief Receives frame data through the LIN Hardware Interface using non- blocking method.
332 * This function will check the checksum byte. If the checksum is correct, it
333 * will receive it with the frame data.
334 * Non-blocking means that the function returns immediately.
335 * The application has to get the receive status to know when the reception is complete.
336 * @note If users use LIN_TimeoutService in a timer interrupt handler, then before using this function,
337 * users have to set timeout counter to an appropriate value by using LIN_SetTimeoutCounter(instance, timeoutValue).
338 * The timeout value should be big enough to complete the reception. Timeout in real time is (timeoutValue) * (time
339 * period
340 * that LIN_TimeoutService is called). For example, if LIN_TimeoutService is called in an timer
341 * interrupt with period of 500 micro seconds, then timeout in real time is
342 * timeoutValue * 500 micro seconds.
343 *
344 * @param instance LPUART instance
345 * @param rxBuff buffer containing 8-bit received data
346 * @param rxSize the number of bytes to receive
347 * @return Operation status.
348 */
349 lin_status_t LIN_DRV_ReceiveFrameData(uint32_t instance, uint8_t *rxBuff, uint8_t rxSize);
350
351 /*!
352 * @brief Aborts an on-going non-blocking transmission/reception.
353 * While performing a non-blocking transferring data, users can call this function
354 * to terminate immediately the transferring.
355 *
356 * @param instance LIN instance
357 * @return Operation status.
358 */
359 lin_status_t LIN_DRV_AbortTransferData(uint32_t instance);
360
361 /*!
362 * @brief Get status of an on-going non-blocking reception
363 * While receiving frame data using non-blocking method, users can
364 * use this function to get status of that receiving.
365 * This function return the current event ID, LIN_RX_BUSY while receiving
366 * and return LIN_SUCCESS, or timeout (LIN_TIMEOUT) when the reception is complete.
367 * The bytesRemaining shows number of bytes that still needed to receive.
368 *
369 * @param instance LPUART instance
370 * @param bytesRemaining Number of bytes still needed to receive
371 * @return Operation status.
372 */
373 lin_status_t LIN_DRV_GetReceiveStatus(uint32_t instance, uint8_t *bytesRemaining);
374
375 /*!
376 * @brief Puts current LIN node to sleep mode
377 * This function changes current node state to LIN_NODE_STATE_SLEEP_MODE
378 *
379 * @param instance LPUART instance
380 * @return Operation status.
381 */
382 lin_status_t LIN_DRV_GoToSleepMode(uint32_t instance);
383
384 /*!
385 * @brief Puts current LIN node to Idle state
386 * This function changes current node state to LIN_NODE_STATE_IDLE
387 *
388 * @param instance LPUART instance
389 * @return Operation status.
390 */
391 lin_status_t LIN_DRV_GotoIdleState(uint32_t instance);
392
393 /*!
394 * @brief Sends a wakeup signal through the LIN Hardware Interface
395 *
396 * @param instance LPUART instance
397 * @return Operation status.
398 */
399 lin_status_t LIN_DRV_SendWakeupSignal(uint32_t instance);
400
401 /*!
402 * @brief Get the current LIN node state
403 *
404 * @param instance LPUART instance
405 * @return current LIN node state
406 */
407 lin_node_state_t LIN_DRV_GetCurrentNodeState(uint32_t instance);
408
409 /*!
410 * @brief Callback function for Timer Interrupt Handler
411 * Users may use (optional, not required) LIN_TimeoutService to check if timeout has occurred during non-blocking frame
412 * data
413 * transmission and reception. User may initialize a timer (for example FTM) in Output Compare Mode
414 * with period of 500 micro seconds (recommended). In timer IRQ handler, call this function.
415 *
416 * @param instance LPUART instance
417 * @return void
418 */
419 void LIN_DRV_TimeoutService(uint32_t instance);
420
421 /*!
422 * @brief Set Value for Timeout Counter that is used in LIN_TimeoutService
423 *
424 * @param instance LPUART instance
425 * @param timeoutValue Timeout Value to be set
426 * @return void
427 */
428 void LIN_SetTimeoutCounter(uint32_t instance, uint32_t timeoutValue);
429
430 /*!
431 * @brief Set Value for Timeout Counter that is used in LIN_TimeoutService
432 *
433 * @param instance LPUART instance
434 * @param timeoutValue Timeout Value to be set
435 * @return void
436 */
LIN_DRV_SetTimeoutCounter(uint32_t instance,uint32_t timeoutValue)437 static inline void LIN_DRV_SetTimeoutCounter(uint32_t instance, uint32_t timeoutValue)
438 {
439 LIN_SetTimeoutCounter(instance, timeoutValue);
440 }
441
442 /*!
443 * @brief Sends frame header out through the LIN Hardware Interface using a non-blocking method.
444 * This function sends LIN Break field, sync field then the ID with
445 * correct parity.
446 *
447 * @param instance LPUART instance
448 * @param id Frame Identifier
449 * @return Operation status.
450 */
451 lin_status_t LIN_DRV_MasterSendHeader(uint32_t instance, uint8_t id);
452
453 /*!
454 * @brief Enables LIN hardware interrupts.
455 *
456 * @param instance LPUART instance
457 * @return Operation status.
458 */
459 lin_status_t LIN_DRV_EnableIRQ(uint32_t instance);
460
461 /*!
462 * @brief Disables LIN hardware interrupts.
463 *
464 * @param instance LPUART instance
465 * @return Operation status.
466 */
467 lin_status_t LIN_DRV_DisableIRQ(uint32_t instance);
468
469 /*!
470 * @brief Interrupt handler for LIN Hardware Interface.
471 *
472 * @param instance LPUART instance
473 * @return void
474 */
475 void LIN_DRV_IRQHandler(uint8_t instance);
476
477 /*!
478 * @brief This function capture bits time to detect break char, calculate
479 * baudrate from sync bits and enable transceiver if autobaud successful.
480 * This function should only be used in Slave.
481 * The timer should be in mode input capture of both rising and falling edges.
482 * The timer input capture pin should be externally connected to RXD pin.
483 *
484 * @param instance LPUART instance
485 * @return Operation status.
486 */
487 lin_status_t LIN_AutoBaudCapture(uint32_t instance);
488
489 /*!
490 * @brief This function capture bits time to detect break char.
491 * Adding this API is just for providing interface for LIN Stack.
492 * @param instance LPUART instance
493 * @return Operation status.
494 */
LIN_DRV_AutoBaudCapture(uint32_t instance)495 static inline lin_status_t LIN_DRV_AutoBaudCapture(uint32_t instance)
496 {
497 return LIN_AutoBaudCapture(instance);
498 }
499
500 /*!
501 * @brief Makes or checks parity bits. If action is checking parity, the function
502 * returns ID value if parity bits are correct or 0xFF if parity bits are incorrect. If action
503 * is making parity bits, then from input value of ID, the function returns PID.
504 * This is not a public API as it is called by other API functions.
505 *
506 * @param PID PID byte in case of checking parity bits or ID byte in case of making parity bits.
507 * @param typeAction: 1 for Checking parity bits, 0 for making parity bits
508 * @return 0xFF if parity bits are incorrect, ID in case of checking parity bits and
509 * they are correct. Function returns PID in case of making parity bits.
510 */
511 uint8_t LIN_ProcessParity(uint8_t PID, uint8_t typeAction);
512
513 /*!
514 * @brief Makes or checks parity bits. This fucntion is the same with LIN_ProcessParity().
515 * Adding this function is just to provide the interface for LIN Stack.
516 *
517 * @param PID PID byte in case of checking parity bits or ID byte in case of making parity bits.
518 * @param typeAction: 1 for Checking parity bits, 0 for making parity bits
519 * @return 0xFF if parity bits are incorrect, ID in case of checking parity bits and
520 * they are correct. Function returns PID in case of making parity bits.
521 */
LIN_DRV_ProcessParity(uint8_t PID,uint8_t typeAction)522 static inline uint8_t LIN_DRV_ProcessParity(uint8_t PID, uint8_t typeAction)
523 {
524 return LIN_ProcessParity(PID, typeAction);
525 }
526
527 /*!
528 * @brief Makes the checksum byte for a frame
529 *
530 * @param buffer Pointer to Tx buffer
531 * @param sizeBuffer Number of bytes that are contained in the buffer.
532 * @param PID Protected Identifier byte.
533 * @return the checksum byte.
534 */
535 uint8_t LIN_MakeChecksumByte(const uint8_t *buffer, uint8_t sizeBuffer, uint8_t PID);
536
537 /*!
538 * @brief Makes the checksum byte for a frame.
539 * This function is the same with LIN_MakeChecksumByte(), And this API is just
540 * to provide interface for LIN Stack.
541 * @param buffer Pointer to Tx buffer
542 * @param sizeBuffer Number of bytes that are contained in the buffer.
543 * @param PID Protected Identifier byte.
544 * @return the checksum byte.
545 */
LIN_DRV_MakeChecksumByte(const uint8_t * buffer,uint8_t sizeBuffer,uint8_t PID)546 static inline uint8_t LIN_DRV_MakeChecksumByte(const uint8_t *buffer, uint8_t sizeBuffer, uint8_t PID)
547 {
548 return LIN_MakeChecksumByte(buffer, sizeBuffer, PID);
549 }
550 /*! @} */
551
552 #if defined(__cplusplus)
553 }
554 #endif
555
556 #endif /* _LIN_DRIVER_H_ */
557