2 * @brief SCI Driver Implementation File
\r
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */
\r
10 /* USER CODE BEGIN (0) */
\r
13 #include "ti_drv_sci.h"
\r
15 /* USER CODE BEGIN (1) */
\r
16 #include "cmdio_tisci.h"
\r
17 #include "os_queue.h"
\r
19 extern tBuffer outBuffer;
\r
20 extern tBuffer inBuffer;
\r
21 static uint32_t receiveError;
\r
23 /** @struct g_sciTransfer
\r
24 * @brief Interrupt mode globals
\r
27 struct g_sciTransfer
\r
35 /** @fn void sciInit(void)
\r
36 * @brief Initializes the SCI Driver
\r
38 * This function initializes the SCI module.
\r
42 /* USER CODE BEGIN (2) */
\r
45 /** @b intalise @b SCI */
\r
47 /** - bring SCI out of reset */
\r
50 /** - Disable all interrupts */
\r
51 sciREG->CLRINT = 0xFFFFFFFFU;
\r
52 sciREG->CLRINTLVL = 0xFFFFFFFFU;
\r
54 /** - global control 1 */
\r
55 sciREG->GCR1 = (1 << 25) /* enable transmit */
\r
56 | (1 << 24) /* enable receive */
\r
57 | (1 << 5) /* internal clock (device has no clock pin) */
\r
58 | ((1-1) << 4) /* number of stop bits */
\r
59 | (0 << 3) /* even parity, otherwise odd */
\r
60 | (0 << 2) /* enable parity */
\r
61 | (1 << 1); /* asynchronous timing mode */
\r
63 /** - set baudrate */
\r
64 sciREG->BAUD = 520; /* baudrate */
\r
66 /** - tranmision length */
\r
67 sciREG->LENGTH = 8 - 1; /* length */
\r
69 /** - set SCI pins functional mode */
\r
70 sciREG->FUN = (1 << 2) /* tx pin */
\r
71 | (1 << 1) /* rx pin */
\r
72 | (0); /* clk pin */
\r
74 /** - set SCI pins default output value */
\r
75 sciREG->DOUT = (0 << 2) /* tx pin */
\r
76 | (0 << 1) /* rx pin */
\r
77 | (0); /* clk pin */
\r
79 /** - set SCI pins output direction */
\r
80 sciREG->DIR = (1 << 2) /* tx pin */
\r
81 | (0 << 1) /* rx pin */
\r
82 | (0); /* clk pin */
\r
84 /** - set SCI pins open drain enable */
\r
85 sciREG->ODR = (0 << 2) /* tx pin */
\r
86 | (0 << 1) /* rx pin */
\r
87 | (0); /* clk pin */
\r
89 /** - set SCI pins pullup/pulldown enable */
\r
90 sciREG->PD = (0 << 2) /* tx pin */
\r
91 | (0 << 1) /* rx pin */
\r
92 | (0); /* clk pin */
\r
94 /** - set SCI pins pullup/pulldown select */
\r
95 sciREG->PSL = (1 << 2) /* tx pin */
\r
96 | (1 << 1) /* rx pin */
\r
97 | (1); /* clk pin */
\r
99 /** - set interrupt level */
\r
100 sciREG->SETINTLVL = (0 << 26) /* Framing error */
\r
101 | (0 << 25) /* Overrun error */
\r
102 | (0 << 24) /* Pariry error */
\r
103 | (0 << 9) /* Receive */
\r
104 | (0 << 8) /* Transmit */
\r
105 | (0 << 1) /* Wakeup */
\r
106 | (0); /* Break detect */
\r
108 /** - set interrupt enable */
\r
109 sciREG->SETINT = (0 << 26) /* Framing error */
\r
110 | (0 << 25) /* Overrun error */
\r
111 | (0 << 24) /* Pariry error */
\r
112 | (1 << 9) /* Receive */
\r
113 | (0 << 1) /* Wakeup */
\r
114 | (0); /* Break detect */
\r
116 /** - inialise global transfer variables */
\r
117 g_sciTransfer[0].mode = 1 << 8;
\r
118 g_sciTransfer[0].length = 0;
\r
120 /** - Finaly start SCI */
\r
121 sciREG->GCR1 |= (1 << 7);
\r
124 /* USER CODE BEGIN (3) */
\r
125 /* USER CODE END */
\r
129 /** @fn void sciSetFunctional(sciBASE_t *sci, uint32_t port)
\r
130 * @brief Change functional behavoiur of pins at runtime.
\r
131 * @param[in] sci - sci module base address
\r
132 * @param[in] port - Value to write to FUN register
\r
134 * Change the value of the PCFUN register at runtime, this allows to
\r
135 * dynaimcaly change the functionality of the SCI pins between functional
\r
138 void sciSetFunctional(sciBASE_t *sci, uint32_t port)
\r
140 /* USER CODE BEGIN (4) */
\r
141 /* USER CODE END */
\r
145 /* USER CODE BEGIN (5) */
\r
146 /* USER CODE END */
\r
150 /** @fn void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)
\r
151 * @brief Change baudrate at runtime.
\r
152 * @param[in] sci - sci module base address
\r
153 * @param[in] baud - baudrate in Hz
\r
155 * Change the SCI baudrate at runtime.
\r
157 void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)
\r
159 double vclk = 80.000 * 1000000.0;
\r
160 uint32_t f = sci->GCR1 & 2 ? 16 : 1;
\r
162 /* USER CODE BEGIN (6) */
\r
163 /* USER CODE END */
\r
165 sci->BAUD = ((uint32_t)((vclk /(f*baud) + 0.5)) - 1) & 0x00FFFFFF;
\r
167 /* USER CODE BEGIN (7) */
\r
168 /* USER CODE END */
\r
172 /** @fn int sciIsTxReady(sciBASE_t *sci)
\r
173 * @brief Check if Tx buffer empty
\r
174 * @param[in] sci - sci module base address
\r
176 * @return The TX ready flag
\r
178 * Checks to see if the Tx buffer ready flag is set, returns
\r
179 * 0 is flags not set otherwise will return the Tx flag itself.
\r
181 int sciIsTxReady(sciBASE_t *sci)
\r
183 /* USER CODE BEGIN (8) */
\r
184 /* USER CODE END */
\r
186 return sci->FLR & SCI_TX_INT;
\r
190 /** @fn void sciSendByte(sciBASE_t *sci, uint8_t byte)
\r
192 * @param[in] sci - sci module base address
\r
193 * @param[in] byte - byte to transfer
\r
195 * Sends a single byte in polling mode, will wait in the
\r
196 * routine until the transmit buffer is empty before sending
\r
197 * the byte. Use sciIsTxReady to check for Tx buffer empty
\r
198 * before calling sciSendByte to avoid waiting.
\r
200 void sciSendByte(sciBASE_t *sci, uint8_t byte)
\r
202 /* USER CODE BEGIN (9) */
\r
203 /* USER CODE END */
\r
205 while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };
\r
208 /* USER CODE BEGIN (10) */
\r
209 /* USER CODE END */
\r
213 /** @fn void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
215 * @param[in] sci - sci module base address
\r
216 * @param[in] length - number of data words to transfer
\r
217 * @param[in] data - pointer to data to send
\r
219 * Send a block of data pointed to by 'data' and 'length' bytes
\r
220 * long. If interrupts have been enabled the data is sent using
\r
221 * interrupt mode, otherwise polling mode is used. In interrupt
\r
222 * mode transmition of the first byte is started and the routine
\r
223 * returns imediatly, sciSend must not be called again until the
\r
224 * transfer is complete, when the sciNotification callback will
\r
225 * be called. In polling mode, sciSend will not return until
\r
226 * the transfer is complete.
\r
228 * @note if data word is less than 8 bits, then the data must be left
\r
229 * aligned in the data byte.
\r
231 void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
233 int index = sci == sciREG ? 0 : 1;
\r
235 /* USER CODE BEGIN (11) */
\r
236 /* USER CODE END */
\r
238 if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)
\r
240 /* we are in interrupt mode */
\r
242 g_sciTransfer[index].length = length;
\r
243 g_sciTransfer[index].data = data;
\r
245 /* start transmit by sending first byte */
\r
246 sci->TD = *g_sciTransfer[index].data++;
\r
247 sci->SETINT = SCI_TX_INT;
\r
251 /* send the data */
\r
252 while (length-- > 0)
\r
254 while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };
\r
259 /* USER CODE BEGIN (12) */
\r
260 /* USER CODE END */
\r
264 /** @fn int sciIsRxReady(sciBASE_t *sci)
\r
265 * @brief Check if Rx buffer full
\r
266 * @param[in] sci - sci module base address
\r
268 * @return The Rx ready flag
\r
270 * Checks to see if the Rx buffer full flag is set, returns
\r
271 * 0 is flags not set otherwise will return the Rx flag itself.
\r
273 int sciIsRxReady(sciBASE_t *sci)
\r
275 /* USER CODE BEGIN (13) */
\r
276 /* USER CODE END */
\r
278 return sci->FLR & SCI_RX_INT;
\r
282 /** @fn int sciRxError(sciBASE_t *sci)
\r
283 * @brief Return Rx Error flags
\r
284 * @param[in] sci - sci module base address
\r
286 * @return The Rx error flags
\r
288 * Returns the Rx framing, overun and parity errors flags,
\r
289 * also clears the error flags before returning.
\r
291 int sciRxError(sciBASE_t *sci)
\r
293 int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);
\r
295 /* USER CODE BEGIN (14) */
\r
296 /* USER CODE END */
\r
298 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
\r
303 /** @fn uint32_t sciReceiveByte(sciBASE_t *sci)
\r
304 * @brief Receive Byte
\r
305 * @param[in] sci - sci module base address
\r
307 * @return Received byte
\r
309 * Recieves a single byte in polling mode. If there is
\r
310 * not a byte in the receive buffer the routine will wait
\r
311 * until one is received. Use sciIsRxReady to check to
\r
312 * see if the buffer is full to avoid waiting.
\r
314 int sciReceiveByte(sciBASE_t *sci)
\r
316 /* USER CODE BEGIN (15) */
\r
317 /* USER CODE END */
\r
319 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
\r
325 /** @fn void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
326 * @brief Receive Data
\r
327 * @param[in] sci - sci module base address
\r
328 * @param[in] length - number of data words to transfer
\r
329 * @param[in] data - pointer to data buffer
\r
331 * Receive a block of 'length' bytes long and place it into the
\r
332 * data buffer pointed to by 'data'. If interrupts have been
\r
333 * enabled the data is received using interrupt mode, otherwise
\r
334 * polling mode is used. In interrupt mode receive is setup and
\r
335 * the routine returns imediatly, sciReceive must not be called
\r
336 * again until the transfer is complete, when the sciNotification
\r
337 * callback will be called. In polling mode, sciReceive will not
\r
338 * return until the transfer is complete.
\r
340 void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
342 /* USER CODE BEGIN (16) */
\r
343 // Delete generated content after user code block!!!
\r
344 if (sci->SETINT & SCI_RX_INT)
\r
346 /* We are in iterrupt mode, clear error flags */
\r
347 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
\r
352 while (length-- > 0)
\r
354 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
\r
358 /* USER CODE END */
\r
361 /* USER CODE BEGIN (17) */
\r
362 /* USER CODE END */
\r
365 /** @fn void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
\r
366 * @brief Enable Loopback mode for self test
\r
367 * @param[in] sci - sci module base address
\r
368 * @param[in] Loopbacktype - Digital or Analog
\r
370 * This function enables the Loopback mode for self test.
\r
372 void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
\r
374 /* USER CODE BEGIN (18) */
\r
375 /* USER CODE END */
\r
377 /* Clear Loopback incase enbaled already */
\r
378 sci->IODFTCTRL = 0;
\r
380 /* Enable Loopback either in Analog or Digital Mode */
\r
381 sci->IODFTCTRL = 0x00000A00
\r
382 | Loopbacktype << 1;
\r
384 /* USER CODE BEGIN (19) */
\r
385 /* USER CODE END */
\r
388 /** @fn void sciDisableLoopback(sciBASE_t *sci)
\r
389 * @brief Enable Loopback mode for self test
\r
390 * @param[in] sci - sci module base address
\r
392 * This function disable the Loopback mode.
\r
394 void sciDisableLoopback(sciBASE_t *sci)
\r
396 /* USER CODE BEGIN (20) */
\r
397 /* USER CODE END */
\r
399 /* Disable Loopback Mode */
\r
400 sci->IODFTCTRL = 0x000005000;
\r
402 /* USER CODE BEGIN (21) */
\r
403 /* USER CODE END */
\r
406 /** @fn sciEnableNotification(sciBASE_t *sci, uint32_t flags)
\r
407 * @brief Enable interrupts
\r
408 * @param[in] sci - sci module base address
\r
409 * @param[in] flags - Interrupts to be enabled, can be ored value of:
\r
410 * SCI_FE_INT - framming error,
\r
411 * SCI_OE_INT - overrun error,
\r
412 * SCI_PE_INT - parity error,
\r
413 * SCI_RX_INT - receive buffer ready,
\r
414 * SCI_TX_INT - transmit buffer ready,
\r
415 * SCI_WAKE_INT - wakeup,
\r
416 * SCI_BREAK_INT - break detect
\r
418 void sciEnableNotification(sciBASE_t *sci, uint32_t flags)
\r
420 int index = sci == sciREG ? 0 : 1;
\r
422 /* USER CODE BEGIN (22) */
\r
423 /* USER CODE END */
\r
425 g_sciTransfer[index].mode |= (flags & SCI_TX_INT);
\r
426 sci->SETINT = (flags & ~SCI_TX_INT);
\r
428 /* USER CODE BEGIN (23) */
\r
429 /* USER CODE END */
\r
433 /** @fn sciDisableNotification(sciBASE_t *sci, uint32_t flags)
\r
434 * @brief Disable interrupts
\r
435 * @param[in] sci - sci module base address
\r
436 * @param[in] flags - Interrupts to be disabled, can be ored value of:
\r
437 * SCI_FE_INT - framming error,
\r
438 * SCI_OE_INT - overrun error,
\r
439 * SCI_PE_INT - parity error,
\r
440 * SCI_RX_INT - receive buffer ready,
\r
441 * SCI_TX_INT - transmit buffer ready,
\r
442 * SCI_WAKE_INT - wakeup,
\r
443 * SCI_BREAK_INT - break detect
\r
445 void sciDisableNotification(sciBASE_t *sci, uint32_t flags)
\r
447 int index = sci == sciREG ? 0 : 1;
\r
449 /* USER CODE BEGIN (24) */
\r
450 /* USER CODE END */
\r
452 g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);
\r
453 sci->CLRINT = (flags & ~SCI_TX_INT);
\r
455 /* USER CODE BEGIN (25) */
\r
456 /* USER CODE END */
\r
460 /** @fn void sciHighLevelInterrupt(void)
\r
461 * @brief Level 0 Interrupt for SCI
\r
463 #pragma INTERRUPT(sciHighLevelInterrupt, IRQ)
\r
465 void sciHighLevelInterrupt(void)
\r
467 uint32_t vec = sciREG->INTVECT0;
\r
469 /* USER CODE BEGIN (26) */
\r
470 // Delete generated content after user code block!!!
\r
474 sciNotification(sciREG, SCI_WAKE_INT);
\r
477 sciNotification(sciREG, SCI_PE_INT);
\r
480 sciNotification(sciREG, SCI_FE_INT);
\r
483 sciNotification(sciREG, SCI_BREAK_INT);
\r
486 sciNotification(sciREG, SCI_OE_INT);
\r
491 { uint8_t byte = sciREG->RD;
\r
492 if (xQueueSendFromISR(inBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL)
\r
494 sciNotification(sciREG, SCI_RX_INT);
\r
502 if (xQueueReceiveFromISR(outBuffer.buf, (uint8_t *)&byte, NULL) == errQUEUE_EMPTY) {
\r
503 sciREG->CLRINT = SCI_TX_INT;
\r
504 outBuffer.flags &= ~BUF_TRANSFER_IN_PROGRESS;
\r
512 /* phantom interrupt, clear flags and return */
\r
513 sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;
\r
516 /* USER CODE END */
\r
517 /* USER CODE BEGIN (27) */
\r
518 /* USER CODE END */
\r
521 /** @fn void sciLowLevelInterrupt(void)
\r
522 * @brief Level 1 Interrupt for SCI
\r
524 #pragma INTERRUPT(sciLowLevelInterrupt, IRQ)
\r
526 void sciLowLevelInterrupt(void)
\r
528 uint32_t vec = sciREG->INTVECT1;
\r
530 /* USER CODE BEGIN (28) */
\r
531 /* USER CODE END */
\r
536 sciNotification(sciREG, SCI_WAKE_INT);
\r
539 sciNotification(sciREG, SCI_PE_INT);
\r
542 sciNotification(sciREG, SCI_FE_INT);
\r
545 sciNotification(sciREG, SCI_BREAK_INT);
\r
548 sciNotification(sciREG, SCI_OE_INT);
\r
553 { uint32_t byte = sciREG->RD;
\r
555 if (g_sciTransfer[0].length > 0)
\r
557 *g_sciTransfer[0].data++ = byte;
\r
558 g_sciTransfer[0].length--;
\r
559 if (g_sciTransfer[0].length == 0)
\r
561 sciNotification(sciREG, SCI_RX_INT);
\r
569 if (--g_sciTransfer[0].length > 0)
\r
571 sciREG->TD = *g_sciTransfer[0].data++;
\r
575 sciREG->CLRINT = SCI_TX_INT;
\r
576 sciNotification(sciREG, SCI_TX_INT);
\r
581 /* phantom interrupt, clear flags and return */
\r
582 sciREG->FLR = sciREG->SETINTLVL & 0x07000303;
\r
585 /* USER CODE BEGIN (29) */
\r
586 /* USER CODE END */
\r