uart1.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of libmc1322x: see http://mc1322x.devl.org
00031  * for details. 
00032  *
00033  *
00034  */
00035 
00036 #include <mc1322x.h>
00037 #include <stdint.h>
00038 
00039 volatile char u1_tx_buf[UART1_TX_BUFFERSIZE];
00040 volatile uint32_t u1_tx_head, u1_tx_tail;
00041 
00042 #if UART1_RX_BUFFERSIZE > 32
00043 volatile char u1_rx_buf[UART1_RX_BUFFERSIZE-32];
00044 volatile uint16_t u1_rx_head, u1_rx_tail,u1_rx_hyst;
00045 #endif
00046 
00047 void uart1_isr(void) {
00048 
00049 #if UART1_RX_BUFFERSIZE > 32
00050   if (*UART1_USTAT & ( 1 << 6)) {   //receive interrupt
00051         while( *UART1_URXCON != 0 ) {   //flush the hardware fifo into the software buffer
00052         uint32_t u1_rx_tail_next;
00053         u1_rx_tail_next = u1_rx_tail+1;         
00054                 if (u1_rx_tail_next >= sizeof(u1_rx_buf))
00055                         u1_rx_tail_next = 0;
00056         if (u1_rx_head != u1_rx_tail_next) {
00057                     u1_rx_buf[u1_rx_tail]= *UART1_UDATA;       
00058                     u1_rx_tail =  u1_rx_tail_next;
00059         } else {                                        //RAM buffer is full
00060                         *UART1_UCON |= (1<<14); //disable rx interrupt until room for another complete flush
00061                         /* this 30 is the fifo trigger set in default_lowlevel.c */
00062                         if (sizeof(u1_rx_buf)>30) u1_rx_hyst=30;else u1_rx_hyst=sizeof(u1_rx_buf);
00063                         return;                                 //hopefully flow control will take over
00064                 }
00065         }
00066     return;
00067   }
00068 #endif
00069 
00070         while( *UART1_UTXCON != 0 ) {
00071                 if (u1_tx_head == u1_tx_tail) {
00072 #if UART1_RX_BUFFERSIZE > 32
00073             *UART1_UCON |= (1 << 13); /*disable tx interrupt */
00074 #else
00075                         disable_irq(UART1);
00076 #endif
00077                         return;
00078                 }
00079 
00080                 *UART1_UDATA = u1_tx_buf[u1_tx_tail];
00081                 u1_tx_tail++;           
00082                 if (u1_tx_tail >= sizeof(u1_tx_buf))
00083                         u1_tx_tail = 0;
00084         }
00085 }
00086 
00087 void uart1_putc(char c) {
00088         /* disable UART1 since */
00089         /* UART1 isr modifies u1_tx_head and u1_tx_tail */ 
00090 #if UART1_RX_BUFFERSIZE > 32
00091             *UART1_UCON |= (1 << 13); /*disable tx interrupt */
00092 #else
00093                         disable_irq(UART1);
00094 #endif
00095 
00096         if( (u1_tx_head == u1_tx_tail) &&
00097             (*UART1_UTXCON != 0)) {
00098                 *UART1_UDATA = c;
00099         } else {
00100                 u1_tx_buf[u1_tx_head] = c;
00101                 u1_tx_head += 1;
00102                 if (u1_tx_head >= sizeof(u1_tx_buf))
00103                         u1_tx_head = 0;
00104                 if (u1_tx_head == u1_tx_tail) { /* drop chars when no room */
00105                         if (u1_tx_head) { u1_tx_head -=1; } else { u1_tx_head = sizeof(u1_tx_buf); }
00106                 }
00107 
00108 #if UART1_RX_BUFFERSIZE > 32
00109         *UART1_UCON &= ~(1 << 13); /*enable tx interrupt */
00110 #else
00111                 enable_irq(UART1);
00112 #endif
00113 
00114         }
00115 }
00116 
00117 uint8_t uart1_getc(void) {
00118 #if UART1_RX_BUFFERSIZE > 32
00119 uint8_t c=0;
00120 /* First pull from the ram buffer */
00121   if (u1_rx_head != u1_rx_tail) {
00122     c = u1_rx_buf[u1_rx_head++];
00123     if (u1_rx_head >= sizeof(u1_rx_buf))
00124         u1_rx_head=0;
00125         if (u1_rx_hyst) {                       //emptying RAM buffer after near overflow
00126           if (--u1_rx_hyst == 0)
00127                 *UART1_UCON &= ~(1<<14);        //enable rx interrupt when enough room for fifo
00128         }
00129         return c;
00130   }
00131 #endif
00132 /* Then pull from the hardware fifo */
00133 //      if (*UART1_URXCON > 0)
00134         return *UART1_UDATA;
00135 }

Generated on Mon Apr 11 14:23:38 2011 for Contiki 2.5 by  doxygen 1.6.1