Declaration fix for build with GCC 3.4
[bertos.git] / drv / ser_avr.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
5  * Copyright 2003,2004 Develer S.r.l. (http://www.develer.com/)
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief AVR UART and SPI I/O driver
14  */
15
16 /*
17  * $Log$
18  * Revision 1.5  2004/06/27 15:25:40  aleph
19  * Add missing callbacks for SPI;
20  * Change UNUSED() macro to new version with two args;
21  * Use TX line filling only on the correct KBUS serial port;
22  * Fix nasty IRQ disabling bug in recv complete hander for port 1.
23  *
24  * Revision 1.4  2004/06/03 11:27:09  bernie
25  * Add dual-license information.
26  *
27  * Revision 1.3  2004/06/02 21:35:24  aleph
28  * Serial enhancements: interruptible receive handler and 8 bit serial status for AVR; remove volatile attribute to FIFOBuffer, useless for new fifobuf routens
29  *
30  * Revision 1.2  2004/05/23 18:21:53  bernie
31  * Trim CVS logs and cleanup header info.
32  *
33  */
34
35 #include "ser.h"
36 #include "ser_p.h"
37 #include "kdebug.h"
38 #include "config.h"
39 #include "hw.h"
40 #include <mware/fifobuf.h>
41
42 extern struct Serial ser_handles[SER_CNT];
43
44 struct AvrSerial
45 {
46         struct SerialHardware hw;
47         struct Serial* serial;
48 };
49
50
51 /* Hardware handshake */
52 #define RTS_ON
53 #define RTS_OFF
54 #define IS_CTS_ON   true
55 #define IS_CTS_OFF  false
56
57
58 /* SPI port and pin configuration */
59 #define SPI_PORT      PORTB
60 #define SPI_DDR       DDRB
61 #define SPI_SCK_BIT   PORTB1
62 #define SPI_MOSI_BIT  PORTB2
63 #define SPI_MISO_BIT  PORTB3
64
65
66 #ifdef __AVR_ATmega103__
67         /* Macro for ATmega103 compatibility */
68         #define UCSR0B UCR
69         #define UDR0   UDR
70         #define UCSR0A USR
71         #define UBRR0L UBRR
72 #else
73         #define UCR  UCSR0B
74         #define UDR  UDR0
75         #define USR  UCSR0A
76 #endif
77
78
79 /* Transmission fill byte */
80 #define SER_FILL_BYTE 0xAA
81
82
83 static void uart0_enabletxirq(UNUSED(struct SerialHardware *, ctx))
84 {
85 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 0)
86         UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN) | BV(UCSZ2);
87 #else
88         UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
89 #endif
90 }
91
92 static void uart0_init(struct SerialHardware *_hw, struct Serial *ser)
93 {
94         struct AvrSerial *hw = (struct AvrSerial *)_hw;
95         hw->serial = ser;
96
97         /* Set TX port as input with pull-up enabled to avoid
98          * noise on the remote RX when TX is disabled */
99         cpuflags_t flags;
100         DISABLE_IRQSAVE(flags);
101         DDRE &= ~BV(PORTE1);
102         PORTE |= BV(PORTE1);
103         ENABLE_IRQRESTORE(flags);
104
105         /* TODO: explain why TX is disabled whenever possible */
106 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 0)
107         /*!
108          * Set multiprocessor mode and 9 bit data frame.
109          * The receiver keep MPCM bit always on. When useful data
110          * is trasmitted the ninth bit is set. Receiver consider the
111          * frame as address info and receive it.
112          * When useless fill bytes are sent the ninth bit is cleared
113          * and the receiver will ignore them, avoiding useless triggering
114          * of RXC interrupt.
115          */
116         UCSR0A = BV(MPCM);
117         UCSR0B = BV(RXCIE) | BV(RXEN) | BV(UCSZ2);
118 #else
119         UCSR0B = BV(RXCIE) | BV(RXEN);
120 #endif
121
122         RTS_ON;
123 }
124
125 static void uart0_cleanup(UNUSED(struct SerialHardware *, ctx))
126 {
127         UCSR0B = 0;
128 }
129
130 static void uart0_setbaudrate(UNUSED(struct SerialHardware *, ctx), unsigned long rate)
131 {
132         // Compute baud-rate period
133         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
134
135 #ifndef __AVR_ATmega103__
136         UBRR0H = (period) >> 8;
137 #endif
138         UBRR0L = (period);
139 }
140
141
142 #ifndef __AVR_ATmega103__
143
144 static void uart1_enabletxirq(UNUSED(struct SerialHardware *, ctx))
145 {
146 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 1)
147         UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN) | BV(UCSZ2);
148 #else
149         UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
150 #endif
151 }
152
153 static void uart1_init(struct SerialHardware *_hw, struct Serial *ser)
154 {
155         struct AvrSerial *hw = (struct AvrSerial *)_hw;
156         hw->serial = ser;
157
158         /* Set TX port as input with pull-up enabled to avoid
159          * noise on the remote RX when TX is disabled */
160         cpuflags_t flags;
161         DISABLE_IRQSAVE(flags);
162         DDRD &= ~BV(PORTD3);
163         PORTD |= BV(PORTD3);
164         ENABLE_IRQRESTORE(flags);
165
166         /* TODO: explain why TX is disabled whenever possible */
167 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 1)
168         /*!  * See comment in uart0_init() */
169         UCSR1A = BV(MPCM);
170         UCSR1B = BV(RXCIE) | BV(RXEN) | BV(UCSZ2);
171 #else
172         UCSR1B = BV(RXCIE) | BV(RXEN);
173 #endif
174
175         RTS_ON;
176 }
177
178 static void uart1_cleanup(UNUSED(struct SerialHardware *, ctx))
179 {
180         UCSR1B = 0;
181 }
182
183 static void uart1_setbaudrate(UNUSED(struct SerialHardware *, ctx), unsigned long rate)
184 {
185         // Compute baud-rate period
186         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
187
188         UBRR1H = (period) >> 8;
189         UBRR1L = (period);
190 }
191
192 static void uart0_setparity(UNUSED(struct SerialHardware *, ctx), int parity)
193 {
194         UCSR0C |= (parity) << UPM0;
195 }
196
197 static void uart1_setparity(UNUSED(struct SerialHardware *, ctx), int parity)
198 {
199         UCSR1C |= (parity) << UPM0;
200 }
201
202 #endif /* !__AVR_ATmega103__ */
203
204
205 static void spi_init(struct SerialHardware *_hw, struct Serial *ser)
206 {
207         struct AvrSerial *hw = (struct AvrSerial *)_hw;
208         hw->serial = ser;
209
210         /* MOSI and SCK out, MISO in */
211         SPI_DDR |= BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT);
212         SPI_DDR &= ~BV(SPI_MISO_BIT);
213         /* Enable SPI, IRQ on, Master, CPU_CLOCK/16 */
214         SPCR = BV(SPE) | BV(SPIE) | BV(MSTR) | BV(SPR0);
215 }
216
217 static void spi_cleanup(UNUSED(struct SerialHardware *, ctx))
218 {
219         SPCR = 0;
220         /* Set all pins as inputs */
221         SPI_DDR &= ~(BV(SPI_MISO_BIT) | BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT));
222 }
223
224 static void spi_setbaudrate(UNUSED(struct SerialHardware *, ctx), UNUSED(unsigned long, rate))
225 {
226         // Do nothing
227 }
228
229 static void spi_setparity(UNUSED(struct SerialHardware *, ctx), UNUSED(int, parity))
230 {
231         // Do nothing
232 }
233
234
235
236 #if defined(CONFIG_SER_HW_HANDSHAKE)
237
238 //! This interrupt is triggered when the CTS line goes high
239 SIGNAL(SIG_CTS)
240 {
241         // Re-enable UDR empty interrupt and TX, then disable CTS interrupt
242         UCR = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
243         cbi(EIMSK, EIMSKB_CTS);
244 }
245
246 #endif // CONFIG_SER_HW_HANDSHAKE
247
248
249 /*!
250  * Serial 0 TX interrupt handler
251  */
252 #ifdef __AVR_ATmega103__
253 SIGNAL(SIG_UART_DATA)
254 #else
255 SIGNAL(SIG_UART0_DATA)
256 #endif
257 {
258         if (fifo_isempty(&ser_handles[SER_UART0].txfifo))
259         {
260 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 0)
261                 /*
262                  * To avoid audio interference: always transmit useless char.
263                  * Send the byte with the ninth bit cleared, the receiver in MCPM mode
264                  * will ignore it.
265                  */
266                 UCSR0B &= ~BV(TXB8);
267                 UDR0 = SER_FILL_BYTE;
268 #else
269                 /* Disable UDR empty interrupt and transmitter */
270                 UCR = BV(RXCIE) | BV(RXEN);
271 #endif
272         }
273 #if defined(CONFIG_SER_HWHANDSHAKE)
274         else if (IS_CTS_OFF)
275         {
276                 // disable rx interrupt and tx, enable CTS interrupt
277                 UCR = BV(RXCIE) | BV(RXEN);
278                 sbi(EIFR, EIMSKB_CTS);
279                 sbi(EIMSK, EIMSKB_CTS);
280         }
281 #endif // CONFIG_SER_HWHANDSHAKE
282         else
283         {
284 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 0)
285                 /* Send with ninth bit set. Receiver in MCPM mode will receive it */
286                 UCSR0B |= BV(TXB8);
287 #endif
288                 UDR = fifo_pop(&ser_handles[SER_UART0].txfifo);
289         }
290 }
291
292 /*!
293  * Serial 1 TX interrupt handler
294  */
295 #ifndef __AVR_ATmega103__
296 SIGNAL(SIG_UART1_DATA)
297 {
298         if (fifo_isempty(&ser_handles[SER_UART1].txfifo))
299         {
300 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 1)
301                 /*
302                  * To avoid audio interference: always transmit useless char.
303                  * Send the byte with the ninth bit cleared, the receiver in MCPM mode
304                  * will ignore it.
305                  */
306                 UCSR1B &= ~BV(TXB8);
307                 UDR1 = SER_FILL_BYTE;
308 #else
309                 /* Disable UDR empty interrupt and transmitter */
310                 UCSR1B = BV(RXCIE) | BV(RXEN);
311 #endif
312         }
313 #if defined(CONFIG_SER_HWHANDSHAKE)
314         else if (IS_CTS_OFF)
315         {
316                 // disable rx interrupt and tx, enable CTS interrupt
317                 UCSR1B = BV(RXCIE) | BV(RXEN);
318                 sbi(EIFR, EIMSKB_CTS);
319                 sbi(EIMSK, EIMSKB_CTS);
320         }
321 #endif // CONFIG_SER_HWHANDSHAKE
322         else
323         {
324 #if defined(CONFIG_SER_TXFILL) && (CONFIG_KBUS_SERIAL_PORT == 1)
325                 /* Send with ninth bit set. Receiver in MCPM mode will receive it */
326                 UCSR1B |= BV(TXB8);
327 #endif
328                 UDR1 = fifo_pop(&ser_handles[SER_UART1].txfifo);
329         }
330 }
331 #endif /* !__AVR_ATmega103__ */
332
333
334 /*!
335  * Serial 0 RX complete interrupt handler.
336  *
337  * This handler is interruptible.
338  * Interrupt are reenabled as soon as recv complete interrupt is
339  * disabled. Using INTERRUPT() is troublesome when the serial
340  * is heavily loaded, because and interrupt could be retriggered
341  * when executing the handler prologue before RXCIE is disabled.
342  */
343 #ifdef __AVR_ATmega103__
344 SIGNAL(SIG_UART_RECV)
345 #else
346 SIGNAL(SIG_UART0_RECV)
347 #endif
348 {
349         /* Disable Recv complete IRQ */
350         UCR &= ~BV(RXCIE);
351         ENABLE_INTS;
352
353         /* Should be read before UDR */
354         ser_handles[SER_UART0].status |= USR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
355
356         /* To clear the RXC flag we must _always_ read the UDR even when we're
357          * not going to accept the incoming data, otherwise a new interrupt
358          * will occur once the handler terminates.
359          */
360         char c = UDR;
361
362         if (fifo_isfull(&ser_handles[SER_UART0].rxfifo))
363                 ser_handles[SER_UART0].status |= SERRF_RXFIFOOVERRUN;
364         else
365         {
366                 fifo_push(&ser_handles[SER_UART0].rxfifo, c);
367 #if defined(CONFIG_SER_HW_HANDSHAKE)
368                 if (fifo_isfull(&ser_handles[SER_UART0].rxfifo))
369                         RTS_OFF;
370 #endif
371         }
372         /* Reenable receive complete int */
373         UCR |= BV(RXCIE);
374 }
375
376 /*!
377  * Serial 1 RX complete interrupt handler.
378  *
379  * This handler is interruptible.
380  * Interrupt are reenabled as soon as recv complete interrupt is
381  * disabled. Using INTERRUPT() is troublesome when the serial
382  * is heavily loaded, because and interrupt could be retriggered
383  * when executing the handler prologue before RXCIE is disabled.
384  */
385 #ifndef __AVR_ATmega103__
386 SIGNAL(SIG_UART1_RECV)
387 {
388         /* Disable Recv complete IRQ */
389         UCSR1B &= ~BV(RXCIE);
390         ENABLE_INTS;
391
392         /* Should be read before UDR */
393         ser_handles[SER_UART1].status |= UCSR1A & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
394
395         /* To avoid an IRQ storm, we must _always_ read the UDR even when we're
396          * not going to accept the incoming data
397          */
398         char c = UDR1;
399
400         if (fifo_isfull(&ser_handles[SER_UART1].rxfifo))
401                 ser_handles[SER_UART1].status |= SERRF_RXFIFOOVERRUN;
402         else
403         {
404                 fifo_push(&ser_handles[SER_UART1].rxfifo, c);
405 #if defined(CONFIG_SER_HW_HANDSHAKE)
406                 if (fifo_isfull(&ser_handles[SER_UART1].rxfifo))
407                         RTS_OFF;
408 #endif
409         }
410         /* Reenable receive complete int */
411         UCSR1B |= BV(RXCIE);
412 }
413 #endif /* !__AVR_ATmega103__ */
414
415
416 /*
417  * SPI Flag: true if we are transmitting/receiving with the SPI.
418  *
419  * This kludge is necessary because the SPI sends and receives bytes
420  * at the same time and the SPI IRQ is unique for send/receive.
421  * The only way to start transmission is to write data in SPDR (this
422  * is done by ser_spi_starttx()). We do this *only* if a transfer is
423  * not already started.
424  */
425 static volatile bool spi_sending = false;
426
427 static void spi_starttx(UNUSED(struct SerialHardware *, ctx))
428 {
429         cpuflags_t flags;
430
431         DISABLE_IRQSAVE(flags);
432
433         /* Send data only if the SPI is not already transmitting */
434         if (!spi_sending && !fifo_isempty(&ser_handles[SER_SPI].txfifo))
435         {
436                 SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo);
437                 spi_sending = true;
438         }
439
440         ENABLE_IRQRESTORE(flags);
441 }
442
443 /*!
444  * SPI interrupt handler
445  */
446 SIGNAL(SIG_SPI)
447 {
448         /* Read incoming byte. */
449         if (!fifo_isfull(&ser_handles[SER_SPI].rxfifo))
450                 fifo_push(&ser_handles[SER_SPI].rxfifo, SPDR);
451         /*
452          * FIXME
453         else
454                 ser_handles[SER_SPI].status |= SERRF_RXFIFOOVERRUN;
455         */
456
457         /* Send */
458         if (!fifo_isempty(&ser_handles[SER_SPI].txfifo))
459                 SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo);
460         else
461                 spi_sending = false;
462 }
463
464
465 /*
466
467 #pragma vector = UART_TXC_vect
468 __interrupt void UART_TXC_interrupt(void)
469 {
470   UCSRB &= ~TXCIE;
471   ReceiveMode();
472   UCSRB = RXCIE | RXEN | TXEN;  //Abilito l'Interrupt in ricezione e RX e TX
473 }
474 */
475
476
477 static const struct SerialHardwareVT UART0_VT =
478 {
479         .init = uart0_init,
480         .cleanup = uart0_cleanup,
481         .setbaudrate = uart0_setbaudrate,
482         .setparity = uart0_setparity,
483         .enabletxirq = uart0_enabletxirq,
484 };
485
486 static const struct SerialHardwareVT UART1_VT =
487 {
488         .init = uart1_init,
489         .cleanup = uart1_cleanup,
490         .setbaudrate = uart1_setbaudrate,
491         .setparity = uart1_setparity,
492         .enabletxirq = uart1_enabletxirq,
493 };
494
495 static const struct SerialHardwareVT SPI_VT =
496 {
497         .init = spi_init,
498         .cleanup = spi_cleanup,
499         .setbaudrate = spi_setbaudrate,
500         .setparity = spi_setparity,
501         .enabletxirq = spi_starttx,
502 };
503
504 static struct AvrSerial UARTDescs[SER_CNT] =
505 {
506         {
507                 .hw = { .table = &UART0_VT },
508         },
509
510         {
511                 .hw = { .table = &UART1_VT },
512         },
513
514         {
515                 .hw = { .table = &SPI_VT },
516         },
517 };
518
519 struct SerialHardware* ser_hw_getdesc(int unit)
520 {
521         ASSERT(unit < SER_CNT);
522         return &UARTDescs[unit].hw;
523 }