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