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 Bernie Innocenti <bernie@codewiz.org>
33 * \brief Buffered serial I/O driver
35 * The serial rx interrupt buffers incoming data in a software FIFO
36 * to decouple the higher level protocols from the line speed.
37 * Outgoing data is buffered as well for better performance.
38 * This driver is not optimized for best performance, but it
39 * has proved to be fast enough to handle transfer rates up to
40 * 38400bps on a 16MHz 80196.
42 * MODULE CONFIGURATION
44 * \li \c CONFIG_SER_HWHANDSHAKE - set to 1 to enable RTS/CTS handshake.
45 * Support is incomplete/untested.
46 * \li \c CONFIG_SER_TXTIMEOUT - Enable software serial transmission timeouts
50 * \author Bernie Innocenti <bernie@codewiz.org>
58 #include "cfg/cfg_ser.h"
59 #include "cfg/cfg_proc.h"
60 #include <cfg/debug.h>
62 #include <mware/formatwr.h>
64 #include <cpu/power.h> /* cpu_relax() */
66 #include <string.h> /* memset() */
69 * Sanity check for config parameters required by this module.
71 #if !defined(CONFIG_KERN) || ((CONFIG_KERN != 0) && CONFIG_KERN != 1)
72 #error CONFIG_KERN must be set to either 0 or 1 in cfg_kern.h
74 #if !defined(CONFIG_SER_RXTIMEOUT)
75 #error CONFIG_SER_TXTIMEOUT missing in cfg_ser.h
77 #if !defined(CONFIG_SER_RXTIMEOUT)
78 #error CONFIG_SER_RXTIMEOUT missing in cfg_ser.h
80 #if !defined(CONFIG_SER_DEFBAUDRATE)
81 #error CONFIG_SER_DEFBAUDRATE missing in cfg_ser.h
85 struct Serial *ser_handles[SER_CNT];
88 * Insert \a c in tx FIFO buffer.
89 * \note This function will switch out the calling process
90 * if the tx buffer is full. If the buffer is full
91 * and \a port->txtimeout is 0 return EOF immediatly.
93 * \return EOF on error or timeout, \a c otherwise.
95 static int ser_putchar(int c, struct Serial *port)
97 if (fifo_isfull_locked(&port->txfifo))
99 #if CONFIG_SER_TXTIMEOUT != -1
100 /* If timeout == 0 we don't want to wait */
101 if (port->txtimeout == 0)
104 ticks_t start_time = timer_clock();
107 /* Wait while buffer is full... */
112 #if CONFIG_SER_TXTIMEOUT != -1
113 if (timer_clock() - start_time >= port->txtimeout)
115 ATOMIC(port->status |= SERRF_TXTIMEOUT);
118 #endif /* CONFIG_SER_TXTIMEOUT */
120 while (fifo_isfull_locked(&port->txfifo));
123 fifo_push_locked(&port->txfifo, (unsigned char)c);
125 /* (re)trigger tx interrupt */
126 port->hw->table->txStart(port->hw);
128 /* Avoid returning signed extended char */
129 return (int)((unsigned char)c);
134 * Fetch a character from the rx FIFO buffer.
135 * \note This function will switch out the calling process
136 * if the rx buffer is empty. If the buffer is empty
137 * and \a port->rxtimeout is 0 return EOF immediatly.
139 * \return EOF on error or timeout, \a c otherwise.
141 static int ser_getchar(struct Serial *port)
143 if (fifo_isempty_locked(&port->rxfifo))
145 #if CONFIG_SER_RXTIMEOUT != -1
146 /* If timeout == 0 we don't want to wait for chars */
147 if (port->rxtimeout == 0)
150 ticks_t start_time = timer_clock();
153 /* Wait while buffer is empty */
158 #if CONFIG_SER_RXTIMEOUT != -1
159 if (timer_clock() - start_time >= port->rxtimeout)
161 ATOMIC(port->status |= SERRF_RXTIMEOUT);
164 #endif /* CONFIG_SER_RXTIMEOUT */
166 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
170 * Get a byte from the FIFO (avoiding sign-extension),
171 * re-enable RTS, then return result.
173 if (ser_getstatus(port) & SERRF_RX)
175 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
179 * Fetch a character from the rx FIFO buffer.
180 * If the buffer is empty, ser_getchar_nowait() returns
182 * \note Deprecated, use ser_getchar with rx_timeout set to 0.
184 int ser_getchar_nowait(struct Serial *fd)
186 if (fifo_isempty_locked(&fd->rxfifo))
189 /* NOTE: the double cast prevents unwanted sign extension */
190 return (int)(unsigned char)fifo_pop_locked(&fd->rxfifo);
196 * Read at most \a size bytes from \a port and put them in \a buf
198 * \return number of bytes actually read.
200 static size_t ser_read(struct KFile *fd, void *_buf, size_t size)
202 Serial *fds = SERIAL_CAST(fd);
205 char *buf = (char *)_buf;
210 if ((c = ser_getchar(fds)) == EOF)
219 * \brief Write a buffer to serial.
221 * \return 0 if OK, EOF in case of error.
223 * \todo Optimize with fifo_pushblock()
225 static size_t ser_write(struct KFile *fd, const void *_buf, size_t size)
227 Serial *fds = SERIAL_CAST(fd);
228 const char *buf = (const char *)_buf;
233 if (ser_putchar(*buf++, fds) == EOF)
241 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
242 void ser_settimeouts(struct Serial *fd, mtime_t rxtimeout, mtime_t txtimeout)
244 fd->rxtimeout = ms_to_ticks(rxtimeout);
245 fd->txtimeout = ms_to_ticks(txtimeout);
247 #endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */
249 #if CONFIG_SER_RXTIMEOUT != -1
251 * Discard input to resynchronize with remote end.
253 * Discard incoming data until the port stops receiving
254 * characters for at least \a delay milliseconds.
256 * \note Serial errors are reset before and after executing the purge.
258 void ser_resync(struct Serial *fd, mtime_t delay)
260 mtime_t old_rxtimeout = ticks_to_ms(fd->rxtimeout);
262 ser_settimeouts(fd, delay, ticks_to_ms(fd->txtimeout));
265 ser_setstatus(fd, 0);
268 while (!(ser_getstatus(fd) & SERRF_RXTIMEOUT));
270 /* Restore port to an usable status */
271 ser_setstatus(fd, 0);
272 ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->txtimeout));
274 #endif /* CONFIG_SER_RXTIMEOUT */
277 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
279 fd->hw->table->setBaudrate(fd->hw, rate);
283 void ser_setparity(struct Serial *fd, int parity)
285 fd->hw->table->setParity(fd->hw, parity);
288 static int ser_error(struct KFile *fd)
290 Serial *fds = SERIAL_CAST(fd);
291 return ser_getstatus(fds);
294 static void ser_clearerr(struct KFile *fd)
296 Serial *fds = SERIAL_CAST(fd);
297 ser_setstatus(fds, 0);
303 * Flush both the RX and TX buffers.
305 void ser_purge(struct Serial *fd)
314 void ser_purgeRx(struct Serial *fd)
316 fifo_flush_locked(&fd->rxfifo);
322 void ser_purgeTx(struct Serial *fd)
324 fifo_flush_locked(&fd->txfifo);
329 * Wait until all pending output is completely
330 * transmitted to the other end.
332 * \note The current implementation only checks the
333 * software transmission queue. Any hardware
336 static int ser_flush(struct KFile *fd)
338 Serial *fds = SERIAL_CAST(fd);
341 * Wait until the FIFO becomes empty, and then until the byte currently in
342 * the hardware register gets shifted out.
344 while (!fifo_isempty(&fds->txfifo)
345 || fds->hw->table->txSending(fds->hw))
352 * Initialize a serial port.
354 * \param fd KFile Serial struct interface.
355 * \param unit Serial unit to open. Possible values are architecture dependant.
357 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
359 ASSERT(unit < countof(ser_handles));
361 ser_handles[unit] = fd;
362 ASSERT(!fd->is_open);
363 DB(fd->is_open = true);
367 fd->hw = ser_hw_getdesc(unit);
369 /* Initialize circular buffers */
370 ASSERT(fd->hw->txbuffer);
371 ASSERT(fd->hw->rxbuffer);
372 fifo_init(&fd->txfifo, fd->hw->txbuffer, fd->hw->txbuffer_size);
373 fifo_init(&fd->rxfifo, fd->hw->rxbuffer, fd->hw->rxbuffer_size);
375 fd->hw->table->init(fd->hw, fd);
377 /* Set default values */
378 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
379 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
381 #if CONFIG_SER_DEFBAUDRATE
382 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
385 /* Clear error flags */
386 ser_setstatus(fd, 0);
393 * Clean up serial port, disabling the associated hardware.
395 static int ser_close(struct KFile *fd)
397 Serial *fds = SERIAL_CAST(fd);
400 ASSERT(port->is_open);
401 DB(port->is_open = false);
403 // Wait until we finish sending everything
406 port->hw->table->cleanup(port->hw);
410 * We purge the FIFO buffer only after the low-level cleanup, so that
411 * we are sure that there are no more interrupts.
418 * Reopen serial port.
420 static struct KFile *ser_reopen(struct KFile *fd)
422 Serial *fds = SERIAL_CAST(fd);
425 ser_open(fds, fds->unit);
430 * Init serial driver for \a unit.
432 void ser_init(struct Serial *fds, unsigned int unit)
434 memset(fds, 0, sizeof(*fds));
436 DB(fds->fd._type = KFT_SERIAL);
437 fds->fd.reopen = ser_reopen;
438 fds->fd.close = ser_close;
439 fds->fd.read = ser_read;
440 fds->fd.write = ser_write;
441 fds->fd.flush = ser_flush;
442 fds->fd.error = ser_error;
443 fds->fd.clearerr = ser_clearerr;
449 * Read data from SPI bus.
450 * Since we are master, we have to trigger slave by sending
451 * fake chars on the bus.
453 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
455 Serial *fd_spi = SERIAL_CAST(fd);
457 ser_flush(&fd_spi->fd);
461 uint8_t *buf = (uint8_t *)_buf;
467 * Send and receive chars 1 by 1, otherwise the rxfifo
470 ser_putchar(0, fd_spi);
472 if ((c = ser_getchar(fd_spi)) == EOF)
482 * Write data to SPI bus.
484 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
486 Serial *fd_spi = SERIAL_CAST(fd);
490 return ser_write(&fd_spi->fd, buf, size);
495 * Init SPI serial driver \a unit in master mode.
497 * This interface implements the SPI master protocol over a serial SPI
498 * driver. This is needed because normal serial driver send/receive data
499 * at the same time. SPI slaves like memories and other peripherals
500 * first receive and *then* send response back instead.
501 * To achieve this, when we are master and we are *sending*,
502 * we have to discard all incoming data. Then, when we want to
503 * receive, we must write fake data to SPI to trigger slave devices.
505 void spimaster_init(Serial *fds, unsigned int unit)
508 fds->fd.read = spimaster_read;
509 fds->fd.write = spimaster_write;