Switch to new kernel config files.
[bertos.git] / bertos / drv / ser.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
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.
10  *
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.
15  *
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
19  *
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.
28  *
29  * Copyright 2003, 2004, 2006 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2000 Bernie Innocenti <bernie@codewiz.org>
31  * -->
32  *
33  * \brief Buffered serial I/O driver
34  *
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.
41  *
42  * MODULE CONFIGURATION
43  *
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
47  *
48  *
49  * \version $Id$
50  * \author Bernie Innocenti <bernie@codewiz.org>
51  */
52
53 #include "ser.h"
54 #include "wdt.h"
55 #include "timer.h"
56 #include "ser_p.h"
57
58 #include "cfg/cfg_ser.h"
59 #include "cfg/cfg_proc.h"
60 #include <cfg/debug.h>
61
62 #include <mware/formatwr.h>
63
64 #include <cpu/power.h> /* cpu_relax() */
65
66 #include <string.h> /* memset() */
67
68 /*
69  * Sanity check for config parameters required by this module.
70  */
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
73 #endif
74 #if !defined(CONFIG_SER_RXTIMEOUT)
75         #error CONFIG_SER_TXTIMEOUT missing in cfg_ser.h
76 #endif
77 #if !defined(CONFIG_SER_RXTIMEOUT)
78         #error CONFIG_SER_RXTIMEOUT missing in cfg_ser.h
79 #endif
80 #if !defined(CONFIG_SER_DEFBAUDRATE)
81         #error CONFIG_SER_DEFBAUDRATE missing in cfg_ser.h
82 #endif
83
84
85 struct Serial *ser_handles[SER_CNT];
86
87 /**
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.
92  *
93  * \return EOF on error or timeout, \a c otherwise.
94  */
95 static int ser_putchar(int c, struct Serial *port)
96 {
97         if (fifo_isfull_locked(&port->txfifo))
98         {
99 #if CONFIG_SER_TXTIMEOUT != -1
100                 /* If timeout == 0 we don't want to wait */
101                 if (port->txtimeout == 0)
102                         return EOF;
103
104                 ticks_t start_time = timer_clock();
105 #endif
106
107                 /* Wait while buffer is full... */
108                 do
109                 {
110                         cpu_relax();
111
112 #if CONFIG_SER_TXTIMEOUT != -1
113                         if (timer_clock() - start_time >= port->txtimeout)
114                         {
115                                 ATOMIC(port->status |= SERRF_TXTIMEOUT);
116                                 return EOF;
117                         }
118 #endif /* CONFIG_SER_TXTIMEOUT */
119                 }
120                 while (fifo_isfull_locked(&port->txfifo));
121         }
122
123         fifo_push_locked(&port->txfifo, (unsigned char)c);
124
125         /* (re)trigger tx interrupt */
126         port->hw->table->txStart(port->hw);
127
128         /* Avoid returning signed extended char */
129         return (int)((unsigned char)c);
130 }
131
132
133 /**
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.
138  *
139  * \return EOF on error or timeout, \a c otherwise.
140  */
141 static int ser_getchar(struct Serial *port)
142 {
143         if (fifo_isempty_locked(&port->rxfifo))
144         {
145 #if CONFIG_SER_RXTIMEOUT != -1
146                 /* If timeout == 0 we don't want to wait for chars */
147                 if (port->rxtimeout == 0)
148                         return EOF;
149
150                 ticks_t start_time = timer_clock();
151 #endif
152
153                 /* Wait while buffer is empty */
154                 do
155                 {
156                         cpu_relax();
157
158 #if CONFIG_SER_RXTIMEOUT != -1
159                         if (timer_clock() - start_time >= port->rxtimeout)
160                         {
161                                 ATOMIC(port->status |= SERRF_RXTIMEOUT);
162                                 return EOF;
163                         }
164 #endif /* CONFIG_SER_RXTIMEOUT */
165                 }
166                 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
167         }
168
169         /*
170          * Get a byte from the FIFO (avoiding sign-extension),
171          * re-enable RTS, then return result.
172          */
173         if (ser_getstatus(port) & SERRF_RX)
174                 return EOF;
175         return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
176 }
177
178 /**
179  * Fetch a character from the rx FIFO buffer.
180  * If the buffer is empty, ser_getchar_nowait() returns
181  * EOF immediatly.
182  * \note Deprecated, use ser_getchar with rx_timeout set to 0.
183  */
184 int ser_getchar_nowait(struct Serial *fd)
185 {
186         if (fifo_isempty_locked(&fd->rxfifo))
187                 return EOF;
188
189         /* NOTE: the double cast prevents unwanted sign extension */
190         return (int)(unsigned char)fifo_pop_locked(&fd->rxfifo);
191 }
192
193
194
195 /**
196  * Read at most \a size bytes from \a port and put them in \a buf
197  *
198  * \return number of bytes actually read.
199  */
200 static size_t ser_read(struct KFile *fd, void *_buf, size_t size)
201 {
202         Serial *fds = SERIAL_CAST(fd);
203
204         size_t i = 0;
205         char *buf = (char *)_buf;
206         int c;
207
208         while (i < size)
209         {
210                 if ((c = ser_getchar(fds)) == EOF)
211                         break;
212                 buf[i++] = c;
213         }
214
215         return i;
216 }
217
218 /**
219  * \brief Write a buffer to serial.
220  *
221  * \return 0 if OK, EOF in case of error.
222  *
223  * \todo Optimize with fifo_pushblock()
224  */
225 static size_t ser_write(struct KFile *fd, const void *_buf, size_t size)
226 {
227         Serial *fds = SERIAL_CAST(fd);
228         const char *buf = (const char *)_buf;
229         size_t i = 0;
230
231         while (size--)
232         {
233                 if (ser_putchar(*buf++, fds) == EOF)
234                         break;
235                 i++;
236         }
237         return i;
238 }
239
240
241 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
242 void ser_settimeouts(struct Serial *fd, mtime_t rxtimeout, mtime_t txtimeout)
243 {
244         fd->rxtimeout = ms_to_ticks(rxtimeout);
245         fd->txtimeout = ms_to_ticks(txtimeout);
246 }
247 #endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */
248
249 #if CONFIG_SER_RXTIMEOUT != -1
250 /**
251  * Discard input to resynchronize with remote end.
252  *
253  * Discard incoming data until the port stops receiving
254  * characters for at least \a delay milliseconds.
255  *
256  * \note Serial errors are reset before and after executing the purge.
257  */
258 void ser_resync(struct Serial *fd, mtime_t delay)
259 {
260         mtime_t old_rxtimeout = ticks_to_ms(fd->rxtimeout);
261
262         ser_settimeouts(fd, delay, ticks_to_ms(fd->txtimeout));
263         do
264         {
265                 ser_setstatus(fd, 0);
266                 ser_getchar(fd);
267         }
268         while (!(ser_getstatus(fd) & SERRF_RXTIMEOUT));
269
270         /* Restore port to an usable status */
271         ser_setstatus(fd, 0);
272         ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->txtimeout));
273 }
274 #endif /* CONFIG_SER_RXTIMEOUT */
275
276
277 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
278 {
279         fd->hw->table->setBaudrate(fd->hw, rate);
280 }
281
282
283 void ser_setparity(struct Serial *fd, int parity)
284 {
285         fd->hw->table->setParity(fd->hw, parity);
286 }
287
288 static int ser_error(struct KFile *fd)
289 {
290         Serial *fds = SERIAL_CAST(fd);
291         return ser_getstatus(fds);
292 }
293
294 static void ser_clearerr(struct KFile *fd)
295 {
296         Serial *fds = SERIAL_CAST(fd);
297         ser_setstatus(fds, 0);
298 }
299
300
301
302 /**
303  * Flush both the RX and TX buffers.
304  */
305 void ser_purge(struct Serial *fd)
306 {
307         ser_purgeRx(fd);
308         ser_purgeTx(fd);
309 }
310
311 /**
312  * Flush RX buffer.
313  */
314 void ser_purgeRx(struct Serial *fd)
315 {
316         fifo_flush_locked(&fd->rxfifo);
317 }
318
319 /**
320  * Flush TX buffer.
321  */
322 void ser_purgeTx(struct Serial *fd)
323 {
324         fifo_flush_locked(&fd->txfifo);
325 }
326
327
328 /**
329  * Wait until all pending output is completely
330  * transmitted to the other end.
331  *
332  * \note The current implementation only checks the
333  *       software transmission queue. Any hardware
334  *       FIFOs are ignored.
335  */
336 static int ser_flush(struct KFile *fd)
337 {
338         Serial *fds = SERIAL_CAST(fd);
339
340         /*
341          * Wait until the FIFO becomes empty, and then until the byte currently in
342          * the hardware register gets shifted out.
343          */
344         while (!fifo_isempty(&fds->txfifo)
345                || fds->hw->table->txSending(fds->hw))
346                 cpu_relax();
347         return 0;
348 }
349
350
351 /**
352  * Initialize a serial port.
353  *
354  * \param fd KFile Serial struct interface.
355  * \param unit  Serial unit to open. Possible values are architecture dependant.
356  */
357 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
358 {
359         ASSERT(unit < countof(ser_handles));
360
361         ser_handles[unit] = fd;
362         ASSERT(!fd->is_open);
363         DB(fd->is_open = true);
364
365         fd->unit = unit;
366
367         fd->hw = ser_hw_getdesc(unit);
368
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);
374
375         fd->hw->table->init(fd->hw, fd);
376
377         /* Set default values */
378 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
379         ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
380 #endif
381 #if CONFIG_SER_DEFBAUDRATE
382         ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
383 #endif
384
385         /* Clear error flags */
386         ser_setstatus(fd, 0);
387
388         return fd;
389 }
390
391
392 /**
393  * Clean up serial port, disabling the associated hardware.
394  */
395 static int ser_close(struct KFile *fd)
396 {
397         Serial *fds = SERIAL_CAST(fd);
398         Serial *port = fds;
399
400         ASSERT(port->is_open);
401         DB(port->is_open = false);
402
403         // Wait until we finish sending everything
404         ser_flush(fd);
405
406         port->hw->table->cleanup(port->hw);
407         DB(port->hw = NULL);
408
409         /*
410          * We purge the FIFO buffer only after the low-level cleanup, so that
411          * we are sure that there are no more interrupts.
412          */
413         ser_purge(fds);
414         return 0;
415 }
416
417 /**
418  * Reopen serial port.
419  */
420 static struct KFile *ser_reopen(struct KFile *fd)
421 {
422         Serial *fds = SERIAL_CAST(fd);
423
424         ser_close(fd);
425         ser_open(fds, fds->unit);
426         return (KFile *)fds;
427 }
428
429 /**
430  * Init serial driver for \a unit.
431  */
432 void ser_init(struct Serial *fds, unsigned int unit)
433 {
434         memset(fds, 0, sizeof(*fds));
435
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;
444         ser_open(fds, unit);
445 }
446
447
448 /**
449  * Read data from SPI bus.
450  * Since we are master, we have to trigger slave by sending
451  * fake chars on the bus.
452  */
453 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
454 {
455         Serial *fd_spi = SERIAL_CAST(fd);
456
457         ser_flush(&fd_spi->fd);
458         ser_purgeRx(fd_spi);
459
460         size_t total_rd = 0;
461         uint8_t *buf = (uint8_t *)_buf;
462         int c;
463
464         while (size--)
465         {
466                 /*
467                  * Send and receive chars 1 by 1, otherwise the rxfifo
468                  * will overrun.
469                  */
470                 ser_putchar(0, fd_spi);
471
472                 if ((c = ser_getchar(fd_spi)) == EOF)
473                         break;
474
475                 *buf++ = c;
476                 total_rd++;
477         }
478         return total_rd;
479 }
480
481 /**
482  * Write data to SPI bus.
483  */
484 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
485 {
486         Serial *fd_spi = SERIAL_CAST(fd);
487
488         ser_purgeRx(fd_spi);
489
490         return ser_write(&fd_spi->fd, buf, size);
491 }
492
493
494 /**
495  * Init SPI serial driver \a unit in master mode.
496  *
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.
504  */
505 void spimaster_init(Serial *fds, unsigned int unit)
506 {
507         ser_init(fds, unit);
508         fds->fd.read = spimaster_read;
509         fds->fd.write = spimaster_write;
510 }
511
512