Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2011, 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 #include "contiki.h" 00032 #include "dev/watchdog.h" 00033 00034 /* dco_required set to 1 will cause the CPU not to go into 00035 sleep modes where the DCO clock stopped */ 00036 int msp430_dco_required; 00037 00038 #if defined(__MSP430__) && defined(__GNUC__) 00039 #define asmv(arg) __asm__ __volatile__(arg) 00040 #endif 00041 /*---------------------------------------------------------------------------*/ 00042 void 00043 msp430_init_dco(void) 00044 { 00045 #ifdef __IAR_SYSTEMS_ICC__ 00046 __bis_SR_register(SCG0); 00047 #else 00048 asmv("bis %0, r2" : : "i" (SCG0)); 00049 #endif 00050 00051 UCSCTL0 = 0x0000; 00052 UCSCTL1 = DCORSEL_4; 00053 00054 UCSCTL2 = MSP430_CPU_SPEED / 32768; 00055 UCSCTL4 = 0x33; /* instead of 0x44 that is DCO/2 */ 00056 00057 #ifdef __IAR_SYSTEMS_ICC__ 00058 __bic_SR_register(SCG0); 00059 #else 00060 asmv("bic %0, r2" : : "i" (SCG0)); 00061 #endif 00062 } 00063 /*---------------------------------------------------------------------------*/ 00064 00065 static void 00066 init_ports(void) 00067 { 00068 /* Turn everything off, device drivers enable what is needed. */ 00069 /* All configured for digital I/O */ 00070 #ifdef P1SEL 00071 P1SEL = 0; 00072 #endif 00073 #ifdef P2SEL 00074 P2SEL = 0; 00075 #endif 00076 #ifdef P3SEL 00077 P3SEL = 0; 00078 #endif 00079 #ifdef P4SEL 00080 P4SEL = 0; 00081 #endif 00082 #ifdef P5SEL 00083 P5SEL = 0; 00084 #endif 00085 #ifdef P6SEL 00086 P6SEL = 0; 00087 #endif 00088 00089 /* All available inputs */ 00090 #ifdef P1DIR 00091 P1DIR = 0; 00092 P1OUT = 0; 00093 #endif 00094 #ifdef P2DIR 00095 P2DIR = 0; 00096 P2OUT = 0; 00097 #endif 00098 #ifdef P3DIR 00099 P3DIR = 0; 00100 P3OUT = 0; 00101 #endif 00102 #ifdef P4DIR 00103 P4DIR = 0; 00104 P4OUT = 0; 00105 #endif 00106 00107 #ifdef P5DIR 00108 P5DIR = 0; 00109 P5OUT = 0; 00110 #endif 00111 00112 #ifdef P6DIR 00113 P6DIR = 0; 00114 P6OUT = 0; 00115 #endif 00116 00117 #ifdef P7DIR 00118 P7DIR = 0; 00119 P7OUT = 0; 00120 #endif 00121 00122 #ifdef P8DIR 00123 P8DIR = 0; 00124 P8OUT = 0; 00125 #endif 00126 00127 P1IE = 0; 00128 P2IE = 0; 00129 } 00130 /*---------------------------------------------------------------------------*/ 00131 /* msp430-ld may align _end incorrectly. Workaround in cpu_init. */ 00132 #if defined(__MSP430__) && defined(__GNUC__) 00133 extern int _end; /* Not in sys/unistd.h */ 00134 static char *cur_break = (char *)&_end; 00135 #endif 00136 00137 /*---------------------------------------------------------------------------*/ 00138 /* add/remove_lpm_req - for requiring a specific LPM mode. currently Contiki */ 00139 /* jumps to LPM3 to save power, but DMA will not work if DCO is not clocked */ 00140 /* so some modules might need to enter their LPM requirements */ 00141 /* NOTE: currently only works with LPM1 (e.g. DCO) requirements. */ 00142 /*---------------------------------------------------------------------------*/ 00143 void 00144 msp430_add_lpm_req(int req) 00145 { 00146 if(req <= MSP430_REQUIRE_LPM1) { 00147 msp430_dco_required++; 00148 } 00149 } 00150 00151 void 00152 msp430_remove_lpm_req(int req) 00153 { 00154 if(req <= MSP430_REQUIRE_LPM1) { 00155 msp430_dco_required--; 00156 } 00157 } 00158 00159 void 00160 msp430_cpu_init(void) 00161 { 00162 dint(); 00163 watchdog_init(); 00164 init_ports(); 00165 msp430_init_dco(); 00166 eint(); 00167 #if defined(__MSP430__) && defined(__GNUC__) 00168 if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */ 00169 cur_break++; 00170 } 00171 #endif 00172 00173 msp430_dco_required = 0; 00174 } 00175 /*---------------------------------------------------------------------------*/ 00176 00177 #define STACK_EXTRA 32 00178 00179 /* 00180 * Allocate memory from the heap. Check that we don't collide with the 00181 * stack right now (some other routine might later). A watchdog might 00182 * be used to check if cur_break and the stack pointer meet during 00183 * runtime. 00184 */ 00185 #if defined(__MSP430__) && defined(__GNUC__) 00186 void * 00187 sbrk(int incr) 00188 { 00189 char *stack_pointer; 00190 00191 asmv("mov r1, %0" : "=r" (stack_pointer)); 00192 stack_pointer -= STACK_EXTRA; 00193 if(incr > (stack_pointer - cur_break)) 00194 return (void *)-1; /* ENOMEM */ 00195 00196 void *old_break = cur_break; 00197 cur_break += incr; 00198 /* 00199 * If the stack was never here then [old_break .. cur_break] should 00200 * be filled with zeros. 00201 */ 00202 return old_break; 00203 } 00204 #endif 00205 /*---------------------------------------------------------------------------*/ 00206 /* 00207 * Mask all interrupts that can be masked. 00208 */ 00209 int 00210 splhigh_(void) 00211 { 00212 int sr; 00213 /* Clear the GIE (General Interrupt Enable) flag. */ 00214 #ifdef __IAR_SYSTEMS_ICC__ 00215 sr = __get_SR_register(); 00216 __bic_SR_register(GIE); 00217 #else 00218 asmv("mov r2, %0" : "=r" (sr)); 00219 asmv("bic %0, r2" : : "i" (GIE)); 00220 #endif 00221 return sr & GIE; /* Ignore other sr bits. */ 00222 } 00223 /*---------------------------------------------------------------------------*/ 00224 #ifdef __IAR_SYSTEMS_ICC__ 00225 int __low_level_init(void) 00226 { 00227 /* turn off watchdog so that C-init will run */ 00228 WDTCTL = WDTPW + WDTHOLD; 00229 /* 00230 * Return value: 00231 * 00232 * 1 - Perform data segment initialization. 00233 * 0 - Skip data segment initialization. 00234 */ 00235 return 1; 00236 } 00237 #endif 00238 /*---------------------------------------------------------------------------*/