Contiki 2.6
|
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 "contiki.h" 00055 #include <string.h> 00056 #include "dev/msb430-uart1.h" 00057 #include "dev/lpm.h" 00058 #include "isr_compat.h" 00059 00060 #ifndef U1ME 00061 #define U1ME ME2 00062 #endif 00063 00064 volatile unsigned char uart_mode = UART_MODE_RESET; 00065 volatile unsigned char uart_lockcnt = 0; 00066 volatile uint8_t uart_edge = 0; 00067 00068 static unsigned char uart_speed_br0[UART_NUM_MODES]; 00069 static unsigned char uart_speed_br1[UART_NUM_MODES]; 00070 static unsigned char uart_speed_bmn[UART_NUM_MODES]; 00071 static uart_handler_t uart_handler[UART_NUM_MODES] = {NULL, NULL}; 00072 00073 /*---------------------------------------------------------------------------*/ 00074 static void 00075 uart_configure(unsigned mode) 00076 { 00077 _DINT(); /* disable interrupts */ 00078 00079 UART_WAIT_TXDONE(); /* wait till all buffered data has been transmitted */ 00080 00081 if(mode == UART_MODE_RS232) { 00082 P5OUT |= 0x01; 00083 /* unselect SPI */ 00084 P3SEL |= 0xC0; 00085 /* select rs232 */ 00086 UCTL1 = SWRST | CHAR; /* 8-bit character */ 00087 UTCTL1 |= SSEL1; /* UCLK = MCLK */ 00088 /* activate */ 00089 U1ME |= UTXE1 | URXE1; /* Enable USART1 TXD/RXD */ 00090 } else if(mode == UART_MODE_SPI) { 00091 P3SEL &= ~0xC0; /* unselect RS232 */ 00092 // to SPI mode 00093 UCTL1 = SWRST | CHAR | SYNC | MM; /* 8-bit SPI Master */ 00094 /* 00095 * SMCLK, 3-pin mode, clock idle low, data valid on 00096 * rising edge, UCLK delayed 00097 */ 00098 UTCTL1 |= CKPH | SSEL1 | SSEL0 | STC; /* activate */ 00099 U1ME |= USPIE1; /* Enable USART1 SPI */ 00100 } 00101 00102 /* restore speed settings */ 00103 UBR01 = uart_speed_br0[mode]; /* set baudrate */ 00104 UBR11 = uart_speed_br1[mode]; 00105 UMCTL1 = uart_speed_bmn[mode]; /* set modulation */ 00106 00107 UCTL1 &= ~SWRST; /* clear reset flag */ 00108 _EINT(); /* enable interrupts */ 00109 } 00110 /*---------------------------------------------------------------------------*/ 00111 void 00112 uart_set_speed(unsigned mode, unsigned ubr0, 00113 unsigned ubr1, unsigned umctl) 00114 { 00115 /* store the setting */ 00116 uart_speed_br0[mode] = ubr0; /* baudrate */ 00117 uart_speed_br1[mode] = ubr1; /* baudrate */ 00118 uart_speed_bmn[mode] = umctl; /* modulation */ 00119 00120 /* reconfigure, if mode active */ 00121 if(uart_mode == mode) { 00122 uart_configure(mode); 00123 } 00124 } 00125 /*---------------------------------------------------------------------------*/ 00126 void 00127 uart_set_handler(unsigned mode, uart_handler_t handler) 00128 { 00129 /* store the setting */ 00130 uart_handler[mode] = handler; 00131 if(mode == uart_mode) { 00132 if(handler == NULL) { 00133 IE2 &= ~URXIE1; /* Disable USART1 RX interrupt */ 00134 } else { 00135 IE2 |= URXIE1; /* Enable USART1 RX interrupt */ 00136 } 00137 } 00138 } 00139 /*---------------------------------------------------------------------------*/ 00140 int 00141 uart_lock(unsigned mode) 00142 { 00143 /* already locked? */ 00144 if(uart_mode != mode && uart_lockcnt > 0) { 00145 return 0; 00146 } 00147 00148 /* increase lock count */ 00149 uart_lockcnt++; 00150 /* switch mode (if neccessary) */ 00151 uart_set_mode(mode); 00152 return 1; 00153 } 00154 /*---------------------------------------------------------------------------*/ 00155 int 00156 uart_lock_wait(unsigned mode) 00157 { 00158 while(UART_WAIT_LOCK(mode)) { 00159 _NOP(); 00160 } 00161 return uart_lock(mode); 00162 } 00163 /*---------------------------------------------------------------------------*/ 00164 int 00165 uart_unlock(unsigned mode) 00166 { 00167 if((uart_lockcnt == 0) || (mode != uart_mode)) { 00168 uart_lockcnt = 0; 00169 uart_set_mode(UART_MODE_DEFAULT); 00170 return 0; 00171 } 00172 00173 /* decrement lock */ 00174 if(uart_lockcnt > 0) { 00175 uart_lockcnt--; 00176 /* if no more locks, switch back to default mode */ 00177 if(uart_lockcnt == 0) { 00178 uart_set_mode(UART_MODE_DEFAULT); 00179 } 00180 return 1; 00181 } 00182 return 0; 00183 } 00184 /*---------------------------------------------------------------------------*/ 00185 void 00186 uart_set_mode(unsigned mode) 00187 { 00188 /* do nothing if the mode is already set */ 00189 if(mode == uart_mode) { 00190 return; 00191 } 00192 00193 IE2 &= ~(URXIE1 | UTXIE1); /* disable irq */ 00194 uart_configure(mode); /* configure uart parameters */ 00195 uart_mode = mode; 00196 00197 if(uart_handler[mode] != NULL) { 00198 IE2 |= URXIE1; /* Enable USART1 RX interrupt */ 00199 } 00200 } 00201 /*---------------------------------------------------------------------------*/ 00202 int 00203 uart_get_mode(void) 00204 { 00205 return uart_mode; 00206 } 00207 /*---------------------------------------------------------------------------*/ 00208 ISR(UART1RX, uart_rx) 00209 { 00210 uart_handler_t handler = uart_handler[uart_mode]; 00211 int c; 00212 00213 if(!(IFG2 & URXIFG1)) { 00214 /* If rising edge is detected, toggle & return */ 00215 uart_edge = 1; 00216 U1TCTL &= ~URXSE; 00217 U1TCTL |= URXSE; 00218 _BIC_SR_IRQ(LPM3_bits); 00219 return; 00220 } 00221 uart_edge = 0; 00222 if(!(URCTL1 & RXERR)) { 00223 c = UART_RX; 00224 if(handler(c)) { 00225 _BIC_SR_IRQ(LPM3_bits); 00226 } 00227 } else { 00228 /* read out the char to clear the interrupt flags. */ 00229 c = UART_RX; 00230 } 00231 }