2 * @brief SCI Driver Implementation File
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */
10 /* USER CODE BEGIN (0) */
13 #include "sys/ti_drv_sci.h"
15 /* USER CODE BEGIN (1) */
16 //#include "cmdproc_io_tisci.h"
17 //#include "os_queue.h"
20 /** @struct g_sciTransfer
21 * @brief Interrupt mode globals
32 /** Buffer used for sending to SCI */
34 /** Buffer used for receiving from SCI */
38 /** @fn void sciInit(void)
39 * @brief Initializes the SCI Driver
41 * This function initializes the SCI module.
45 /* USER CODE BEGIN (2) */
48 /** Initialize buffers */
49 sciOutBuffer.buf = xQueueCreate(MAX_BUFFER_LEN, sizeof(uint8_t));
50 sciOutBuffer.mutex = xSemaphoreCreateMutex();
51 sciOutBuffer.flags = 0;
52 sciInBuffer.buf = xQueueCreate(MAX_BUFFER_LEN, sizeof(uint8_t));
53 sciInBuffer.mutex = xSemaphoreCreateMutex();
54 sciInBuffer.flags = 0;
56 /** @b Initialize @b SCI */
58 /** - bring SCI out of reset */
61 /** - Disable all interrupts */
62 sciREG->CLRINT = 0xFFFFFFFFU;
63 sciREG->CLRINTLVL = 0xFFFFFFFFU;
65 /** - global control 1 */
66 sciREG->GCR1 = (1 << 25) /* enable transmit */
67 | (1 << 24) /* enable receive */
68 | (1 << 5) /* internal clock (device has no clock pin) */
69 | ((1-1) << 4) /* number of stop bits */
70 | (0 << 3) /* even parity, otherwise odd */
71 | (0 << 2) /* enable parity */
72 | (1 << 1); /* asynchronous timing mode */
75 sciREG->BAUD = 520; /* baudrate */
77 /** - tranmision length */
78 sciREG->LENGTH = 8 - 1; /* length */
80 /** - set SCI pins functional mode */
81 sciREG->FUN = (1 << 2) /* tx pin */
82 | (1 << 1) /* rx pin */
85 /** - set SCI pins default output value */
86 sciREG->DOUT = (0 << 2) /* tx pin */
87 | (0 << 1) /* rx pin */
90 /** - set SCI pins output direction */
91 sciREG->DIR = (1 << 2) /* tx pin */
92 | (0 << 1) /* rx pin */
95 /** - set SCI pins open drain enable */
96 sciREG->ODR = (0 << 2) /* tx pin */
97 | (0 << 1) /* rx pin */
100 /** - set SCI pins pullup/pulldown enable */
101 sciREG->PD = (0 << 2) /* tx pin */
102 | (0 << 1) /* rx pin */
105 /** - set SCI pins pullup/pulldown select */
106 sciREG->PSL = (1 << 2) /* tx pin */
107 | (1 << 1) /* rx pin */
110 /** - set interrupt level */
111 sciREG->SETINTLVL = (0 << 26) /* Framing error */
112 | (0 << 25) /* Overrun error */
113 | (0 << 24) /* Pariry error */
114 | (0 << 9) /* Receive */
115 | (0 << 8) /* Transmit */
116 | (0 << 1) /* Wakeup */
117 | (0); /* Break detect */
119 /** - set interrupt enable */
120 sciREG->SETINT = (0 << 26) /* Framing error */
121 | (0 << 25) /* Overrun error */
122 | (0 << 24) /* Pariry error */
123 | (1 << 9) /* Receive */
124 | (0 << 1) /* Wakeup */
125 | (0); /* Break detect */
127 /** - inialise global transfer variables */
128 g_sciTransfer[0].mode = 1 << 8;
129 g_sciTransfer[0].length = 0;
131 /** - Finaly start SCI */
132 sciREG->GCR1 |= (1 << 7);
135 /* USER CODE BEGIN (3) */
140 /** @fn void sciSetFunctional(sciBASE_t *sci, uint32_t port)
141 * @brief Change functional behavoiur of pins at runtime.
142 * @param[in] sci - sci module base address
143 * @param[in] port - Value to write to FUN register
145 * Change the value of the PCFUN register at runtime, this allows to
146 * dynaimcaly change the functionality of the SCI pins between functional
149 void sciSetFunctional(sciBASE_t *sci, uint32_t port)
151 /* USER CODE BEGIN (4) */
156 /* USER CODE BEGIN (5) */
161 /** @fn void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)
162 * @brief Change baudrate at runtime.
163 * @param[in] sci - sci module base address
164 * @param[in] baud - baudrate in Hz
166 * Change the SCI baudrate at runtime.
168 void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)
170 double vclk = 80.000 * 1000000.0;
171 uint32_t f = sci->GCR1 & 2 ? 16 : 1;
173 /* USER CODE BEGIN (6) */
176 sci->BAUD = ((uint32_t)((vclk /(f*baud) + 0.5)) - 1) & 0x00FFFFFF;
178 /* USER CODE BEGIN (7) */
183 /** @fn int sciIsTxReady(sciBASE_t *sci)
184 * @brief Check if Tx buffer empty
185 * @param[in] sci - sci module base address
187 * @return The TX ready flag
189 * Checks to see if the Tx buffer ready flag is set, returns
190 * 0 is flags not set otherwise will return the Tx flag itself.
192 int sciIsTxReady(sciBASE_t *sci)
194 /* USER CODE BEGIN (8) */
197 return sci->FLR & SCI_TX_INT;
201 /** @fn void sciSendByte(sciBASE_t *sci, uint8_t byte)
203 * @param[in] sci - sci module base address
204 * @param[in] byte - byte to transfer
206 * Sends a single byte in polling mode, will wait in the
207 * routine until the transmit buffer is empty before sending
208 * the byte. Use sciIsTxReady to check for Tx buffer empty
209 * before calling sciSendByte to avoid waiting.
212 void sciSendByte(sciBASE_t *sci, uint8_t byte)
214 while ((sci->FLR & SCI_TX_INT) == 0) {}; // Wait
220 /** @fn void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
222 * @param[in] sci - sci module base address
223 * @param[in] length - number of data words to transfer
224 * @param[in] data - pointer to data to send
226 * Send a block of data pointed to by 'data' and 'length' bytes
227 * long. If interrupts have been enabled the data is sent using
228 * interrupt mode, otherwise polling mode is used. In interrupt
229 * mode transmition of the first byte is started and the routine
230 * returns imediatly, sciSend must not be called again until the
231 * transfer is complete, when the sciNotification callback will
232 * be called. In polling mode, sciSend will not return until
233 * the transfer is complete.
235 * @note if data word is less than 8 bits, then the data must be left
236 * aligned in the data byte.
238 // Unused, see drv/sci.c/drv_sci_send()
240 void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
242 int index = sci == sciREG ? 0 : 1;
244 if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)
246 // We are in interrupt mode
247 g_sciTransfer[index].length = length;
248 g_sciTransfer[index].data = data;
250 // Start transmit by sending first byte
251 sci->TD = *g_sciTransfer[index].data++;
252 sci->SETINT = SCI_TX_INT;
259 while ((sci->FLR & SCI_TX_INT) == 0) {}; // Wait
266 /** @fn int sciIsRxReady(sciBASE_t *sci)
267 * @brief Check if Rx buffer full
268 * @param[in] sci - sci module base address
270 * @return The Rx ready flag
272 * Checks to see if the Rx buffer full flag is set, returns
273 * 0 is flags not set otherwise will return the Rx flag itself.
275 int sciIsRxReady(sciBASE_t *sci)
277 /* USER CODE BEGIN (13) */
280 return sci->FLR & SCI_RX_INT;
284 /** @fn int sciRxError(sciBASE_t *sci)
285 * @brief Return Rx Error flags
286 * @param[in] sci - sci module base address
288 * @return The Rx error flags
290 * Returns the Rx framing, overun and parity errors flags,
291 * also clears the error flags before returning.
293 int sciRxError(sciBASE_t *sci)
295 int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);
297 /* USER CODE BEGIN (14) */
300 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
305 /** @fn uint32_t sciReceiveByte(sciBASE_t *sci)
306 * @brief Receive Byte
307 * @param[in] sci - sci module base address
309 * @return Received byte
311 * Recieves a single byte in polling mode. If there is
312 * not a byte in the receive buffer the routine will wait
313 * until one is received. Use sciIsRxReady to check to
314 * see if the buffer is full to avoid waiting.
316 int sciReceiveByte(sciBASE_t *sci)
318 /* USER CODE BEGIN (15) */
321 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
327 /** @fn void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
328 * @brief Receive Data
329 * @param[in] sci - sci module base address
330 * @param[in] length - number of data words to transfer
331 * @param[in] data - pointer to data buffer
333 * Receive a block of 'length' bytes long and place it into the
334 * data buffer pointed to by 'data'. If interrupts have been
335 * enabled the data is received using interrupt mode, otherwise
336 * polling mode is used. In interrupt mode receive is setup and
337 * the routine returns imediatly, sciReceive must not be called
338 * again until the transfer is complete, when the sciNotification
339 * callback will be called. In polling mode, sciReceive will not
340 * return until the transfer is complete.
342 void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
344 /* USER CODE BEGIN (16) */
345 // Delete generated content after user code block!!!
346 if (sci->SETINT & SCI_RX_INT)
348 /* We are in iterrupt mode, clear error flags */
349 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
356 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
363 /* USER CODE BEGIN (17) */
367 /** @fn void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
368 * @brief Enable Loopback mode for self test
369 * @param[in] sci - sci module base address
370 * @param[in] Loopbacktype - Digital or Analog
372 * This function enables the Loopback mode for self test.
374 void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
376 /* USER CODE BEGIN (18) */
379 /* Clear Loopback incase enbaled already */
382 /* Enable Loopback either in Analog or Digital Mode */
383 sci->IODFTCTRL = 0x00000A00
386 /* USER CODE BEGIN (19) */
390 /** @fn void sciDisableLoopback(sciBASE_t *sci)
391 * @brief Enable Loopback mode for self test
392 * @param[in] sci - sci module base address
394 * This function disable the Loopback mode.
396 void sciDisableLoopback(sciBASE_t *sci)
398 /* USER CODE BEGIN (20) */
401 /* Disable Loopback Mode */
402 sci->IODFTCTRL = 0x000005000;
404 /* USER CODE BEGIN (21) */
408 /** @fn sciEnableNotification(sciBASE_t *sci, uint32_t flags)
409 * @brief Enable interrupts
410 * @param[in] sci - sci module base address
411 * @param[in] flags - Interrupts to be enabled, can be ored value of:
412 * SCI_FE_INT - framming error,
413 * SCI_OE_INT - overrun error,
414 * SCI_PE_INT - parity error,
415 * SCI_RX_INT - receive buffer ready,
416 * SCI_TX_INT - transmit buffer ready,
417 * SCI_WAKE_INT - wakeup,
418 * SCI_BREAK_INT - break detect
420 void sciEnableNotification(sciBASE_t *sci, uint32_t flags)
422 int index = sci == sciREG ? 0 : 1;
424 /* USER CODE BEGIN (22) */
427 g_sciTransfer[index].mode |= (flags & SCI_TX_INT);
428 sci->SETINT = (flags & ~SCI_TX_INT);
430 /* USER CODE BEGIN (23) */
435 /** @fn sciDisableNotification(sciBASE_t *sci, uint32_t flags)
436 * @brief Disable interrupts
437 * @param[in] sci - sci module base address
438 * @param[in] flags - Interrupts to be disabled, can be ored value of:
439 * SCI_FE_INT - framming error,
440 * SCI_OE_INT - overrun error,
441 * SCI_PE_INT - parity error,
442 * SCI_RX_INT - receive buffer ready,
443 * SCI_TX_INT - transmit buffer ready,
444 * SCI_WAKE_INT - wakeup,
445 * SCI_BREAK_INT - break detect
447 void sciDisableNotification(sciBASE_t *sci, uint32_t flags)
449 int index = sci == sciREG ? 0 : 1;
451 /* USER CODE BEGIN (24) */
454 g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);
455 sci->CLRINT = (flags & ~SCI_TX_INT);
457 /* USER CODE BEGIN (25) */
461 static uint32_t receiveError;
463 /** @fn void sciHighLevelInterrupt(void)
464 * @brief Level 0 Interrupt for SCI
466 #pragma INTERRUPT(sciHighLevelInterrupt, IRQ)
468 void sciHighLevelInterrupt(void)
470 uint32_t vec = sciREG->INTVECT0;
472 /* USER CODE BEGIN (26) */
473 // Delete generated content after user code block!!!
477 sciNotification(sciREG, SCI_WAKE_INT);
480 sciNotification(sciREG, SCI_PE_INT);
483 sciNotification(sciREG, SCI_FE_INT);
486 sciNotification(sciREG, SCI_BREAK_INT);
489 sciNotification(sciREG, SCI_OE_INT);
494 { uint8_t byte = sciREG->RD;
495 if (xQueueSendFromISR(sciInBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL) {
498 sciNotification(sciREG, SCI_RX_INT);
506 if (xQueueReceiveFromISR(sciOutBuffer.buf, (uint8_t *)&byte, NULL) == errQUEUE_EMPTY) {
507 sciREG->CLRINT = SCI_TX_INT;
508 sciOutBuffer.flags &= ~BUF_TRANSFER_IN_PROGRESS;
516 // phantom interrupt, clear flags and return
517 sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;
521 /* USER CODE BEGIN (27) */
525 /** @fn void sciLowLevelInterrupt(void)
526 * @brief Level 1 Interrupt for SCI
528 #pragma INTERRUPT(sciLowLevelInterrupt, IRQ)
530 void sciLowLevelInterrupt(void)
532 uint32_t vec = sciREG->INTVECT1;
534 /* USER CODE BEGIN (28) */
540 sciNotification(sciREG, SCI_WAKE_INT);
543 sciNotification(sciREG, SCI_PE_INT);
546 sciNotification(sciREG, SCI_FE_INT);
549 sciNotification(sciREG, SCI_BREAK_INT);
552 sciNotification(sciREG, SCI_OE_INT);
557 { uint32_t byte = sciREG->RD;
559 if (g_sciTransfer[0].length > 0)
561 *g_sciTransfer[0].data++ = byte;
562 g_sciTransfer[0].length--;
563 if (g_sciTransfer[0].length == 0)
565 sciNotification(sciREG, SCI_RX_INT);
573 if (--g_sciTransfer[0].length > 0)
575 sciREG->TD = *g_sciTransfer[0].data++;
579 sciREG->CLRINT = SCI_TX_INT;
580 sciNotification(sciREG, SCI_TX_INT);
585 /* phantom interrupt, clear flags and return */
586 sciREG->FLR = sciREG->SETINTLVL & 0x07000303;
589 /* USER CODE BEGIN (29) */