Use appconfig.h instead of cfg/config.h.
[bertos.git] / drv / ser.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
6  * This file is part of DevLib - See README.devlib for information.
7  * -->
8  *
9  * \brief Buffered serial I/O driver
10  *
11  * The serial rx interrupt buffers incoming data in a software FIFO
12  * to decouple the higher level protocols from the line speed.
13  * Outgoing data is buffered as well for better performance.
14  * This driver is not optimized for best performance, but it
15  * has proved to be fast enough to handle transfer rates up to
16  * 38400bps on a 16MHz 80196.
17  *
18  * MODULE CONFIGURATION
19  *
20  *  \li \c CONFIG_SER_HWHANDSHAKE - set to 1 to enable RTS/CTS handshake.
21  *         Support is incomplete/untested.
22  *  \li \c CONFIG_SER_TXTIMEOUT - Enable software serial transmission timeouts
23  *
24  *
25  * \version $Id$
26  * \author Bernardo Innocenti <bernie@develer.com>
27  */
28
29 /*#*
30  *#* $Log$
31  *#* Revision 1.27  2005/11/27 23:33:40  bernie
32  *#* Use appconfig.h instead of cfg/config.h.
33  *#*
34  *#* Revision 1.26  2005/11/04 16:20:02  bernie
35  *#* Fix reference to README.devlib in header.
36  *#*
37  *#* Revision 1.25  2005/04/11 19:10:27  bernie
38  *#* Include top-level headers from cfg/ subdir.
39  *#*
40  *#* Revision 1.24  2005/01/21 20:13:15  aleph
41  *#* Fix drain at ser_close()
42  *#*
43  *#* Revision 1.23  2005/01/14 00:47:07  aleph
44  *#* ser_drain(): Wait for hw transmission complete.
45  *#*
46  *#* Revision 1.22  2004/12/08 08:56:14  bernie
47  *#* Rename time_t to mtime_t.
48  *#*
49  *#* Revision 1.21  2004/11/16 18:10:13  bernie
50  *#* Add sanity checks for missing configuration parameters.
51  *#*
52  *#* Revision 1.20  2004/10/19 11:48:00  bernie
53  *#* Remove unused variable.
54  *#*
55  *#* Revision 1.19  2004/10/19 08:14:13  bernie
56  *#* Fix a few longstanding bugs wrt status handling (made by rasky on scfirm).
57  *#*
58  *#* Revision 1.18  2004/09/20 03:31:15  bernie
59  *#* Sanitize for C++.
60  *#*
61  *#* Revision 1.17  2004/09/14 21:06:07  bernie
62  *#* Use debug.h instead of kdebug.h; Spelling fixes.
63  *#*
64  *#* Revision 1.16  2004/09/06 21:40:50  bernie
65  *#* Move buffer handling in chip-specific driver.
66  *#*
67  *#* Revision 1.15  2004/08/25 14:12:08  rasky
68  *#* Aggiornato il comment block dei log RCS
69  *#*
70  *#* Revision 1.14  2004/08/24 16:22:57  bernie
71  *#* Thinkos; Doxygen fixes
72  *#*
73  *#* Revision 1.13  2004/08/24 16:20:48  bernie
74  *#* ser_read(): Make buffer argument void *#* for consistency with ANSI C and ser_write()
75  *#*
76  *#* Revision 1.12  2004/08/24 13:49:39  bernie
77  *#* Fix thinko.
78  *#*
79  *#* Revision 1.11  2004/08/15 05:32:22  bernie
80  *#* ser_resync(): New function.
81  *#*
82  *#* Revision 1.10  2004/08/10 06:29:50  bernie
83  *#* Rename timer_gettick() to timer_ticks().
84  *#*
85  *#* Revision 1.9  2004/08/08 06:06:20  bernie
86  *#* Use new-style CONFIG_ idiom; Fix module-wide documentation.
87  *#*
88  *#* Revision 1.8  2004/07/29 22:57:09  bernie
89  *#* ser_drain(): New function; Make Serial::is_open a debug-only feature; Switch to new-style CONFIG_* macros.
90  *#*
91  *#* Revision 1.7  2004/07/18 21:49:03  bernie
92  *#* Make CONFIG_SER_DEFBAUDRATE optional.
93  *#*
94  *#* Revision 1.6  2004/06/07 15:56:28  aleph
95  *#* Remove cast-as-lvalue extension abuse
96  *#*
97  *#* Revision 1.5  2004/06/06 16:41:44  bernie
98  *#* ser_putchar(): Use fifo_push_locked() to fix potential race on 8bit processors.
99  *#*
100  *#* Revision 1.4  2004/06/03 11:27:09  bernie
101  *#* Add dual-license information.
102  *#*
103  *#* Revision 1.3  2004/06/02 21:35:24  aleph
104  *#* Serial enhancements: interruptible receive handler and 8 bit serial status for AVR; remove volatile attribute to FIFOBuffer, useless for new fifobuf routens
105  *#*
106  *#* Revision 1.2  2004/05/23 18:21:53  bernie
107  *#* Trim CVS logs and cleanup header info.
108  *#*
109  *#*/
110
111 #include "ser.h"
112 #include "ser_p.h"
113 #include <mware/formatwr.h>
114 #include <cfg/debug.h>
115 #include <hw.h>
116 #include <appconfig.h>
117
118 /*
119  * Sanity check for config parameters required by this module.
120  */
121 #if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1)
122         #error CONFIG_KERNEL must be set to either 0 or 1 in config.h
123 #endif
124 #if !defined(CONFIG_SER_RXTIMEOUT)
125         #error CONFIG_SER_TXTIMEOUT missing in config.h
126 #endif
127 #if !defined(CONFIG_SER_RXTIMEOUT)
128         #error CONFIG_SER_RXTIMEOUT missing in config.h
129 #endif
130 #if !defined(CONFIG_SER_GETS) || ((CONFIG_SER_GETS != 0) && CONFIG_SER_GETS != 1)
131         #error CONFIG_SER_GETS must be set to either 0 or 1 in config.h
132 #endif
133 #if !defined(CONFIG_SER_DEFBAUDRATE)
134         #error CONFIG_SER_DEFBAUDRATE missing in config.h
135 #endif
136 #if !defined(CONFIG_PRINTF)
137         #error CONFIG_PRINTF missing in config.h
138 #endif
139
140 #if CONFIG_KERNEL
141         #include <kern/proc.h>
142 #endif
143
144 #if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1
145         #include <drv/timer.h>
146 #endif
147
148
149 /* Serial configuration parameters */
150 #define SER_CTSDELAY        70  /*!< CTS line retry interval (ms) */
151 #define SER_TXPOLLDELAY      2  /*!< Transmit buffer full retry interval (ms) */
152 #define SER_RXPOLLDELAY      2  /*!< Receive buffer empty retry interval (ms) */
153
154
155 struct Serial ser_handles[SER_CNT];
156
157
158 /*!
159  * Inserisce il carattere c nel buffer di trasmissione.
160  * Questa funzione mette il processo chiamante in attesa
161  * quando il buffer e' pieno.
162  *
163  * \return EOF in caso di errore o timeout, altrimenti
164  *         il carattere inviato.
165  */
166 int ser_putchar(int c, struct Serial *port)
167 {
168         //ASSERT_VALID_FIFO(&port->txfifo);
169         if (fifo_isfull_locked(&port->txfifo))
170         {
171 #if CONFIG_SER_TXTIMEOUT != -1
172                 mtime_t start_time = timer_ticks();
173 #endif
174
175                 /* Attende finche' il buffer e' pieno... */
176                 do
177                 {
178 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
179                         /* Give up timeslice to other processes. */
180                         proc_switch();
181 #endif
182 #if CONFIG_SER_TXTIMEOUT != -1
183                         if (timer_ticks() - start_time >= port->txtimeout)
184                         {
185                                 port->status |= SERRF_TXTIMEOUT;
186                                 return EOF;
187                         }
188 #endif /* CONFIG_SER_TXTIMEOUT */
189                 }
190                 while (fifo_isfull_locked(&port->txfifo));
191         }
192
193         fifo_push_locked(&port->txfifo, (unsigned char)c);
194
195         /* (re)trigger tx interrupt */
196         port->hw->table->txStart(port->hw);
197
198         /* Avoid returning signed extended char */
199         return (int)((unsigned char)c);
200 }
201
202
203 /*!
204  * Preleva un carattere dal buffer di ricezione.
205  * Questa funzione mette il processo chiamante in attesa
206  * quando il buffer e' vuoto. L'attesa ha un timeout
207  * di ser_rxtimeout millisecondi.
208  *
209  * \return EOF in caso di errore o timeout, altrimenti
210  *         il carattere ricevuto.
211  */
212 int ser_getchar(struct Serial *port)
213 {
214         if (fifo_isempty_locked(&port->rxfifo))
215         {
216 #if CONFIG_SER_RXTIMEOUT != -1
217                 mtime_t start_time = timer_ticks();
218 #endif
219                 /* Wait while buffer is empty */
220                 do
221                 {
222 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
223                         /* Give up timeslice to other processes. */
224                         proc_switch();
225 #endif
226 #if CONFIG_SER_RXTIMEOUT != -1
227                         if (timer_ticks() - start_time >= port->rxtimeout)
228                         {
229                                 port->status |= SERRF_RXTIMEOUT;
230                                 return EOF;
231                         }
232 #endif /* CONFIG_SER_RXTIMEOUT */
233                 }
234                 while (fifo_isempty_locked(&port->rxfifo) && (port->status & SERRF_RX) == 0);
235         }
236
237         /*
238          * Get a byte from the FIFO (avoiding sign-extension),
239          * re-enable RTS, then return result.
240          */
241         if (port->status & SERRF_RX)
242                 return EOF;
243         return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
244 }
245
246
247 /*!
248  * Preleva un carattere dal buffer di ricezione.
249  * Se il buffer e' vuoto, ser_getchar_nowait() ritorna
250  * immediatamente EOF.
251  */
252 int ser_getchar_nowait(struct Serial *port)
253 {
254         if (fifo_isempty_locked(&port->rxfifo))
255                 return EOF;
256
257         /* NOTE: the double cast prevents unwanted sign extension */
258         return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
259 }
260
261
262 #if CONFIG_SER_GETS
263 /*!
264  * Read a line long at most as size and put it
265  * in buf.
266  * \return number of chars read or EOF in case
267  *         of error.
268  */
269 int ser_gets(struct Serial *port, char *buf, int size)
270 {
271         return ser_gets_echo(port, buf, size, false);
272 }
273
274
275 /*!
276  * Read a line long at most as size and put it
277  * in buf, with optional echo.
278  *
279  * \return number of chars read, or EOF in case
280  *         of error.
281  */
282 int ser_gets_echo(struct Serial *port, char *buf, int size, bool echo)
283 {
284         int i = 0;
285         int c;
286
287         for (;;)
288         {
289                 if ((c = ser_getchar(port)) == EOF)
290                 {
291                         buf[i] = '\0';
292                         return -1;
293                 }
294
295                 /* FIXME */
296                 if (c == '\r' || c == '\n' || i >= size-1)
297                 {
298                         buf[i] = '\0';
299                         if (echo)
300                                 ser_print(port, "\r\n");
301                         break;
302                 }
303                 buf[i++] = c;
304                 if (echo)
305                         ser_putchar(c, port);
306         }
307
308         return i;
309 }
310 #endif /* !CONFIG_SER_GETS */
311
312
313 /*!
314  * Read at most \a size bytes from \a port and put them in \a buf
315  *
316  * \return number of bytes actually read, or EOF in
317  *         case of error.
318  */
319 int ser_read(struct Serial *port, void *buf, size_t size)
320 {
321         size_t i = 0;
322         char *_buf = (char *)buf;
323         int c;
324
325         while (i < size)
326         {
327                 if ((c = ser_getchar(port)) == EOF)
328                         return EOF;
329                 _buf[i++] = c;
330         }
331
332         return i;
333 }
334
335
336 /*!
337  * Write a string to serial.
338  * \return 0 if OK, EOF in case of error.
339  */
340 int ser_print(struct Serial *port, const char *s)
341 {
342         while (*s)
343         {
344                 if (ser_putchar(*s++, port) == EOF)
345                         return EOF;
346         }
347         return 0;
348 }
349
350
351 /*!
352  * \brief Write a buffer to serial.
353  *
354  * \return 0 if OK, EOF in case of error.
355  *
356  * \todo Optimize with fifo_pushblock()
357  */
358 int ser_write(struct Serial *port, const void *_buf, size_t len)
359 {
360         const char *buf = (const char *)_buf;
361
362         while (len--)
363         {
364                 if (ser_putchar(*buf++, port) == EOF)
365                         return EOF;
366         }
367         return 0;
368 }
369
370
371 #if CONFIG_PRINTF
372 /*!
373  * Formatted write
374  */
375 int ser_printf(struct Serial *port, const char *format, ...)
376 {
377         va_list ap;
378         int len;
379
380         va_start(ap, format);
381         len = _formatted_write(format, (void (*)(char, void *))ser_putchar, port, ap);
382         va_end(ap);
383
384         return len;
385 }
386 #endif /* CONFIG_PRINTF */
387
388
389 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
390 void ser_settimeouts(struct Serial *port, mtime_t rxtimeout, mtime_t txtimeout)
391 {
392         port->rxtimeout = rxtimeout;
393         port->txtimeout = txtimeout;
394 }
395 #endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */
396
397 #if CONFIG_SER_RXTIMEOUT != -1
398 /*!
399  * Discard input to resynchronize with remote end.
400  *
401  * Discard incoming data until the port stops receiving
402  * characters for at least \a delay milliseconds.
403  *
404  * \note Serial errors are reset before and after executing the purge.
405  */
406 void ser_resync(struct Serial *port, mtime_t delay)
407 {
408         mtime_t old_rxtimeout = port->rxtimeout;
409
410         ser_settimeouts(port, delay, port->txtimeout);
411         do
412         {
413                 ser_setstatus(port, 0);
414                 ser_getchar(port);
415         }
416         while (!(ser_getstatus(port) & SERRF_RXTIMEOUT));
417
418         /* Restore port to an usable status */
419         ser_setstatus(port, 0);
420         ser_settimeouts(port, old_rxtimeout, port->txtimeout);
421 }
422 #endif /* CONFIG_SER_RXTIMEOUT */
423
424
425 void ser_setbaudrate(struct Serial *port, unsigned long rate)
426 {
427         port->hw->table->setBaudrate(port->hw, rate);
428 }
429
430
431 void ser_setparity(struct Serial *port, int parity)
432 {
433         port->hw->table->setParity(port->hw, parity);
434 }
435
436
437 /*!
438  * Flush both the RX and TX buffers.
439  */
440 void ser_purge(struct Serial *port)
441 {
442         fifo_flush_locked(&port->rxfifo);
443         fifo_flush_locked(&port->txfifo);
444 }
445
446
447 /*!
448  * Wait until all pending output is completely
449  * transmitted to the other end.
450  *
451  * \note The current implementation only checks the
452  *       software transmission queue. Any hardware
453  *       FIFOs are ignored.
454  */
455 void ser_drain(struct Serial *ser)
456 {
457         /*
458          * Wait until the FIFO is empty, and then until the byte currently in
459          * the hardware register gets shifted out.
460          */
461         while (!fifo_isempty(&ser->txfifo)
462                || ser->hw->table->txSending(ser->hw))
463         {
464                 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
465                         /* Give up timeslice to other processes. */
466                         proc_switch();
467                 #endif
468         }
469 }
470
471
472 /*!
473  * Initialize serial
474  */
475 struct Serial *ser_open(unsigned int unit)
476 {
477         struct Serial *port;
478
479         ASSERT(unit < countof(ser_handles));
480         port = &ser_handles[unit];
481
482         ASSERT(!port->is_open);
483         DB(port->is_open = true;)
484
485         port->unit = unit;
486
487         port->hw = ser_hw_getdesc(unit);
488
489         /* Initialize circular buffers */
490         ASSERT(port->hw->txbuffer);
491         ASSERT(port->hw->rxbuffer);
492         fifo_init(&port->txfifo, port->hw->txbuffer, port->hw->txbuffer_size);
493         fifo_init(&port->rxfifo, port->hw->rxbuffer, port->hw->rxbuffer_size);
494
495         port->hw->table->init(port->hw, port);
496
497         /* Set default values */
498 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
499         ser_settimeouts(port, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
500 #endif
501 #if CONFIG_SER_DEFBAUDRATE
502         ser_setbaudrate(port, CONFIG_SER_DEFBAUDRATE);
503 #endif
504
505         /* Clear error flags */
506         ser_setstatus(port, 0);
507
508         return port;
509 }
510
511
512 /*!
513  * Clean up serial port, disabling the associated hardware.
514  */
515 void ser_close(struct Serial *port)
516 {
517         ASSERT(port->is_open);
518         DB(port->is_open = false;)
519
520         // Wait until we finish sending everything
521         ser_drain(port);
522
523         port->hw->table->cleanup(port->hw);
524         DB(port->hw = NULL;)
525
526         /*
527          * We purge the FIFO buffer only after the low-level cleanup, so that
528          * we are sure that there are no more interrupts.
529          */
530         ser_purge(port);
531 }