Add first sckel of serial module for arm.
[bertos.git] / cpu / arm / drv / ser_at91.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 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
31  *
32  * -->
33  *
34  * \brief ARM UART and SPI I/O driver
35  *
36  *
37  * \version $Id: ser_amr.c 18280 2007-10-11 15:14:20Z asterix $
38  * \author Daniele Basile <asterix@develer.com>
39  */
40
41 #include <io/at91sam7s.h>
42
43 //#include "ser_at91.h"
44 #include <drv/ser.h>
45 #include <drv/ser_p.h>
46
47 #include <hw/hw_ser.h>  /* Required for bus macros overrides */
48 #include <hw/hw_cpu.h>  /* CLOCK_FREQ */
49
50 #include <appconfig.h>
51 #include <mware/fifobuf.h>
52
53 #include <cfg/debug.h>
54 #include <drv/timer.h>
55
56
57 //TODO
58 #if !CONFIG_SER_HWHANDSHAKE
59         /**
60          * \name Hardware handshake (RTS/CTS).
61          * \{
62          */
63         #define RTS_ON      do {} while (0)
64         #define RTS_OFF     do {} while (0)
65         #define IS_CTS_ON   true
66         #define EIMSKF_CTS  0 /**< Dummy value, must be overridden */
67         /*\}*/
68 #endif
69
70 #if CPU_AVR_ATMEGA1281
71         #define BIT_RXCIE0 RXCIE0
72         #define BIT_RXEN0  RXEN0
73         #define BIT_TXEN0  TXEN0
74         #define BIT_UDRIE0 UDRIE0
75
76         #define BIT_RXCIE1 RXCIE1
77         #define BIT_RXEN1  RXEN1
78         #define BIT_TXEN1  TXEN1
79         #define BIT_UDRIE1 UDRIE1
80 #else
81         #define BIT_RXCIE0 RXCIE
82         #define BIT_RXEN0  RXEN
83         #define BIT_TXEN0  TXEN
84         #define BIT_UDRIE0 UDRIE
85
86         #define BIT_RXCIE1 RXCIE
87         #define BIT_RXEN1  RXEN
88         #define BIT_TXEN1  TXEN
89         #define BIT_UDRIE1 UDRIE
90 #endif
91
92
93 /**
94  * \name Overridable serial bus hooks
95  *
96  * These can be redefined in hw.h to implement
97  * special bus policies such as half-duplex, 485, etc.
98  *
99  *
100  * \code
101  *  TXBEGIN      TXCHAR      TXEND  TXOFF
102  *    |   __________|__________ |     |
103  *    |   |   |   |   |   |   | |     |
104  *    v   v   v   v   v   v   v v     v
105  * ______  __  __  __  __  __  __  ________________
106  *       \/  \/  \/  \/  \/  \/  \/
107  * ______/\__/\__/\__/\__/\__/\__/
108  *
109  * \endcode
110  *
111  * \{
112  */
113 #ifndef SER_UART0_BUS_TXINIT
114         /**
115          * Default TXINIT macro - invoked in uart0_init()
116          *
117          * - Enable both the receiver and the transmitter
118          * - Enable only the RX complete interrupt
119          */
120         #define SER_UART0_BUS_TXINIT do { \
121                 UCSR0B = BV(BIT_RXCIE0) | BV(BIT_RXEN0) | BV(BIT_TXEN0); \
122         } while (0)
123 #endif
124
125 #ifndef SER_UART0_BUS_TXBEGIN
126         /**
127          * Invoked before starting a transmission
128          *
129          * - Enable both the receiver and the transmitter
130          * - Enable both the RX complete and UDR empty interrupts
131          */
132         #define SER_UART0_BUS_TXBEGIN do { \
133                 UCSR0B = BV(BIT_RXCIE0) | BV(BIT_UDRIE0) | BV(BIT_RXEN0) | BV(BIT_TXEN0); \
134         } while (0)
135 #endif
136
137 #ifndef SER_UART0_BUS_TXCHAR
138         /**
139          * Invoked to send one character.
140          */
141         #define SER_UART0_BUS_TXCHAR(c) do { \
142                 UDR0 = (c); \
143         } while (0)
144 #endif
145
146 #ifndef SER_UART0_BUS_TXEND
147         /**
148          * Invoked as soon as the txfifo becomes empty
149          *
150          * - Keep both the receiver and the transmitter enabled
151          * - Keep the RX complete interrupt enabled
152          * - Disable the UDR empty interrupt
153          */
154         #define SER_UART0_BUS_TXEND do { \
155                 UCSR0B = BV(BIT_RXCIE0) | BV(BIT_RXEN0) | BV(BIT_TXEN0); \
156         } while (0)
157 #endif
158
159 #ifndef SER_UART0_BUS_TXOFF
160         /**
161          * \def SER_UART0_BUS_TXOFF
162          *
163          * Invoked after the last character has been transmitted
164          *
165          * The default is no action.
166          */
167         #ifdef __doxygen__
168         #define SER_UART0_BUS_TXOFF
169         #endif
170 #endif
171
172 #ifndef SER_UART1_BUS_TXINIT
173         /** \sa SER_UART0_BUS_TXINIT */
174         #define SER_UART1_BUS_TXINIT do { \
175                 UCSR1B = BV(BIT_RXCIE1) | BV(BIT_RXEN1) | BV(BIT_TXEN1); \
176         } while (0)
177 #endif
178 #ifndef SER_UART1_BUS_TXBEGIN
179         /** \sa SER_UART0_BUS_TXBEGIN */
180         #define SER_UART1_BUS_TXBEGIN do { \
181                 UCSR1B = BV(BIT_RXCIE1) | BV(BIT_UDRIE1) | BV(BIT_RXEN1) | BV(BIT_TXEN1); \
182         } while (0)
183 #endif
184 #ifndef SER_UART1_BUS_TXCHAR
185         /** \sa SER_UART0_BUS_TXCHAR */
186         #define SER_UART1_BUS_TXCHAR(c) do { \
187                 UDR1 = (c); \
188         } while (0)
189 #endif
190 #ifndef SER_UART1_BUS_TXEND
191         /** \sa SER_UART0_BUS_TXEND */
192         #define SER_UART1_BUS_TXEND do { \
193                 UCSR1B = BV(BIT_RXCIE1) | BV(BIT_RXEN1) | BV(BIT_TXEN1); \
194         } while (0)
195 #endif
196 #ifndef SER_UART1_BUS_TXOFF
197         /**
198          * \def SER_UART1_BUS_TXOFF
199          *
200          * \see SER_UART0_BUS_TXOFF
201          */
202         #ifdef __doxygen__
203         #define SER_UART1_BUS_TXOFF
204         #endif
205 #endif
206 /*\}*/
207
208
209 /**
210  * \name Overridable SPI hooks
211  *
212  * These can be redefined in hw.h to implement
213  * special bus policies such as slave select pin handling, etc.
214  *
215  * \{
216  */
217 #ifndef SER_SPI_BUS_TXINIT
218         /**
219          * Default TXINIT macro - invoked in spi_init()
220          * The default is no action.
221          */
222         #define SER_SPI_BUS_TXINIT
223 #endif
224
225 #ifndef SER_SPI_BUS_TXCLOSE
226         /**
227          * Invoked after the last character has been transmitted.
228          * The default is no action.
229          */
230         #define SER_SPI_BUS_TXCLOSE
231 #endif
232 /*\}*/
233
234
235 /* SPI port and pin configuration */
236 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103 || CPU_AVR_ATMEGA1281
237         #define SPI_PORT      PORTB
238         #define SPI_DDR       DDRB
239         #define SPI_SS_BIT    PB0
240         #define SPI_SCK_BIT   PB1
241         #define SPI_MOSI_BIT  PB2
242         #define SPI_MISO_BIT  PB3
243 #elif CPU_AVR_ATMEGA8
244         #define SPI_PORT      PORTB
245         #define SPI_DDR       DDRB
246         #define SPI_SS_BIT    PB2
247         #define SPI_SCK_BIT   PB5
248         #define SPI_MOSI_BIT  PB3
249         #define SPI_MISO_BIT  PB4
250 #else
251         #error Unknown architecture
252 #endif
253
254 /* USART register definitions */
255 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
256         #define AVR_HAS_UART1 1
257 #elif CPU_AVR_ATMEGA8
258         #define AVR_HAS_UART1 0
259         #define UCSR0A UCSRA
260         #define UCSR0B UCSRB
261         #define UCSR0C UCSRC
262         #define UDR0   UDR
263         #define UBRR0L UBRRL
264         #define UBRR0H UBRRH
265         #define SIG_UART0_DATA SIG_UART_DATA
266         #define SIG_UART0_RECV SIG_UART_RECV
267         #define SIG_UART0_TRANS SIG_UART_TRANS
268 #elif CPU_AVR_ATMEGA103
269         #define AVR_HAS_UART1 0
270         #define UCSR0B UCR
271         #define UDR0   UDR
272         #define UCSR0A USR
273         #define UBRR0L UBRR
274         #define SIG_UART0_DATA SIG_UART_DATA
275         #define SIG_UART0_RECV SIG_UART_RECV
276         #define SIG_UART0_TRANS SIG_UART_TRANS
277 #else
278         #error Unknown architecture
279 #endif
280
281
282 /**
283  * \def CONFIG_SER_STROBE
284  *
285  * This is a debug facility that can be used to
286  * monitor SER interrupt activity on an external pin.
287  *
288  * To use strobes, redefine the macros SER_STROBE_ON,
289  * SER_STROBE_OFF and SER_STROBE_INIT and set
290  * CONFIG_SER_STROBE to 1.
291  */
292 #if !defined(CONFIG_SER_STROBE) || !CONFIG_SER_STROBE
293         #define SER_STROBE_ON    do {/*nop*/} while(0)
294         #define SER_STROBE_OFF   do {/*nop*/} while(0)
295         #define SER_STROBE_INIT  do {/*nop*/} while(0)
296 #endif
297
298
299 /* From the high-level serial driver */
300 extern struct Serial ser_handles[SER_CNT];
301
302 /* TX and RX buffers */
303 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
304 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
305 #if AVR_HAS_UART1
306         static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
307         static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
308 #endif
309 static unsigned char spi_txbuffer[CONFIG_SPI_TXBUFSIZE];
310 static unsigned char spi_rxbuffer[CONFIG_SPI_RXBUFSIZE];
311
312
313 /**
314  * Internal hardware state structure
315  *
316  * The \a sending variable is true while the transmission
317  * interrupt is retriggering itself.
318  *
319  * For the USARTs the \a sending flag is useful for taking specific
320  * actions before sending a burst of data, at the start of a trasmission
321  * but not before every char sent.
322  *
323  * For the SPI, this flag is necessary because the SPI sends and receives
324  * bytes at the same time and the SPI IRQ is unique for send/receive.
325  * The only way to start transmission is to write data in SPDR (this
326  * is done by spi_starttx()). We do this *only* if a transfer is
327  * not already started.
328  */
329 struct AvrSerial
330 {
331         struct SerialHardware hw;
332         volatile bool sending;
333 };
334
335
336 /*
337  * These are to trick GCC into *not* using absolute addressing mode
338  * when accessing ser_handles, which is very expensive.
339  *
340  * Accessing through these pointers generates much shorter
341  * (and hopefully faster) code.
342  */
343 struct Serial *ser_uart0 = &ser_handles[SER_UART0];
344 #if AVR_HAS_UART1
345 struct Serial *ser_uart1 = &ser_handles[SER_UART1];
346 #endif
347 struct Serial *ser_spi = &ser_handles[SER_SPI];
348
349
350
351 /*
352  * Callbacks
353  */
354 static void uart0_init(
355         UNUSED_ARG(struct SerialHardware *, _hw),
356         UNUSED_ARG(struct Serial *, ser))
357 {
358         SER_UART0_BUS_TXINIT;
359         RTS_ON;
360         SER_STROBE_INIT;
361 }
362
363 static void uart0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
364 {
365         UCSR0B = 0;
366 }
367
368 static void uart0_enabletxirq(struct SerialHardware *_hw)
369 {
370         struct AvrSerial *hw = (struct AvrSerial *)_hw;
371
372         /*
373          * WARNING: racy code here!  The tx interrupt sets hw->sending to false
374          * when it runs with an empty fifo.  The order of statements in the
375          * if-block matters.
376          */
377         if (!hw->sending)
378         {
379                 hw->sending = true;
380                 SER_UART0_BUS_TXBEGIN;
381         }
382 }
383
384 static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
385 {
386         /* Compute baud-rate period */
387         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
388
389 #if !CPU_AVR_ATMEGA103
390         UBRR0H = (period) >> 8;
391 #endif
392         UBRR0L = (period);
393
394         //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
395 }
396
397 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
398 {
399 #if !CPU_AVR_ATMEGA103
400         UCSR0C = (UCSR0C & ~(BV(UPM01) | BV(UPM00))) | ((parity) << UPM00);
401 #endif
402 }
403
404 #if AVR_HAS_UART1
405
406 static void uart1_init(
407         UNUSED_ARG(struct SerialHardware *, _hw),
408         UNUSED_ARG(struct Serial *, ser))
409 {
410         SER_UART1_BUS_TXINIT;
411         RTS_ON;
412         SER_STROBE_INIT;
413 }
414
415 static void uart1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
416 {
417         UCSR1B = 0;
418 }
419
420 static void uart1_enabletxirq(struct SerialHardware *_hw)
421 {
422         struct AvrSerial *hw = (struct AvrSerial *)_hw;
423
424         /*
425          * WARNING: racy code here!  The tx interrupt
426          * sets hw->sending to false when it runs with
427          * an empty fifo.  The order of the statements
428          * in the if-block matters.
429          */
430         if (!hw->sending)
431         {
432                 hw->sending = true;
433                 SER_UART1_BUS_TXBEGIN;
434         }
435 }
436
437 static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
438 {
439         /* Compute baud-rate period */
440         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
441
442         UBRR1H = (period) >> 8;
443         UBRR1L = (period);
444
445         //DB(kprintf("uart1_setbaudrate(rate=%ld): period=%d\n", rate, period);)
446 }
447
448 static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
449 {
450         UCSR1C = (UCSR1C & ~(BV(UPM11) | BV(UPM10))) | ((parity) << UPM10);
451 }
452
453 #endif // AVR_HAS_UART1
454
455 static void spi_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
456 {
457         /*
458          * Set MOSI and SCK ports out, MISO in.
459          *
460          * The ATmega64/128 datasheet explicitly states that the input/output
461          * state of the SPI pins is not significant, as when the SPI is
462          * active the I/O port are overrided.
463          * This is *blatantly FALSE*.
464          *
465          * Moreover, the MISO pin on the board_kc *must* be in high impedance
466          * state even when the SPI is off, because the line is wired together
467          * with the KBus serial RX, and the transmitter of the slave boards
468          * would be unable to drive the line.
469          */
470         ATOMIC(SPI_DDR |= (BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT)));
471
472         /*
473          * If the SPI master mode is activated and the SS pin is in input and tied low,
474          * the SPI hardware will automatically switch to slave mode!
475          * For proper communication this pins should therefore be:
476          * - as output
477          * - as input but tied high forever!
478          * This driver set the pin as output.
479          */
480         #warning SPI SS pin set as output for proper operation, check schematics for possible conflicts.
481         ATOMIC(SPI_DDR |= BV(SPI_SS_BIT));
482
483         ATOMIC(SPI_DDR &= ~BV(SPI_MISO_BIT));
484         /* Enable SPI, IRQ on, Master */
485         SPCR = BV(SPE) | BV(SPIE) | BV(MSTR);
486
487         /* Set data order */
488         #if CONFIG_SPI_DATA_ORDER == SER_LSB_FIRST
489                 SPCR |= BV(DORD);
490         #endif
491
492         /* Set SPI clock rate */
493         #if CONFIG_SPI_CLOCK_DIV == 128
494                 SPCR |= (BV(SPR1) | BV(SPR0));
495         #elif (CONFIG_SPI_CLOCK_DIV == 64 || CONFIG_SPI_CLOCK_DIV == 32)
496                 SPCR |= BV(SPR1);
497         #elif (CONFIG_SPI_CLOCK_DIV == 16 || CONFIG_SPI_CLOCK_DIV == 8)
498                 SPCR |= BV(SPR0);
499         #elif (CONFIG_SPI_CLOCK_DIV == 4 || CONFIG_SPI_CLOCK_DIV == 2)
500                 // SPR0 & SDPR1 both at 0
501         #else
502                 #error Unsupported SPI clock division factor.
503         #endif
504
505         /* Set SPI2X bit (spi double frequency) */
506         #if (CONFIG_SPI_CLOCK_DIV == 128 || CONFIG_SPI_CLOCK_DIV == 64 \
507           || CONFIG_SPI_CLOCK_DIV == 16 || CONFIG_SPI_CLOCK_DIV == 4)
508                 SPSR &= ~BV(SPI2X);
509         #elif (CONFIG_SPI_CLOCK_DIV == 32 || CONFIG_SPI_CLOCK_DIV == 8 || CONFIG_SPI_CLOCK_DIV == 2)
510                 SPSR |= BV(SPI2X);
511         #else
512                 #error Unsupported SPI clock division factor.
513         #endif
514
515         /* Set clock polarity */
516         #if CONFIG_SPI_CLOCK_POL == 1
517                 SPCR |= BV(CPOL);
518         #endif
519
520         /* Set clock phase */
521         #if CONFIG_SPI_CLOCK_PHASE == 1
522                 SPCR |= BV(CPHA);
523         #endif
524         SER_SPI_BUS_TXINIT;
525
526         SER_STROBE_INIT;
527 }
528
529 static void spi_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
530 {
531         SPCR = 0;
532
533         SER_SPI_BUS_TXCLOSE;
534
535         /* Set all pins as inputs */
536         ATOMIC(SPI_DDR &= ~(BV(SPI_MISO_BIT) | BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT) | BV(SPI_SS_BIT)));
537 }
538
539 static void spi_starttx(struct SerialHardware *_hw)
540 {
541         struct AvrSerial *hw = (struct AvrSerial *)_hw;
542
543         cpuflags_t flags;
544         IRQ_SAVE_DISABLE(flags);
545
546         /* Send data only if the SPI is not already transmitting */
547         if (!hw->sending && !fifo_isempty(&ser_spi->txfifo))
548         {
549                 hw->sending = true;
550                 SPDR = fifo_pop(&ser_spi->txfifo);
551         }
552
553         IRQ_RESTORE(flags);
554 }
555
556 static void spi_setbaudrate(
557         UNUSED_ARG(struct SerialHardware *, _hw),
558         UNUSED_ARG(unsigned long, rate))
559 {
560         // nop
561 }
562
563 static void spi_setparity(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(int, parity))
564 {
565         // nop
566 }
567
568 static bool tx_sending(struct SerialHardware* _hw)
569 {
570         struct AvrSerial *hw = (struct AvrSerial *)_hw;
571         return hw->sending;
572 }
573
574
575
576 // FIXME: move into compiler.h?  Ditch?
577 #if COMPILER_C99
578         #define C99INIT(name,val) .name = val
579 #elif defined(__GNUC__)
580         #define C99INIT(name,val) name: val
581 #else
582         #warning No designated initializers, double check your code
583         #define C99INIT(name,val) (val)
584 #endif
585
586 /*
587  * High-level interface data structures
588  */
589 static const struct SerialHardwareVT UART0_VT =
590 {
591         C99INIT(init, uart0_init),
592         C99INIT(cleanup, uart0_cleanup),
593         C99INIT(setBaudrate, uart0_setbaudrate),
594         C99INIT(setParity, uart0_setparity),
595         C99INIT(txStart, uart0_enabletxirq),
596         C99INIT(txSending, tx_sending),
597 };
598
599 #if AVR_HAS_UART1
600 static const struct SerialHardwareVT UART1_VT =
601 {
602         C99INIT(init, uart1_init),
603         C99INIT(cleanup, uart1_cleanup),
604         C99INIT(setBaudrate, uart1_setbaudrate),
605         C99INIT(setParity, uart1_setparity),
606         C99INIT(txStart, uart1_enabletxirq),
607         C99INIT(txSending, tx_sending),
608 };
609 #endif // AVR_HAS_UART1
610
611 static const struct SerialHardwareVT SPI_VT =
612 {
613         C99INIT(init, spi_init),
614         C99INIT(cleanup, spi_cleanup),
615         C99INIT(setBaudrate, spi_setbaudrate),
616         C99INIT(setParity, spi_setparity),
617         C99INIT(txStart, spi_starttx),
618         C99INIT(txSending, tx_sending),
619 };
620
621 static struct AvrSerial UARTDescs[SER_CNT] =
622 {
623         {
624                 C99INIT(hw, /**/) {
625                         C99INIT(table, &UART0_VT),
626                         C99INIT(txbuffer, uart0_txbuffer),
627                         C99INIT(rxbuffer, uart0_rxbuffer),
628                         C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
629                         C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
630                 },
631                 C99INIT(sending, false),
632         },
633 #if AVR_HAS_UART1
634         {
635                 C99INIT(hw, /**/) {
636                         C99INIT(table, &UART1_VT),
637                         C99INIT(txbuffer, uart1_txbuffer),
638                         C99INIT(rxbuffer, uart1_rxbuffer),
639                         C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
640                         C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
641                 },
642                 C99INIT(sending, false),
643         },
644 #endif
645         {
646                 C99INIT(hw, /**/) {
647                         C99INIT(table, &SPI_VT),
648                         C99INIT(txbuffer, spi_txbuffer),
649                         C99INIT(rxbuffer, spi_rxbuffer),
650                         C99INIT(txbuffer_size, sizeof(spi_txbuffer)),
651                         C99INIT(rxbuffer_size, sizeof(spi_rxbuffer)),
652                 },
653                 C99INIT(sending, false),
654         }
655 };
656
657 struct SerialHardware *ser_hw_getdesc(int unit)
658 {
659         ASSERT(unit < SER_CNT);
660         return &UARTDescs[unit].hw;
661 }
662
663
664 /*
665  * Interrupt handlers
666  */
667
668 #if CONFIG_SER_HWHANDSHAKE
669
670 /// This interrupt is triggered when the CTS line goes high
671 SIGNAL(SIG_CTS)
672 {
673         // Re-enable UDR empty interrupt and TX, then disable CTS interrupt
674         UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
675         EIMSK &= ~EIMSKF_CTS;
676 }
677
678 #endif // CONFIG_SER_HWHANDSHAKE
679
680
681 /**
682  * Serial 0 TX interrupt handler
683  */
684 SIGNAL(USART0_UDRE_vect)
685 {
686         SER_STROBE_ON;
687
688         struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
689
690         if (fifo_isempty(txfifo))
691         {
692                 SER_UART0_BUS_TXEND;
693 #ifndef SER_UART0_BUS_TXOFF
694                 UARTDescs[SER_UART0].sending = false;
695 #endif
696         }
697 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103
698         else if (!IS_CTS_ON)
699         {
700                 // Disable rx interrupt and tx, enable CTS interrupt
701                 // UNTESTED
702                 UCSR0B = BV(RXCIE) | BV(RXEN) | BV(TXEN);
703                 EIFR |= EIMSKF_CTS;
704                 EIMSK |= EIMSKF_CTS;
705         }
706 #endif
707         else
708         {
709                 char c = fifo_pop(txfifo);
710                 SER_UART0_BUS_TXCHAR(c);
711         }
712
713         SER_STROBE_OFF;
714 }
715
716 #ifdef SER_UART0_BUS_TXOFF
717 /**
718  * Serial port 0 TX complete interrupt handler.
719  *
720  * This IRQ is usually disabled.  The UDR-empty interrupt
721  * enables it when there's no more data to transmit.
722  * We need to wait until the last character has been
723  * transmitted before switching the 485 transceiver to
724  * receive mode.
725  *
726  * The txfifo might have been refilled by putchar() while
727  * we were waiting for the transmission complete interrupt.
728  * In this case, we must restart the UDR empty interrupt,
729  * otherwise we'd stop the serial port with some data
730  * still pending in the buffer.
731  */
732 SIGNAL(SIG_UART0_TRANS)
733 {
734         SER_STROBE_ON;
735
736         struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
737         if (fifo_isempty(txfifo))
738         {
739                 SER_UART0_BUS_TXOFF;
740                 UARTDescs[SER_UART0].sending = false;
741         }
742         else
743                 UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
744
745         SER_STROBE_OFF;
746 }
747 #endif /* SER_UART0_BUS_TXOFF */
748
749
750 #if AVR_HAS_UART1
751
752 /**
753  * Serial 1 TX interrupt handler
754  */
755 SIGNAL(USART1_UDRE_vect)
756 {
757         SER_STROBE_ON;
758
759         struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
760
761         if (fifo_isempty(txfifo))
762         {
763                 SER_UART1_BUS_TXEND;
764 #ifndef SER_UART1_BUS_TXOFF
765                 UARTDescs[SER_UART1].sending = false;
766 #endif
767         }
768 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103
769         else if (!IS_CTS_ON)
770         {
771                 // Disable rx interrupt and tx, enable CTS interrupt
772                 // UNTESTED
773                 UCSR1B = BV(RXCIE) | BV(RXEN) | BV(TXEN);
774                 EIFR |= EIMSKF_CTS;
775                 EIMSK |= EIMSKF_CTS;
776         }
777 #endif
778         else
779         {
780                 char c = fifo_pop(txfifo);
781                 SER_UART1_BUS_TXCHAR(c);
782         }
783
784         SER_STROBE_OFF;
785 }
786
787 #ifdef SER_UART1_BUS_TXOFF
788 /**
789  * Serial port 1 TX complete interrupt handler.
790  *
791  * \sa port 0 TX complete handler.
792  */
793 SIGNAL(SIG_UART1_TRANS)
794 {
795         SER_STROBE_ON;
796
797         struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
798         if (fifo_isempty(txfifo))
799         {
800                 SER_UART1_BUS_TXOFF;
801                 UARTDescs[SER_UART1].sending = false;
802         }
803         else
804                 UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
805
806         SER_STROBE_OFF;
807 }
808 #endif /* SER_UART1_BUS_TXOFF */
809
810 #endif // AVR_HAS_UART1
811
812
813 /**
814  * Serial 0 RX complete interrupt handler.
815  *
816  * This handler is interruptible.
817  * Interrupt are reenabled as soon as recv complete interrupt is
818  * disabled. Using INTERRUPT() is troublesome when the serial
819  * is heavily loaded, because an interrupt could be retriggered
820  * when executing the handler prologue before RXCIE is disabled.
821  *
822  * \note The code that re-enables interrupts is commented out
823  *       because in some nasty cases the interrupt is retriggered.
824  *       This is probably due to the RXC flag being set before
825  *       RXCIE is cleared.  Unfortunately the RXC flag is read-only
826  *       and can't be cleared by code.
827  */
828 SIGNAL(USART0_RX_vect)
829 {
830         SER_STROBE_ON;
831
832         /* Disable Recv complete IRQ */
833         //UCSR0B &= ~BV(RXCIE);
834         //IRQ_ENABLE;
835
836         /* Should be read before UDR */
837         ser_uart0->status |= UCSR0A & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
838
839         /* To clear the RXC flag we must _always_ read the UDR even when we're
840          * not going to accept the incoming data, otherwise a new interrupt
841          * will occur once the handler terminates.
842          */
843         char c = UDR0;
844         struct FIFOBuffer * const rxfifo = &ser_uart0->rxfifo;
845
846         if (fifo_isfull(rxfifo))
847                 ser_uart0->status |= SERRF_RXFIFOOVERRUN;
848         else
849         {
850                 fifo_push(rxfifo, c);
851 #if CONFIG_SER_HWHANDSHAKE
852                 if (fifo_isfull(rxfifo))
853                         RTS_OFF;
854 #endif
855         }
856
857         /* Reenable receive complete int */
858         //IRQ_DISABLE;
859         //UCSR0B |= BV(RXCIE);
860
861         SER_STROBE_OFF;
862 }
863
864
865 #if AVR_HAS_UART1
866
867 /**
868  * Serial 1 RX complete interrupt handler.
869  *
870  * This handler is interruptible.
871  * Interrupt are reenabled as soon as recv complete interrupt is
872  * disabled. Using INTERRUPT() is troublesome when the serial
873  * is heavily loaded, because an interrupt could be retriggered
874  * when executing the handler prologue before RXCIE is disabled.
875  *
876  * \see SIGNAL(USART1_RX_vect)
877  */
878 SIGNAL(USART1_RX_vect)
879 {
880         SER_STROBE_ON;
881
882         /* Disable Recv complete IRQ */
883         //UCSR1B &= ~BV(RXCIE);
884         //IRQ_ENABLE;
885
886         /* Should be read before UDR */
887         ser_uart1->status |= UCSR1A & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
888
889         /* To avoid an IRQ storm, we must _always_ read the UDR even when we're
890          * not going to accept the incoming data
891          */
892         char c = UDR1;
893         struct FIFOBuffer * const rxfifo = &ser_uart1->rxfifo;
894         //ASSERT_VALID_FIFO(rxfifo);
895
896         if (UNLIKELY(fifo_isfull(rxfifo)))
897                 ser_uart1->status |= SERRF_RXFIFOOVERRUN;
898         else
899         {
900                 fifo_push(rxfifo, c);
901 #if CONFIG_SER_HWHANDSHAKE
902                 if (fifo_isfull(rxfifo))
903                         RTS_OFF;
904 #endif
905         }
906         /* Re-enable receive complete int */
907         //IRQ_DISABLE;
908         //UCSR1B |= BV(RXCIE);
909
910         SER_STROBE_OFF;
911 }
912
913 #endif // AVR_HAS_UART1
914
915
916 /**
917  * SPI interrupt handler
918  */
919 SIGNAL(SIG_SPI)
920 {
921         SER_STROBE_ON;
922
923         /* Read incoming byte. */
924         if (!fifo_isfull(&ser_spi->rxfifo))
925                 fifo_push(&ser_spi->rxfifo, SPDR);
926         /*
927          * FIXME
928         else
929                 ser_spi->status |= SERRF_RXFIFOOVERRUN;
930         */
931
932         /* Send */
933         if (!fifo_isempty(&ser_spi->txfifo))
934                 SPDR = fifo_pop(&ser_spi->txfifo);
935         else
936                 UARTDescs[SER_SPI].sending = false;
937
938         SER_STROBE_OFF;
939 }