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