Add dual-license information.
[bertos.git] / drv / ser_avr.c
index c3bab672a356e0197e3d4013324d4ea080cea135..9e417cc9b40b4e8b95cfef96b8ff1b2827809e62 100755 (executable)
@@ -1,9 +1,9 @@
-/**
+/*!
  * \file
  * <!--
  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
- * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
- * All Rights Reserved.
+ * Copyright 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See devlib/README for information.
  * -->
  *
  * \version $Id$
 
 /*
  * $Log$
- * Revision 1.1  2004/05/23 18:10:11  bernie
- * Import drv/ modules.
- *
- * Revision 1.30  2004/05/19 17:06:11  bernie
- * Serial TX fill mode
- *
- * Revision 1.29  2004/05/16 19:16:46  aleph
- * Serial always transmitting, first try
- *
- * Revision 1.28  2004/05/14 12:09:00  aleph
- * Fix TX port pull-ups
+ * Revision 1.4  2004/06/03 11:27:09  bernie
+ * Add dual-license information.
  *
- * Revision 1.27  2004/05/08 13:56:02  aleph
- * Adapt avr serial driver to new design
+ * Revision 1.3  2004/06/02 21:35:24  aleph
+ * Serial enhancements: interruptible receive handler and 8 bit serial status for AVR; remove volatile attribute to FIFOBuffer, useless for new fifobuf routens
  *
- * Revision 1.25  2004/04/28 13:42:16  aleph
- * Serial port fixes
+ * Revision 1.2  2004/05/23 18:21:53  bernie
+ * Trim CVS logs and cleanup header info.
  *
- * Revision 1.24  2004/04/08 14:17:27  bernie
- * Change serial to disable TX when not sending data
- *
- * Revision 1.23  2004/04/03 20:39:41  aleph
- * Remove strobe
- *
- * Revision 1.22  2004/03/29 17:01:02  aleph
- * Add function to set serial parity, fix it when ser_open is used
  */
 
 #include "ser.h"
@@ -76,14 +59,14 @@ struct AvrSerial
 
 #ifdef __AVR_ATmega103__
        /* Macro for ATmega103 compatibility */
-       #define UCSR0B UCR 
-       #define UDR0   UDR 
-       #define UCSR0A USR 
+       #define UCSR0B UCR
+       #define UDR0   UDR
+       #define UCSR0A USR
        #define UBRR0L UBRR
 #else
-       #define UCR  UCSR0B 
-       #define UDR  UDR0  
-       #define USR  UCSR0A 
+       #define UCR  UCSR0B
+       #define UDR  UDR0
+       #define USR  UCSR0A
 #endif
 
 
@@ -307,7 +290,13 @@ SIGNAL(SIG_UART1_DATA)
 
 
 /*!
- * Serial 0 RX complete interrupt handler
+ * Serial 0 RX complete interrupt handler.
+ *
+ * This handler is interruptible.
+ * Interrupt are reenabled as soon as recv complete interrupt is
+ * disabled. Using INTERRUPT() is troublesome when the serial
+ * is heavily loaded, because and interrupt could be retriggered
+ * when executing the handler prologue before RXCIE is disabled.
  */
 #ifdef __AVR_ATmega103__
 SIGNAL(SIG_UART_RECV)
@@ -315,6 +304,10 @@ SIGNAL(SIG_UART_RECV)
 SIGNAL(SIG_UART0_RECV)
 #endif
 {
+       /* Disable Recv complete IRQ */
+       UCR &= ~BV(RXCIE);
+       ENABLE_INTS;
+
        /* Should be read before UDR */
        ser_handles[SER_UART0].status |= USR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
 
@@ -334,14 +327,26 @@ SIGNAL(SIG_UART0_RECV)
                        RTS_OFF;
 #endif
        }
+       /* Reenable receive complete int */
+       UCR |= BV(RXCIE);
 }
 
 /*!
- * Serial 1 RX complete interrupt handler
+ * Serial 1 RX complete interrupt handler.
+ *
+ * This handler is interruptible.
+ * Interrupt are reenabled as soon as recv complete interrupt is
+ * disabled. Using INTERRUPT() is troublesome when the serial
+ * is heavily loaded, because and interrupt could be retriggered
+ * when executing the handler prologue before RXCIE is disabled.
  */
 #ifndef __AVR_ATmega103__
 SIGNAL(SIG_UART1_RECV)
 {
+       /* Disable Recv complete IRQ */
+       UCSR0B &= ~BV(RXCIE);
+       ENABLE_INTS;
+
        /* Should be read before UDR */
        ser_handles[SER_UART1].status |= UCSR1A & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
 
@@ -360,6 +365,8 @@ SIGNAL(SIG_UART1_RECV)
                        RTS_OFF;
 #endif
        }
+       /* Reenable receive complete int */
+       UCSR0B |= BV(RXCIE);
 }
 #endif /* !__AVR_ATmega103__ */
 
@@ -384,7 +391,7 @@ static void spi_starttx(UNUSED(struct SerialHardware *ctx))
        /* Send data only if the SPI is not already transmitting */
        if (!spi_sending && !fifo_isempty(&ser_handles[SER_SPI].txfifo))
        {
-               SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo); 
+               SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo);
                spi_sending = true;
        }
 
@@ -420,12 +427,12 @@ __interrupt void UART_TXC_interrupt(void)
 {
   UCSRB &= ~TXCIE;
   ReceiveMode();
-  UCSRB = RXCIE | RXEN | TXEN;  //Abilito l'Interrupt in ricezione e RX e TX  
+  UCSRB = RXCIE | RXEN | TXEN;  //Abilito l'Interrupt in ricezione e RX e TX
 }
 */
 
 
-static const struct SerialHardwareVT UART0_VT = 
+static const struct SerialHardwareVT UART0_VT =
 {
        .init = uart0_init,
        .cleanup = uart0_cleanup,
@@ -434,7 +441,7 @@ static const struct SerialHardwareVT UART0_VT =
        .enabletxirq = uart0_enabletxirq,
 };
 
-static const struct SerialHardwareVT UART1_VT = 
+static const struct SerialHardwareVT UART1_VT =
 {
        .init = uart1_init,
        .cleanup = uart1_cleanup,
@@ -443,7 +450,7 @@ static const struct SerialHardwareVT UART1_VT =
        .enabletxirq = uart1_enabletxirq,
 };
 
-static const struct SerialHardwareVT SPI_VT = 
+static const struct SerialHardwareVT SPI_VT =
 {
        .init = spi_init,
        .cleanup = spi_cleanup,
@@ -452,17 +459,17 @@ static const struct SerialHardwareVT SPI_VT =
 
 static struct AvrSerial UARTDescs[SER_CNT] =
 {
-       { 
-               .hw = { .table = &UART0_VT }, 
-       },
-       
-       { 
-               .hw = { .table = &UART1_VT }, 
-       },  
-
-       { 
-               .hw = { .table = &SPI_VT }, 
-       },  
+       {
+               .hw = { .table = &UART0_VT },
+       },
+
+       {
+               .hw = { .table = &UART1_VT },
+       },
+
+       {
+               .hw = { .table = &SPI_VT },
+       },
 };
 
 struct SerialHardware* ser_hw_getdesc(int unit)