--- /dev/null
+/** @file sci.c \r
+* @brief SCI Driver Implementation File\r
+* @date 15.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 "sci.h"\r
+\r
+/* USER CODE BEGIN (1) */\r
+#include "cmdio_tisci.h"\r
+#include "os_queue.h"\r
+\r
+extern tBuffer outBuffer;\r
+extern tBuffer inBuffer;\r
+static uint32_t receiveError;\r
+/* USER CODE END */\r
+/** @struct g_sciTransfer\r
+* @brief Interrupt mode globals\r
+*\r
+*/\r
+struct g_sciTransfer\r
+{\r
+ uint32_t mode;\r
+ uint32_t length;\r
+ uint8_t *data;\r
+} g_sciTransfer[2];\r
+\r
+\r
+/** @fn void sciInit(void)\r
+* @brief Initializes the SCI Driver\r
+*\r
+* This function initializes the SCI module.\r
+*/\r
+void sciInit(void)\r
+{\r
+/* USER CODE BEGIN (2) */\r
+/* USER CODE END */\r
+\r
+ /** @b intalise @b SCI */\r
+\r
+ /** - bring SCI out of reset */\r
+ sciREG->GCR0 = 1U;\r
+\r
+ /** - Disable all interrupts */\r
+ sciREG->CLRINT = 0xFFFFFFFFU;\r
+ sciREG->CLRINTLVL = 0xFFFFFFFFU;\r
+\r
+ /** - global control 1 */\r
+ sciREG->GCR1 = (1 << 25) /* enable transmit */\r
+ | (1 << 24) /* enable receive */\r
+ | (1 << 5) /* internal clock (device has no clock pin) */\r
+ | ((2-1) << 4) /* number of stop bits */\r
+ | (0 << 3) /* even parity, otherwise odd */\r
+ | (0 << 2) /* enable parity */\r
+ | (1 << 1); /* asynchronous timing mode */\r
+\r
+ /** - set baudrate */\r
+ sciREG->BAUD = 520; /* baudrate */\r
+\r
+ /** - tranmision length */\r
+ sciREG->LENGTH = 8 - 1; /* length */\r
+\r
+ /** - set SCI pins functional mode */\r
+ sciREG->FUN = (1 << 2) /* tx pin */\r
+ | (1 << 1) /* rx pin */\r
+ | (0); /* clk pin */\r
+\r
+ /** - set SCI pins default output value */\r
+ sciREG->DOUT = (0 << 2) /* tx pin */\r
+ | (0 << 1) /* rx pin */\r
+ | (0); /* clk pin */\r
+\r
+ /** - set SCI pins output direction */\r
+ sciREG->DIR = (1 << 2) /* tx pin */\r
+ | (0 << 1) /* rx pin */\r
+ | (0); /* clk pin */\r
+\r
+ /** - set SCI pins open drain enable */\r
+ sciREG->ODR = (0 << 2) /* tx pin */\r
+ | (0 << 1) /* rx pin */\r
+ | (0); /* clk pin */\r
+\r
+ /** - set SCI pins pullup/pulldown enable */\r
+ sciREG->PD = (0 << 2) /* tx pin */\r
+ | (0 << 1) /* rx pin */\r
+ | (0); /* clk pin */\r
+\r
+ /** - set SCI pins pullup/pulldown select */\r
+ sciREG->PSL = (1 << 2) /* tx pin */\r
+ | (1 << 1) /* rx pin */\r
+ | (1); /* clk pin */\r
+\r
+ /** - set interrupt level */\r
+ sciREG->SETINTLVL = (0 << 26) /* Framing error */\r
+ | (0 << 25) /* Overrun error */\r
+ | (0 << 24) /* Pariry error */\r
+ | (0 << 9) /* Receive */\r
+ | (0 << 8) /* Transmit */\r
+ | (0 << 1) /* Wakeup */\r
+ | (0); /* Break detect */\r
+\r
+ /** - set interrupt enable */\r
+ sciREG->SETINT = (0 << 26) /* Framing error */\r
+ | (0 << 25) /* Overrun error */\r
+ | (0 << 24) /* Pariry error */\r
+ | (1 << 9) /* Receive */\r
+ | (0 << 1) /* Wakeup */\r
+ | (0); /* Break detect */\r
+\r
+ /** - inialise global transfer variables */\r
+ g_sciTransfer[0].mode = 1 << 8;\r
+ g_sciTransfer[0].length = 0;\r
+\r
+ /** - Finaly start SCI */\r
+ sciREG->GCR1 |= (1 << 7);\r
+\r
+\r
+/* USER CODE BEGIN (3) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void sciSetFunctional(sciBASE_t *sci, uint32_t port)\r
+* @brief Change functional behavoiur of pins at runtime.\r
+* @param[in] sci - sci 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 SCI pins between functional\r
+* and GIO mode.\r
+*/\r
+void sciSetFunctional(sciBASE_t *sci, uint32_t port)\r
+{\r
+/* USER CODE BEGIN (4) */\r
+/* USER CODE END */\r
+\r
+ sci->FUN = port;\r
+\r
+/* USER CODE BEGIN (5) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)\r
+* @brief Change baudrate at runtime.\r
+* @param[in] sci - sci module base address\r
+* @param[in] baud - baudrate in Hz\r
+*\r
+* Change the SCI baudrate at runtime.\r
+*/\r
+void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)\r
+{\r
+ double vclk = 80.000 * 1000000.0;\r
+ uint32_t f = sci->GCR1 & 2 ? 16 : 1;\r
+\r
+/* USER CODE BEGIN (6) */\r
+/* USER CODE END */\r
+\r
+ sci->BAUD = ((uint32_t)((vclk /(f*baud) + 0.5)) - 1) & 0x00FFFFFF;\r
+\r
+/* USER CODE BEGIN (7) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn int sciIsTxReady(sciBASE_t *sci)\r
+* @brief Check if Tx buffer empty\r
+* @param[in] sci - sci 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
+int sciIsTxReady(sciBASE_t *sci)\r
+{\r
+/* USER CODE BEGIN (8) */\r
+/* USER CODE END */\r
+\r
+ return sci->FLR & SCI_TX_INT;\r
+}\r
+\r
+\r
+/** @fn void sciSendByte(sciBASE_t *sci, uint8_t byte)\r
+* @brief Send Byte\r
+* @param[in] sci - sci module base address\r
+* @param[in] byte - byte to transfer\r
+*\r
+* Sends a single byte in polling mode, will wait in the\r
+* routine until the transmit buffer is empty before sending\r
+* the byte. Use sciIsTxReady to check for Tx buffer empty\r
+* before calling sciSendByte to avoid waiting.\r
+*/\r
+void sciSendByte(sciBASE_t *sci, uint8_t byte)\r
+{\r
+/* USER CODE BEGIN (9) */\r
+/* USER CODE END */\r
+\r
+ while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };\r
+ sci->TD = byte;\r
+\r
+/* USER CODE BEGIN (10) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
+* @brief Send Data\r
+* @param[in] sci - sci module base address\r
+* @param[in] length - number of data words to transfer\r
+* @param[in] data - pointer to data to send\r
+*\r
+* Send a block of data pointed to by 'data' and 'length' bytes\r
+* long. If interrupts have been enabled the data is sent using\r
+* interrupt mode, otherwise polling mode is used. In interrupt\r
+* mode transmition of the first byte is started and the routine\r
+* returns imediatly, sciSend must not be called again until the\r
+* transfer is complete, when the sciNotification callback will\r
+* be called. In polling mode, sciSend will not return until \r
+* the transfer is complete.\r
+*\r
+* @note if data word is less than 8 bits, then the data must be left\r
+* aligned in the data byte.\r
+*/\r
+void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
+{\r
+ int index = sci == sciREG ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (11) */\r
+/* USER CODE END */\r
+\r
+ if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)\r
+ {\r
+ /* we are in interrupt mode */\r
+ \r
+ g_sciTransfer[index].length = length;\r
+ g_sciTransfer[index].data = data;\r
+\r
+ /* start transmit by sending first byte */ \r
+ sci->TD = *g_sciTransfer[index].data++;\r
+ sci->SETINT = SCI_TX_INT;\r
+ }\r
+ else\r
+ {\r
+ /* send the data */\r
+ while (length-- > 0)\r
+ {\r
+ while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };\r
+ sci->TD = *data++;\r
+ }\r
+ }\r
+\r
+/* USER CODE BEGIN (12) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn int sciIsRxReady(sciBASE_t *sci)\r
+* @brief Check if Rx buffer full\r
+* @param[in] sci - sci 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
+int sciIsRxReady(sciBASE_t *sci)\r
+{\r
+/* USER CODE BEGIN (13) */\r
+/* USER CODE END */\r
+\r
+ return sci->FLR & SCI_RX_INT;\r
+}\r
+\r
+\r
+/** @fn int sciRxError(sciBASE_t *sci)\r
+* @brief Return Rx Error flags\r
+* @param[in] sci - sci module base address\r
+*\r
+* @return The Rx error flags\r
+*\r
+* Returns the Rx framing, overun and parity errors flags,\r
+* also clears the error flags before returning.\r
+*/\r
+int sciRxError(sciBASE_t *sci)\r
+{\r
+ int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);\r
+\r
+/* USER CODE BEGIN (14) */\r
+/* USER CODE END */\r
+\r
+ sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;\r
+ return status;\r
+}\r
+\r
+\r
+/** @fn uint32_t sciReceiveByte(sciBASE_t *sci)\r
+* @brief Receive Byte\r
+* @param[in] sci - sci module base address\r
+*\r
+* @return Received byte\r
+*\r
+* Recieves a single byte in polling mode. If there is\r
+* not a byte in the receive buffer the routine will wait\r
+* until one is received. Use sciIsRxReady to check to\r
+* see if the buffer is full to avoid waiting.\r
+*/\r
+int sciReceiveByte(sciBASE_t *sci)\r
+{\r
+/* USER CODE BEGIN (15) */\r
+/* USER CODE END */\r
+\r
+ while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };\r
+\r
+ return sci->RD;\r
+}\r
+\r
+\r
+/** @fn void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
+* @brief Receive Data\r
+* @param[in] sci - sci module base address\r
+* @param[in] length - number of data words to transfer\r
+* @param[in] data - pointer to data buffer\r
+*\r
+* Receive a block of 'length' bytes long and place it into the \r
+* data buffer pointed to by 'data'. If interrupts have been \r
+* enabled the data is received using interrupt mode, otherwise\r
+* polling mode is used. In interrupt mode receive is setup and\r
+* the routine returns imediatly, sciReceive must not be called \r
+* again until the transfer is complete, when the sciNotification \r
+* callback will be called. In polling mode, sciReceive will not\r
+* return until the transfer is complete.\r
+*/\r
+void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
+{\r
+/* USER CODE BEGIN (16) */\r
+ // Delete generated content after user code block!!!\r
+ if (sci->SETINT & SCI_RX_INT)\r
+ {\r
+ /* We are in iterrupt mode, clear error flags */\r
+ sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;\r
+\r
+ }\r
+ else\r
+ { \r
+ while (length-- > 0)\r
+ {\r
+ while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };\r
+ *data++ = sci->RD;\r
+ }\r
+ }\r
+/* USER CODE END */\r
+\r
+/* USER CODE BEGIN (17) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] sci - sci module base address\r
+* @param[in] Loopbacktype - Digital or Analog\r
+*\r
+* This function enables the Loopback mode for self test.\r
+*/\r
+void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)\r
+{\r
+/* USER CODE BEGIN (18) */\r
+/* USER CODE END */\r
+ \r
+ /* Clear Loopback incase enbaled already */\r
+ sci->IODFTCTRL = 0;\r
+ \r
+ /* Enable Loopback either in Analog or Digital Mode */\r
+ sci->IODFTCTRL = 0x00000A00\r
+ | Loopbacktype << 1;\r
+ \r
+/* USER CODE BEGIN (19) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void sciDisableLoopback(sciBASE_t *sci)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] sci - sci module base address\r
+*\r
+* This function disable the Loopback mode.\r
+*/\r
+void sciDisableLoopback(sciBASE_t *sci)\r
+{\r
+/* USER CODE BEGIN (20) */\r
+/* USER CODE END */\r
+ \r
+ /* Disable Loopback Mode */\r
+ sci->IODFTCTRL = 0x000005000;\r
+ \r
+/* USER CODE BEGIN (21) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn sciEnableNotification(sciBASE_t *sci, uint32_t flags)\r
+* @brief Enable interrupts\r
+* @param[in] sci - sci module base address\r
+* @param[in] flags - Interrupts to be enabled, can be ored value of:\r
+* SCI_FE_INT - framming error,\r
+* SCI_OE_INT - overrun error,\r
+* SCI_PE_INT - parity error,\r
+* SCI_RX_INT - receive buffer ready,\r
+* SCI_TX_INT - transmit buffer ready,\r
+* SCI_WAKE_INT - wakeup,\r
+* SCI_BREAK_INT - break detect\r
+*/\r
+void sciEnableNotification(sciBASE_t *sci, uint32_t flags)\r
+{\r
+ int index = sci == sciREG ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (22) */\r
+/* USER CODE END */\r
+\r
+ g_sciTransfer[index].mode |= (flags & SCI_TX_INT);\r
+ sci->SETINT = (flags & ~SCI_TX_INT);\r
+\r
+/* USER CODE BEGIN (23) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn sciDisableNotification(sciBASE_t *sci, uint32_t flags)\r
+* @brief Disable interrupts\r
+* @param[in] sci - sci module base address\r
+* @param[in] flags - Interrupts to be disabled, can be ored value of:\r
+* SCI_FE_INT - framming error,\r
+* SCI_OE_INT - overrun error,\r
+* SCI_PE_INT - parity error,\r
+* SCI_RX_INT - receive buffer ready,\r
+* SCI_TX_INT - transmit buffer ready,\r
+* SCI_WAKE_INT - wakeup,\r
+* SCI_BREAK_INT - break detect\r
+*/\r
+void sciDisableNotification(sciBASE_t *sci, uint32_t flags)\r
+{\r
+ int index = sci == sciREG ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (24) */\r
+/* USER CODE END */\r
+\r
+ g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);\r
+ sci->CLRINT = (flags & ~SCI_TX_INT);\r
+\r
+/* USER CODE BEGIN (25) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn void sciHighLevelInterrupt(void)\r
+* @brief Level 0 Interrupt for SCI\r
+*/\r
+#pragma INTERRUPT(sciHighLevelInterrupt, IRQ)\r
+\r
+void sciHighLevelInterrupt(void)\r
+{\r
+ uint32_t vec = sciREG->INTVECT0;\r
+\r
+/* USER CODE BEGIN (26) */\r
+ // Delete generated content after user code block!!!\r
+ switch (vec)\r
+ {\r
+ case 1:\r
+ sciNotification(sciREG, SCI_WAKE_INT);\r
+ break;\r
+ case 3:\r
+ sciNotification(sciREG, SCI_PE_INT);\r
+ break;\r
+ case 6:\r
+ sciNotification(sciREG, SCI_FE_INT);\r
+ break;\r
+ case 7:\r
+ sciNotification(sciREG, SCI_BREAK_INT);\r
+ break;\r
+ case 9:\r
+ sciNotification(sciREG, SCI_OE_INT);\r
+ break;\r
+\r
+ case 11:\r
+ /* receive */\r
+ { uint8_t byte = sciREG->RD;\r
+ if (xQueueSendFromISR(inBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL)\r
+ receiveError++;\r
+ sciNotification(sciREG, SCI_RX_INT);\r
+ }\r
+ break;\r
+\r
+ case 12:\r
+ /* transmit */\r
+ {\r
+ uint8_t byte = 0;\r
+ if (xQueueReceiveFromISR(outBuffer.buf, (uint8_t *)&byte, NULL) == errQUEUE_EMPTY) {\r
+ sciREG->CLRINT = SCI_TX_INT;\r
+ outBuffer.flags &= ~BUF_TRANSFER_IN_PROGRESS;\r
+ }\r
+ else {\r
+ sciREG->TD = byte;\r
+ }\r
+ }\r
+ break;\r
+ default:\r
+ /* phantom interrupt, clear flags and return */\r
+ sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;\r
+ break;\r
+ }\r
+/* USER CODE END */\r
+\r
+/* USER CODE BEGIN (27) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void sciLowLevelInterrupt(void)\r
+* @brief Level 1 Interrupt for SCI\r
+*/\r
+#pragma INTERRUPT(sciLowLevelInterrupt, IRQ)\r
+\r
+void sciLowLevelInterrupt(void)\r
+{\r
+ uint32_t vec = sciREG->INTVECT1;\r
+\r
+/* USER CODE BEGIN (28) */\r
+/* USER CODE END */\r
+\r
+ switch (vec)\r
+ {\r
+ case 1:\r
+ sciNotification(sciREG, SCI_WAKE_INT);\r
+ break;\r
+ case 3:\r
+ sciNotification(sciREG, SCI_PE_INT);\r
+ break;\r
+ case 6:\r
+ sciNotification(sciREG, SCI_FE_INT);\r
+ break;\r
+ case 7:\r
+ sciNotification(sciREG, SCI_BREAK_INT);\r
+ break;\r
+ case 9:\r
+ sciNotification(sciREG, SCI_OE_INT);\r
+ break;\r
+\r
+ case 11:\r
+ /* receive */\r
+ { uint32_t byte = sciREG->RD;\r
+\r
+ if (g_sciTransfer[0].length > 0)\r
+ {\r
+ *g_sciTransfer[0].data++ = byte;\r
+ g_sciTransfer[0].length--;\r
+ if (g_sciTransfer[0].length == 0)\r
+ {\r
+ sciNotification(sciREG, SCI_RX_INT);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+\r
+ case 12:\r
+ /* transmit */\r
+ if (--g_sciTransfer[0].length > 0)\r
+ {\r
+ sciREG->TD = *g_sciTransfer[0].data++;\r
+ }\r
+ else\r
+ {\r
+ sciREG->CLRINT = SCI_TX_INT;\r
+ sciNotification(sciREG, SCI_TX_INT);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ /* phantom interrupt, clear flags and return */\r
+ sciREG->FLR = sciREG->SETINTLVL & 0x07000303;\r
+ break;\r
+ }\r
+/* USER CODE BEGIN (29) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+\r