Contiki 2.5
uart.c
Go to the documentation of this file.
1 /** @file hal/micro/cortexm3/uart.c
2  * @brief STM32W uart drivers, supporting IAR's standard library
3  * IO routines.
4  *
5  * <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. -->
6  */
7 
8 #include PLATFORM_HEADER
9 #include "hal/micro/micro-common.h"
11 #include "uart.h"
12 #ifdef __GNUC__
13 #include <sys/stat.h>
14 #include <stdio.h>
15 #define _LLIO_STDIN ((int) stdin)
16 #define _LLIO_STDOUT ((int) stdout)
17 #define _LLIO_STDERR ((int) stderr)
18 #define _LLIO_ERROR (-1)
19 #define __write _write
20 #define __read _read
21 #undef putchar
22 void __io_putchar( char c );
23 int putchar (int c)
24 {
25  __io_putchar((char) c);
26  return c;
27 }
28 #endif
29 #define RECEIVE_QUEUE_SIZE (128)
30 
31 int8u rxQ[RECEIVE_QUEUE_SIZE];
32 int16u rxHead;
33 int16u rxTail;
34 int16u rxUsed;
35 
36 //////////////////////////////////////////////////////////////////////////////
37 // Initialization
38 
39 void uartInit(int32u baudrate, int8u databits, SerialParity parity, int8u stopbits)
40 {
41  int32u tempcfg;
42  int32u tmp;
43 
44  assert( (baudrate >= 300) && (baudrate <=921600) );
45 
46  tmp = (2*12000000L + baudrate/2) / baudrate;
47  SC1_UARTFRAC = tmp & 1;
48  SC1_UARTPER = tmp / 2;
49 
50  if(databits == 7) {
51  tempcfg = 0;
52  } else {
53  tempcfg = SC_UART8BIT;
54  }
55 
56  if (parity == PARITY_ODD) {
57  tempcfg |= SC_UARTPAR | SC_UARTODD;
58  } else if( parity == PARITY_EVEN ) {
59  tempcfg |= SC_UARTPAR;
60  }
61 
62  if ((stopbits & 0x0F) >= 2) {
63  tempcfg |= SC_UART2STP;
64  }
65  SC1_UARTCFG = tempcfg;
66 
67  SC1_MODE = SC1_MODE_UART;
68 
69  rxHead=0;
70  rxTail=0;
71  rxUsed=0;
72 
73  halGpioConfig(PORTB_PIN(1),GPIOCFG_OUT_ALT);
74  halGpioConfig(PORTB_PIN(2),GPIOCFG_IN);
75 
76  // Make the RX Valid interrupt level sensitive (instead of edge)
77  SC1_INTMODE = SC_RXVALLEVEL;
78  // Enable just RX interrupts; TX interrupts are controlled separately
79  INT_SC1CFG |= (INT_SCRXVAL |
80  INT_SCRXOVF |
81  INT_SC1FRMERR |
82  INT_SC1PARERR);
83  INT_SC1FLAG = 0xFFFF; // Clear any stale interrupts
84  INT_CFGSET = INT_SC1;
85 }
86 
87 //////////////////////////////////////////////////////////////////////////////
88 // Transmit
89 
90 // IAR Standard library hook for serial output
91 size_t __write(int handle, const unsigned char * buffer, size_t size)
92 {
93  size_t nChars = 0;
94 
95  /* This template only writes to "standard out" and "standard err",
96  * for all other file handles it returns failure. */
97  if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
98  return _LLIO_ERROR;
99  }
100 
101  if (buffer == 0) {
102  // This means that we should flush internal buffers.
103  //spin until TX complete (TX is idle)
104  while ((SC1_UARTSTAT&SC_UARTTXIDLE)!=SC_UARTTXIDLE) {}
105  return 0;
106  }
107 
108  // ensure port is configured for UART
109  if(SC1_MODE != SC1_MODE_UART) {
110  return _LLIO_ERROR;
111  }
112 
113  while(size--) {
114  //spin until data register has room for more data
115  while ((SC1_UARTSTAT&SC_UARTTXFREE)!=SC_UARTTXFREE) {}
116  SC1_DATA = *buffer;
117  buffer++;
118 
119  ++nChars;
120  }
121 
122  return nChars;
123 }
124 #ifdef __GNUC__
125 int fflush (FILE *f)
126 #endif
127 #ifdef __ICCARM__
128 size_t fflush(int handle)
129 #endif
130 {
131  return __write(_LLIO_STDOUT, NULL, 0);
132 }
133 
134 static void halInternalUart1TxIsr(void)
135 {
136  // Nothing for now, as ouput is blocking from the __write function
137 }
138 
139 
140 //////////////////////////////////////////////////////////////////////////////
141 // Receive
142 
143 // IAR Standard library hook for serial input
144 size_t __read(int handle, unsigned char * buffer, size_t size)
145 {
146  int nChars = 0;
147 
148  /* This template only reads from "standard in", for all other file
149  * handles it returns failure. */
150  if (handle != _LLIO_STDIN)
151  {
152  return _LLIO_ERROR;
153  }
154 
155  for(nChars = 0; (rxUsed>0) && (nChars < size); nChars++) {
156  ATOMIC(
157  *buffer++ = rxQ[rxTail];
158  rxTail = (rxTail+1) % RECEIVE_QUEUE_SIZE;
159  rxUsed--;
160  )
161  }
162 
163  return nChars;
164 }
165 
166 static void halInternalUart1RxIsr(void)
167 {
168 
169  // At present we really don't care which interrupt(s)
170  // occurred, just that one did. Loop reading RXVALID
171  // data, processing any errors noted
172  // along the way.
173  while ( SC1_UARTSTAT & SC_UARTRXVAL ) {
174  int8u errors = SC1_UARTSTAT & (SC_UARTFRMERR |
175  SC_UARTRXOVF |
176  SC_UARTPARERR );
177  int8u incoming = (int8u) SC1_DATA;
178 
179  if ( (errors == 0) && (rxUsed < (RECEIVE_QUEUE_SIZE-1)) ) {
180  rxQ[rxHead] = incoming;
181  rxHead = (rxHead+1) % RECEIVE_QUEUE_SIZE;
182  rxUsed++;
183  } else {
184  // IAR standard library doesn't allow for any error handling in the
185  // case of rx errors or not having space in the receive queue, so the
186  // errors are just silently dropped.
187  }
188  } // end of while ( SC1_UARTSTAT & SC1_UARTRXVAL )
189 }
190 
191 
192 //////////////////////////////////////////////////////////////////////////////
193 // Interrupts
194 
195 void halSc1Isr(void)
196 {
197  int32u interrupt;
198 
199  //this read and mask is performed in two steps otherwise the compiler
200  //will complain about undefined order of volatile access
201  interrupt = INT_SC1FLAG;
202  interrupt &= INT_SC1CFG;
203 
204  while (interrupt != 0) {
205 
206  INT_SC1FLAG = interrupt; // acknowledge the interrupts early
207 
208  // RX events
209  if ( interrupt & (INT_SCRXVAL | // RX has data
210  INT_SCRXOVF | // RX Overrun error
211  INT_SC1FRMERR | // RX Frame error
212  INT_SC1PARERR ) // RX Parity error
213  ) {
214  halInternalUart1RxIsr();
215  }
216 
217  // TX events
218  if ( interrupt & (INT_SCTXFREE | // TX has room
219  INT_SCTXIDLE ) // TX idle (more room)
220  ) {
221  halInternalUart1TxIsr();
222  }
223 
224  interrupt = INT_SC1FLAG;
225  interrupt &= INT_SC1CFG;
226  }
227 }
228 
229 /*******************************************************************************
230 * Function Name : __io_getcharNonBlocking
231 * Description : Non blocking read
232 * Input : none
233 * Output : dataByte: buffer containing the read byte if any
234 * Return : TRUE if there is a data, FALSE otherwise
235 *******************************************************************************/
236 boolean __io_getcharNonBlocking(int8u *data)
237 {
238  if (__read(_LLIO_STDIN,data,1))
239  return TRUE;
240  else
241  return FALSE;
242 }/* end serialReadByte() */
243 
244 void __io_putchar( char c )
245 {
246  __write(_LLIO_STDOUT, (unsigned char *)&c, 1);
247 }
248 
249 int __io_getchar()
250 {
251  unsigned char c;
252  __read(_LLIO_STDIN, &c, 1);
253  return (int)(c);
254 }
255 
256 void __io_flush( void )
257 {
258  __write(_LLIO_STDOUT, NULL, 0);
259 }