]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - source/ti_drv_sci.c
Source and Header files modified
[pes-rpp/rpp-test-sw.git] / source / ti_drv_sci.c
1 /** @file sci.c \r
2 *   @brief SCI Driver Implementation File\r
3 *   @date 15.Mar.2012\r
4 *   @version 03.01.00\r
5 *\r
6 */\r
7 \r
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */\r
9 \r
10 /* USER CODE BEGIN (0) */\r
11 /* USER CODE END */\r
12 \r
13 #include "ti_drv_sci.h"\r
14 \r
15 /* USER CODE BEGIN (1) */\r
16 #include "cmdio_tisci.h"\r
17 #include "os_queue.h"\r
18 \r
19 extern tBuffer outBuffer;\r
20 extern tBuffer inBuffer;\r
21 static uint32_t receiveError;\r
22 /* USER CODE END */\r
23 /** @struct g_sciTransfer\r
24 *   @brief Interrupt mode globals\r
25 *\r
26 */\r
27 struct g_sciTransfer\r
28 {\r
29     uint32_t       mode;\r
30     uint32_t       length;\r
31     uint8_t *data;\r
32 } g_sciTransfer[2];\r
33 \r
34 \r
35 /** @fn void sciInit(void)\r
36 *   @brief Initializes the SCI Driver\r
37 *\r
38 *   This function initializes the SCI module.\r
39 */\r
40 void sciInit(void)\r
41 {\r
42 /* USER CODE BEGIN (2) */\r
43 /* USER CODE END */\r
44 \r
45     /** @b intalise @b SCI */\r
46 \r
47     /** - bring SCI out of reset */\r
48     sciREG->GCR0 = 1U;\r
49 \r
50     /** - Disable all interrupts */\r
51     sciREG->CLRINT    = 0xFFFFFFFFU;\r
52     sciREG->CLRINTLVL = 0xFFFFFFFFU;\r
53 \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
62 \r
63     /** - set baudrate */\r
64     sciREG->BAUD = 520;  /* baudrate */\r
65 \r
66     /** - tranmision length */\r
67     sciREG->LENGTH = 8 - 1;  /* length */\r
68 \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
73 \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
78 \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
83 \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
88 \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
93 \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
98 \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
107 \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
115 \r
116     /** - inialise global transfer variables */\r
117     g_sciTransfer[0].mode   = 1 << 8;\r
118     g_sciTransfer[0].length = 0;\r
119 \r
120     /** - Finaly start SCI */\r
121     sciREG->GCR1 |= (1 << 7);\r
122 \r
123 \r
124 /* USER CODE BEGIN (3) */\r
125 /* USER CODE END */\r
126 }\r
127 \r
128 \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
133 *\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
136 *   and GIO mode.\r
137 */\r
138 void sciSetFunctional(sciBASE_t *sci, uint32_t port)\r
139 {\r
140 /* USER CODE BEGIN (4) */\r
141 /* USER CODE END */\r
142 \r
143     sci->FUN = port;\r
144 \r
145 /* USER CODE BEGIN (5) */\r
146 /* USER CODE END */\r
147 }\r
148 \r
149 \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
154 *\r
155 *   Change the SCI baudrate at runtime.\r
156 */\r
157 void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)\r
158 {\r
159     double   vclk = 80.000 * 1000000.0;\r
160     uint32_t f    = sci->GCR1 & 2 ? 16 : 1;\r
161 \r
162 /* USER CODE BEGIN (6) */\r
163 /* USER CODE END */\r
164 \r
165     sci->BAUD = ((uint32_t)((vclk /(f*baud) + 0.5)) - 1) & 0x00FFFFFF;\r
166 \r
167 /* USER CODE BEGIN (7) */\r
168 /* USER CODE END */\r
169 }\r
170 \r
171 \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
175 *\r
176 *   @return The TX ready flag\r
177 *\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
180 */\r
181 int sciIsTxReady(sciBASE_t *sci)\r
182 {\r
183 /* USER CODE BEGIN (8) */\r
184 /* USER CODE END */\r
185 \r
186     return sci->FLR & SCI_TX_INT;\r
187 }\r
188 \r
189 \r
190 /** @fn void sciSendByte(sciBASE_t *sci, uint8_t byte)\r
191 *   @brief Send Byte\r
192 *   @param[in] sci  - sci module base address\r
193 *   @param[in] byte - byte to transfer\r
194 *\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
199 */\r
200 void sciSendByte(sciBASE_t *sci, uint8_t byte)\r
201 {\r
202 /* USER CODE BEGIN (9) */\r
203 /* USER CODE END */\r
204 \r
205     while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };\r
206     sci->TD = byte;\r
207 \r
208 /* USER CODE BEGIN (10) */\r
209 /* USER CODE END */\r
210 }\r
211 \r
212 \r
213 /** @fn void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
214 *   @brief Send 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
218 *\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
227 *\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
230 */\r
231 void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
232 {\r
233     int index = sci == sciREG ? 0 : 1;\r
234 \r
235 /* USER CODE BEGIN (11) */\r
236 /* USER CODE END */\r
237 \r
238     if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)\r
239     {\r
240         /* we are in interrupt mode */\r
241         \r
242         g_sciTransfer[index].length = length;\r
243         g_sciTransfer[index].data   = data;\r
244 \r
245         /* start transmit by sending first byte */        \r
246         sci->TD     = *g_sciTransfer[index].data++;\r
247         sci->SETINT = SCI_TX_INT;\r
248     }\r
249     else\r
250     {\r
251         /* send the data */\r
252         while (length-- > 0)\r
253         {\r
254             while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };\r
255             sci->TD = *data++;\r
256         }\r
257     }\r
258 \r
259 /* USER CODE BEGIN (12) */\r
260 /* USER CODE END */\r
261 }\r
262 \r
263 \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
267 *\r
268 *   @return The Rx ready flag\r
269 *\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
272 */\r
273 int sciIsRxReady(sciBASE_t *sci)\r
274 {\r
275 /* USER CODE BEGIN (13) */\r
276 /* USER CODE END */\r
277 \r
278     return sci->FLR & SCI_RX_INT;\r
279 }\r
280 \r
281 \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
285 *\r
286 *   @return The Rx error flags\r
287 *\r
288 *   Returns the Rx framing, overun and parity errors flags,\r
289 *   also clears the error flags before returning.\r
290 */\r
291 int sciRxError(sciBASE_t *sci)\r
292 {\r
293     int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);\r
294 \r
295 /* USER CODE BEGIN (14) */\r
296 /* USER CODE END */\r
297 \r
298     sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;\r
299     return status;\r
300 }\r
301 \r
302 \r
303 /** @fn uint32_t sciReceiveByte(sciBASE_t *sci)\r
304 *   @brief Receive Byte\r
305 *   @param[in] sci - sci module base address\r
306 *\r
307 *   @return Received byte\r
308 *\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
313 */\r
314 int sciReceiveByte(sciBASE_t *sci)\r
315 {\r
316 /* USER CODE BEGIN (15) */\r
317 /* USER CODE END */\r
318 \r
319     while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };\r
320 \r
321     return sci->RD;\r
322 }\r
323 \r
324 \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
330 *\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
339 */\r
340 void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)\r
341 {\r
342 /* USER CODE BEGIN (16) */\r
343         // Delete generated content after user code block!!!\r
344     if (sci->SETINT & SCI_RX_INT)\r
345     {\r
346         /* We are in iterrupt mode, clear error flags */\r
347         sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;\r
348 \r
349     }\r
350     else\r
351     {   \r
352         while (length-- > 0)\r
353         {\r
354             while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };\r
355             *data++ = sci->RD;\r
356         }\r
357     }\r
358 /* USER CODE END */\r
359 \r
360 \r
361 /* USER CODE BEGIN (17) */\r
362 /* USER CODE END */\r
363 }\r
364 \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
369 *\r
370 *   This function enables the Loopback mode for self test.\r
371 */\r
372 void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)\r
373 {\r
374 /* USER CODE BEGIN (18) */\r
375 /* USER CODE END */\r
376     \r
377         /* Clear Loopback incase enbaled already */\r
378         sci->IODFTCTRL = 0;\r
379         \r
380         /* Enable Loopback either in Analog or Digital Mode */\r
381     sci->IODFTCTRL = 0x00000A00\r
382                    | Loopbacktype << 1;\r
383         \r
384 /* USER CODE BEGIN (19) */\r
385 /* USER CODE END */\r
386 }\r
387 \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
391 *\r
392 *   This function disable the Loopback mode.\r
393 */\r
394 void sciDisableLoopback(sciBASE_t *sci)\r
395 {\r
396 /* USER CODE BEGIN (20) */\r
397 /* USER CODE END */\r
398     \r
399         /* Disable Loopback Mode */\r
400     sci->IODFTCTRL = 0x000005000;\r
401         \r
402 /* USER CODE BEGIN (21) */\r
403 /* USER CODE END */\r
404 }\r
405 \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
417 */\r
418 void sciEnableNotification(sciBASE_t *sci, uint32_t flags)\r
419 {\r
420     int index = sci == sciREG ? 0 : 1;\r
421 \r
422 /* USER CODE BEGIN (22) */\r
423 /* USER CODE END */\r
424 \r
425     g_sciTransfer[index].mode |= (flags & SCI_TX_INT);\r
426     sci->SETINT                = (flags & ~SCI_TX_INT);\r
427 \r
428 /* USER CODE BEGIN (23) */\r
429 /* USER CODE END */\r
430 }\r
431 \r
432 \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
444 */\r
445 void sciDisableNotification(sciBASE_t *sci, uint32_t flags)\r
446 {\r
447     int index = sci == sciREG ? 0 : 1;\r
448 \r
449 /* USER CODE BEGIN (24) */\r
450 /* USER CODE END */\r
451 \r
452     g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);\r
453     sci->CLRINT                = (flags & ~SCI_TX_INT);\r
454 \r
455 /* USER CODE BEGIN (25) */\r
456 /* USER CODE END */\r
457 }\r
458 \r
459 \r
460 /** @fn void sciHighLevelInterrupt(void)\r
461 *   @brief Level 0 Interrupt for SCI\r
462 */\r
463 #pragma INTERRUPT(sciHighLevelInterrupt, IRQ)\r
464 \r
465 void sciHighLevelInterrupt(void)\r
466 {\r
467     uint32_t vec = sciREG->INTVECT0;\r
468 \r
469 /* USER CODE BEGIN (26) */\r
470         // Delete generated content after user code block!!!\r
471     switch (vec)\r
472     {\r
473     case 1:\r
474         sciNotification(sciREG, SCI_WAKE_INT);\r
475         break;\r
476     case 3:\r
477         sciNotification(sciREG, SCI_PE_INT);\r
478         break;\r
479     case 6:\r
480         sciNotification(sciREG, SCI_FE_INT);\r
481         break;\r
482     case 7:\r
483         sciNotification(sciREG, SCI_BREAK_INT);\r
484         break;\r
485     case 9:\r
486         sciNotification(sciREG, SCI_OE_INT);\r
487         break;\r
488 \r
489     case 11:\r
490         /* receive */\r
491         {   uint8_t byte = sciREG->RD;\r
492                 if (xQueueSendFromISR(inBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL)\r
493                         receiveError++;\r
494                 sciNotification(sciREG, SCI_RX_INT);\r
495         }\r
496         break;\r
497 \r
498     case 12:\r
499         /* transmit */\r
500         {\r
501                         uint8_t byte = 0;\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
505                         }\r
506                         else {\r
507                                 sciREG->TD     = byte;\r
508                         }\r
509         }\r
510         break;\r
511      default:\r
512         /* phantom interrupt, clear flags and return */\r
513         sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;\r
514         break;\r
515     }\r
516 /* USER CODE END */\r
517 /* USER CODE BEGIN (27) */\r
518 /* USER CODE END */\r
519 }\r
520 \r
521 /** @fn void sciLowLevelInterrupt(void)\r
522 *   @brief Level 1 Interrupt for SCI\r
523 */\r
524 #pragma INTERRUPT(sciLowLevelInterrupt, IRQ)\r
525 \r
526 void sciLowLevelInterrupt(void)\r
527 {\r
528     uint32_t vec = sciREG->INTVECT1;\r
529 \r
530 /* USER CODE BEGIN (28) */\r
531 /* USER CODE END */\r
532 \r
533     switch (vec)\r
534     {\r
535     case 1:\r
536         sciNotification(sciREG, SCI_WAKE_INT);\r
537         break;\r
538     case 3:\r
539         sciNotification(sciREG, SCI_PE_INT);\r
540         break;\r
541     case 6:\r
542         sciNotification(sciREG, SCI_FE_INT);\r
543         break;\r
544     case 7:\r
545         sciNotification(sciREG, SCI_BREAK_INT);\r
546         break;\r
547     case 9:\r
548         sciNotification(sciREG, SCI_OE_INT);\r
549         break;\r
550 \r
551     case 11:\r
552         /* receive */\r
553         {   uint32_t byte = sciREG->RD;\r
554 \r
555             if (g_sciTransfer[0].length > 0)\r
556             {\r
557                 *g_sciTransfer[0].data++ = byte;\r
558                 g_sciTransfer[0].length--;\r
559                 if (g_sciTransfer[0].length == 0)\r
560                 {\r
561                     sciNotification(sciREG, SCI_RX_INT);\r
562                 }\r
563             }\r
564         }\r
565         break;\r
566 \r
567     case 12:\r
568         /* transmit */\r
569         if (--g_sciTransfer[0].length > 0)\r
570         {\r
571             sciREG->TD = *g_sciTransfer[0].data++;\r
572         }\r
573         else\r
574         {\r
575             sciREG->CLRINT = SCI_TX_INT;\r
576             sciNotification(sciREG, SCI_TX_INT);\r
577         }\r
578         break;\r
579 \r
580     default:\r
581         /* phantom interrupt, clear flags and return */\r
582         sciREG->FLR = sciREG->SETINTLVL & 0x07000303;\r
583          break;\r
584     }\r
585 /* USER CODE BEGIN (29) */\r
586 /* USER CODE END */\r
587 }\r
588 \r
589 \r
590 \r