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