00001 /* 00002 Copyright 2007, Freie Universitaet Berlin. All rights reserved. 00003 00004 These sources were developed at the Freie Universität Berlin, Computer 00005 Systems and Telematics group. 00006 00007 Redistribution and use in source and binary forms, with or without 00008 modification, are permitted provided that the following conditions are 00009 met: 00010 00011 - Redistributions of source code must retain the above copyright 00012 notice, this list of conditions and the following disclaimer. 00013 00014 - Redistributions in binary form must reproduce the above copyright 00015 notice, this list of conditions and the following disclaimer in the 00016 documentation and/or other materials provided with the distribution. 00017 00018 - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its 00019 contributors may be used to endorse or promote products derived from 00020 this software without specific prior written permission. 00021 00022 This software is provided by FUB and the contributors on an "as is" 00023 basis, without any representations or warranties of any kind, express 00024 or implied including, but not limited to, representations or 00025 warranties of non-infringement, merchantability or fitness for a 00026 particular purpose. In no event shall FUB or contributors be liable 00027 for any direct, indirect, incidental, special, exemplary, or 00028 consequential damages (including, but not limited to, procurement of 00029 substitute goods or services; loss of use, data, or profits; or 00030 business interruption) however caused and on any theory of liability, 00031 whether in contract, strict liability, or tort (including negligence 00032 or otherwise) arising in any way out of the use of this software, even 00033 if advised of the possibility of such damage. 00034 00035 This implementation was developed by the CST group at the FUB. 00036 00037 For documentation and questions please use the web site 00038 http://scatterweb.mi.fu-berlin.de and the mailinglist 00039 scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website). 00040 Berlin, 2007 00041 */ 00042 00043 /** 00044 * @file ScatterWeb.Uart.c 00045 * @addtogroup interfaces 00046 * @brief UART interface 00047 * @author Michael Baar <baar@inf.fu-berlin.de> 00048 * 00049 * UART switch for RS232 and SPI protocols on UART1 written for 00050 * ScatterWeb MSB boards. Compatible to ScatterWeb EOS, 00051 * ScatterWeb Bootload and Contiki. 00052 */ 00053 00054 #include <io.h> 00055 #include <signal.h> 00056 #include <string.h> 00057 #include "dev/msb430-uart1.h" 00058 #include "msp430.h" 00059 #include "dev/lpm.h" 00060 00061 #ifndef U1ME 00062 #define U1ME ME2 00063 #endif 00064 00065 volatile unsigned char uart_mode = UART_MODE_RESET; 00066 volatile unsigned char uart_lockcnt = 0; 00067 volatile uint8_t uart_edge = 0; 00068 00069 static unsigned char uart_speed_br0[UART_NUM_MODES]; 00070 static unsigned char uart_speed_br1[UART_NUM_MODES]; 00071 static unsigned char uart_speed_bmn[UART_NUM_MODES]; 00072 static uart_handler_t uart_handler[UART_NUM_MODES] = {NULL, NULL}; 00073 00074 /*---------------------------------------------------------------------------*/ 00075 static void 00076 uart_configure(unsigned mode) 00077 { 00078 _DINT(); /* disable interrupts */ 00079 00080 UART_WAIT_TXDONE(); /* wait till all buffered data has been transmitted */ 00081 00082 if(mode == UART_MODE_RS232) { 00083 P5OUT |= 0x01; 00084 /* unselect SPI */ 00085 P3SEL |= 0xC0; 00086 /* select rs232 */ 00087 UCTL1 = SWRST | CHAR; /* 8-bit character */ 00088 UTCTL1 |= SSEL1; /* UCLK = MCLK */ 00089 /* activate */ 00090 U1ME |= UTXE1 | URXE1; /* Enable USART1 TXD/RXD */ 00091 } else if(mode == UART_MODE_SPI) { 00092 P3SEL &= ~0xC0; /* unselect RS232 */ 00093 // to SPI mode 00094 UCTL1 = SWRST | CHAR | SYNC | MM; /* 8-bit SPI Master */ 00095 /* 00096 * SMCLK, 3-pin mode, clock idle low, data valid on 00097 * rising edge, UCLK delayed 00098 */ 00099 UTCTL1 |= CKPH | SSEL1 | SSEL0 | STC; /* activate */ 00100 U1ME |= USPIE1; /* Enable USART1 SPI */ 00101 } 00102 00103 /* restore speed settings */ 00104 UBR01 = uart_speed_br0[mode]; /* set baudrate */ 00105 UBR11 = uart_speed_br1[mode]; 00106 UMCTL1 = uart_speed_bmn[mode]; /* set modulation */ 00107 00108 UCTL1 &= ~SWRST; /* clear reset flag */ 00109 _EINT(); /* enable interrupts */ 00110 } 00111 /*---------------------------------------------------------------------------*/ 00112 void 00113 uart_set_speed(unsigned mode, unsigned ubr0, 00114 unsigned ubr1, unsigned umctl) 00115 { 00116 /* store the setting */ 00117 uart_speed_br0[mode] = ubr0; /* baudrate */ 00118 uart_speed_br1[mode] = ubr1; /* baudrate */ 00119 uart_speed_bmn[mode] = umctl; /* modulation */ 00120 00121 /* reconfigure, if mode active */ 00122 if(uart_mode == mode) { 00123 uart_configure(mode); 00124 } 00125 } 00126 /*---------------------------------------------------------------------------*/ 00127 void 00128 uart_set_handler(unsigned mode, uart_handler_t handler) 00129 { 00130 /* store the setting */ 00131 uart_handler[mode] = handler; 00132 if(mode == uart_mode) { 00133 if(handler == NULL) { 00134 IE2 &= ~URXIE1; /* Disable USART1 RX interrupt */ 00135 } else { 00136 IE2 |= URXIE1; /* Enable USART1 RX interrupt */ 00137 } 00138 } 00139 } 00140 /*---------------------------------------------------------------------------*/ 00141 int 00142 uart_lock(unsigned mode) 00143 { 00144 /* already locked? */ 00145 if(uart_mode != mode && uart_lockcnt > 0) { 00146 return 0; 00147 } 00148 00149 /* increase lock count */ 00150 uart_lockcnt++; 00151 /* switch mode (if neccessary) */ 00152 uart_set_mode(mode); 00153 return 1; 00154 } 00155 /*---------------------------------------------------------------------------*/ 00156 int 00157 uart_lock_wait(unsigned mode) 00158 { 00159 while(UART_WAIT_LOCK(mode)) { 00160 _NOP(); 00161 } 00162 return uart_lock(mode); 00163 } 00164 /*---------------------------------------------------------------------------*/ 00165 int 00166 uart_unlock(unsigned mode) 00167 { 00168 if((uart_lockcnt == 0) || (mode != uart_mode)) { 00169 uart_lockcnt = 0; 00170 uart_set_mode(UART_MODE_DEFAULT); 00171 return 0; 00172 } 00173 00174 /* decrement lock */ 00175 if(uart_lockcnt > 0) { 00176 uart_lockcnt--; 00177 /* if no more locks, switch back to default mode */ 00178 if(uart_lockcnt == 0) { 00179 uart_set_mode(UART_MODE_DEFAULT); 00180 } 00181 return 1; 00182 } 00183 return 0; 00184 } 00185 /*---------------------------------------------------------------------------*/ 00186 void 00187 uart_set_mode(unsigned mode) 00188 { 00189 /* do nothing if the mode is already set */ 00190 if(mode == uart_mode) { 00191 return; 00192 } 00193 00194 IE2 &= ~(URXIE1 | UTXIE1); /* disable irq */ 00195 uart_configure(mode); /* configure uart parameters */ 00196 uart_mode = mode; 00197 00198 if(uart_handler[mode] != NULL) { 00199 IE2 |= URXIE1; /* Enable USART1 RX interrupt */ 00200 } 00201 } 00202 /*---------------------------------------------------------------------------*/ 00203 int 00204 uart_get_mode(void) 00205 { 00206 return uart_mode; 00207 } 00208 /*---------------------------------------------------------------------------*/ 00209 interrupt(UART1RX_VECTOR) 00210 uart_rx(void) 00211 { 00212 uart_handler_t handler = uart_handler[uart_mode]; 00213 int c; 00214 00215 if(!(IFG2 & URXIFG1)) { 00216 /* If rising edge is detected, toggle & return */ 00217 uart_edge = 1; 00218 U1TCTL &= ~URXSE; 00219 U1TCTL |= URXSE; 00220 _BIC_SR_IRQ(LPM3_bits); 00221 return; 00222 } 00223 uart_edge = 0; 00224 if(!(URCTL1 & RXERR)) { 00225 c = UART_RX; 00226 if(handler(c)) { 00227 _BIC_SR_IRQ(LPM3_bits); 00228 } 00229 } else { 00230 /* read out the char to clear the interrupt flags. */ 00231 c = UART_RX; 00232 } 00233 }