Contiki 2.6

msb430-uart1.c

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 }