2 * @brief SCI Driver Implementation File
\r
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */
\r
10 /* USER CODE BEGIN (0) */
\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 | ((2-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 = 0 << 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 /* Using interrupt, does not work. Sometimes a character is lost */
\r
237 // if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)
\r
239 /* start transmit by sending first byte */
\r
240 // uint8_t byte = 0;
\r
241 // if (xQueueReceiveFromISR(outBuffer.buf, (uint8_t *)&byte, NULL) == pdPASS) {
\r
243 // sci->SETINT = SCI_TX_INT;
\r
248 /* send the data *///
\r
249 // while (length-- > 0)
\r
251 // while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };
\r
252 // sci->TD = *data++;
\r
255 /* USER CODE END */
\r
257 if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)
\r
259 /* we are in interrupt mode */
\r
261 g_sciTransfer[index].length = length;
\r
262 g_sciTransfer[index].data = data;
\r
264 /* start transmit by sending first byte */
\r
265 sci->TD = *g_sciTransfer[index].data++;
\r
266 sci->SETINT = SCI_TX_INT;
\r
270 /* send the data */
\r
271 while (xQueueIsQueueEmptyFromISR(outBuffer.buf) != pdTRUE)
\r
273 while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };
\r
275 xQueueReceiveFromISR(outBuffer.buf, (void *)&byte, NULL);
\r
280 /* USER CODE BEGIN (12) */
\r
281 /* USER CODE END */
\r
285 /** @fn int sciIsRxReady(sciBASE_t *sci)
\r
286 * @brief Check if Rx buffer full
\r
287 * @param[in] sci - sci module base address
\r
289 * @return The Rx ready flag
\r
291 * Checks to see if the Rx buffer full flag is set, returns
\r
292 * 0 is flags not set otherwise will return the Rx flag itself.
\r
294 int sciIsRxReady(sciBASE_t *sci)
\r
296 /* USER CODE BEGIN (13) */
\r
297 /* USER CODE END */
\r
299 return sci->FLR & SCI_RX_INT;
\r
303 /** @fn int sciRxError(sciBASE_t *sci)
\r
304 * @brief Return Rx Error flags
\r
305 * @param[in] sci - sci module base address
\r
307 * @return The Rx error flags
\r
309 * Returns the Rx framing, overun and parity errors flags,
\r
310 * also clears the error flags before returning.
\r
312 int sciRxError(sciBASE_t *sci)
\r
314 int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);
\r
316 /* USER CODE BEGIN (14) */
\r
317 /* USER CODE END */
\r
319 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
\r
324 /** @fn uint32_t sciReceiveByte(sciBASE_t *sci)
\r
325 * @brief Receive Byte
\r
326 * @param[in] sci - sci module base address
\r
328 * @return Received byte
\r
330 * Recieves a single byte in polling mode. If there is
\r
331 * not a byte in the receive buffer the routine will wait
\r
332 * until one is received. Use sciIsRxReady to check to
\r
333 * see if the buffer is full to avoid waiting.
\r
335 int sciReceiveByte(sciBASE_t *sci)
\r
337 /* USER CODE BEGIN (15) */
\r
338 /* USER CODE END */
\r
340 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
\r
346 /** @fn void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
347 * @brief Receive Data
\r
348 * @param[in] sci - sci module base address
\r
349 * @param[in] length - number of data words to transfer
\r
350 * @param[in] data - pointer to data buffer
\r
352 * Receive a block of 'length' bytes long and place it into the
\r
353 * data buffer pointed to by 'data'. If interrupts have been
\r
354 * enabled the data is received using interrupt mode, otherwise
\r
355 * polling mode is used. In interrupt mode receive is setup and
\r
356 * the routine returns imediatly, sciReceive must not be called
\r
357 * again until the transfer is complete, when the sciNotification
\r
358 * callback will be called. In polling mode, sciReceive will not
\r
359 * return until the transfer is complete.
\r
361 void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
\r
363 /* USER CODE BEGIN (16) */
\r
364 if (sci->SETINT & SCI_RX_INT)
\r
366 /* clear error flags */
\r
367 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
\r
372 while (length-- > 0)
\r
374 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
\r
378 /* USER CODE END */
\r
380 if (sci->SETINT & SCI_RX_INT)
\r
382 /* we are in interrupt mode */
\r
383 int index = sci == sciREG ? 0 : 1;
\r
385 /* clear error flags */
\r
386 sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
\r
388 g_sciTransfer[index].length = length;
\r
389 g_sciTransfer[index].data = data;
\r
393 while (length-- > 0)
\r
395 while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
\r
399 /* USER CODE BEGIN (17) */
\r
400 /* USER CODE END */
\r
403 /** @fn void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
\r
404 * @brief Enable Loopback mode for self test
\r
405 * @param[in] sci - sci module base address
\r
406 * @param[in] Loopbacktype - Digital or Analog
\r
408 * This function enables the Loopback mode for self test.
\r
410 void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
\r
412 /* USER CODE BEGIN (18) */
\r
413 /* USER CODE END */
\r
415 /* Clear Loopback incase enbaled already */
\r
416 sci->IODFTCTRL = 0;
\r
418 /* Enable Loopback either in Analog or Digital Mode */
\r
419 sci->IODFTCTRL = 0x00000A00
\r
420 | Loopbacktype << 1;
\r
422 /* USER CODE BEGIN (19) */
\r
423 /* USER CODE END */
\r
426 /** @fn void sciDisableLoopback(sciBASE_t *sci)
\r
427 * @brief Enable Loopback mode for self test
\r
428 * @param[in] sci - sci module base address
\r
430 * This function disable the Loopback mode.
\r
432 void sciDisableLoopback(sciBASE_t *sci)
\r
434 /* USER CODE BEGIN (20) */
\r
435 /* USER CODE END */
\r
437 /* Disable Loopback Mode */
\r
438 sci->IODFTCTRL = 0x000005000;
\r
440 /* USER CODE BEGIN (21) */
\r
441 /* USER CODE END */
\r
444 /** @fn sciEnableNotification(sciBASE_t *sci, uint32_t flags)
\r
445 * @brief Enable interrupts
\r
446 * @param[in] sci - sci module base address
\r
447 * @param[in] flags - Interrupts to be enabled, can be ored value of:
\r
448 * SCI_FE_INT - framming error,
\r
449 * SCI_OE_INT - overrun error,
\r
450 * SCI_PE_INT - parity error,
\r
451 * SCI_RX_INT - receive buffer ready,
\r
452 * SCI_TX_INT - transmit buffer ready,
\r
453 * SCI_WAKE_INT - wakeup,
\r
454 * SCI_BREAK_INT - break detect
\r
456 void sciEnableNotification(sciBASE_t *sci, uint32_t flags)
\r
458 int index = sci == sciREG ? 0 : 1;
\r
460 /* USER CODE BEGIN (22) */
\r
461 /* USER CODE END */
\r
463 g_sciTransfer[index].mode |= (flags & SCI_TX_INT);
\r
464 sci->SETINT = (flags & ~SCI_TX_INT);
\r
466 /* USER CODE BEGIN (23) */
\r
467 /* USER CODE END */
\r
471 /** @fn sciDisableNotification(sciBASE_t *sci, uint32_t flags)
\r
472 * @brief Disable interrupts
\r
473 * @param[in] sci - sci module base address
\r
474 * @param[in] flags - Interrupts to be disabled, can be ored value of:
\r
475 * SCI_FE_INT - framming error,
\r
476 * SCI_OE_INT - overrun error,
\r
477 * SCI_PE_INT - parity error,
\r
478 * SCI_RX_INT - receive buffer ready,
\r
479 * SCI_TX_INT - transmit buffer ready,
\r
480 * SCI_WAKE_INT - wakeup,
\r
481 * SCI_BREAK_INT - break detect
\r
483 void sciDisableNotification(sciBASE_t *sci, uint32_t flags)
\r
485 int index = sci == sciREG ? 0 : 1;
\r
487 /* USER CODE BEGIN (24) */
\r
488 /* USER CODE END */
\r
490 g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);
\r
491 sci->CLRINT = (flags & ~SCI_TX_INT);
\r
493 /* USER CODE BEGIN (25) */
\r
494 /* USER CODE END */
\r
498 /** @fn void sciHighLevelInterrupt(void)
\r
499 * @brief Level 0 Interrupt for SCI
\r
501 #pragma INTERRUPT(sciHighLevelInterrupt, IRQ)
\r
503 void sciHighLevelInterrupt(void)
\r
505 uint32_t vec = sciREG->INTVECT0;
\r
507 /* USER CODE BEGIN (26) */
\r
511 sciNotification(sciREG, SCI_WAKE_INT);
\r
514 sciNotification(sciREG, SCI_PE_INT);
\r
517 sciNotification(sciREG, SCI_FE_INT);
\r
520 sciNotification(sciREG, SCI_BREAK_INT);
\r
523 sciNotification(sciREG, SCI_OE_INT);
\r
528 { uint8_t byte = sciREG->RD;
\r
529 if (xQueueSendFromISR(inBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL)
\r
531 sciNotification(sciREG, SCI_RX_INT);
\r
537 /* using interrupt, does not work properly, sometimes a character is lost */
\r
538 /* if (xQueueIsQueueEmptyFromISR(outBuffer.buf) == pdTRUE) {
\r
539 sciREG->CLRINT = SCI_TX_INT;
\r
540 sciNotification(sciREG, SCI_TX_INT);
\r
544 xQueueReceiveFromISR(outBuffer.buf, (uint8_t *)&byte, NULL);
\r
545 while (sciIsTxReady(sciREG) == 0)
\r
551 if (--g_sciTransfer[0].length > 0)
\r
553 sciREG->TD = *g_sciTransfer[0].data++;
\r
557 sciREG->CLRINT = SCI_TX_INT;
\r
558 sciNotification(sciREG, SCI_TX_INT);
\r
563 /* phantom interrupt, clear flags and return */
\r
564 sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;
\r
567 /* USER CODE END */
\r
569 /* USER CODE BEGIN (27) */
\r
570 /* USER CODE END */
\r
573 /** @fn void sciLowLevelInterrupt(void)
\r
574 * @brief Level 1 Interrupt for SCI
\r
576 #pragma INTERRUPT(sciLowLevelInterrupt, IRQ)
\r
578 void sciLowLevelInterrupt(void)
\r
580 uint32_t vec = sciREG->INTVECT1;
\r
581 /* USER CODE BEGIN (28) */
\r
582 /* USER CODE END */
\r
587 sciNotification(sciREG, SCI_WAKE_INT);
\r
590 sciNotification(sciREG, SCI_PE_INT);
\r
593 sciNotification(sciREG, SCI_FE_INT);
\r
596 sciNotification(sciREG, SCI_BREAK_INT);
\r
599 sciNotification(sciREG, SCI_OE_INT);
\r
604 { uint32_t byte = sciREG->RD;
\r
606 if (g_sciTransfer[0].length > 0)
\r
608 *g_sciTransfer[0].data++ = byte;
\r
609 g_sciTransfer[0].length--;
\r
610 if (g_sciTransfer[0].length == 0)
\r
612 sciNotification(sciREG, SCI_RX_INT);
\r
620 if (--g_sciTransfer[0].length > 0)
\r
622 sciREG->TD = *g_sciTransfer[0].data++;
\r
626 sciREG->CLRINT = SCI_TX_INT;
\r
627 sciNotification(sciREG, SCI_TX_INT);
\r
632 /* phantom interrupt, clear flags and return */
\r
633 sciREG->FLR = sciREG->SETINTLVL & 0x07000303;
\r
636 /* USER CODE BEGIN (29) */
\r
637 /* USER CODE END */
\r