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>
61 #include <string.h> /* memset */
64 * Sanity check for config parameters required by this module.
66 #if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1)
67 #error CONFIG_KERNEL must be set to either 0 or 1 in config.h
69 #if !defined(CONFIG_SER_RXTIMEOUT)
70 #error CONFIG_SER_TXTIMEOUT missing in config.h
72 #if !defined(CONFIG_SER_RXTIMEOUT)
73 #error CONFIG_SER_RXTIMEOUT missing in config.h
75 #if !defined(CONFIG_SER_DEFBAUDRATE)
76 #error CONFIG_SER_DEFBAUDRATE missing in config.h
80 #include <kern/proc.h>
83 #if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1
84 #include <drv/timer.h>
88 /* Serial configuration parameters */
89 #define SER_CTSDELAY 70 /**< CTS line retry interval (ms) */
90 #define SER_TXPOLLDELAY 2 /**< Transmit buffer full retry interval (ms) */
91 #define SER_RXPOLLDELAY 2 /**< Receive buffer empty retry interval (ms) */
94 struct Serial ser_handles[SER_CNT];
98 * Inserisce il carattere c nel buffer di trasmissione.
99 * Questa funzione mette il processo chiamante in attesa
100 * quando il buffer e' pieno.
102 * \return EOF in caso di errore o timeout, altrimenti
103 * il carattere inviato.
105 static int ser_putchar(int c, struct Serial *port)
107 //ASSERT_VALID_FIFO(&port->txfifo);
108 if (fifo_isfull_locked(&port->txfifo))
110 #if CONFIG_SER_TXTIMEOUT != -1
111 ticks_t start_time = timer_clock();
114 /* Attende finche' il buffer e' pieno... */
118 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
119 /* Give up timeslice to other processes. */
122 #if CONFIG_SER_TXTIMEOUT != -1
123 if (timer_clock() - start_time >= port->txtimeout)
125 ATOMIC(port->status |= SERRF_TXTIMEOUT);
128 #endif /* CONFIG_SER_TXTIMEOUT */
130 while (fifo_isfull_locked(&port->txfifo));
133 fifo_push_locked(&port->txfifo, (unsigned char)c);
135 /* (re)trigger tx interrupt */
136 port->hw->table->txStart(port->hw);
138 /* Avoid returning signed extended char */
139 return (int)((unsigned char)c);
144 * Preleva un carattere dal buffer di ricezione.
145 * Questa funzione mette il processo chiamante in attesa
146 * quando il buffer e' vuoto. L'attesa ha un timeout
147 * di ser_rxtimeout millisecondi.
149 * \return EOF in caso di errore o timeout, altrimenti
150 * il carattere ricevuto.
152 static int ser_getchar(struct Serial *port)
154 if (fifo_isempty_locked(&port->rxfifo))
156 #if CONFIG_SER_RXTIMEOUT != -1
157 ticks_t start_time = timer_clock();
159 /* Wait while buffer is empty */
163 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
164 /* Give up timeslice to other processes. */
167 #if CONFIG_SER_RXTIMEOUT != -1
168 if (timer_clock() - start_time >= port->rxtimeout)
170 ATOMIC(port->status |= SERRF_RXTIMEOUT);
173 #endif /* CONFIG_SER_RXTIMEOUT */
175 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
179 * Get a byte from the FIFO (avoiding sign-extension),
180 * re-enable RTS, then return result.
182 if (ser_getstatus(port) & SERRF_RX)
184 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
188 * Preleva un carattere dal buffer di ricezione.
189 * Se il buffer e' vuoto, ser_getchar_nowait() ritorna
190 * immediatamente EOF.
192 int ser_getchar_nowait(struct KFileSerial *fd)
194 if (fifo_isempty_locked(&fd->ser->rxfifo))
197 /* NOTE: the double cast prevents unwanted sign extension */
198 return (int)(unsigned char)fifo_pop_locked(&fd->ser->rxfifo);
203 * Read at most \a size bytes from \a port and put them in \a buf
205 * \return number of bytes actually read.
207 static size_t ser_read(struct KFile *fd, void *_buf, size_t size)
209 KFileSerial *fds = KFILESERIAL(fd);
212 char *buf = (char *)_buf;
217 if ((c = ser_getchar(fds->ser)) == EOF)
226 * \brief Write a buffer to serial.
228 * \return 0 if OK, EOF in case of error.
230 * \todo Optimize with fifo_pushblock()
232 static size_t ser_write(struct KFile *fd, const void *_buf, size_t size)
234 KFileSerial *fds = KFILESERIAL(fd);
235 const char *buf = (const char *)_buf;
240 if (ser_putchar(*buf++, fds->ser) == EOF)
248 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
249 void ser_settimeouts(struct KFileSerial *fd, mtime_t rxtimeout, mtime_t txtimeout)
251 fd->ser->rxtimeout = ms_to_ticks(rxtimeout);
252 fd->ser->txtimeout = ms_to_ticks(txtimeout);
254 #endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */
256 #if CONFIG_SER_RXTIMEOUT != -1
258 * Discard input to resynchronize with remote end.
260 * Discard incoming data until the port stops receiving
261 * characters for at least \a delay milliseconds.
263 * \note Serial errors are reset before and after executing the purge.
265 void ser_resync(struct KFileSerial *fd, mtime_t delay)
267 mtime_t old_rxtimeout = ticks_to_ms(fd->ser->rxtimeout);
269 ser_settimeouts(fd, delay, ticks_to_ms(fd->ser->txtimeout));
272 ser_setstatus(fd->ser, 0);
273 ser_getchar(fd->ser);
275 while (!(ser_getstatus(fd->ser) & SERRF_RXTIMEOUT));
277 /* Restore port to an usable status */
278 ser_setstatus(fd->ser, 0);
279 ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->ser->txtimeout));
281 #endif /* CONFIG_SER_RXTIMEOUT */
284 void ser_setbaudrate(struct KFileSerial *fd, unsigned long rate)
286 fd->ser->hw->table->setBaudrate(fd->ser->hw, rate);
290 void ser_setparity(struct KFileSerial *fd, int parity)
292 fd->ser->hw->table->setParity(fd->ser->hw, parity);
295 static int ser_error(struct KFile *fd)
297 KFileSerial *fds = KFILESERIAL(fd);
298 return ser_getstatus(fds->ser);
301 static void ser_clearerr(struct KFile *fd)
303 KFileSerial *fds = KFILESERIAL(fd);
304 ser_setstatus(fds->ser, 0);
310 * Flush both the RX and TX buffers.
312 void ser_purge(struct KFileSerial *fd)
321 void ser_purgeRx(struct KFileSerial *fd)
323 fifo_flush_locked(&fd->ser->rxfifo);
329 void ser_purgeTx(struct KFileSerial *fd)
331 fifo_flush_locked(&fd->ser->txfifo);
336 * Wait until all pending output is completely
337 * transmitted to the other end.
339 * \note The current implementation only checks the
340 * software transmission queue. Any hardware
343 static int ser_flush(struct KFile *fd)
345 KFileSerial *fds = KFILESERIAL(fd);
348 * Wait until the FIFO becomes empty, and then until the byte currently in
349 * the hardware register gets shifted out.
351 while (!fifo_isempty(&fds->ser->txfifo)
352 || fds->ser->hw->table->txSending(fds->ser->hw))
354 #if CONFIG_KERNEL && CONFIG_KERN_SCHED
355 /* Give up timeslice to other processes. */
365 * Initialize a serial port.
367 * \param fd KFile Serial struct interface.
368 * \param unit Serial unit to open. Possible values are architecture dependant.
370 static struct Serial *ser_open(struct KFileSerial *fd, unsigned int unit)
374 ASSERT(unit < countof(ser_handles));
375 port = &ser_handles[unit];
377 ASSERT(!port->is_open);
378 DB(port->is_open = true);
382 port->hw = ser_hw_getdesc(unit);
384 /* Initialize circular buffers */
385 ASSERT(port->hw->txbuffer);
386 ASSERT(port->hw->rxbuffer);
387 fifo_init(&port->txfifo, port->hw->txbuffer, port->hw->txbuffer_size);
388 fifo_init(&port->rxfifo, port->hw->rxbuffer, port->hw->rxbuffer_size);
390 port->hw->table->init(port->hw, port);
393 /* Set default values */
394 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
395 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
397 #if CONFIG_SER_DEFBAUDRATE
398 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
401 /* Clear error flags */
402 ser_setstatus(port, 0);
409 * Clean up serial port, disabling the associated hardware.
411 static int ser_close(struct KFile *fd)
413 KFileSerial *fds = KFILESERIAL(fd);
414 Serial *port = fds->ser;
416 ASSERT(port->is_open);
417 DB(port->is_open = false);
419 // Wait until we finish sending everything
422 port->hw->table->cleanup(port->hw);
426 * We purge the FIFO buffer only after the low-level cleanup, so that
427 * we are sure that there are no more interrupts.
434 * Reopen serial port.
436 static struct KFile *ser_reopen(struct KFile *fd)
438 KFileSerial *fds = KFILESERIAL(fd);
441 ser_open(fds, fds->ser->unit);
446 * Init serial driver for \a unit.
448 void ser_init(struct KFileSerial *fds, unsigned int unit)
450 memset(fds, 0, sizeof(*fds));
452 DB(fds->fd._type = KFT_SERIAL);
453 fds->fd.reopen = ser_reopen;
454 fds->fd.close = ser_close;
455 fds->fd.read = ser_read;
456 fds->fd.write = ser_write;
457 fds->fd.flush = ser_flush;
458 fds->fd.error = ser_error;
459 fds->fd.clearerr = ser_clearerr;
465 * Read data from SPI bus.
466 * Since we are master, we have to trigger slave by sending
467 * fake chars on the bus.
469 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
471 KFileSerial *fd_spi = KFILESERIAL(fd);
473 ser_flush(&fd_spi->fd);
477 uint8_t *buf = (uint8_t *)_buf;
483 * Send and receive chars 1 by 1, otherwise the rxfifo
486 ser_putchar(0, fd_spi->ser);
488 if ((c = ser_getchar(fd_spi->ser)) == EOF)
498 * Write data to SPI bus.
500 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
502 KFileSerial *fd_spi = KFILESERIAL(fd);
506 return ser_write(&fd_spi->fd, buf, size);
511 * Init SPI serial driver \a unit in master mode.
513 * This interface implements the SPI master protocol over a serial SPI
514 * driver. This is needed because normal serial driver send/receive data
515 * at the same time. SPI slaves like memories and other peripherals
516 * first receive and *then* send response back instead.
517 * To achieve this, when we are master and we are *sending*,
518 * we have to discard all incoming data. Then, when we want to
519 * receive, we must write fake data to SPI to trigger slave devices.
521 void spimaster_init(KFileSerial *fds, unsigned int unit)
524 fds->fd.read = spimaster_read;
525 fds->fd.write = spimaster_write;