4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2003, 2004, 2006 Develer S.r.l. (http://www.develer.com/)
30 * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
34 * \brief Buffered serial I/O driver
36 * The serial rx interrupt buffers incoming data in a software FIFO
37 * to decouple the higher level protocols from the line speed.
38 * Outgoing data is buffered as well for better performance.
39 * This driver is not optimized for best performance, but it
40 * has proved to be fast enough to handle transfer rates up to
41 * 38400bps on a 16MHz 80196.
43 * MODULE CONFIGURATION
45 * \li \c CONFIG_SER_HWHANDSHAKE - set to 1 to enable RTS/CTS handshake.
46 * Support is incomplete/untested.
47 * \li \c CONFIG_SER_TXTIMEOUT - Enable software serial transmission timeouts
51 * \author Bernardo Innocenti <bernie@develer.com>
57 #include <mware/formatwr.h>
58 #include <cfg/debug.h>
59 #include <appconfig.h>
62 * Sanity check for config parameters required by this module.
64 #if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1)
65 #error CONFIG_KERNEL must be set to either 0 or 1 in config.h
67 #if !defined(CONFIG_SER_RXTIMEOUT)
68 #error CONFIG_SER_TXTIMEOUT missing in config.h
70 #if !defined(CONFIG_SER_RXTIMEOUT)
71 #error CONFIG_SER_RXTIMEOUT missing in config.h
73 #if !defined(CONFIG_SER_GETS) || ((CONFIG_SER_GETS != 0) && CONFIG_SER_GETS != 1)
74 #error CONFIG_SER_GETS must be set to either 0 or 1 in config.h
76 #if !defined(CONFIG_SER_DEFBAUDRATE)
77 #error CONFIG_SER_DEFBAUDRATE missing in config.h
79 #if !defined(CONFIG_PRINTF)
80 #error CONFIG_PRINTF missing in config.h
84 #include <kern/proc.h>
87 #if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1
88 #include <drv/timer.h>
92 /* Serial configuration parameters */
93 #define SER_CTSDELAY 70 /**< CTS line retry interval (ms) */
94 #define SER_TXPOLLDELAY 2 /**< Transmit buffer full retry interval (ms) */
95 #define SER_RXPOLLDELAY 2 /**< Receive buffer empty retry interval (ms) */
98 struct Serial ser_handles[SER_CNT];
102 * Inserisce il carattere c nel buffer di trasmissione.
103 * Questa funzione mette il processo chiamante in attesa
104 * quando il buffer e' pieno.
106 * \return EOF in caso di errore o timeout, altrimenti
107 * il carattere inviato.
109 int ser_putchar(int c, struct Serial *port)
111 //ASSERT_VALID_FIFO(&port->txfifo);
112 if (fifo_isfull_locked(&port->txfifo))
114 #if CONFIG_SER_TXTIMEOUT != -1
115 ticks_t start_time = timer_clock();
118 /* Attende finche' il buffer e' pieno... */
122 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
123 /* Give up timeslice to other processes. */
126 #if CONFIG_SER_TXTIMEOUT != -1
127 if (timer_clock() - start_time >= port->txtimeout)
129 ATOMIC(port->status |= SERRF_TXTIMEOUT);
132 #endif /* CONFIG_SER_TXTIMEOUT */
134 while (fifo_isfull_locked(&port->txfifo));
137 fifo_push_locked(&port->txfifo, (unsigned char)c);
139 /* (re)trigger tx interrupt */
140 port->hw->table->txStart(port->hw);
142 /* Avoid returning signed extended char */
143 return (int)((unsigned char)c);
148 * Preleva un carattere dal buffer di ricezione.
149 * Questa funzione mette il processo chiamante in attesa
150 * quando il buffer e' vuoto. L'attesa ha un timeout
151 * di ser_rxtimeout millisecondi.
153 * \return EOF in caso di errore o timeout, altrimenti
154 * il carattere ricevuto.
156 int ser_getchar(struct Serial *port)
158 if (fifo_isempty_locked(&port->rxfifo))
160 #if CONFIG_SER_RXTIMEOUT != -1
161 ticks_t start_time = timer_clock();
163 /* Wait while buffer is empty */
167 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
168 /* Give up timeslice to other processes. */
171 #if CONFIG_SER_RXTIMEOUT != -1
172 if (timer_clock() - start_time >= port->rxtimeout)
174 ATOMIC(port->status |= SERRF_RXTIMEOUT);
177 #endif /* CONFIG_SER_RXTIMEOUT */
179 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
183 * Get a byte from the FIFO (avoiding sign-extension),
184 * re-enable RTS, then return result.
186 if (ser_getstatus(port) & SERRF_RX)
188 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
193 * Preleva un carattere dal buffer di ricezione.
194 * Se il buffer e' vuoto, ser_getchar_nowait() ritorna
195 * immediatamente EOF.
197 int ser_getchar_nowait(struct Serial *port)
199 if (fifo_isempty_locked(&port->rxfifo))
202 /* NOTE: the double cast prevents unwanted sign extension */
203 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
209 * Read a line long at most as size and put it
211 * \return number of chars read or EOF in case
214 int ser_gets(struct Serial *port, char *buf, int size)
216 return ser_gets_echo(port, buf, size, false);
221 * Read a line long at most as size and put it
222 * in buf, with optional echo.
224 * \return number of chars read, or EOF in case
227 int ser_gets_echo(struct Serial *port, char *buf, int size, bool echo)
234 if ((c = ser_getchar(port)) == EOF)
241 if (c == '\r' || c == '\n' || i >= size-1)
245 ser_print(port, "\r\n");
250 ser_putchar(c, port);
255 #endif /* !CONFIG_SER_GETS */
259 * Read at most \a size bytes from \a port and put them in \a buf
261 * \return number of bytes actually read, or EOF in
264 int ser_read(struct Serial *port, void *buf, size_t size)
267 char *_buf = (char *)buf;
272 if ((c = ser_getchar(port)) == EOF)
282 * Write a string to serial.
283 * \return 0 if OK, EOF in case of error.
285 int ser_print(struct Serial *port, const char *s)
289 if (ser_putchar(*s++, port) == EOF)
297 * \brief Write a buffer to serial.
299 * \return 0 if OK, EOF in case of error.
301 * \todo Optimize with fifo_pushblock()
303 int ser_write(struct Serial *port, const void *_buf, size_t len)
305 const char *buf = (const char *)_buf;
309 if (ser_putchar(*buf++, port) == EOF)
320 int ser_printf(struct Serial *port, const char *format, ...)
325 va_start(ap, format);
326 len = _formatted_write(format, (void (*)(char, void *))ser_putchar, port, ap);
331 #endif /* CONFIG_PRINTF */
334 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
335 void ser_settimeouts(struct Serial *port, mtime_t rxtimeout, mtime_t txtimeout)
337 port->rxtimeout = ms_to_ticks(rxtimeout);
338 port->txtimeout = ms_to_ticks(txtimeout);
340 #endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */
342 #if CONFIG_SER_RXTIMEOUT != -1
344 * Discard input to resynchronize with remote end.
346 * Discard incoming data until the port stops receiving
347 * characters for at least \a delay milliseconds.
349 * \note Serial errors are reset before and after executing the purge.
351 void ser_resync(struct Serial *port, mtime_t delay)
353 mtime_t old_rxtimeout = ticks_to_ms(port->rxtimeout);
355 ser_settimeouts(port, delay, ticks_to_ms(port->txtimeout));
358 ser_setstatus(port, 0);
361 while (!(ser_getstatus(port) & SERRF_RXTIMEOUT));
363 /* Restore port to an usable status */
364 ser_setstatus(port, 0);
365 ser_settimeouts(port, old_rxtimeout, ticks_to_ms(port->txtimeout));
367 #endif /* CONFIG_SER_RXTIMEOUT */
370 void ser_setbaudrate(struct Serial *port, unsigned long rate)
372 port->hw->table->setBaudrate(port->hw, rate);
376 void ser_setparity(struct Serial *port, int parity)
378 port->hw->table->setParity(port->hw, parity);
383 * Flush both the RX and TX buffers.
385 void ser_purge(struct Serial *port)
387 fifo_flush_locked(&port->rxfifo);
388 fifo_flush_locked(&port->txfifo);
393 * Wait until all pending output is completely
394 * transmitted to the other end.
396 * \note The current implementation only checks the
397 * software transmission queue. Any hardware
400 void ser_drain(struct Serial *ser)
403 * Wait until the FIFO becomes empty, and then until the byte currently in
404 * the hardware register gets shifted out.
406 while (!fifo_isempty(&ser->txfifo)
407 || ser->hw->table->txSending(ser->hw))
409 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
410 /* Give up timeslice to other processes. */
419 * Initialize a serial port.
421 * \param unit Serial unit to open. Possible values are architecture dependant.
423 struct Serial *ser_open(unsigned int unit)
427 ASSERT(unit < countof(ser_handles));
428 port = &ser_handles[unit];
430 ASSERT(!port->is_open);
431 DB(port->is_open = true;)
435 port->hw = ser_hw_getdesc(unit);
437 /* Initialize circular buffers */
438 ASSERT(port->hw->txbuffer);
439 ASSERT(port->hw->rxbuffer);
440 fifo_init(&port->txfifo, port->hw->txbuffer, port->hw->txbuffer_size);
441 fifo_init(&port->rxfifo, port->hw->rxbuffer, port->hw->rxbuffer_size);
443 port->hw->table->init(port->hw, port);
445 /* Set default values */
446 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
447 ser_settimeouts(port, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
449 #if CONFIG_SER_DEFBAUDRATE
450 ser_setbaudrate(port, CONFIG_SER_DEFBAUDRATE);
453 /* Clear error flags */
454 ser_setstatus(port, 0);
461 * Clean up serial port, disabling the associated hardware.
463 void ser_close(struct Serial *port)
465 ASSERT(port->is_open);
466 DB(port->is_open = false;)
468 // Wait until we finish sending everything
471 port->hw->table->cleanup(port->hw);
475 * We purge the FIFO buffer only after the low-level cleanup, so that
476 * we are sure that there are no more interrupts.