Contiki 2.5
msb430-uart1.c
1 /*
2 Copyright 2007, Freie Universitaet Berlin. All rights reserved.
3 
4 These sources were developed at the Freie Universität Berlin, Computer
5 Systems and Telematics group.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
9 met:
10 
11 - Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 
14 - Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17 
18 - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
19 contributors may be used to endorse or promote products derived from
20 this software without specific prior written permission.
21 
22 This software is provided by FUB and the contributors on an "as is"
23 basis, without any representations or warranties of any kind, express
24 or implied including, but not limited to, representations or
25 warranties of non-infringement, merchantability or fitness for a
26 particular purpose. In no event shall FUB or contributors be liable
27 for any direct, indirect, incidental, special, exemplary, or
28 consequential damages (including, but not limited to, procurement of
29 substitute goods or services; loss of use, data, or profits; or
30 business interruption) however caused and on any theory of liability,
31 whether in contract, strict liability, or tort (including negligence
32 or otherwise) arising in any way out of the use of this software, even
33 if advised of the possibility of such damage.
34 
35 This implementation was developed by the CST group at the FUB.
36 
37 For documentation and questions please use the web site
38 http://scatterweb.mi.fu-berlin.de and the mailinglist
39 scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
40 Berlin, 2007
41 */
42 
43 /**
44  * @file ScatterWeb.Uart.c
45  * @addtogroup interfaces
46  * @brief UART interface
47  * @author Michael Baar <baar@inf.fu-berlin.de>
48  *
49  * UART switch for RS232 and SPI protocols on UART1 written for
50  * ScatterWeb MSB boards. Compatible to ScatterWeb EOS,
51  * ScatterWeb Bootload and Contiki.
52  */
53 
54 #include "contiki.h"
55 #include <string.h>
56 #include "dev/msb430-uart1.h"
57 #include "dev/lpm.h"
58 
59 #ifndef U1ME
60 #define U1ME ME2
61 #endif
62 
63 volatile unsigned char uart_mode = UART_MODE_RESET;
64 volatile unsigned char uart_lockcnt = 0;
65 volatile uint8_t uart_edge = 0;
66 
67 static unsigned char uart_speed_br0[UART_NUM_MODES];
68 static unsigned char uart_speed_br1[UART_NUM_MODES];
69 static unsigned char uart_speed_bmn[UART_NUM_MODES];
70 static uart_handler_t uart_handler[UART_NUM_MODES] = {NULL, NULL};
71 
72 /*---------------------------------------------------------------------------*/
73 static void
74 uart_configure(unsigned mode)
75 {
76  _DINT(); /* disable interrupts */
77 
78  UART_WAIT_TXDONE(); /* wait till all buffered data has been transmitted */
79 
80  if(mode == UART_MODE_RS232) {
81  P5OUT |= 0x01;
82  /* unselect SPI */
83  P3SEL |= 0xC0;
84  /* select rs232 */
85  UCTL1 = SWRST | CHAR; /* 8-bit character */
86  UTCTL1 |= SSEL1; /* UCLK = MCLK */
87  /* activate */
88  U1ME |= UTXE1 | URXE1; /* Enable USART1 TXD/RXD */
89  } else if(mode == UART_MODE_SPI) {
90  P3SEL &= ~0xC0; /* unselect RS232 */
91  // to SPI mode
92  UCTL1 = SWRST | CHAR | SYNC | MM; /* 8-bit SPI Master */
93  /*
94  * SMCLK, 3-pin mode, clock idle low, data valid on
95  * rising edge, UCLK delayed
96  */
97  UTCTL1 |= CKPH | SSEL1 | SSEL0 | STC; /* activate */
98  U1ME |= USPIE1; /* Enable USART1 SPI */
99  }
100 
101  /* restore speed settings */
102  UBR01 = uart_speed_br0[mode]; /* set baudrate */
103  UBR11 = uart_speed_br1[mode];
104  UMCTL1 = uart_speed_bmn[mode]; /* set modulation */
105 
106  UCTL1 &= ~SWRST; /* clear reset flag */
107  _EINT(); /* enable interrupts */
108 }
109 /*---------------------------------------------------------------------------*/
110 void
111 uart_set_speed(unsigned mode, unsigned ubr0,
112  unsigned ubr1, unsigned umctl)
113 {
114  /* store the setting */
115  uart_speed_br0[mode] = ubr0; /* baudrate */
116  uart_speed_br1[mode] = ubr1; /* baudrate */
117  uart_speed_bmn[mode] = umctl; /* modulation */
118 
119  /* reconfigure, if mode active */
120  if(uart_mode == mode) {
121  uart_configure(mode);
122  }
123 }
124 /*---------------------------------------------------------------------------*/
125 void
126 uart_set_handler(unsigned mode, uart_handler_t handler)
127 {
128  /* store the setting */
129  uart_handler[mode] = handler;
130  if(mode == uart_mode) {
131  if(handler == NULL) {
132  IE2 &= ~URXIE1; /* Disable USART1 RX interrupt */
133  } else {
134  IE2 |= URXIE1; /* Enable USART1 RX interrupt */
135  }
136  }
137 }
138 /*---------------------------------------------------------------------------*/
139 int
140 uart_lock(unsigned mode)
141 {
142  /* already locked? */
143  if(uart_mode != mode && uart_lockcnt > 0) {
144  return 0;
145  }
146 
147  /* increase lock count */
148  uart_lockcnt++;
149  /* switch mode (if neccessary) */
150  uart_set_mode(mode);
151  return 1;
152 }
153 /*---------------------------------------------------------------------------*/
154 int
155 uart_lock_wait(unsigned mode)
156 {
157  while(UART_WAIT_LOCK(mode)) {
158  _NOP();
159  }
160  return uart_lock(mode);
161 }
162 /*---------------------------------------------------------------------------*/
163 int
164 uart_unlock(unsigned mode)
165 {
166  if((uart_lockcnt == 0) || (mode != uart_mode)) {
167  uart_lockcnt = 0;
168  uart_set_mode(UART_MODE_DEFAULT);
169  return 0;
170  }
171 
172  /* decrement lock */
173  if(uart_lockcnt > 0) {
174  uart_lockcnt--;
175  /* if no more locks, switch back to default mode */
176  if(uart_lockcnt == 0) {
177  uart_set_mode(UART_MODE_DEFAULT);
178  }
179  return 1;
180  }
181  return 0;
182 }
183 /*---------------------------------------------------------------------------*/
184 void
185 uart_set_mode(unsigned mode)
186 {
187  /* do nothing if the mode is already set */
188  if(mode == uart_mode) {
189  return;
190  }
191 
192  IE2 &= ~(URXIE1 | UTXIE1); /* disable irq */
193  uart_configure(mode); /* configure uart parameters */
194  uart_mode = mode;
195 
196  if(uart_handler[mode] != NULL) {
197  IE2 |= URXIE1; /* Enable USART1 RX interrupt */
198  }
199 }
200 /*---------------------------------------------------------------------------*/
201 int
202 uart_get_mode(void)
203 {
204  return uart_mode;
205 }
206 /*---------------------------------------------------------------------------*/
207 interrupt(UART1RX_VECTOR)
208 uart_rx(void)
209 {
210  uart_handler_t handler = uart_handler[uart_mode];
211  int c;
212 
213  if(!(IFG2 & URXIFG1)) {
214  /* If rising edge is detected, toggle & return */
215  uart_edge = 1;
216  U1TCTL &= ~URXSE;
217  U1TCTL |= URXSE;
218  _BIC_SR_IRQ(LPM3_bits);
219  return;
220  }
221  uart_edge = 0;
222  if(!(URCTL1 & RXERR)) {
223  c = UART_RX;
224  if(handler(c)) {
225  _BIC_SR_IRQ(LPM3_bits);
226  }
227  } else {
228  /* read out the char to clear the interrupt flags. */
229  c = UART_RX;
230  }
231 }