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 
35 #if defined(__MSP430__) && defined(__GNUC__)
36 #define asmv(arg) __asm__ __volatile__(arg)
37 #endif
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  if(CALBC1_8MHZ != 0xFF) {
71  DCOCTL = 0x00;
72  BCSCTL1 = CALBC1_8MHZ; /*Set DCO to 8MHz */
73  DCOCTL = CALDCO_8MHZ;
74  } else { /*start using reasonable values at 8 Mhz */
75  DCOCTL = 0x00;
76  BCSCTL1 = 0x8D;
77  DCOCTL = 0x88;
78  }
79 
80  /*BCSCTL1 |= XT2OFF; // Make sure XT2 is off */
81  /* BCSCTL2 = 0x00; // MCLK = DCOCLK/1 */
82  /* SMCLK = DCOCLK/1 */
83  /* DCO Internal Resistor */
84 }
85 /*---------------------------------------------------------------------------*/
86 static void
87 init_ports(void)
88 {
89  /* Turn everything off, device drivers enable what is needed. */
90 
91  /* All configured for digital I/O */
92 #ifdef P1SEL
93  P1SEL = 0;
94 #endif
95 #ifdef P2SEL
96  P2SEL = 0;
97 #endif
98 #ifdef P3SEL
99  P3SEL = 0;
100 #endif
101 #ifdef P4SEL
102  P4SEL = 0;
103 #endif
104 #ifdef P5SEL
105  P5SEL = 0;
106 #endif
107 #ifdef P6SEL
108  P6SEL = 0;
109 #endif
110 
111  /* All available inputs */
112 #ifdef P1DIR
113  P1DIR = 0;
114  P1OUT = 0;
115 #endif
116 #ifdef P2DIR
117  P2DIR = 0;
118  P2OUT = 0;
119 #endif
120 #ifdef P3DIR
121  P3DIR = 0;
122  P3OUT = 0;
123 #endif
124 #ifdef P4DIR
125  P4DIR = 0;
126  P4OUT = 0;
127 #endif
128 
129 #ifdef P5DIR
130  P5DIR = 0;
131  P5OUT = 0;
132 #endif
133 
134 #ifdef P6DIR
135  P6DIR = 0;
136  P6OUT = 0;
137 #endif
138 
139 #ifdef P7DIR
140  P7DIR = 0;
141  P7OUT = 0;
142 #endif
143 
144 #ifdef P8DIR
145  P8DIR = 0;
146  P8OUT = 0;
147 #endif
148 
149  P1IE = 0;
150  P2IE = 0;
151 }
152 /*---------------------------------------------------------------------------*/
153 /* msp430-ld may align _end incorrectly. Workaround in cpu_init. */
154 #if defined(__MSP430__) && defined(__GNUC__)
155 extern int _end; /* Not in sys/unistd.h */
156 static char *cur_break = (char *)&_end;
157 #endif
158 
159 void
160 msp430_cpu_init(void)
161 {
162  dint();
163  watchdog_init();
164  init_ports();
165  /* set DCO to a reasonable default value (8MHz) */
166  msp430_init_dco();
167  /* calibrate the DCO step-by-step */
168  msp430_sync_dco();
169  eint();
170 #if defined(__MSP430__) && defined(__GNUC__)
171  if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */
172  cur_break++;
173  }
174 #endif
175 }
176 /*---------------------------------------------------------------------------*/
177 
178 /*---------------------------------------------------------------------------*/
179 /*
180  * Mask all interrupts that can be masked.
181  */
182 int
183 splhigh_(void)
184 {
185  /* Clear the GIE (General Interrupt Enable) flag. */
186  int sr;
187 #ifdef __IAR_SYSTEMS_ICC__
188  sr = __get_SR_register();
189  __bic_SR_register(GIE);
190 #else
191  asmv("mov r2, %0" : "=r" (sr));
192  asmv("bic %0, r2" : : "i" (GIE));
193 #endif
194  return sr & GIE; /* Ignore other sr bits. */
195 }
196 /*---------------------------------------------------------------------------*/
197 /*
198  * Restore previous interrupt mask.
199  */
200 /* void */
201 /* splx_(int sr) */
202 /* { */
203 /* #ifdef __IAR_SYSTEMS_ICC__ */
204 /* __bis_SR_register(sr); */
205 /* #else */
206 /* /\* If GIE was set, restore it. *\/ */
207 /* asmv("bis %0, r2" : : "r" (sr)); */
208 /* #endif */
209 /* } */
210 /*---------------------------------------------------------------------------*/
211 #ifdef __IAR_SYSTEMS_ICC__
212 int __low_level_init(void)
213 {
214  /* turn off watchdog so that C-init will run */
215  WDTCTL = WDTPW + WDTHOLD;
216  /*
217  * Return value:
218  *
219  * 1 - Perform data segment initialization.
220  * 0 - Skip data segment initialization.
221  */
222  return 1;
223 }
224 #endif
225 /*---------------------------------------------------------------------------*/
226 void
227 msp430_sync_dco(void) {
228  uint16_t oldcapture;
229  int16_t diff;
230  /* DELTA_2 assumes an ACLK of 32768 Hz */
231 #define DELTA_2 ((MSP430_CPU_SPEED) / 32768)
232 
233  /* Select SMCLK clock, and capture on ACLK for TBCCR6 */
234  TBCTL = TBSSEL1 | TBCLR;
235  TBCCTL6 = CCIS0 + CM0 + CAP;
236  /* start the timer */
237  TBCTL |= MC1;
238 
239  while(1) {
240  /* wait for the next capture */
241  TBCCTL6 &= ~CCIFG;
242  while(!(TBCCTL6 & CCIFG));
243  oldcapture = TBCCR6;
244 
245  /* wait for the next capture - and calculate difference */
246  TBCCTL6 &= ~CCIFG;
247  while(!(TBCCTL6 & CCIFG));
248  diff = TBCCR6 - oldcapture;
249 
250  /* resynchronize the DCO speed if not at target */
251  if(DELTA_2 == diff) {
252  break; /* if equal, leave "while(1)" */
253  } else if(DELTA_2 < diff) { /* DCO is too fast, slow it down */
254  DCOCTL--;
255  if(DCOCTL == 0xFF) { /* Did DCO roll under? */
256  BCSCTL1--;
257  }
258  } else { /* -> Select next lower RSEL */
259  DCOCTL++;
260  if(DCOCTL == 0x00) { /* Did DCO roll over? */
261  BCSCTL1++;
262  }
263  /* -> Select next higher RSEL */
264  }
265  }
266 
267  /* Stop the timer - conserves energy according to user guide */
268  TBCTL = 0;
269 }
270 /*---------------------------------------------------------------------------*/
void watchdog_init(void)
Copyright (c) 2014, Analog Devices, Inc.
Definition: watchdog.c:42