2 * @brief LIN Driver Implementation File
\r
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */
\r
10 /* USER CODE BEGIN (0) */
\r
13 #include "ti_drv_lin.h"
\r
15 /* USER CODE BEGIN (1) */
\r
18 /** @fn void linInit(void)
\r
19 * @brief Initializes the lin Driver
\r
21 * This function initializes the lin module.
\r
25 /* USER CODE BEGIN (2) */
\r
27 /** @b intalise @b LIN */
\r
29 /** - Release from reset */
\r
32 /** - Start LIN configuration
\r
33 * - Keep state machine in software reset
\r
37 /** - Enable LIN Mode */
\r
38 linREG->GCR1 = 0x40U;
\r
40 /** - Setup control register 1
\r
41 * - Enable transmitter
\r
43 * - Stop when debug mode is entered
\r
44 * - Disable Loopback mode
\r
45 * - Disable / Enable HGENCTRL (Mask filtering with ID-Byte)
\r
46 * - Use enhance checksum
\r
47 * - Enable multi buffer mode
\r
48 * - Disable automatic baudrate adjustment
\r
49 * - Disable sleep mode
\r
50 * - Set LIN module as master
\r
51 * - Enable/Disable parity
\r
52 * - Disable data length control in ID4 and ID5
\r
54 linREG->GCR1 |= 0x03000C60U
\r
58 /** - Setup maximum baud rate prescaler */
\r
59 linREG->MBRSR = 3600U;
\r
61 /** - Setup baud rate prescaler */
\r
62 linREG->BRSR = 249U;
\r
64 /** - Setup RX and TX reception masks */
\r
65 linREG->MASK = (0xFFU << 16U) | 0xFFU;
\r
69 * - Sync break extension
\r
71 linREG->COMP = ((1U - 1U) << 8U) | (13U - 13U);
\r
73 /** - Setup response length */
\r
74 linREG->LENGTH = (8U - 1U);
\r
76 /** - Set LIN pins functional mode
\r
81 linREG->FUN = 4U | 2U | 0U;
\r
83 /** - Set LIN pins default output value
\r
88 linREG->DOUT = 0U | 0U | 0U;
\r
90 /** - Set LIN pins output direction
\r
95 linREG->DIR = 0U | 0U | 0U;
\r
97 /** - Set LIN pins open drain enable
\r
102 linREG->ODR = 0U | 0U | 0U;
\r
104 /** - Set LIN pins pullup/pulldown enable
\r
109 linREG->PD = 0U | 0U | 0U;
\r
111 /** - Set LIN pins pullup/pulldown select
\r
116 linREG->PSL = 4U | 2U | 1U;
\r
118 /** - Set interrupt level
\r
119 * - Bit error level
\r
120 * - Physical bus error level
\r
121 * - Checksum error level
\r
122 * - Inconsistent sync field error level
\r
123 * - No response error level
\r
124 * - Framing error level
\r
125 * - Overrun error level
\r
126 * - Parity error level
\r
127 * - Identifier level
\r
130 * - Timeout after 3 wakeup signals level
\r
131 * - Timeout after wakeup signal level
\r
134 * - Break detect level
\r
136 linREG->SETINTLVL = 0x00000000U
\r
153 /** - Set interrupt enable
\r
154 * - Enable/Disable bit error
\r
155 * - Enable/Disable physical bus error level
\r
156 * - Enable/Disable checksum error level
\r
157 * - Enable/Disable inconsistent sync field error level
\r
158 * - Enable/Disable no response error level
\r
159 * - Enable/Disable framing error level
\r
160 * - Enable/Disable overrun error level
\r
161 * - Enable/Disable parity error level
\r
162 * - Enable/Disable identifier level
\r
163 * - Enable/Disable RX level
\r
164 * - Enable/Disable TX level
\r
165 * - Enable/Disable timeout after 3 wakeup signals level
\r
166 * - Enable/Disable timeout after wakeup signal level
\r
167 * - Enable/Disable timeout level
\r
168 * - Enable/Disable wakeup level
\r
169 * - Enable/Disable break detect level
\r
171 linREG->SETINT = 0x00000000U
\r
188 /** - Finaly start LIN */
\r
189 linREG->GCR1 |= 0x00000080U;
\r
191 /* USER CODE BEGIN (3) */
\r
192 /* USER CODE END */
\r
196 /** @fn void linSetFunctional(linBASE_t *lin, uint32_t port)
\r
197 * @brief Change functional behavoiur of pins at runtime.
\r
198 * @param[in] lin - lin module base address
\r
199 * @param[in] port - Value to write to FUN register
\r
201 * Change the value of the PCFUN register at runtime, this allows to
\r
202 * dynaimcaly change the functionality of the LIN pins between functional
\r
205 void linSetFunctional(linBASE_t *lin, uint32_t port)
\r
207 /* USER CODE BEGIN (4) */
\r
208 /* USER CODE END */
\r
212 /* USER CODE BEGIN (5) */
\r
213 /* USER CODE END */
\r
217 /** @fn void linSendHeader(linBASE_t *lin, uint8_t identifier)
\r
218 * @brief Send lin header.
\r
219 * @param[in] lin - lin module base address
\r
220 * @param[in] identifier - lin header id
\r
222 * Send lin header including sync break field, sync field and identifier.
\r
224 void linSendHeader(linBASE_t *lin, uint8_t identifier)
\r
226 /* USER CODE BEGIN (6) */
\r
227 /* USER CODE END */
\r
229 lin->IDBYTE = identifier;
\r
231 /* USER CODE BEGIN (7) */
\r
232 /* USER CODE END */
\r
236 /** @fn void linSendWakupSignal(linBASE_t *lin)
\r
237 * @brief Send lin wakeup signal.
\r
238 * @param[in] lin - lin module base address
\r
240 * Send lin wakeup signal to terminate the sleep mode of any lin node connected to the BUS.
\r
242 void linSendWakupSignal(linBASE_t *lin)
\r
244 /* USER CODE BEGIN (8) */
\r
245 /* USER CODE END */
\r
247 lin->TDx[0] = 0xF0;
\r
248 lin->GCR2 |= 0x00000100U;
\r
250 /* USER CODE BEGIN (9) */
\r
251 /* USER CODE END */
\r
254 /** @fn void linEnterSleep(linBASE_t *lin)
\r
255 * @brief Take Module to Sleep.
\r
256 * @param[in] lin - lin module base address
\r
258 * Application must call this function to take Module to Sleep when Sleep command is received.
\r
259 * This function can also be called to forcefully enter Sleep when no activity on BUS.
\r
261 void linEnterSleep(linBASE_t *lin)
\r
263 /* USER CODE BEGIN (10) */
\r
264 /* USER CODE END */
\r
265 lin->GCR2 |= 0x00000001U;
\r
266 /* USER CODE BEGIN (11) */
\r
267 /* USER CODE END */
\r
270 /** @fn void linSoftwareReset(linBASE_t *lin)
\r
271 * @brief Perform sofware reset.
\r
272 * @param[in] lin - lin module base address
\r
274 * Perform software reset of lin module.
\r
275 * This function will reset the lin state machine and clear all pending flags.
\r
276 * It is required to call this function after a wakeup signal has been sent.
\r
278 void linSoftwareReset(linBASE_t *lin)
\r
280 /* USER CODE BEGIN (12) */
\r
281 /* USER CODE END */
\r
283 lin->GCR1 &= ~0x00000080U;
\r
284 lin->GCR1 |= 0x00000080U;
\r
286 /* USER CODE BEGIN (13) */
\r
287 /* USER CODE END */
\r
290 /** @fn uint32_t linIsTxReady(linBASE_t *lin)
\r
291 * @brief Check if Tx buffer empty
\r
292 * @param[in] lin - lin module base address
\r
294 * @return The TX ready flag
\r
296 * Checks to see if the Tx buffer ready flag is set, returns
\r
297 * 0 is flags not set otherwise will return the Tx flag itself.
\r
299 uint32_t linIsTxReady(linBASE_t *lin)
\r
301 /* USER CODE BEGIN (14) */
\r
302 /* USER CODE END */
\r
304 return lin->FLR & LIN_TX_READY;
\r
307 /** @fn void linSetLength(linBASE_t *lin, uint32_t length)
\r
309 * @param[in] lin - lin module base address
\r
310 * @param[in] length - number of data words in bytes. Range: 1-8.
\r
312 * Send data response length in bytes.
\r
314 void linSetLength(linBASE_t *lin, uint32_t length)
\r
316 /* USER CODE BEGIN (15) */
\r
317 /* USER CODE END */
\r
319 lin->LENGTH = length - 1U;
\r
321 /* USER CODE BEGIN (16) */
\r
322 /* USER CODE END */
\r
325 /** @fn void linSend(linBASE_t *lin, const uint8_t *data)
\r
327 * @param[in] lin - lin module base address
\r
328 * @param[in] data - pointer to data to send
\r
330 * Send a block of data pointed to by 'data'.
\r
331 * The number of data to transmit must be set with 'linSetLength' before.
\r
333 void linSend(linBASE_t *lin, const uint8_t *data)
\r
336 int length = lin->LENGTH;
\r
337 uint8_t *pData = (uint8_t *)data + length;
\r
339 /* USER CODE BEGIN (17) */
\r
340 /* USER CODE END */
\r
342 for (i = length; i >= 0; i--)
\r
344 lin->TDx[i] = *pData--;
\r
347 /* USER CODE BEGIN (18) */
\r
348 /* USER CODE END */
\r
351 /** @fn uint32_t linIsRxReady(linBASE_t *lin)
\r
352 * @brief Check if Rx buffer full
\r
353 * @param[in] lin - lin module base address
\r
355 * @return The Rx ready flag
\r
357 * Checks to see if the Rx buffer full flag is set, returns
\r
358 * 0 is flags not set otherwise will return the Rx flag itself.
\r
360 uint32_t linIsRxReady(linBASE_t *lin)
\r
362 /* USER CODE BEGIN (19) */
\r
363 /* USER CODE END */
\r
365 return lin->FLR & LIN_RX_INT;
\r
369 /** @fn uint32_t linTxRxError(linBASE_t *lin)
\r
370 * @brief Return Tx and Rx Error flags
\r
371 * @param[in] lin - lin module base address
\r
373 * @return The Tx and Rx error flags
\r
375 * Returns the bit, physical bus, checksum, inconsisten sync field,
\r
376 * no response, framing, overun, parity and timeout error flags.
\r
377 * It also clears the error flags before returning.
\r
379 uint32_t linTxRxError(linBASE_t *lin)
\r
381 uint32_t status = lin->FLR & (LIN_BE_INT
\r
393 lin->FLR = LIN_BE_INT
\r
405 /* USER CODE BEGIN (20) */
\r
406 /* USER CODE END */
\r
412 /** @fn uint32_t linGetIdentifier(linBASE_t *lin)
\r
413 * @brief Get last received identifier
\r
414 * @param[in] lin - lin module base address
\r
416 * @return Identifier
\r
418 * Read last received identifier.
\r
420 uint32_t linGetIdentifier(linBASE_t *lin)
\r
422 /* USER CODE BEGIN (21) */
\r
423 /* USER CODE END */
\r
428 /** @fn void linGetData(linBASE_t *lin, uint8_t * const data)
\r
429 * @brief Read received data
\r
430 * @param[in] lin - lin module base address
\r
431 * @param[in] data - pointer to data buffer
\r
433 * Read a block of bytes and place it into the data buffer pointed to by 'data'.
\r
435 void linGetData(linBASE_t *lin, uint8_t * const data)
\r
438 uint32_t length = lin->LENGTH;
\r
439 uint8_t *pData = (uint8_t *)data;
\r
441 /* USER CODE BEGIN (22) */
\r
442 /* USER CODE END */
\r
444 for (i = 0U; i <= length; i++)
\r
446 *pData++ = lin->RDx[i];
\r
449 /* USER CODE BEGIN (23) */
\r
450 /* USER CODE END */
\r
454 /** @fn void linEnableLoopback(linBASE_t *lin, Loopbacktype_t Loopbacktype)
\r
455 * @brief Enable Loopback mode for self test
\r
456 * @param[in] lin - lin module base address
\r
457 * @param[in] Loopbacktype - Digital or Analog
\r
459 * This function enables the Loopback mode for self test.
\r
461 void linEnableLoopback(linBASE_t *lin, Loopbacktype_t Loopbacktype)
\r
463 /* USER CODE BEGIN (24) */
\r
464 /* USER CODE END */
\r
466 /* Clear Loopback incase enbaled already */
\r
467 lin->IODFTCTRL = 0;
\r
469 /* Enable Loopback either in Analog or Digital Mode */
\r
470 lin->IODFTCTRL = 0x00000A00
\r
471 | Loopbacktype << 1;
\r
473 /* USER CODE BEGIN (25) */
\r
474 /* USER CODE END */
\r
477 /** @fn void linDisableLoopback(linBASE_t *lin)
\r
478 * @brief Enable Loopback mode for self test
\r
479 * @param[in] lin - lin module base address
\r
481 * This function disable the Loopback mode.
\r
483 void linDisableLoopback(linBASE_t *lin)
\r
485 /* USER CODE BEGIN (26) */
\r
486 /* USER CODE END */
\r
488 /* Disable Loopback Mode */
\r
489 lin->IODFTCTRL = 0x000005000;
\r
491 /* USER CODE BEGIN (27) */
\r
492 /* USER CODE END */
\r
496 /** @fn linEnableNotification(linBASE_t *lin, uint32_t flags)
\r
497 * @brief Enable interrupts
\r
498 * @param[in] lin - lin module base address
\r
499 * @param[in] flags - Interrupts to be enabled, can be ored value of:
\r
500 * LIN_BE_INT - bit error,
\r
501 * LIN_PBE_INT - physical bus error,
\r
502 * LIN_CE_INT - checksum error,
\r
503 * LIN_ISFE_INT - inconsistent sync field error,
\r
504 * LIN_NRE_INT - no response error,
\r
505 * LIN_FE_INT - framming error,
\r
506 * LIN_OE_INT - overrun error,
\r
507 * LIN_PE_INT - parity error,
\r
508 * LIN_ID_INT - received matching identifier,
\r
509 * LIN_RX_INT - receive buffer ready,
\r
510 * LIN_TOA3WUS_INT - time out after 3 wakeup signals,
\r
511 * LIN_TOAWUS_INT - time out after wakeup signal,
\r
512 * LIN_TO_INT - time out signal,
\r
513 * LIN_WAKEUP_INT - wakeup,
\r
514 * LIN_BREAK_INT - break detect
\r
516 void linEnableNotification(linBASE_t *lin, uint32_t flags)
\r
518 /* USER CODE BEGIN (28) */
\r
519 /* USER CODE END */
\r
521 lin->SETINT = flags;
\r
523 /* USER CODE BEGIN (29) */
\r
524 /* USER CODE END */
\r
528 /** @fn linDisableNotification(linBASE_t *lin, uint32_t flags)
\r
529 * @brief Disable interrupts
\r
530 * @param[in] lin - lin module base address
\r
531 * @param[in] flags - Interrupts to be disabled, can be ored value of:
\r
532 * LIN_BE_INT - bit error,
\r
533 * LIN_PBE_INT - physical bus error,
\r
534 * LIN_CE_INT - checksum error,
\r
535 * LIN_ISFE_INT - inconsistent sync field error,
\r
536 * LIN_NRE_INT - no response error,
\r
537 * LIN_FE_INT - framming error,
\r
538 * LIN_OE_INT - overrun error,
\r
539 * LIN_PE_INT - parity error,
\r
540 * LIN_ID_INT - received matching identifier,
\r
541 * LIN_RX_INT - receive buffer ready,
\r
542 * LIN_TOA3WUS_INT - time out after 3 wakeup signals,
\r
543 * LIN_TOAWUS_INT - time out after wakeup signal,
\r
544 * LIN_TO_INT - time out signal,
\r
545 * LIN_WAKEUP_INT - wakeup,
\r
546 * LIN_BREAK_INT - break detect
\r
548 void linDisableNotification(linBASE_t *lin, uint32_t flags)
\r
550 /* USER CODE BEGIN (30) */
\r
551 /* USER CODE END */
\r
553 lin->CLRINT = flags;
\r
555 /* USER CODE BEGIN (31) */
\r
556 /* USER CODE END */
\r
560 /** @fn void linHighLevelInterrupt(void)
\r
561 * @brief Level 0 Interrupt for LIN
\r
563 #pragma INTERRUPT(linHighLevelInterrupt, IRQ)
\r
565 void linHighLevelInterrupt(void)
\r
567 uint32_t vec = linREG->INTVECT0;
\r
569 /* USER CODE BEGIN (32) */
\r
570 /* USER CODE END */
\r
574 case 1: linNotification(linREG, LIN_WAKEUP_INT); break;
\r
575 case 2: linNotification(linREG, LIN_ISFE_INT); break;
\r
576 case 3: linNotification(linREG, LIN_PE_INT); break;
\r
577 case 4: linNotification(linREG, LIN_ID_INT); break;
\r
578 case 5: linNotification(linREG, LIN_PBE_INT); break;
\r
579 case 6: linNotification(linREG, LIN_FE_INT); break;
\r
580 case 7: linNotification(linREG, LIN_BREAK_INT); break;
\r
581 case 8: linNotification(linREG, LIN_CE_INT); break;
\r
582 case 9: linNotification(linREG, LIN_OE_INT); break;
\r
583 case 10: linNotification(linREG, LIN_BE_INT); break;
\r
584 case 11: linNotification(linREG, LIN_RX_INT); break;
\r
585 case 13: linNotification(linREG, LIN_NRE_INT); break;
\r
586 case 14: linNotification(linREG, LIN_TOAWUS_INT); break;
\r
587 case 15: linNotification(linREG, LIN_TOA3WUS_INT); break;
\r
588 case 16: linNotification(linREG, LIN_TO_INT); break;
\r
590 /* phantom interrupt, perform software reset */
\r
591 linREG->GCR1 &= ~0x00000080U;
\r
592 linREG->GCR1 |= 0x00000080U;
\r
595 /* USER CODE BEGIN (33) */
\r
596 /* USER CODE END */
\r
600 /** @fn void linLowLevelInterrupt(void)
\r
601 * @brief Level 1 Interrupt for LIN
\r
603 #pragma INTERRUPT(linLowLevelInterrupt, IRQ)
\r
605 void linLowLevelInterrupt(void)
\r
607 uint32_t vec = linREG->INTVECT1;
\r
609 /* USER CODE BEGIN (34) */
\r
610 /* USER CODE END */
\r
614 case 1: linNotification(linREG, LIN_WAKEUP_INT); break;
\r
615 case 2: linNotification(linREG, LIN_ISFE_INT); break;
\r
616 case 3: linNotification(linREG, LIN_PE_INT); break;
\r
617 case 4: linNotification(linREG, LIN_ID_INT); break;
\r
618 case 5: linNotification(linREG, LIN_PBE_INT); break;
\r
619 case 6: linNotification(linREG, LIN_FE_INT); break;
\r
620 case 7: linNotification(linREG, LIN_BREAK_INT); break;
\r
621 case 8: linNotification(linREG, LIN_CE_INT); break;
\r
622 case 9: linNotification(linREG, LIN_OE_INT); break;
\r
623 case 10: linNotification(linREG, LIN_BE_INT); break;
\r
624 case 11: linNotification(linREG, LIN_RX_INT); break;
\r
625 case 13: linNotification(linREG, LIN_NRE_INT); break;
\r
626 case 14: linNotification(linREG, LIN_TOAWUS_INT); break;
\r
627 case 15: linNotification(linREG, LIN_TOA3WUS_INT); break;
\r
628 case 16: linNotification(linREG, LIN_TO_INT); break;
\r
630 /* phantom interrupt, perform software reset */
\r
631 linREG->GCR1 &= ~0x00000080U;
\r
632 linREG->GCR1 |= 0x00000080U;
\r
635 /* USER CODE BEGIN (35) */
\r
636 /* USER CODE END */
\r