]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp/lib/rpp/src/sys/ti_drv_sci.c
bdab7021604c7dc3e21a08ce5c699ffce5c681fd
[pes-rpp/rpp-test-sw.git] / rpp / lib / rpp / src / sys / ti_drv_sci.c
1 /** @file sci.c
2 *   @brief SCI Driver Implementation File
3 *   @date 15.Mar.2012
4 *   @version 03.01.00
5 *
6 */
7
8 /* (c) Texas Instruments 2009-2012, All rights reserved. */
9
10 /* USER CODE BEGIN (0) */
11 /* USER CODE END */
12
13 #include "sys/ti_drv_sci.h"
14
15 /* USER CODE BEGIN (1) */
16 //#include "cmdproc_io_tisci.h"
17 //#include "os_queue.h"
18
19 /* USER CODE END */
20 /** @struct g_sciTransfer
21 *   @brief Interrupt mode globals
22 *
23 */
24 struct g_sciTransfer
25 {
26     uint32_t       mode;
27     uint32_t       length;
28     uint8_t *data;
29 } g_sciTransfer[2];
30
31
32 /** Buffer used for sending to SCI */
33 tBuffer sciOutBuffer;
34 /** Buffer used for receiving from SCI */
35 tBuffer sciInBuffer;
36
37
38 /** @fn void sciInit(void)
39 *   @brief Initializes the SCI Driver
40 *
41 *   This function initializes the SCI module.
42 */
43 void sciInit(void)
44 {
45 /* USER CODE BEGIN (2) */
46 /* USER CODE END */
47
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;
55
56     /** @b Initialize @b SCI */
57
58     /** - bring SCI out of reset */
59     sciREG->GCR0 = 1U;
60
61     /** - Disable all interrupts */
62     sciREG->CLRINT    = 0xFFFFFFFFU;
63     sciREG->CLRINTLVL = 0xFFFFFFFFU;
64
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 */
73
74     /** - set baudrate */
75     sciREG->BAUD = 520;  /* baudrate */
76
77     /** - tranmision length */
78     sciREG->LENGTH = 8 - 1;  /* length */
79
80     /** - set SCI pins functional mode */
81     sciREG->FUN = (1 << 2)  /* tx pin */
82                  | (1 << 1)  /* rx pin */
83                  | (0);  /* clk pin */
84
85     /** - set SCI pins default output value */
86     sciREG->DOUT = (0 << 2)  /* tx pin */
87                   | (0 << 1)  /* rx pin */
88                   | (0);  /* clk pin */
89
90     /** - set SCI pins output direction */
91     sciREG->DIR = (1 << 2)  /* tx pin */
92                  | (0 << 1)  /* rx pin */
93                  | (0);  /* clk pin */
94
95     /** - set SCI pins open drain enable */
96     sciREG->ODR = (0 << 2)  /* tx pin */
97                  | (0 << 1)  /* rx pin */
98                  | (0);  /* clk pin */
99
100     /** - set SCI pins pullup/pulldown enable */
101     sciREG->PD = (0 << 2)  /* tx pin */
102                 | (0 << 1)  /* rx pin */
103                 | (0);  /* clk pin */
104
105     /** - set SCI pins pullup/pulldown select */
106     sciREG->PSL = (1 << 2)  /* tx pin */
107                  | (1 << 1)  /* rx pin */
108                  | (1);  /* clk pin */
109
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 */
118
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 */
126
127     /** - inialise global transfer variables */
128     g_sciTransfer[0].mode   = 1 << 8;
129     g_sciTransfer[0].length = 0;
130
131     /** - Finaly start SCI */
132     sciREG->GCR1 |= (1 << 7);
133
134
135 /* USER CODE BEGIN (3) */
136 /* USER CODE END */
137 }
138
139
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
144 *
145 *   Change the value of the PCFUN register at runtime, this allows to
146 *   dynaimcaly change the functionality of the SCI pins between functional
147 *   and GIO mode.
148 */
149 void sciSetFunctional(sciBASE_t *sci, uint32_t port)
150 {
151 /* USER CODE BEGIN (4) */
152 /* USER CODE END */
153
154     sci->FUN = port;
155
156 /* USER CODE BEGIN (5) */
157 /* USER CODE END */
158 }
159
160
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
165 *
166 *   Change the SCI baudrate at runtime.
167 */
168 void sciSetBaudrate(sciBASE_t *sci, uint32_t baud)
169 {
170     double   vclk = 80.000 * 1000000.0;
171     uint32_t f    = sci->GCR1 & 2 ? 16 : 1;
172
173 /* USER CODE BEGIN (6) */
174 /* USER CODE END */
175
176     sci->BAUD = ((uint32_t)((vclk /(f*baud) + 0.5)) - 1) & 0x00FFFFFF;
177
178 /* USER CODE BEGIN (7) */
179 /* USER CODE END */
180 }
181
182
183 /** @fn int sciIsTxReady(sciBASE_t *sci)
184 *   @brief Check if Tx buffer empty
185 *   @param[in] sci - sci module base address
186 *
187 *   @return The TX ready flag
188 *
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.
191 */
192 int sciIsTxReady(sciBASE_t *sci)
193 {
194 /* USER CODE BEGIN (8) */
195 /* USER CODE END */
196
197     return sci->FLR & SCI_TX_INT;
198 }
199
200
201 /** @fn void sciSendByte(sciBASE_t *sci, uint8_t byte)
202 *   @brief Send Byte
203 *   @param[in] sci  - sci module base address
204 *   @param[in] byte - byte to transfer
205 *
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.
210 */
211 /*
212 void sciSendByte(sciBASE_t *sci, uint8_t byte)
213 {
214     while ((sci->FLR & SCI_TX_INT) == 0) {}; // Wait
215     sci->TD = byte;
216 }
217 */
218
219
220 /** @fn void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
221 *   @brief Send 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
225 *
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.
234 *
235 *   @note if data word is less than 8 bits, then the data must be left
236 *         aligned in the data byte.
237 */
238 // Unused, see drv/sci.c/drv_sci_send()
239 /*
240 void sciSend(sciBASE_t *sci, uint32_t length, uint8_t *data)
241 {
242     int index = sci == sciREG ? 0 : 1;
243
244     if ((g_sciTransfer[index].mode & SCI_TX_INT) != 0)
245     {
246         // We are in interrupt mode
247         g_sciTransfer[index].length = length;
248         g_sciTransfer[index].data   = data;
249
250         // Start transmit by sending first byte
251         sci->TD     = *g_sciTransfer[index].data++;
252         sci->SETINT = SCI_TX_INT;
253     }
254     else
255     {
256         // Send the data
257         while (length-- > 0)
258         {
259             while ((sci->FLR & SCI_TX_INT) == 0) {}; // Wait
260             sci->TD = *data++;
261         }
262     }
263 }
264 */
265
266 /** @fn int sciIsRxReady(sciBASE_t *sci)
267 *   @brief Check if Rx buffer full
268 *   @param[in] sci - sci module base address
269 *
270 *   @return The Rx ready flag
271 *
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.
274 */
275 int sciIsRxReady(sciBASE_t *sci)
276 {
277 /* USER CODE BEGIN (13) */
278 /* USER CODE END */
279
280     return sci->FLR & SCI_RX_INT;
281 }
282
283
284 /** @fn int sciRxError(sciBASE_t *sci)
285 *   @brief Return Rx Error flags
286 *   @param[in] sci - sci module base address
287 *
288 *   @return The Rx error flags
289 *
290 *   Returns the Rx framing, overun and parity errors flags,
291 *   also clears the error flags before returning.
292 */
293 int sciRxError(sciBASE_t *sci)
294 {
295     int status = sci->FLR & (SCI_FE_INT | SCI_OE_INT |SCI_PE_INT);
296
297 /* USER CODE BEGIN (14) */
298 /* USER CODE END */
299
300     sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
301     return status;
302 }
303
304
305 /** @fn uint32_t sciReceiveByte(sciBASE_t *sci)
306 *   @brief Receive Byte
307 *   @param[in] sci - sci module base address
308 *
309 *   @return Received byte
310 *
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.
315 */
316 int sciReceiveByte(sciBASE_t *sci)
317 {
318 /* USER CODE BEGIN (15) */
319 /* USER CODE END */
320
321     while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
322
323     return sci->RD;
324 }
325
326
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
332 *
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.
341 */
342 void sciReceive(sciBASE_t *sci, uint32_t length, uint8_t *data)
343 {
344 /* USER CODE BEGIN (16) */
345     // Delete generated content after user code block!!!
346     if (sci->SETINT & SCI_RX_INT)
347     {
348         /* We are in iterrupt mode, clear error flags */
349         sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;
350
351     }
352     else
353     {
354         while (length-- > 0)
355         {
356             while ((sci->FLR & SCI_RX_INT) == 0) { /* wait */ };
357             *data++ = sci->RD;
358         }
359     }
360 /* USER CODE END */
361
362
363 /* USER CODE BEGIN (17) */
364 /* USER CODE END */
365 }
366
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
371 *
372 *   This function enables the Loopback mode for self test.
373 */
374 void sciEnableLoopback(sciBASE_t *sci, Loopbacktype_t Loopbacktype)
375 {
376 /* USER CODE BEGIN (18) */
377 /* USER CODE END */
378
379     /* Clear Loopback incase enbaled already */
380     sci->IODFTCTRL = 0;
381
382     /* Enable Loopback either in Analog or Digital Mode */
383     sci->IODFTCTRL = 0x00000A00
384                    | Loopbacktype << 1;
385
386 /* USER CODE BEGIN (19) */
387 /* USER CODE END */
388 }
389
390 /** @fn void sciDisableLoopback(sciBASE_t *sci)
391 *   @brief Enable Loopback mode for self test
392 *   @param[in] sci        - sci module base address
393 *
394 *   This function disable the Loopback mode.
395 */
396 void sciDisableLoopback(sciBASE_t *sci)
397 {
398 /* USER CODE BEGIN (20) */
399 /* USER CODE END */
400
401     /* Disable Loopback Mode */
402     sci->IODFTCTRL = 0x000005000;
403
404 /* USER CODE BEGIN (21) */
405 /* USER CODE END */
406 }
407
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
419 */
420 void sciEnableNotification(sciBASE_t *sci, uint32_t flags)
421 {
422     int index = sci == sciREG ? 0 : 1;
423
424 /* USER CODE BEGIN (22) */
425 /* USER CODE END */
426
427     g_sciTransfer[index].mode |= (flags & SCI_TX_INT);
428     sci->SETINT                = (flags & ~SCI_TX_INT);
429
430 /* USER CODE BEGIN (23) */
431 /* USER CODE END */
432 }
433
434
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
446 */
447 void sciDisableNotification(sciBASE_t *sci, uint32_t flags)
448 {
449     int index = sci == sciREG ? 0 : 1;
450
451 /* USER CODE BEGIN (24) */
452 /* USER CODE END */
453
454     g_sciTransfer[index].mode &= ~(flags & SCI_TX_INT);
455     sci->CLRINT                = (flags & ~SCI_TX_INT);
456
457 /* USER CODE BEGIN (25) */
458 /* USER CODE END */
459 }
460
461 static uint32_t receiveError;
462
463 /** @fn void sciHighLevelInterrupt(void)
464 *   @brief Level 0 Interrupt for SCI
465 */
466 #pragma INTERRUPT(sciHighLevelInterrupt, IRQ)
467
468 void sciHighLevelInterrupt(void)
469 {
470     uint32_t vec = sciREG->INTVECT0;
471
472 /* USER CODE BEGIN (26) */
473     // Delete generated content after user code block!!!
474     switch (vec)
475     {
476     case 1:
477         sciNotification(sciREG, SCI_WAKE_INT);
478         break;
479     case 3:
480         sciNotification(sciREG, SCI_PE_INT);
481         break;
482     case 6:
483         sciNotification(sciREG, SCI_FE_INT);
484         break;
485     case 7:
486         sciNotification(sciREG, SCI_BREAK_INT);
487         break;
488     case 9:
489         sciNotification(sciREG, SCI_OE_INT);
490         break;
491
492     case 11:
493         // Receive
494         {   uint8_t byte = sciREG->RD;
495             if (xQueueSendFromISR(sciInBuffer.buf, (void*)&byte, NULL) == errQUEUE_FULL) {
496                 receiveError++;
497             }
498             sciNotification(sciREG, SCI_RX_INT);
499         }
500         break;
501
502     case 12:
503         // Transmit
504         {
505             uint8_t byte = 0;
506             if (xQueueReceiveFromISR(sciOutBuffer.buf, (uint8_t *)&byte, NULL) == errQUEUE_EMPTY) {
507                 sciREG->CLRINT = SCI_TX_INT;
508                 sciOutBuffer.flags &= ~BUF_TRANSFER_IN_PROGRESS;
509             }
510             else {
511                 sciREG->TD     = byte;
512             }
513         }
514         break;
515      default:
516         // phantom interrupt, clear flags and return
517         sciREG->FLR = ~sciREG->SETINTLVL & 0x07000303;
518         break;
519     }
520 /* USER CODE END */
521 /* USER CODE BEGIN (27) */
522 /* USER CODE END */
523 }
524
525 /** @fn void sciLowLevelInterrupt(void)
526 *   @brief Level 1 Interrupt for SCI
527 */
528 #pragma INTERRUPT(sciLowLevelInterrupt, IRQ)
529
530 void sciLowLevelInterrupt(void)
531 {
532     uint32_t vec = sciREG->INTVECT1;
533
534 /* USER CODE BEGIN (28) */
535 /* USER CODE END */
536
537     switch (vec)
538     {
539     case 1:
540         sciNotification(sciREG, SCI_WAKE_INT);
541         break;
542     case 3:
543         sciNotification(sciREG, SCI_PE_INT);
544         break;
545     case 6:
546         sciNotification(sciREG, SCI_FE_INT);
547         break;
548     case 7:
549         sciNotification(sciREG, SCI_BREAK_INT);
550         break;
551     case 9:
552         sciNotification(sciREG, SCI_OE_INT);
553         break;
554
555     case 11:
556         /* receive */
557         {   uint32_t byte = sciREG->RD;
558
559             if (g_sciTransfer[0].length > 0)
560             {
561                 *g_sciTransfer[0].data++ = byte;
562                 g_sciTransfer[0].length--;
563                 if (g_sciTransfer[0].length == 0)
564                 {
565                     sciNotification(sciREG, SCI_RX_INT);
566                 }
567             }
568         }
569         break;
570
571     case 12:
572         /* transmit */
573         if (--g_sciTransfer[0].length > 0)
574         {
575             sciREG->TD = *g_sciTransfer[0].data++;
576         }
577         else
578         {
579             sciREG->CLRINT = SCI_TX_INT;
580             sciNotification(sciREG, SCI_TX_INT);
581         }
582         break;
583
584     default:
585         /* phantom interrupt, clear flags and return */
586         sciREG->FLR = sciREG->SETINTLVL & 0x07000303;
587          break;
588     }
589 /* USER CODE BEGIN (29) */
590 /* USER CODE END */
591 }
592
593
594