Contiki 2.6

uart2.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 u2_tx_buf[UART2_TX_BUFFERSIZE];
00040 volatile uint32_t u2_tx_head, u2_tx_tail;
00041 
00042 #if UART2_RX_BUFFERSIZE > 32
00043 volatile char u2_rx_buf[UART2_RX_BUFFERSIZE-32];
00044 volatile uint32_t u2_rx_head, u2_rx_tail;
00045 #endif
00046 
00047 void uart2_isr(void) {
00048 
00049 #if UART2_RX_BUFFERSIZE > 32
00050         if (*UART2_USTAT & ( 1 << 6)) {   //receive interrupt
00051                 while( *UART2_URXCON != 0 ) {   //flush the hardware fifo into the software buffer
00052                         uint32_t u2_rx_tail_next;
00053                         u2_rx_tail_next = u2_rx_tail+1;
00054                         if (u2_rx_tail_next >= sizeof(u2_rx_buf))
00055                                 u2_rx_tail_next = 0;
00056                         if (u2_rx_head != u2_rx_tail_next) {
00057                                 u2_rx_buf[u2_rx_tail]= *UART2_UDATA;
00058                                 u2_rx_tail =  u2_rx_tail_next;
00059                         } else {  //buffer is full, flush the fifo
00060                                 while (*UART2_URXCON !=0) if (*UART2_UDATA);
00061                         }
00062                 }
00063                 return;
00064         }
00065 #endif
00066 
00067         while( *UART2_UTXCON != 0 ) {
00068                 if (u2_tx_head == u2_tx_tail) {
00069 #if UART2_RX_BUFFERSIZE > 32
00070             *UART2_UCON |= (1 << 13); /*disable tx interrupt */
00071 #else
00072                         disable_irq(UART2);
00073 #endif
00074                         return;
00075                 }
00076 
00077                 *UART2_UDATA = u2_tx_buf[u2_tx_tail];
00078                 u2_tx_tail++;
00079                 if (u2_tx_tail >= sizeof(u2_tx_buf))
00080                         u2_tx_tail = 0;
00081         }
00082 }
00083 
00084 void uart2_putc(char c) {
00085         /* disable UART2 since */
00086         /* UART2 isr modifies u2_tx_head and u2_tx_tail */
00087 #if UART2_RX_BUFFERSIZE > 32
00088             *UART2_UCON |= (1 << 13); /*disable tx interrupt */
00089 #else
00090                         disable_irq(UART2);
00091 #endif
00092 
00093         if( (u2_tx_head == u2_tx_tail) &&
00094             (*UART2_UTXCON != 0)) {
00095                 *UART2_UDATA = c;
00096         } else {
00097                 u2_tx_buf[u2_tx_head] = c;
00098                 u2_tx_head += 1;
00099                 if (u2_tx_head >= sizeof(u2_tx_buf))
00100                         u2_tx_head = 0;
00101                 if (u2_tx_head == u2_tx_tail) { /* drop chars when no room */
00102 #if UART2_DROP_CHARS
00103                         if (u2_tx_head) { u2_tx_head -=1; } else { u2_tx_head = sizeof(u2_tx_buf); }
00104 #else
00105                         {
00106                                 uint32_t  u2_tx_tail_save=u2_tx_tail;
00107                                 /* Back up head to show buffer not empty, and enable tx interrupt */
00108                                 u2_tx_head--;
00109 #if UART2_RX_BUFFERSIZE > 32
00110                                 *UART2_UCON &= ~(1 << 13); /*enable tx interrupt */
00111 #else
00112                                 enable_irq(UART2);
00113 #endif
00114                                 /* Tail will change after one character goes out */
00115                                 while (u2_tx_tail_save == u2_tx_tail) ;
00116                                 /* Restore head to character we just stuffed */
00117                                 u2_tx_head++;
00118                                 return;
00119                         }
00120 #endif /* UART2_DROP_CHARS */
00121                 }
00122 
00123 #if UART2_RX_BUFFERSIZE > 32
00124                 *UART2_UCON &= ~(1 << 13); /*enable tx interrupt */
00125 #else
00126                 enable_irq(UART2);
00127 #endif
00128 
00129         }
00130 }
00131 
00132 uint8_t uart2_getc(void) {
00133 #if UART2_RX_BUFFERSIZE > 32
00134 /* First pull from the ram buffer */
00135 uint8_t c=0;
00136   if (u2_rx_head != u2_rx_tail) {
00137     c = u2_rx_buf[u2_rx_head++];
00138     if (u2_rx_head >= sizeof(u2_rx_buf))
00139         u2_rx_head=0;
00140     return c;
00141   }
00142 #endif
00143 /* Then pull from the hardware fifo */
00144         while(uart2_can_get() == 0) { continue; }
00145         return *UART2_UDATA;
00146 }