--- /dev/null
+/** @file lin.c \r
+* @brief LIN Driver Implementation File\r
+* @date 20.Mar.2012\r
+* @version 03.01.00\r
+*\r
+*/\r
+\r
+/* (c) Texas Instruments 2009-2012, All rights reserved. */\r
+\r
+/* USER CODE BEGIN (0) */\r
+/* USER CODE END */\r
+\r
+#include "lin.h"\r
+\r
+/* USER CODE BEGIN (1) */\r
+/* USER CODE END */\r
+\r
+/** @fn void linInit(void)\r
+* @brief Initializes the lin Driver\r
+*\r
+* This function initializes the lin module.\r
+*/\r
+void linInit(void)\r
+{\r
+/* USER CODE BEGIN (2) */\r
+/* USER CODE END */\r
+ /** @b intalise @b LIN */\r
+\r
+ /** - Release from reset */\r
+ linREG->GCR0 = 1U;\r
+\r
+ /** - Start LIN configuration \r
+ * - Keep state machine in software reset\r
+ */\r
+ linREG->GCR1 = 00U;\r
+\r
+ /** - Enable LIN Mode */\r
+ linREG->GCR1 = 0x40U;\r
+ \r
+ /** - Setup control register 1\r
+ * - Enable transmitter\r
+ * - Enable receiver\r
+ * - Stop when debug mode is entered\r
+ * - Disable Loopback mode\r
+ * - Disable / Enable HGENCTRL (Mask filtering with ID-Byte)\r
+ * - Use enhance checksum\r
+ * - Enable multi buffer mode\r
+ * - Disable automatic baudrate adjustment\r
+ * - Disable sleep mode\r
+ * - Set LIN module as master\r
+ * - Enable/Disable parity\r
+ * - Disable data length control in ID4 and ID5\r
+ */\r
+ linREG->GCR1 |= 0x03000C60U \r
+ | (1U << 12U)\r
+ | (0U << 2U);\r
+ \r
+ /** - Setup maximum baud rate prescaler */\r
+ linREG->MBRSR = 3600U;\r
+\r
+ /** - Setup baud rate prescaler */\r
+ linREG->BRSR = 249U;\r
+\r
+ /** - Setup RX and TX reception masks */\r
+ linREG->MASK = (0xFFU << 16U) | 0xFFU;\r
+\r
+ /** - Setup compare\r
+ * - Sync delimiter\r
+ * - Sync break extension\r
+ */\r
+ linREG->COMP = ((1U - 1U) << 8U) | (13U - 13U);\r
+\r
+ /** - Setup response length */\r
+ linREG->LENGTH = (8U - 1U);\r
+\r
+ /** - Set LIN pins functional mode \r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->FUN = 4U | 2U | 0U;\r
+\r
+ /** - Set LIN pins default output value\r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->DOUT = 0U | 0U | 0U;\r
+\r
+ /** - Set LIN pins output direction\r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->DIR = 0U | 0U | 0U;\r
+\r
+ /** - Set LIN pins open drain enable\r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->ODR = 0U | 0U | 0U;\r
+\r
+ /** - Set LIN pins pullup/pulldown enable\r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->PD = 0U | 0U | 0U;\r
+\r
+ /** - Set LIN pins pullup/pulldown select\r
+ * - TX\r
+ * - RX\r
+ * - CLK\r
+ */\r
+ linREG->PSL = 4U | 2U | 1U;\r
+\r
+ /** - Set interrupt level \r
+ * - Bit error level\r
+ * - Physical bus error level\r
+ * - Checksum error level\r
+ * - Inconsistent sync field error level\r
+ * - No response error level\r
+ * - Framing error level\r
+ * - Overrun error level\r
+ * - Parity error level\r
+ * - Identifier level\r
+ * - RX level\r
+ * - TX level\r
+ * - Timeout after 3 wakeup signals level\r
+ * - Timeout after wakeup signal level\r
+ * - Timeout level\r
+ * - Wakeup level\r
+ * - Break detect level\r
+ */\r
+ linREG->SETINTLVL = 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U;\r
+\r
+ /** - Set interrupt enable \r
+ * - Enable/Disable bit error\r
+ * - Enable/Disable physical bus error level\r
+ * - Enable/Disable checksum error level\r
+ * - Enable/Disable inconsistent sync field error level\r
+ * - Enable/Disable no response error level\r
+ * - Enable/Disable framing error level\r
+ * - Enable/Disable overrun error level\r
+ * - Enable/Disable parity error level\r
+ * - Enable/Disable identifier level\r
+ * - Enable/Disable RX level\r
+ * - Enable/Disable TX level\r
+ * - Enable/Disable timeout after 3 wakeup signals level\r
+ * - Enable/Disable timeout after wakeup signal level\r
+ * - Enable/Disable timeout level\r
+ * - Enable/Disable wakeup level\r
+ * - Enable/Disable break detect level\r
+ */\r
+ linREG->SETINT = 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U\r
+ | 0x00000000U;\r
+\r
+ /** - Finaly start LIN */\r
+ linREG->GCR1 |= 0x00000080U;\r
+\r
+/* USER CODE BEGIN (3) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linSetFunctional(linBASE_t *lin, uint32_t port)\r
+* @brief Change functional behavoiur of pins at runtime.\r
+* @param[in] lin - lin module base address\r
+* @param[in] port - Value to write to FUN register\r
+*\r
+* Change the value of the PCFUN register at runtime, this allows to\r
+* dynaimcaly change the functionality of the LIN pins between functional\r
+* and GIO mode.\r
+*/\r
+void linSetFunctional(linBASE_t *lin, uint32_t port)\r
+{\r
+/* USER CODE BEGIN (4) */\r
+/* USER CODE END */\r
+\r
+ lin->FUN = port;\r
+\r
+/* USER CODE BEGIN (5) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linSendHeader(linBASE_t *lin, uint8_t identifier)\r
+* @brief Send lin header.\r
+* @param[in] lin - lin module base address\r
+* @param[in] identifier - lin header id\r
+*\r
+* Send lin header including sync break field, sync field and identifier.\r
+*/\r
+void linSendHeader(linBASE_t *lin, uint8_t identifier)\r
+{\r
+/* USER CODE BEGIN (6) */\r
+/* USER CODE END */\r
+\r
+ lin->IDBYTE = identifier;\r
+\r
+/* USER CODE BEGIN (7) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linSendWakupSignal(linBASE_t *lin)\r
+* @brief Send lin wakeup signal.\r
+* @param[in] lin - lin module base address\r
+*\r
+* Send lin wakeup signal to terminate the sleep mode of any lin node connected to the BUS.\r
+*/\r
+void linSendWakupSignal(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (8) */\r
+/* USER CODE END */\r
+\r
+ lin->TDx[0] = 0xF0;\r
+ lin->GCR2 |= 0x00000100U;\r
+\r
+/* USER CODE BEGIN (9) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void linEnterSleep(linBASE_t *lin)\r
+* @brief Take Module to Sleep.\r
+* @param[in] lin - lin module base address\r
+*\r
+* Application must call this function to take Module to Sleep when Sleep command is received.\r
+* This function can also be called to forcefully enter Sleep when no activity on BUS.\r
+*/\r
+void linEnterSleep(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (10) */\r
+/* USER CODE END */\r
+ lin->GCR2 |= 0x00000001U;\r
+/* USER CODE BEGIN (11) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void linSoftwareReset(linBASE_t *lin)\r
+* @brief Perform sofware reset.\r
+* @param[in] lin - lin module base address\r
+*\r
+* Perform software reset of lin module.\r
+* This function will reset the lin state machine and clear all pending flags.\r
+* It is required to call this function after a wakeup signal has been sent.\r
+*/\r
+void linSoftwareReset(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (12) */\r
+/* USER CODE END */\r
+\r
+ lin->GCR1 &= ~0x00000080U;\r
+ lin->GCR1 |= 0x00000080U;\r
+\r
+/* USER CODE BEGIN (13) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn uint32_t linIsTxReady(linBASE_t *lin)\r
+* @brief Check if Tx buffer empty\r
+* @param[in] lin - lin module base address\r
+*\r
+* @return The TX ready flag\r
+*\r
+* Checks to see if the Tx buffer ready flag is set, returns\r
+* 0 is flags not set otherwise will return the Tx flag itself.\r
+*/\r
+uint32_t linIsTxReady(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (14) */\r
+/* USER CODE END */\r
+\r
+ return lin->FLR & LIN_TX_READY;\r
+}\r
+\r
+/** @fn void linSetLength(linBASE_t *lin, uint32_t length)\r
+* @brief Send Data\r
+* @param[in] lin - lin module base address\r
+* @param[in] length - number of data words in bytes. Range: 1-8.\r
+*\r
+* Send data response length in bytes. \r
+*/\r
+void linSetLength(linBASE_t *lin, uint32_t length)\r
+{\r
+/* USER CODE BEGIN (15) */\r
+/* USER CODE END */\r
+\r
+ lin->LENGTH = length - 1U;\r
+\r
+/* USER CODE BEGIN (16) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void linSend(linBASE_t *lin, const uint8_t *data)\r
+* @brief Send Data\r
+* @param[in] lin - lin module base address\r
+* @param[in] data - pointer to data to send\r
+*\r
+* Send a block of data pointed to by 'data'.\r
+* The number of data to transmit must be set with 'linSetLength' before. \r
+*/\r
+void linSend(linBASE_t *lin, const uint8_t *data)\r
+{\r
+ int i;\r
+ int length = lin->LENGTH;\r
+ uint8_t *pData = (uint8_t *)data + length;\r
+\r
+/* USER CODE BEGIN (17) */\r
+/* USER CODE END */\r
+\r
+ for (i = length; i >= 0; i--)\r
+ {\r
+ lin->TDx[i] = *pData--;\r
+ }\r
+\r
+/* USER CODE BEGIN (18) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn uint32_t linIsRxReady(linBASE_t *lin)\r
+* @brief Check if Rx buffer full\r
+* @param[in] lin - lin module base address\r
+*\r
+* @return The Rx ready flag\r
+*\r
+* Checks to see if the Rx buffer full flag is set, returns\r
+* 0 is flags not set otherwise will return the Rx flag itself.\r
+*/\r
+uint32_t linIsRxReady(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (19) */\r
+/* USER CODE END */\r
+\r
+ return lin->FLR & LIN_RX_INT;\r
+}\r
+\r
+\r
+/** @fn uint32_t linTxRxError(linBASE_t *lin)\r
+* @brief Return Tx and Rx Error flags\r
+* @param[in] lin - lin module base address\r
+*\r
+* @return The Tx and Rx error flags\r
+*\r
+* Returns the bit, physical bus, checksum, inconsisten sync field,\r
+* no response, framing, overun, parity and timeout error flags.\r
+* It also clears the error flags before returning.\r
+*/\r
+uint32_t linTxRxError(linBASE_t *lin)\r
+{\r
+ uint32_t status = lin->FLR & (LIN_BE_INT \r
+ | LIN_PBE_INT \r
+ | LIN_CE_INT \r
+ | LIN_ISFE_INT \r
+ | LIN_NRE_INT \r
+ | LIN_FE_INT \r
+ | LIN_OE_INT \r
+ | LIN_PE_INT \r
+ | LIN_TOA3WUS_INT \r
+ | LIN_TOAWUS_INT \r
+ | LIN_TO_INT);\r
+\r
+ lin->FLR = LIN_BE_INT \r
+ | LIN_PBE_INT \r
+ | LIN_CE_INT \r
+ | LIN_ISFE_INT \r
+ | LIN_NRE_INT \r
+ | LIN_FE_INT \r
+ | LIN_OE_INT \r
+ | LIN_PE_INT \r
+ | LIN_TOA3WUS_INT \r
+ | LIN_TOAWUS_INT \r
+ | LIN_TO_INT;\r
+\r
+/* USER CODE BEGIN (20) */\r
+/* USER CODE END */\r
+\r
+ return status;\r
+}\r
+\r
+\r
+/** @fn uint32_t linGetIdentifier(linBASE_t *lin)\r
+* @brief Get last received identifier\r
+* @param[in] lin - lin module base address\r
+*\r
+* @return Identifier\r
+*\r
+* Read last received identifier.\r
+*/\r
+uint32_t linGetIdentifier(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (21) */\r
+/* USER CODE END */\r
+ return lin->RXID;\r
+}\r
+\r
+\r
+/** @fn void linGetData(linBASE_t *lin, uint8_t * const data)\r
+* @brief Read received data\r
+* @param[in] lin - lin module base address\r
+* @param[in] data - pointer to data buffer\r
+*\r
+* Read a block of bytes and place it into the data buffer pointed to by 'data'.\r
+*/\r
+void linGetData(linBASE_t *lin, uint8_t * const data)\r
+{\r
+ uint32_t i;\r
+ uint32_t length = lin->LENGTH;\r
+ uint8_t *pData = (uint8_t *)data;\r
+\r
+/* USER CODE BEGIN (22) */\r
+/* USER CODE END */\r
+\r
+ for (i = 0U; i <= length; i++)\r
+ {\r
+ *pData++ = lin->RDx[i];\r
+ }\r
+\r
+/* USER CODE BEGIN (23) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linEnableLoopback(linBASE_t *lin, Loopbacktype_t Loopbacktype)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] lin - lin module base address\r
+* @param[in] Loopbacktype - Digital or Analog\r
+*\r
+* This function enables the Loopback mode for self test.\r
+*/\r
+void linEnableLoopback(linBASE_t *lin, Loopbacktype_t Loopbacktype)\r
+{\r
+/* USER CODE BEGIN (24) */\r
+/* USER CODE END */\r
+ \r
+ /* Clear Loopback incase enbaled already */\r
+ lin->IODFTCTRL = 0;\r
+ \r
+ /* Enable Loopback either in Analog or Digital Mode */\r
+ lin->IODFTCTRL = 0x00000A00\r
+ | Loopbacktype << 1;\r
+ \r
+/* USER CODE BEGIN (25) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void linDisableLoopback(linBASE_t *lin)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] lin - lin module base address\r
+*\r
+* This function disable the Loopback mode.\r
+*/\r
+void linDisableLoopback(linBASE_t *lin)\r
+{\r
+/* USER CODE BEGIN (26) */\r
+/* USER CODE END */\r
+ \r
+ /* Disable Loopback Mode */\r
+ lin->IODFTCTRL = 0x000005000;\r
+ \r
+/* USER CODE BEGIN (27) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn linEnableNotification(linBASE_t *lin, uint32_t flags)\r
+* @brief Enable interrupts\r
+* @param[in] lin - lin module base address\r
+* @param[in] flags - Interrupts to be enabled, can be ored value of:\r
+* LIN_BE_INT - bit error,\r
+* LIN_PBE_INT - physical bus error,\r
+* LIN_CE_INT - checksum error,\r
+* LIN_ISFE_INT - inconsistent sync field error,\r
+* LIN_NRE_INT - no response error,\r
+* LIN_FE_INT - framming error,\r
+* LIN_OE_INT - overrun error,\r
+* LIN_PE_INT - parity error,\r
+* LIN_ID_INT - received matching identifier,\r
+* LIN_RX_INT - receive buffer ready,\r
+* LIN_TOA3WUS_INT - time out after 3 wakeup signals,\r
+* LIN_TOAWUS_INT - time out after wakeup signal,\r
+* LIN_TO_INT - time out signal,\r
+* LIN_WAKEUP_INT - wakeup,\r
+* LIN_BREAK_INT - break detect\r
+*/\r
+void linEnableNotification(linBASE_t *lin, uint32_t flags)\r
+{\r
+/* USER CODE BEGIN (28) */\r
+/* USER CODE END */\r
+\r
+ lin->SETINT = flags;\r
+\r
+/* USER CODE BEGIN (29) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn linDisableNotification(linBASE_t *lin, uint32_t flags)\r
+* @brief Disable interrupts\r
+* @param[in] lin - lin module base address\r
+* @param[in] flags - Interrupts to be disabled, can be ored value of:\r
+* LIN_BE_INT - bit error,\r
+* LIN_PBE_INT - physical bus error,\r
+* LIN_CE_INT - checksum error,\r
+* LIN_ISFE_INT - inconsistent sync field error,\r
+* LIN_NRE_INT - no response error,\r
+* LIN_FE_INT - framming error,\r
+* LIN_OE_INT - overrun error,\r
+* LIN_PE_INT - parity error,\r
+* LIN_ID_INT - received matching identifier,\r
+* LIN_RX_INT - receive buffer ready,\r
+* LIN_TOA3WUS_INT - time out after 3 wakeup signals,\r
+* LIN_TOAWUS_INT - time out after wakeup signal,\r
+* LIN_TO_INT - time out signal,\r
+* LIN_WAKEUP_INT - wakeup,\r
+* LIN_BREAK_INT - break detect\r
+*/\r
+void linDisableNotification(linBASE_t *lin, uint32_t flags)\r
+{\r
+/* USER CODE BEGIN (30) */\r
+/* USER CODE END */\r
+\r
+ lin->CLRINT = flags;\r
+\r
+/* USER CODE BEGIN (31) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linHighLevelInterrupt(void)\r
+* @brief Level 0 Interrupt for LIN\r
+*/\r
+#pragma INTERRUPT(linHighLevelInterrupt, IRQ)\r
+\r
+void linHighLevelInterrupt(void)\r
+{\r
+ uint32_t vec = linREG->INTVECT0;\r
+\r
+/* USER CODE BEGIN (32) */\r
+/* USER CODE END */\r
+\r
+ switch (vec)\r
+ {\r
+ case 1: linNotification(linREG, LIN_WAKEUP_INT); break;\r
+ case 2: linNotification(linREG, LIN_ISFE_INT); break;\r
+ case 3: linNotification(linREG, LIN_PE_INT); break;\r
+ case 4: linNotification(linREG, LIN_ID_INT); break;\r
+ case 5: linNotification(linREG, LIN_PBE_INT); break;\r
+ case 6: linNotification(linREG, LIN_FE_INT); break;\r
+ case 7: linNotification(linREG, LIN_BREAK_INT); break;\r
+ case 8: linNotification(linREG, LIN_CE_INT); break;\r
+ case 9: linNotification(linREG, LIN_OE_INT); break;\r
+ case 10: linNotification(linREG, LIN_BE_INT); break;\r
+ case 11: linNotification(linREG, LIN_RX_INT); break;\r
+ case 13: linNotification(linREG, LIN_NRE_INT); break;\r
+ case 14: linNotification(linREG, LIN_TOAWUS_INT); break;\r
+ case 15: linNotification(linREG, LIN_TOA3WUS_INT); break;\r
+ case 16: linNotification(linREG, LIN_TO_INT); break;\r
+ default:\r
+ /* phantom interrupt, perform software reset */\r
+ linREG->GCR1 &= ~0x00000080U;\r
+ linREG->GCR1 |= 0x00000080U;\r
+ break;\r
+ }\r
+/* USER CODE BEGIN (33) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void linLowLevelInterrupt(void)\r
+* @brief Level 1 Interrupt for LIN\r
+*/\r
+#pragma INTERRUPT(linLowLevelInterrupt, IRQ)\r
+\r
+void linLowLevelInterrupt(void)\r
+{\r
+ uint32_t vec = linREG->INTVECT1;\r
+\r
+/* USER CODE BEGIN (34) */\r
+/* USER CODE END */\r
+\r
+ switch (vec)\r
+ {\r
+ case 1: linNotification(linREG, LIN_WAKEUP_INT); break;\r
+ case 2: linNotification(linREG, LIN_ISFE_INT); break;\r
+ case 3: linNotification(linREG, LIN_PE_INT); break;\r
+ case 4: linNotification(linREG, LIN_ID_INT); break;\r
+ case 5: linNotification(linREG, LIN_PBE_INT); break;\r
+ case 6: linNotification(linREG, LIN_FE_INT); break;\r
+ case 7: linNotification(linREG, LIN_BREAK_INT); break;\r
+ case 8: linNotification(linREG, LIN_CE_INT); break;\r
+ case 9: linNotification(linREG, LIN_OE_INT); break;\r
+ case 10: linNotification(linREG, LIN_BE_INT); break;\r
+ case 11: linNotification(linREG, LIN_RX_INT); break;\r
+ case 13: linNotification(linREG, LIN_NRE_INT); break;\r
+ case 14: linNotification(linREG, LIN_TOAWUS_INT); break;\r
+ case 15: linNotification(linREG, LIN_TOA3WUS_INT); break;\r
+ case 16: linNotification(linREG, LIN_TO_INT); break;\r
+ default:\r
+ /* phantom interrupt, perform software reset */\r
+ linREG->GCR1 &= ~0x00000080U;\r
+ linREG->GCR1 |= 0x00000080U;\r
+ break;\r
+ }\r
+/* USER CODE BEGIN (35) */\r
+/* USER CODE END */\r
+}\r
+\r