Contiki 2.5
uart2.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This file is part of libmc1322x: see http://mc1322x.devl.org
31  * for details.
32  *
33  *
34  */
35 
36 #include <mc1322x.h>
37 #include <stdint.h>
38 
39 volatile char u2_tx_buf[UART2_TX_BUFFERSIZE];
40 volatile uint32_t u2_tx_head, u2_tx_tail;
41 
42 #if UART2_RX_BUFFERSIZE > 32
43 volatile char u2_rx_buf[UART2_RX_BUFFERSIZE-32];
44 volatile uint32_t u2_rx_head, u2_rx_tail;
45 #endif
46 
47 void uart2_isr(void) {
48 
49 #if UART2_RX_BUFFERSIZE > 32
50  if (*UART2_USTAT & ( 1 << 6)) { //receive interrupt
51  while( *UART2_URXCON != 0 ) { //flush the hardware fifo into the software buffer
52  uint32_t u2_rx_tail_next;
53  u2_rx_tail_next = u2_rx_tail+1;
54  if (u2_rx_tail_next >= sizeof(u2_rx_buf))
55  u2_rx_tail_next = 0;
56  if (u2_rx_head != u2_rx_tail_next) {
57  u2_rx_buf[u2_rx_tail]= *UART2_UDATA;
58  u2_rx_tail = u2_rx_tail_next;
59  } else { //buffer is full, flush the fifo
60  while (*UART2_URXCON !=0) if (*UART2_UDATA);
61  }
62  }
63  return;
64  }
65 #endif
66 
67  while( *UART2_UTXCON != 0 ) {
68  if (u2_tx_head == u2_tx_tail) {
69 #if UART2_RX_BUFFERSIZE > 32
70  *UART2_UCON |= (1 << 13); /*disable tx interrupt */
71 #else
72  disable_irq(UART2);
73 #endif
74  return;
75  }
76 
77  *UART2_UDATA = u2_tx_buf[u2_tx_tail];
78  u2_tx_tail++;
79  if (u2_tx_tail >= sizeof(u2_tx_buf))
80  u2_tx_tail = 0;
81  }
82 }
83 
84 void uart2_putc(char c) {
85  /* disable UART2 since */
86  /* UART2 isr modifies u2_tx_head and u2_tx_tail */
87 #if UART2_RX_BUFFERSIZE > 32
88  *UART2_UCON |= (1 << 13); /*disable tx interrupt */
89 #else
90  disable_irq(UART2);
91 #endif
92 
93  if( (u2_tx_head == u2_tx_tail) &&
94  (*UART2_UTXCON != 0)) {
95  *UART2_UDATA = c;
96  } else {
97  u2_tx_buf[u2_tx_head] = c;
98  u2_tx_head += 1;
99  if (u2_tx_head >= sizeof(u2_tx_buf))
100  u2_tx_head = 0;
101  if (u2_tx_head == u2_tx_tail) { /* drop chars when no room */
102 #if UART2_DROP_CHARS
103  if (u2_tx_head) { u2_tx_head -=1; } else { u2_tx_head = sizeof(u2_tx_buf); }
104 #else
105  {
106  uint32_t u2_tx_tail_save=u2_tx_tail;
107  /* Back up head to show buffer not empty, and enable tx interrupt */
108  u2_tx_head--;
109 #if UART2_RX_BUFFERSIZE > 32
110  *UART2_UCON &= ~(1 << 13); /*enable tx interrupt */
111 #else
112  enable_irq(UART2);
113 #endif
114  /* Tail will change after one character goes out */
115  while (u2_tx_tail_save == u2_tx_tail) ;
116  /* Restore head to character we just stuffed */
117  u2_tx_head++;
118  return;
119  }
120 #endif /* UART2_DROP_CHARS */
121  }
122 
123 #if UART2_RX_BUFFERSIZE > 32
124  *UART2_UCON &= ~(1 << 13); /*enable tx interrupt */
125 #else
126  enable_irq(UART2);
127 #endif
128 
129  }
130 }
131 
132 uint8_t uart2_getc(void) {
133 #if UART2_RX_BUFFERSIZE > 32
134 /* First pull from the ram buffer */
135 uint8_t c=0;
136  if (u2_rx_head != u2_rx_tail) {
137  c = u2_rx_buf[u2_rx_head++];
138  if (u2_rx_head >= sizeof(u2_rx_buf))
139  u2_rx_head=0;
140  return c;
141  }
142 #endif
143 /* Then pull from the hardware fifo */
144  while(uart2_can_get() == 0) { continue; }
145  return *UART2_UDATA;
146 }