Contiki 3.x
msp430.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 #include "contiki.h"
33 #include "dev/watchdog.h"
34 #include "dev/leds.h"
35 #include "net/ip/uip.h"
36 
37 static unsigned long dco_speed;
38 
39 /*---------------------------------------------------------------------------*/
40 #if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND
41 void *
42 w_memcpy(void *out, const void *in, size_t n)
43 {
44  uint8_t *src, *dest;
45  src = (uint8_t *) in;
46  dest = (uint8_t *) out;
47  while(n-- > 0) {
48  *dest++ = *src++;
49  }
50  return out;
51 }
52 #endif /* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */
53 /*---------------------------------------------------------------------------*/
54 #if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND
55 void *
56 w_memset(void *out, int value, size_t n)
57 {
58  uint8_t *dest;
59  dest = (uint8_t *) out;
60  while(n-- > 0) {
61  *dest++ = value & 0xff;
62  }
63  return out;
64 }
65 #endif /* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */
66 /*---------------------------------------------------------------------------*/
67 void
68 msp430_init_dco(void)
69 {
70 }
71 /*---------------------------------------------------------------------------*/
72 unsigned long
73 msp430_dco_speed(void)
74 {
75  return dco_speed;
76 }
77 /*---------------------------------------------------------------------------*/
78 void
79 msp430_set_dco_speed(unsigned long mhz)
80 {
81  int multiplier;
82 
83  dco_speed = mhz;
84 
85  dint();
86  /* DCO multiplier m for x MHz:
87  (m + 1) * FLLRef = Fdco
88  (m + 1) * 32768 = x MHz
89  m = x / 32768 - 1
90  Set FLL Div = fDCOCLK/2
91  */
92 
93  multiplier = mhz / 32768UL - 1;
94 
95  __bis_SR_register(SCG0);
96  UCSCTL0 = 0x0000;
97 
98  /* Select DCO range 24MHz operation */
99  UCSCTL1 = DCORSEL_5;
100 
101  /* Set computed DCO multiplier */
102  UCSCTL2 = FLLD_1 + multiplier;
103 
104  __bic_SR_register(SCG0);
105 
106  do {
107  /* Clear XT2,XT1,DCO fault flags */
108  UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
109  /* Clear fault flags */
110  SFRIFG1 &= ~OFIFG;
111 
112  __delay_cycles(10000);
113  /* Test oscillator fault flag */
114  } while(SFRIFG1 & OFIFG);
115 
116  UCSCTL3 |= SELREF_0;
117 
118  UCSCTL4 |= SELA_0;
119 
120  eint();
121 }
122 /*---------------------------------------------------------------------------*/
123 void
124 msp430_quick_synch_dco(void)
125 {
126  msp430_set_dco_speed(F_CPU);
127 }
128 /*---------------------------------------------------------------------------*/
129 static void
130 init_ports(void)
131 {
132  /* Turn everything off, device drivers enable what is needed. */
133 
134  /* All configured for digital I/O */
135 #ifdef P1SEL
136  P1SEL = 0;
137 #endif
138 #ifdef P2SEL
139  P2SEL = 0;
140 #endif
141 #ifdef P3SEL
142  P3SEL = 0;
143 #endif
144 #ifdef P4SEL
145  P4SEL = 0;
146 #endif
147 #ifdef P5SEL
148  P5SEL = 0;
149 #endif
150 #ifdef P6SEL
151  P6SEL = 0;
152 #endif
153 
154  /* All available inputs */
155 #ifdef P1DIR
156  P1DIR = 0;
157  P1OUT = 0;
158 #endif
159 #ifdef P2DIR
160  P2DIR = 1 << 6; /* output needed for the below config ? */
161  P2OUT = 0;
162  P2SEL = 1 << 6; /* test for setting the P2.6 to ACKL output */
163 #endif
164 #ifdef P3DIR
165  P3DIR = 0;
166  P3OUT = 0;
167 #endif
168 #ifdef P4DIR
169  P4DIR = 0;
170  P4OUT = 0;
171 #endif
172 
173 #ifdef P5DIR
174  P5DIR = 0;
175  P5OUT = 0;
176 #endif
177 
178 #ifdef P6DIR
179  P6DIR = 0;
180  P6OUT = 0;
181 #endif
182 
183 #ifdef P7DIR
184  P7DIR = 0;
185  P7OUT = 0;
186  P7SEL |= 0x03; /* Configure for ext clock function on these pins */
187 #endif
188 
189 #ifdef P8DIR
190  P8DIR = 0;
191  P8OUT = 0;
192 #endif
193 
194  P1IE = 0;
195  P2IE = 0;
196 }
197 /*---------------------------------------------------------------------------*/
198 /* msp430-ld may align _end incorrectly. Workaround in cpu_init. */
199 #ifndef __IAR_SYSTEMS_ICC__
200 extern int _end; /* Not in sys/unistd.h */
201 static char *cur_break = (char *)&_end;
202 #endif
203 
204 void
205 msp430_cpu_init(void)
206 {
207  dint();
208  watchdog_init();
209  init_ports();
210  dco_speed = 1048576; /* Default bootup DCO frequency */
211  msp430_quick_synch_dco();
212  eint();
213 #ifndef __IAR_SYSTEMS_ICC__
214  if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */
215  cur_break++;
216  }
217 #endif
218 }
219 /*---------------------------------------------------------------------------*/
220 #define asmv(arg) __asm__ __volatile__(arg)
221 
222 #define STACK_EXTRA 32
223 
224 /*
225  * Allocate memory from the heap. Check that we don't collide with the
226  * stack right now (some other routine might later). A watchdog might
227  * be used to check if cur_break and the stack pointer meet during
228  * runtime.
229  */
230 
231 #if 0
232 void *
233 sbrk(int incr)
234 {
235  char *stack_pointer;
236 #ifdef __IAR_SYSTEMS_ICC__
237  stack_pointer = (char *) __get_SP_register();
238  /* TODO: add code here... */
239  return 0;
240 #else
241  asmv("mov r1, %0" : "=r" (stack_pointer));
242  stack_pointer -= STACK_EXTRA;
243  if(incr > (stack_pointer - cur_break))
244  return (void *)-1; /* ENOMEM */
245 
246  void *old_break = cur_break;
247  cur_break += incr;
248  /*
249  * If the stack was never here then [old_break .. cur_break] should
250  * be filled with zeros.
251  */
252  return old_break;
253 #endif
254 }
255 #endif
256 /*---------------------------------------------------------------------------*/
257 /*
258  * Mask all interrupts that can be masked.
259  */
260 int
261 splhigh_(void)
262 {
263  /* Clear the GIE (General Interrupt Enable) flag. */
264  int sr;
265 #ifdef __IAR_SYSTEMS_ICC__
266  sr = __get_SR_register();
267  __bic_SR_register(GIE);
268 #else
269  asmv("mov r2, %0" : "=r" (sr));
270  asmv("bic %0, r2" : : "i" (GIE));
271 #endif
272  return sr & GIE; /* Ignore other sr bits. */
273 }
274 /*---------------------------------------------------------------------------*/
275 /*
276  * Restore previous interrupt mask.
277  */
278 void
279 splx_(int sr)
280 {
281  /* If GIE was set, restore it. */
282 #ifdef __IAR_SYSTEMS_ICC__
283  __bis_SR_register(sr);
284 #else
285  asmv("bis %0, r2" : : "r" (sr));
286 #endif
287 }
288 
289 #ifdef __IAR_SYSTEMS_ICC__
290 int __low_level_init(void)
291 {
292  /* turn off watchdog so that C-init will run */
293  WDTCTL = WDTPW + WDTHOLD;
294  /*
295  * Return value:
296  *
297  * 1 - Perform data segment initialization.
298  * 0 - Skip data segment initialization.
299  */
300 
301  return 1;
302 }
303 #endif
304 /*---------------------------------------------------------------------------*/
305 void
306 msp430_sync_dco(void)
307 {
308 }
309 /*---------------------------------------------------------------------------*/
#define F_CPU
CPU core frequency resulting from the chosen divisors and multipliers.
Definition: config-clocks.h:87
Header file for the uIP TCP/IP stack.
#define __delay_cycles(x)
__delay_cycles() is an intrinsic IAR call; however, we have explicity disallowed it since it is too s...
Definition: gnu.h:169
void watchdog_init(void)
Copyright (c) 2014, Analog Devices, Inc.
Definition: watchdog.c:42