]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Proper support for the new basic_clock+ peripheral. Default UART baud rate is
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Tue, 9 Sep 2008 04:35:28 +0000 (04:35 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 1 Dec 2009 03:00:51 +0000 (20:00 -0700)
115200, 8 data bits, no parity, 1 stop bit.  tmicore overrides the default MCLK
setting of 4MHz (binary) in favor of 8MHz (binary).  The updated clock init
code ensures SMCLK is 1MHz (binary) when DCOCLK is 1MHz, 2MHz, 4MHz or 8MHz.

tos/chips/msp430/clock2/Msp430ClockP.nc [new file with mode: 0644]
tos/chips/msp430/usci/Msp430UartP.nc
tos/platforms/tmicore/MoteClockP.nc

diff --git a/tos/chips/msp430/clock2/Msp430ClockP.nc b/tos/chips/msp430/clock2/Msp430ClockP.nc
new file mode 100644 (file)
index 0000000..6649b01
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2008, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Clock initialization for msp430's with the newer basic clock +, sometimes
+ * referred to as basic clock 2.  Derived from the Msp430ClockP for the
+ * original basic clock peripheral (chips/msp430/clock/Msp430ClockP.nc), with
+ * some refinements suggested by TI in ther example code, filename
+ * MSP430x261x_dco_flashcal.c.
+ * 
+ * @author R. Steve McKown <smckown@gmail.com>
+ */
+#include <Msp430DcoSpec.h>
+
+#include "Msp430Timer.h"
+
+module Msp430ClockP @safe()
+{
+  provides interface Init;
+  provides interface Msp430ClockInit;
+}
+implementation
+{
+#if 0
+  MSP430REG_NORACE(IE1);
+  MSP430REG_NORACE(TACTL);
+  MSP430REG_NORACE(TAIV);
+  MSP430REG_NORACE(TBCTL);
+  MSP430REG_NORACE(TBIV);
+#endif
+
+  enum
+  {
+    DCOX = DCO2 + DCO1 + DCO0,
+    MODX = MOD4 + MOD3 + MOD2 + MOD1 + MOD0,
+    RSELX = RSEL3 + RSEL2 + RSEL1 + RSEL0,
+    ACLK_CALIB_PERIOD = 8,
+    TARGET_DCO_DELTA = (TARGET_DCO_KHZ / ACLK_KHZ) * ACLK_CALIB_PERIOD,
+  };
+
+
+  command void Msp430ClockInit.defaultSetupDcoCalibrate()
+  {
+    /* WARNING: Haven't verified that CCI2B, selected via CCIS_1 below, maps
+     * to ACLK for all msp430 chips, as required by this component.
+     */
+
+    BCSCTL1 |= DIVA_3;                 /* ACLK/8 */
+    TACCTL2 = CM_1 + CCIS_1 + CAP;     /* Capture on rising ACLK */
+    TACTL = TASSEL_2 + MC_2 + TACLR;   /* Continuous mode, source SMCLK */
+   }
+    
+  command void Msp430ClockInit.defaultInitClocks()
+  {
+    const unsigned int divider = TARGET_DCO_KHZ / 1000;
+
+    BCSCTL1 &= ~DIVA_3;                        /* ACLK = LFXT1/1 */
+
+    /* TinyOS upper layers assumes that SMCLK has been set to 1,048,576HZ.  If
+     * DCOCLK has been set to 1x, 2x, 4x or 8x this value, we can set SMCLK to
+     * the expected value.   Platforms using different clocks will have to set
+     * the divider or adjust its upper layers accordingly.
+     */
+    if (divider >= 8)
+      BCSCTL2 = DIVS_3;
+    else if (divider >= 4)
+      BCSCTL2 = DIVS_2;
+    else if (divider >= 2)
+      BCSCTL2 = DIVS_1;
+    else
+      BCSCTL2 = DIVS_0;
+
+    /* No interrupt for oscillator fault */
+    CLR_FLAG( IE1, OFIE );
+  }
+
+  command void Msp430ClockInit.defaultInitTimerA()
+  {
+    TACTL = TASSEL_2 | TACLR | TAIE;
+  }
+
+  command void Msp430ClockInit.defaultInitTimerB()
+  {
+    TBCTL = TBSSEL_1 | TACLR | TBIE;
+  }
+
+  default event void Msp430ClockInit.setupDcoCalibrate()
+  {
+    call Msp430ClockInit.defaultSetupDcoCalibrate();
+  }
+  
+  default event void Msp430ClockInit.initClocks()
+  {
+    call Msp430ClockInit.defaultInitClocks();
+  }
+
+  default event void Msp430ClockInit.initTimerA()
+  {
+    call Msp430ClockInit.defaultInitTimerA();
+  }
+
+  default event void Msp430ClockInit.initTimerB()
+  {
+    call Msp430ClockInit.defaultInitTimerB();
+  }
+
+
+  void startTimerA()
+  {
+    /* Start TimerA for continuous mode */
+    TACTL = (TACTL & ~MC_3) | MC_2;
+  }
+
+  void stopTimerA()
+  {
+    TACTL &= ~MC_3;
+  }
+
+  void startTimerB()
+  {
+    /* Start TimerB in continuous mode */
+    TBCTL = (TBCTL & ~MC_3) | MC_2;
+  }
+
+  void stopTimerB()
+  {
+    TBCTL &= ~MC_3;
+  }
+
+  void set_dco_calib(uint16_t calib)
+  {
+    BCSCTL1 = (BCSCTL1 & ~RSELX) | ((calib >> 8) & RSELX);
+    DCOCTL = calib & 0xff;
+  }
+
+  uint16_t test_calib_busywait_delta(uint16_t calib)
+  {
+    uint16_t capture;
+
+    set_dco_calib(calib);
+
+    /* Capture first TAR on ACLK boundary */
+    while (!(CCIFG & TACCTL2));
+    TACCTL2 &= ~CCIFG;
+    capture = TACCR2;
+
+    /* Capture next TAR */
+    while (!(CCIFG & TACCTL2));
+    TACCTL2 &= ~CCIFG;
+
+    /* Return TimerA ticks in LFXT1/8 time window */
+    return TACCR2 - capture;
+  }
+
+  void busyCalibrateDco()
+  {
+    /* calib are these bits MSb to LSb: RSELx DCOx MODx */
+    uint16_t calib;
+    uint16_t step;
+
+    for (calib = 0, step = 0x1000; step != 0; step >>= 1) {
+      // if the step is not past the target, commit it
+      if (test_calib_busywait_delta(calib | step) <= TARGET_DCO_DELTA )
+        calib |= step;
+    }
+
+    /* if DCOx is all 1's in calib, then MODx must be set to 0 */
+    if ((calib & DCOX) == DCOX)
+      calib &= ~RSELX;
+
+    set_dco_calib( calib );
+    TACCTL2 = 0;                               /* Stop TACCR2 */
+    TACTL = 0;                                 /* Stop Timer_A */
+  }
+
+  command error_t Init.init()
+  {
+    /* Reset timers and clear interrupt vectors */
+    TACTL = TACLR;
+    TAIV = 0;
+    TBCTL = TBCLR;
+    TBIV = 0;
+
+    atomic
+    {
+      signal Msp430ClockInit.setupDcoCalibrate();
+      busyCalibrateDco();
+      signal Msp430ClockInit.initClocks();
+      signal Msp430ClockInit.initTimerA();
+      signal Msp430ClockInit.initTimerB();
+      startTimerA();
+      startTimerB();
+    }
+
+    return SUCCESS;
+  }
+}
+
index ce31d9ce9e4c83b1aedf7c6471851e83a7232a65..7b39bbcd8c8a20b318e47cc91d823d64a9bc6436 100644 (file)
@@ -284,9 +284,9 @@ implementation {
   {
     const static msp430_usci_uart_t def = { 
       ctl0: UCMODE_0,          /* async, lsb first, 8N1 */
-      ctl1: UCSWRST|UCSSEL_1,  /* clock uart from SMCLK */
-      brx: UBRX_32768HZ_9600,
-      mctl: UMCTL_32768HZ_9600,
+      ctl1: UCSWRST|UCSSEL_3,  /* clock uart from SMCLK */
+      brx: UBRX_1MHZ_115200,
+      mctl: UMCTL_1MHZ_115200,
       irtctl: 0,
       irrctl: 0,
       abctl: 0,
index 543aab467e4bc3800ffc1d5a500167a5dc61aa59..3502a0a4f9c58b7fa996463933697626489ecec8 100644 (file)
@@ -50,6 +50,9 @@ module MoteClockP {
 implementation {
   command error_t Init.init()
   {
+    uint16_t i;
+
+#if defined (CALDCO_8MHZ_) && !defined(__DisableCalData)
     if (CALBC1_8MHZ != 0xff || CALDCO_8MHZ != 0xff) {
       /* Use built-in constant */
       atomic {
@@ -64,17 +67,16 @@ implementation {
        BCSCTL2 = SELM_0 | DIVM_0 | DIVS_3;
        DCOCTL = CALDCO_8MHZ;
 
-       /* Turn on TimerB, aka the 32KHz clock */
-       TBCTL |= MC1;
+       /* Turn on TimerB, driven by ACLK */
+       TBCTL |= MC_2;
       }
       return SUCCESS;
-    } else {
-      /* Constant not present; calibrate on the fly */
-      int i;
-
-      for (i = 0; i < 0xfffe; i++); /* ensure LFXT1 is stable */
-      return call SubInit.init();
     }
+#endif
+
+    /* Calibrate DCOCLK to ACLK when calibration data are disabled or erased */
+    for (i = 0; i < 0xfffe; i++); /* ensure LFXT1 is stable */
+    return call SubInit.init();
   }
 
   event void Msp430ClockInit.setupDcoCalibrate()
@@ -84,9 +86,7 @@ implementation {
 
   event void Msp430ClockInit.initClocks()
   {
-    /* We run at 8MHz, so SMCLK divider needs to be /8 */
     call Msp430ClockInit.defaultInitClocks();
-    BCSCTL2 |= DIVS_3;
   }
 
   event void Msp430ClockInit.initTimerA()