Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2005, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$Id: msp430.c,v 1.1 2010/08/24 16:26:38 joxe Exp $ 00032 */ 00033 #include "contiki.h" 00034 #include "dev/watchdog.h" 00035 #include "dev/leds.h" 00036 #include "net/uip.h" 00037 00038 static unsigned long dco_speed; 00039 00040 /*---------------------------------------------------------------------------*/ 00041 #if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND 00042 void * 00043 w_memcpy(void *out, const void *in, size_t n) 00044 { 00045 uint8_t *src, *dest; 00046 src = (uint8_t *) in; 00047 dest = (uint8_t *) out; 00048 while(n-- > 0) { 00049 *dest++ = *src++; 00050 } 00051 return out; 00052 } 00053 #endif /* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */ 00054 /*---------------------------------------------------------------------------*/ 00055 #if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND 00056 void * 00057 w_memset(void *out, int value, size_t n) 00058 { 00059 uint8_t *dest; 00060 dest = (uint8_t *) out; 00061 while(n-- > 0) { 00062 *dest++ = value & 0xff; 00063 } 00064 return out; 00065 } 00066 #endif /* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */ 00067 /*---------------------------------------------------------------------------*/ 00068 void 00069 msp430_init_dco(void) 00070 { 00071 } 00072 /*---------------------------------------------------------------------------*/ 00073 unsigned long 00074 msp430_dco_speed(void) 00075 { 00076 return dco_speed; 00077 } 00078 /*---------------------------------------------------------------------------*/ 00079 void 00080 msp430_set_dco_speed(unsigned long mhz) 00081 { 00082 int multiplier; 00083 00084 dco_speed = mhz; 00085 00086 dint(); 00087 /* DCO multiplier m for x MHz: 00088 (m + 1) * FLLRef = Fdco 00089 (m + 1) * 32768 = x MHz 00090 m = x / 32768 - 1 00091 Set FLL Div = fDCOCLK/2 00092 */ 00093 00094 multiplier = mhz / 32768UL - 1; 00095 00096 __bis_SR_register(SCG0); 00097 UCSCTL0 = 0x0000; 00098 00099 /* Select DCO range 24MHz operation */ 00100 UCSCTL1 = DCORSEL_5; 00101 00102 /* Set computed DCO multiplier */ 00103 UCSCTL2 = FLLD_1 + multiplier; 00104 00105 __bic_SR_register(SCG0); 00106 00107 do { 00108 /* Clear XT2,XT1,DCO fault flags */ 00109 UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); 00110 /* Clear fault flags */ 00111 SFRIFG1 &= ~OFIFG; 00112 00113 __delay_cycles(10000); 00114 /* Test oscillator fault flag */ 00115 } while(SFRIFG1 & OFIFG); 00116 00117 UCSCTL3 |= SELREF_0; 00118 00119 UCSCTL4 |= SELA_0; 00120 00121 eint(); 00122 } 00123 /*---------------------------------------------------------------------------*/ 00124 void 00125 msp430_quick_synch_dco(void) 00126 { 00127 msp430_set_dco_speed(F_CPU); 00128 } 00129 /*---------------------------------------------------------------------------*/ 00130 static void 00131 init_ports(void) 00132 { 00133 /* Turn everything off, device drivers enable what is needed. */ 00134 00135 /* All configured for digital I/O */ 00136 #ifdef P1SEL 00137 P1SEL = 0; 00138 #endif 00139 #ifdef P2SEL 00140 P2SEL = 0; 00141 #endif 00142 #ifdef P3SEL 00143 P3SEL = 0; 00144 #endif 00145 #ifdef P4SEL 00146 P4SEL = 0; 00147 #endif 00148 #ifdef P5SEL 00149 P5SEL = 0; 00150 #endif 00151 #ifdef P6SEL 00152 P6SEL = 0; 00153 #endif 00154 00155 /* All available inputs */ 00156 #ifdef P1DIR 00157 P1DIR = 0; 00158 P1OUT = 0; 00159 #endif 00160 #ifdef P2DIR 00161 P2DIR = 1 << 6; /* output needed for the below config ? */ 00162 P2OUT = 0; 00163 P2SEL = 1 << 6; /* test for setting the P2.6 to ACKL output */ 00164 #endif 00165 #ifdef P3DIR 00166 P3DIR = 0; 00167 P3OUT = 0; 00168 #endif 00169 #ifdef P4DIR 00170 P4DIR = 0; 00171 P4OUT = 0; 00172 #endif 00173 00174 #ifdef P5DIR 00175 P5DIR = 0; 00176 P5OUT = 0; 00177 #endif 00178 00179 #ifdef P6DIR 00180 P6DIR = 0; 00181 P6OUT = 0; 00182 #endif 00183 00184 #ifdef P7DIR 00185 P7DIR = 0; 00186 P7OUT = 0; 00187 P7SEL |= 0x03; /* Configure for ext clock function on these pins */ 00188 #endif 00189 00190 #ifdef P8DIR 00191 P8DIR = 0; 00192 P8OUT = 0; 00193 #endif 00194 00195 P1IE = 0; 00196 P2IE = 0; 00197 } 00198 /*---------------------------------------------------------------------------*/ 00199 /* msp430-ld may align _end incorrectly. Workaround in cpu_init. */ 00200 #ifndef __IAR_SYSTEMS_ICC__ 00201 extern int _end; /* Not in sys/unistd.h */ 00202 static char *cur_break = (char *)&_end; 00203 #endif 00204 00205 void 00206 msp430_cpu_init(void) 00207 { 00208 dint(); 00209 watchdog_init(); 00210 init_ports(); 00211 dco_speed = 1048576; /* Default bootup DCO frequency */ 00212 msp430_quick_synch_dco(); 00213 eint(); 00214 #ifndef __IAR_SYSTEMS_ICC__ 00215 if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */ 00216 cur_break++; 00217 } 00218 #endif 00219 } 00220 /*---------------------------------------------------------------------------*/ 00221 #define asmv(arg) __asm__ __volatile__(arg) 00222 00223 #define STACK_EXTRA 32 00224 00225 /* 00226 * Allocate memory from the heap. Check that we don't collide with the 00227 * stack right now (some other routine might later). A watchdog might 00228 * be used to check if cur_break and the stack pointer meet during 00229 * runtime. 00230 */ 00231 00232 #if 0 00233 void * 00234 sbrk(int incr) 00235 { 00236 char *stack_pointer; 00237 #ifdef __IAR_SYSTEMS_ICC__ 00238 stack_pointer = (char *) __get_SP_register(); 00239 /* TODO: add code here... */ 00240 return 0; 00241 #else 00242 asmv("mov r1, %0" : "=r" (stack_pointer)); 00243 stack_pointer -= STACK_EXTRA; 00244 if(incr > (stack_pointer - cur_break)) 00245 return (void *)-1; /* ENOMEM */ 00246 00247 void *old_break = cur_break; 00248 cur_break += incr; 00249 /* 00250 * If the stack was never here then [old_break .. cur_break] should 00251 * be filled with zeros. 00252 */ 00253 return old_break; 00254 #endif 00255 } 00256 #endif 00257 /*---------------------------------------------------------------------------*/ 00258 /* 00259 * Mask all interrupts that can be masked. 00260 */ 00261 int 00262 splhigh_(void) 00263 { 00264 /* Clear the GIE (General Interrupt Enable) flag. */ 00265 int sr; 00266 #ifdef __IAR_SYSTEMS_ICC__ 00267 sr = __get_SR_register(); 00268 __bic_SR_register(GIE); 00269 #else 00270 asmv("mov r2, %0" : "=r" (sr)); 00271 asmv("bic %0, r2" : : "i" (GIE)); 00272 #endif 00273 return sr & GIE; /* Ignore other sr bits. */ 00274 } 00275 /*---------------------------------------------------------------------------*/ 00276 /* 00277 * Restore previous interrupt mask. 00278 */ 00279 void 00280 splx_(int sr) 00281 { 00282 /* If GIE was set, restore it. */ 00283 #ifdef __IAR_SYSTEMS_ICC__ 00284 __bis_SR_register(sr); 00285 #else 00286 asmv("bis %0, r2" : : "r" (sr)); 00287 #endif 00288 } 00289 00290 #ifdef __IAR_SYSTEMS_ICC__ 00291 int __low_level_init(void) 00292 { 00293 /* turn off watchdog so that C-init will run */ 00294 WDTCTL = WDTPW + WDTHOLD; 00295 /* 00296 * Return value: 00297 * 00298 * 1 - Perform data segment initialization. 00299 * 0 - Skip data segment initialization. 00300 */ 00301 00302 return 1; 00303 } 00304 #endif 00305 /*---------------------------------------------------------------------------*/ 00306 void 00307 msp430_sync_dco(void) 00308 { 00309 } 00310 /*---------------------------------------------------------------------------*/