Contiki 2.6

msp430.c

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 /*---------------------------------------------------------------------------*/