avrSerial  1.0
Multi-UART Library for many AVR devices
 All Files Functions Groups
serial.c
Go to the documentation of this file.
1 /*
2  * serial.c
3  *
4  * Copyright (c) 2012, Thomas Buck <xythobuz@me.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * - Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * - Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <avr/io.h>
31 #include <avr/interrupt.h>
32 #include <stdint.h>
33 
34 #include "serial.h"
35 #include "serial_device.h"
36 
51 // #define SERIALINJECTCR
52 
53 #ifndef RX_BUFFER_SIZE
54 #define RX_BUFFER_SIZE 32
55 #endif
56 
57 #ifndef TX_BUFFER_SIZE
58 #define TX_BUFFER_SIZE 16
59 #endif
60 
62 #define FLOWCONTROL
63 
64 #define FLOWMARK 5
65 #define XON 0x11
66 #define XOFF 0x13
68 #if (RX_BUFFER_SIZE < 2) || (TX_BUFFER_SIZE < 2)
69 #error SERIAL BUFFER TOO SMALL!
70 #endif
71 
72 #ifdef FLOWCONTROL
73 #if (RX_BUFFER_SIZE < 8) || (TX_BUFFER_SIZE < 8)
74 #error SERIAL BUFFER TOO SMALL!
75 #endif
76 #endif
77 
78 #if ((RX_BUFFER_SIZE + TX_BUFFER_SIZE) * UART_COUNT) >= (RAMEND - 0x60)
79 #error SERIAL BUFFER TOO LARGE!
80 #endif
81 
82 // serialRegisters
83 #define SERIALDATA 0
84 #define SERIALB 1
85 #define SERIALC 2
86 #define SERIALA 3
87 #define SERIALUBRRH 4
88 #define SERIALUBRRL 5
89 
90 // serialBits
91 #define SERIALUCSZ0 0
92 #define SERIALUCSZ1 1
93 #define SERIALRXCIE 2
94 #define SERIALRXEN 3
95 #define SERIALTXEN 4
96 #define SERIALUDRIE 5
97 #define SERIALUDRE 6
98 
99 uint8_t volatile rxBuffer[UART_COUNT][RX_BUFFER_SIZE];
100 uint8_t volatile txBuffer[UART_COUNT][TX_BUFFER_SIZE];
101 uint16_t volatile rxRead[UART_COUNT];
102 uint16_t volatile rxWrite[UART_COUNT];
103 uint16_t volatile txRead[UART_COUNT];
104 uint16_t volatile txWrite[UART_COUNT];
105 uint8_t volatile shouldStartTransmission[UART_COUNT];
106 
107 #ifdef FLOWCONTROL
108 uint8_t volatile sendThisNext[UART_COUNT];
109 uint8_t volatile flow[UART_COUNT];
110 uint8_t volatile rxBufferElements[UART_COUNT];
111 #endif
112 
113 uint8_t serialAvailable(void) {
114  return UART_COUNT;
115 }
116 
117 void serialInit(uint8_t uart, uint16_t baud) {
118  if (uart >= UART_COUNT)
119  return;
120 
121  // Initialize state variables
122  rxRead[uart] = 0;
123  rxWrite[uart] = 0;
124  txRead[uart] = 0;
125  txWrite[uart] = 0;
126  shouldStartTransmission[uart] = 1;
127 #ifdef FLOWCONTROL
128  sendThisNext[uart] = 0;
129  flow[uart] = 1;
130  rxBufferElements[uart] = 0;
131 #endif
132 
133  // Default Configuration: 8N1
134  *serialRegisters[uart][SERIALC] = (1 << serialBits[uart][SERIALUCSZ0]) | (1 << serialBits[uart][SERIALUCSZ1]);
135 
136  // Set baudrate
137 #if SERIALBAUDBIT == 8
138  *serialRegisters[uart][SERIALUBRRH] = (baud >> 8);
139  *serialRegisters[uart][SERIALUBRRL] = baud;
140 #else
141  *serialBaudRegisters[uart] = baud;
142 #endif
143 
144  *serialRegisters[uart][SERIALB] = (1 << serialBits[uart][SERIALRXCIE]); // Enable Interrupts
145  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALRXEN]) | (1 << serialBits[uart][SERIALTXEN]); // Enable Receiver/Transmitter
146 }
147 
148 void serialClose(uint8_t uart) {
149  if (uart >= UART_COUNT)
150  return;
151 
152  uint8_t sreg = SREG;
153  sei();
154  while (!serialTxBufferEmpty(uart));
155  while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE])); // Wait while Transmit Interrupt is on
156  cli();
157  *serialRegisters[uart][SERIALB] = 0;
158  *serialRegisters[uart][SERIALC] = 0;
159  SREG = sreg;
160 }
161 
162 #ifdef FLOWCONTROL
163 void setFlow(uint8_t uart, uint8_t on) {
164  if (uart >= UART_COUNT)
165  return;
166 
167  if (flow[uart] != on) {
168  if (on == 1) {
169  // Send XON
170  while (sendThisNext[uart] != 0);
171  sendThisNext[uart] = XON;
172  flow[uart] = 1;
173  if (shouldStartTransmission[uart]) {
174  shouldStartTransmission[uart] = 0;
175  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
176  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
177  }
178  } else {
179  // Send XOFF
180  sendThisNext[uart] = XOFF;
181  flow[uart] = 0;
182  if (shouldStartTransmission[uart]) {
183  shouldStartTransmission[uart] = 0;
184  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
185  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
186  }
187  }
188  // Wait till it's transmitted
189  while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE]));
190  }
191 }
192 #endif
193 
194 // ---------------------
195 // | Reception |
196 // ---------------------
197 
198 uint8_t serialHasChar(uint8_t uart) {
199  if (uart >= UART_COUNT)
200  return 0;
201 
202  if (rxRead[uart] != rxWrite[uart]) { // True if char available
203  return 1;
204  } else {
205  return 0;
206  }
207 }
208 
209 uint8_t serialGetBlocking(uint8_t uart) {
210  if (uart >= UART_COUNT)
211  return 0;
212 
213  while(!serialHasChar(uart));
214  return serialGet(uart);
215 }
216 
217 uint8_t serialGet(uint8_t uart) {
218  if (uart >= UART_COUNT)
219  return 0;
220 
221  uint8_t c;
222 
223 #ifdef FLOWCONTROL
224  rxBufferElements[uart]--;
225  if ((flow[uart] == 0) && (rxBufferElements[uart] <= FLOWMARK)) {
226  while (sendThisNext[uart] != 0);
227  sendThisNext[uart] = XON;
228  flow[uart] = 1;
229  if (shouldStartTransmission[uart]) {
230  shouldStartTransmission[uart] = 0;
231  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
232  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
233  }
234  }
235 #endif
236 
237  if (rxRead[uart] != rxWrite[uart]) {
238  c = rxBuffer[uart][rxRead[uart]];
239  rxBuffer[uart][rxRead[uart]] = 0;
240  if (rxRead[uart] < (RX_BUFFER_SIZE - 1)) {
241  rxRead[uart]++;
242  } else {
243  rxRead[uart] = 0;
244  }
245  return c;
246  } else {
247  return 0;
248  }
249 }
250 
251 uint8_t serialRxBufferFull(uint8_t uart) {
252  if (uart >= UART_COUNT)
253  return 0;
254 
255  return (((rxWrite[uart] + 1) == rxRead[uart]) || ((rxRead[uart] == 0) && ((rxWrite[uart] + 1) == RX_BUFFER_SIZE)));
256 }
257 
258 uint8_t serialRxBufferEmpty(uint8_t uart) {
259  if (uart >= UART_COUNT)
260  return 0;
261 
262  if (rxRead[uart] != rxWrite[uart]) {
263  return 0;
264  } else {
265  return 1;
266  }
267 }
268 
269 // ----------------------
270 // | Transmission |
271 // ----------------------
272 
273 void serialWrite(uint8_t uart, uint8_t data) {
274  if (uart >= UART_COUNT)
275  return;
276 
277 #ifdef SERIALINJECTCR
278  if (data == '\n') {
279  serialWrite(uart, '\r');
280  }
281 #endif
282  while (serialTxBufferFull(uart));
283 
284  txBuffer[uart][txWrite[uart]] = data;
285  if (txWrite[uart] < (TX_BUFFER_SIZE - 1)) {
286  txWrite[uart]++;
287  } else {
288  txWrite[uart] = 0;
289  }
290  if (shouldStartTransmission[uart]) {
291  shouldStartTransmission[uart] = 0;
292  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
293  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
294  }
295 }
296 
297 void serialWriteString(uint8_t uart, const char *data) {
298  if (uart >= UART_COUNT)
299  return;
300 
301  if (data == 0) {
302  serialWriteString(uart, "NULL");
303  } else {
304  while (*data != '\0') {
305  serialWrite(uart, *data++);
306  }
307  }
308 }
309 
310 uint8_t serialTxBufferFull(uint8_t uart) {
311  if (uart >= UART_COUNT)
312  return 0;
313 
314  return (((txWrite[uart] + 1) == txRead[uart]) || ((txRead[uart] == 0) && ((txWrite[uart] + 1) == TX_BUFFER_SIZE)));
315 }
316 
317 uint8_t serialTxBufferEmpty(uint8_t uart) {
318  if (uart >= UART_COUNT)
319  return 0;
320 
321  if (txRead[uart] != txWrite[uart]) {
322  return 0;
323  } else {
324  return 1;
325  }
326 }
327 
328 void serialReceiveInterrupt(uint8_t uart) {
329  rxBuffer[uart][rxWrite[uart]] = *serialRegisters[uart][SERIALDATA];
330  if (rxWrite[uart] < (RX_BUFFER_SIZE - 1)) {
331  rxWrite[uart]++;
332  } else {
333  rxWrite[uart] = 0;
334  }
335 
336 #ifdef FLOWCONTROL
337  rxBufferElements[uart]++;
338  if ((flow[uart] == 1) && (rxBufferElements[uart] >= (RX_BUFFER_SIZE - FLOWMARK))) {
339  sendThisNext[uart] = XOFF;
340  flow[uart] = 0;
341  if (shouldStartTransmission[uart]) {
342  shouldStartTransmission[uart] = 0;
343  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
344  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
345  }
346  }
347 #endif
348 }
349 
350 void serialTransmitInterrupt(uint8_t uart) {
351 #ifdef FLOWCONTROL
352  if (sendThisNext[uart]) {
353  *serialRegisters[uart][SERIALDATA] = sendThisNext[uart];
354  sendThisNext[uart] = 0;
355  } else {
356 #endif
357  if (txRead[uart] != txWrite[uart]) {
358  *serialRegisters[uart][SERIALDATA] = txBuffer[uart][txRead[uart]];
359  if (txRead[uart] < (TX_BUFFER_SIZE -1)) {
360  txRead[uart]++;
361  } else {
362  txRead[uart] = 0;
363  }
364  } else {
365  shouldStartTransmission[uart] = 1;
366  *serialRegisters[uart][SERIALB] &= ~(1 << serialBits[uart][SERIALUDRIE]); // Disable Interrupt
367  }
368 #ifdef FLOWCONTROL
369  }
370 #endif
371 }
372 
373 ISR(SERIALRECIEVEINTERRUPT) { // Receive complete
374  serialReceiveInterrupt(0);
375 }
376 
377 ISR(SERIALTRANSMITINTERRUPT) { // Data register empty
378  serialTransmitInterrupt(0);
379 }
380 
381 #if UART_COUNT > 1
382 ISR(SERIALRECIEVEINTERRUPT1) { // Receive complete
383  serialReceiveInterrupt(1);
384 }
385 
386 ISR(SERIALTRANSMITINTERRUPT1) { // Data register empty
387  serialTransmitInterrupt(1);
388 }
389 #endif
390 
391 #if UART_COUNT > 2
392 ISR(SERIALRECIEVEINTERRUPT2) { // Receive complete
393  serialReceiveInterrupt(2);
394 }
395 
396 ISR(SERIALTRANSMITINTERRUPT2) { // Data register empty
397  serialTransmitInterrupt(2);
398 }
399 #endif
400 
401 #if UART_COUNT > 3
402 ISR(SERIALRECIEVEINTERRUPT3) { // Receive complete
403  serialReceiveInterrupt(3);
404 }
405 
406 ISR(SERIALTRANSMITINTERRUPT3) { // Data register empty
407  serialTransmitInterrupt(3);
408 }
409 #endif
410