From: smckown Date: Tue, 9 Sep 2008 14:32:48 +0000 (+0000) Subject: Move the clock components back into msp430/timer. It appears that supporting X-Git-Tag: release/2.1.0-1~62 X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=commitdiff_plain;h=002a2a8179c362a87f5f11eff42cc6d84d70a5be;p=tinyos-2.x.git Move the clock components back into msp430/timer. It appears that supporting the new basic clock module+ is so straightforward we don't need to separate it out. Moving things back reduces change to the main tree, making it more likely for the changes to be accepted. --- diff --git a/tos/chips/msp430/clock/Msp430ClockC.nc b/tos/chips/msp430/clock/Msp430ClockC.nc deleted file mode 100644 index ec37861a..00000000 --- a/tos/chips/msp430/clock/Msp430ClockC.nc +++ /dev/null @@ -1,38 +0,0 @@ - -/* "Copyright (c) 2000-2003 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement - * is hereby granted, provided that the above copyright notice, the following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY - * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Cory Sharp - */ - -generic configuration Msp430ClockC(uint16_t TARGET_DCO_KHZ, uint16_t ACLK_KHZ) -{ - provides interface Init; - provides interface Msp430ClockInit; -} -implementation -{ - components new Msp430ClockP(TARGET_DCO_KHZ, ACLK_KHZ); - - Init = Msp430ClockP; - Msp430ClockInit = Msp430ClockP; -} - diff --git a/tos/chips/msp430/clock/Msp430ClockInit.nc b/tos/chips/msp430/clock/Msp430ClockInit.nc deleted file mode 100644 index e78caf18..00000000 --- a/tos/chips/msp430/clock/Msp430ClockInit.nc +++ /dev/null @@ -1,39 +0,0 @@ - -/* "Copyright (c) 2000-2003 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement - * is hereby granted, provided that the above copyright notice, the following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY - * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Cory Sharp - * @author Vlado Handziski - */ - -interface Msp430ClockInit -{ - event void setupDcoCalibrate(); - event void initClocks(); - event void initTimerA(); - event void initTimerB(); - - command void defaultSetupDcoCalibrate(); - command void defaultInitClocks(); - command void defaultInitTimerA(); - command void defaultInitTimerB(); -} - diff --git a/tos/chips/msp430/clock/Msp430ClockP.nc b/tos/chips/msp430/clock/Msp430ClockP.nc deleted file mode 100644 index 82e776c0..00000000 --- a/tos/chips/msp430/clock/Msp430ClockP.nc +++ /dev/null @@ -1,261 +0,0 @@ -//$Id$ - -/* "Copyright (c) 2000-2003 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement - * is hereby granted, provided that the above copyright notice, the following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY - * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Cory Sharp - * @author Vlado Handziski - */ - -#include "Msp430Timer.h" - -generic module Msp430ClockP(uint16_t TARGET_DCO_KHZ, uint16_t ACLK_KHZ) @safe() -{ - provides interface Init; - provides interface Msp430ClockInit; -} -implementation -{ - MSP430REG_NORACE(IE1); - MSP430REG_NORACE(TACTL); - MSP430REG_NORACE(TAIV); - MSP430REG_NORACE(TBCTL); - MSP430REG_NORACE(TBIV); - - #if defined(__MSP430_HAS_BC2__) /* basic clock module+ */ - #define FIRST_STEP 0x1000 - #else /* orig basic clock module */ - #define RSEL3 0 - #define FIRST_STEP 0x800 - #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() - { - - // --- setup --- - - TACTL = TASSEL1 | MC1; // source SMCLK, continuous mode, everything else 0 - TBCTL = TBSSEL0 | MC1; - BCSCTL1 = XT2OFF | RSEL2; - BCSCTL2 = 0; - TBCCTL0 = CM0; - } - - command void Msp430ClockInit.defaultInitClocks() - { - const unsigned int divider = TARGET_DCO_KHZ / 1000; - - // BCSCTL1 - // .XT2OFF = 1; disable the external oscillator for SCLK and MCLK - // .XTS = 0; set low frequency mode for LXFT1 - // .DIVA = 0; set the divisor on ACLK to 1 - // .RSEL, do not modify - BCSCTL1 = XT2OFF | (BCSCTL1 & RSELX); - - // BCSCTL2 - // .SELM = 0; select DCOCLK as source for MCLK - // .DIVM = 0; set the divisor of MCLK to 1 - // .SELS = 0; select DCOCLK as source for SCLK - // .DIVS = see below - // .DCOR = 0; select internal resistor for DCO - // - // TinyOS upper layers assume SMCLK runs at 1 binary MHz, or 1,048,576HZ. - // If DCOCLK has been set to 1, 2, 4 or 8 binary MHz, we can correctly set - // SMCLK to the expected value. Platforms using different clocks should - // set the divider by overriding Msp430ClockInit.initClocks(), calling - // Msp430ClockInit.defaultInitClocks(), then massaging the DIVS bits as - // required. - if (divider >= 8) - BCSCTL2 = DIVS_3; - else if (divider >= 4) - BCSCTL2 = DIVS_2; - else if (divider >= 2) - BCSCTL2 = DIVS_1; - else - BCSCTL2 = DIVS_0; - - - // IE1.OFIE = 0; no interrupt for oscillator fault - CLR_FLAG( IE1, OFIE ); - } - - command void Msp430ClockInit.defaultInitTimerA() - { - TAR = 0; - - // TACTL - // .TACLGRP = 0; each TACL group latched independently - // .CNTL = 0; 16-bit counter - // .TASSEL = 2; source SMCLK = DCO/4 - // .ID = 0; input divisor of 1 - // .MC = 0; initially disabled - // .TACLR = 0; reset timer A - // .TAIE = 1; enable timer A interrupts - TACTL = TASSEL1 | TAIE; - } - - command void Msp430ClockInit.defaultInitTimerB() - { - TBR = 0; - - // TBCTL - // .TBCLGRP = 0; each TBCL group latched independently - // .CNTL = 0; 16-bit counter - // .TBSSEL = 1; source ACLK - // .ID = 0; input divisor of 1 - // .MC = 0; initially disabled - // .TBCLR = 0; reset timer B - // .TBIE = 1; enable timer B interrupts - TBCTL = TBSSEL0 | 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() - { - // TACTL.MC = 2; continuous mode - TACTL = MC1 | (TACTL & ~(MC1|MC0)); - } - - void stopTimerA() - { - //TACTL.MC = 0; stop timer B - TACTL = TACTL & ~(MC1|MC0); - } - - void startTimerB() - { - // TBCTL.MC = 2; continuous mode - TBCTL = MC1 | (TBCTL & ~(MC1|MC0)); - } - - void stopTimerB() - { - //TBCTL.MC = 0; stop timer B - TBCTL = TBCTL & ~(MC1|MC0); - } - - void set_dco_calib( int calib ) - { - BCSCTL1 = (BCSCTL1 & ~RSELX) | ((calib >> 8) & RSELX); - DCOCTL = calib & 0xff; - } - - uint16_t test_calib_busywait_delta( int calib ) - { - int8_t aclk_count = 2; - uint16_t dco_prev = 0; - uint16_t dco_curr = 0; - - set_dco_calib( calib ); - - while( aclk_count-- > 0 ) - { - TBCCR0 = TBR + ACLK_CALIB_PERIOD; // set next interrupt - TBCCTL0 &= ~CCIFG; // clear pending interrupt - while( (TBCCTL0 & CCIFG) == 0 ); // busy wait - dco_prev = dco_curr; - dco_curr = TAR; - } - - return dco_curr - dco_prev; - } - - // busyCalibrateDCO - // Should take about 9ms if ACLK_CALIB_PERIOD=8. - // DCOCTL and BCSCTL1 are calibrated when done. - void busyCalibrateDco() - { - // --- variables --- - int calib; - int step; - - // --- calibrate --- - - // Binary search for RSEL,DCO,DCOMOD. - // It's okay that RSEL isn't monotonic. - - for( calib=0,step=FIRST_STEP; 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 1s in calib, then MODx is not useable, set it to 0 - if( (calib & DCOX) == DCOX ) - calib &= ~MODX; - - set_dco_calib( calib ); - } - - 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; - } -} - diff --git a/tos/chips/msp430/clock/Msp430DcoCalibC.nc b/tos/chips/msp430/clock/Msp430DcoCalibC.nc deleted file mode 100644 index 78e4e9e4..00000000 --- a/tos/chips/msp430/clock/Msp430DcoCalibC.nc +++ /dev/null @@ -1,36 +0,0 @@ - -/* "Copyright (c) 2000-2003 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement - * is hereby granted, provided that the above copyright notice, the following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY - * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Cory Sharp - */ - -configuration Msp430DcoCalibC -{ -} -implementation -{ - components Msp430DcoCalibP, Msp430TimerC; - - Msp430DcoCalibP.TimerMicro -> Msp430TimerC.TimerA; - Msp430DcoCalibP.Timer32khz -> Msp430TimerC.TimerB; -} - diff --git a/tos/chips/msp430/clock/Msp430DcoCalibP.nc b/tos/chips/msp430/clock/Msp430DcoCalibP.nc deleted file mode 100644 index d75e9aad..00000000 --- a/tos/chips/msp430/clock/Msp430DcoCalibP.nc +++ /dev/null @@ -1,82 +0,0 @@ - -/* "Copyright (c) 2000-2003 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement - * is hereby granted, provided that the above copyright notice, the following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY - * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Cory Sharp - */ - -#error "Msp430DcoCalibP is broken and will incorrectly adjust TimerA because it does not take into account MCU sleep." - -module Msp430DcoCalibP -{ - uses interface Msp430Timer as TimerMicro; - uses interface Msp430Timer as Timer32khz; -} -implementation -{ - uint16_t m_prev; - - enum - { - TARGET_DELTA = 2048, // number of 32khz ticks during 65536 ticks at 1mhz - MAX_DEVIATION = 7, // about 0.35% error - }; - - // this gets executed 32 times a second - async event void TimerMicro.overflow() - { - uint16_t now = call Timer32khz.get(); - uint16_t delta = now - m_prev; - m_prev = now; - - if( delta > (TARGET_DELTA+MAX_DEVIATION) ) - { - // too many 32khz ticks means the DCO is running too slow, speed it up - if( DCOCTL < 0xe0 ) - { - DCOCTL++; - } - else if( (BCSCTL1 & 7) < 7 ) - { - BCSCTL1++; - DCOCTL = 96; - } - } - else if( delta < (TARGET_DELTA-MAX_DEVIATION) ) - { - // too few 32khz ticks means the DCO is running too fast, slow it down - if( DCOCTL > 0 ) - { - DCOCTL--; - } - else if( (BCSCTL1 & 7) > 0 ) - { - BCSCTL1--; - DCOCTL = 128; - } - } - } - - async event void Timer32khz.overflow() - { - } -} - diff --git a/tos/chips/msp430/timer/Msp430ClockC.nc b/tos/chips/msp430/timer/Msp430ClockC.nc new file mode 100644 index 00000000..ec37861a --- /dev/null +++ b/tos/chips/msp430/timer/Msp430ClockC.nc @@ -0,0 +1,38 @@ + +/* "Copyright (c) 2000-2003 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * @author Cory Sharp + */ + +generic configuration Msp430ClockC(uint16_t TARGET_DCO_KHZ, uint16_t ACLK_KHZ) +{ + provides interface Init; + provides interface Msp430ClockInit; +} +implementation +{ + components new Msp430ClockP(TARGET_DCO_KHZ, ACLK_KHZ); + + Init = Msp430ClockP; + Msp430ClockInit = Msp430ClockP; +} + diff --git a/tos/chips/msp430/timer/Msp430ClockInit.nc b/tos/chips/msp430/timer/Msp430ClockInit.nc new file mode 100644 index 00000000..e78caf18 --- /dev/null +++ b/tos/chips/msp430/timer/Msp430ClockInit.nc @@ -0,0 +1,39 @@ + +/* "Copyright (c) 2000-2003 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * @author Cory Sharp + * @author Vlado Handziski + */ + +interface Msp430ClockInit +{ + event void setupDcoCalibrate(); + event void initClocks(); + event void initTimerA(); + event void initTimerB(); + + command void defaultSetupDcoCalibrate(); + command void defaultInitClocks(); + command void defaultInitTimerA(); + command void defaultInitTimerB(); +} + diff --git a/tos/chips/msp430/timer/Msp430ClockP.nc b/tos/chips/msp430/timer/Msp430ClockP.nc new file mode 100644 index 00000000..82e776c0 --- /dev/null +++ b/tos/chips/msp430/timer/Msp430ClockP.nc @@ -0,0 +1,261 @@ +//$Id$ + +/* "Copyright (c) 2000-2003 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * @author Cory Sharp + * @author Vlado Handziski + */ + +#include "Msp430Timer.h" + +generic module Msp430ClockP(uint16_t TARGET_DCO_KHZ, uint16_t ACLK_KHZ) @safe() +{ + provides interface Init; + provides interface Msp430ClockInit; +} +implementation +{ + MSP430REG_NORACE(IE1); + MSP430REG_NORACE(TACTL); + MSP430REG_NORACE(TAIV); + MSP430REG_NORACE(TBCTL); + MSP430REG_NORACE(TBIV); + + #if defined(__MSP430_HAS_BC2__) /* basic clock module+ */ + #define FIRST_STEP 0x1000 + #else /* orig basic clock module */ + #define RSEL3 0 + #define FIRST_STEP 0x800 + #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() + { + + // --- setup --- + + TACTL = TASSEL1 | MC1; // source SMCLK, continuous mode, everything else 0 + TBCTL = TBSSEL0 | MC1; + BCSCTL1 = XT2OFF | RSEL2; + BCSCTL2 = 0; + TBCCTL0 = CM0; + } + + command void Msp430ClockInit.defaultInitClocks() + { + const unsigned int divider = TARGET_DCO_KHZ / 1000; + + // BCSCTL1 + // .XT2OFF = 1; disable the external oscillator for SCLK and MCLK + // .XTS = 0; set low frequency mode for LXFT1 + // .DIVA = 0; set the divisor on ACLK to 1 + // .RSEL, do not modify + BCSCTL1 = XT2OFF | (BCSCTL1 & RSELX); + + // BCSCTL2 + // .SELM = 0; select DCOCLK as source for MCLK + // .DIVM = 0; set the divisor of MCLK to 1 + // .SELS = 0; select DCOCLK as source for SCLK + // .DIVS = see below + // .DCOR = 0; select internal resistor for DCO + // + // TinyOS upper layers assume SMCLK runs at 1 binary MHz, or 1,048,576HZ. + // If DCOCLK has been set to 1, 2, 4 or 8 binary MHz, we can correctly set + // SMCLK to the expected value. Platforms using different clocks should + // set the divider by overriding Msp430ClockInit.initClocks(), calling + // Msp430ClockInit.defaultInitClocks(), then massaging the DIVS bits as + // required. + if (divider >= 8) + BCSCTL2 = DIVS_3; + else if (divider >= 4) + BCSCTL2 = DIVS_2; + else if (divider >= 2) + BCSCTL2 = DIVS_1; + else + BCSCTL2 = DIVS_0; + + + // IE1.OFIE = 0; no interrupt for oscillator fault + CLR_FLAG( IE1, OFIE ); + } + + command void Msp430ClockInit.defaultInitTimerA() + { + TAR = 0; + + // TACTL + // .TACLGRP = 0; each TACL group latched independently + // .CNTL = 0; 16-bit counter + // .TASSEL = 2; source SMCLK = DCO/4 + // .ID = 0; input divisor of 1 + // .MC = 0; initially disabled + // .TACLR = 0; reset timer A + // .TAIE = 1; enable timer A interrupts + TACTL = TASSEL1 | TAIE; + } + + command void Msp430ClockInit.defaultInitTimerB() + { + TBR = 0; + + // TBCTL + // .TBCLGRP = 0; each TBCL group latched independently + // .CNTL = 0; 16-bit counter + // .TBSSEL = 1; source ACLK + // .ID = 0; input divisor of 1 + // .MC = 0; initially disabled + // .TBCLR = 0; reset timer B + // .TBIE = 1; enable timer B interrupts + TBCTL = TBSSEL0 | 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() + { + // TACTL.MC = 2; continuous mode + TACTL = MC1 | (TACTL & ~(MC1|MC0)); + } + + void stopTimerA() + { + //TACTL.MC = 0; stop timer B + TACTL = TACTL & ~(MC1|MC0); + } + + void startTimerB() + { + // TBCTL.MC = 2; continuous mode + TBCTL = MC1 | (TBCTL & ~(MC1|MC0)); + } + + void stopTimerB() + { + //TBCTL.MC = 0; stop timer B + TBCTL = TBCTL & ~(MC1|MC0); + } + + void set_dco_calib( int calib ) + { + BCSCTL1 = (BCSCTL1 & ~RSELX) | ((calib >> 8) & RSELX); + DCOCTL = calib & 0xff; + } + + uint16_t test_calib_busywait_delta( int calib ) + { + int8_t aclk_count = 2; + uint16_t dco_prev = 0; + uint16_t dco_curr = 0; + + set_dco_calib( calib ); + + while( aclk_count-- > 0 ) + { + TBCCR0 = TBR + ACLK_CALIB_PERIOD; // set next interrupt + TBCCTL0 &= ~CCIFG; // clear pending interrupt + while( (TBCCTL0 & CCIFG) == 0 ); // busy wait + dco_prev = dco_curr; + dco_curr = TAR; + } + + return dco_curr - dco_prev; + } + + // busyCalibrateDCO + // Should take about 9ms if ACLK_CALIB_PERIOD=8. + // DCOCTL and BCSCTL1 are calibrated when done. + void busyCalibrateDco() + { + // --- variables --- + int calib; + int step; + + // --- calibrate --- + + // Binary search for RSEL,DCO,DCOMOD. + // It's okay that RSEL isn't monotonic. + + for( calib=0,step=FIRST_STEP; 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 1s in calib, then MODx is not useable, set it to 0 + if( (calib & DCOX) == DCOX ) + calib &= ~MODX; + + set_dco_calib( calib ); + } + + 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; + } +} + diff --git a/tos/chips/msp430/timer/Msp430DcoCalibC.nc b/tos/chips/msp430/timer/Msp430DcoCalibC.nc new file mode 100644 index 00000000..78e4e9e4 --- /dev/null +++ b/tos/chips/msp430/timer/Msp430DcoCalibC.nc @@ -0,0 +1,36 @@ + +/* "Copyright (c) 2000-2003 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * @author Cory Sharp + */ + +configuration Msp430DcoCalibC +{ +} +implementation +{ + components Msp430DcoCalibP, Msp430TimerC; + + Msp430DcoCalibP.TimerMicro -> Msp430TimerC.TimerA; + Msp430DcoCalibP.Timer32khz -> Msp430TimerC.TimerB; +} + diff --git a/tos/chips/msp430/timer/Msp430DcoCalibP.nc b/tos/chips/msp430/timer/Msp430DcoCalibP.nc new file mode 100644 index 00000000..d75e9aad --- /dev/null +++ b/tos/chips/msp430/timer/Msp430DcoCalibP.nc @@ -0,0 +1,82 @@ + +/* "Copyright (c) 2000-2003 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * @author Cory Sharp + */ + +#error "Msp430DcoCalibP is broken and will incorrectly adjust TimerA because it does not take into account MCU sleep." + +module Msp430DcoCalibP +{ + uses interface Msp430Timer as TimerMicro; + uses interface Msp430Timer as Timer32khz; +} +implementation +{ + uint16_t m_prev; + + enum + { + TARGET_DELTA = 2048, // number of 32khz ticks during 65536 ticks at 1mhz + MAX_DEVIATION = 7, // about 0.35% error + }; + + // this gets executed 32 times a second + async event void TimerMicro.overflow() + { + uint16_t now = call Timer32khz.get(); + uint16_t delta = now - m_prev; + m_prev = now; + + if( delta > (TARGET_DELTA+MAX_DEVIATION) ) + { + // too many 32khz ticks means the DCO is running too slow, speed it up + if( DCOCTL < 0xe0 ) + { + DCOCTL++; + } + else if( (BCSCTL1 & 7) < 7 ) + { + BCSCTL1++; + DCOCTL = 96; + } + } + else if( delta < (TARGET_DELTA-MAX_DEVIATION) ) + { + // too few 32khz ticks means the DCO is running too fast, slow it down + if( DCOCTL > 0 ) + { + DCOCTL--; + } + else if( (BCSCTL1 & 7) > 0 ) + { + BCSCTL1--; + DCOCTL = 128; + } + } + } + + async event void Timer32khz.overflow() + { + } +} + diff --git a/tos/platforms/eyesIFX/.family b/tos/platforms/eyesIFX/.family index f40d14fe..fa237c92 100644 --- a/tos/platforms/eyesIFX/.family +++ b/tos/platforms/eyesIFX/.family @@ -17,7 +17,6 @@ push( @includes, qw( %T/chips/ad5200 %T/chips/msp430 %T/chips/msp430/adc12 - %T/chips/msp430/clock %T/chips/msp430/dma %T/chips/msp430/pins %T/chips/msp430/sensors diff --git a/tos/platforms/shimmer/.platform b/tos/platforms/shimmer/.platform index 310bbb72..ecaad4be 100644 --- a/tos/platforms/shimmer/.platform +++ b/tos/platforms/shimmer/.platform @@ -27,7 +27,6 @@ push( @includes, qw( %T/chips/cc2420/unique %T/chips/msp430 %T/chips/msp430/adc12 - %T/chips/msp430/clock %T/chips/msp430/dma %T/chips/msp430/pins %T/chips/msp430/timer diff --git a/tos/platforms/telosa/.platform b/tos/platforms/telosa/.platform index 00f9de94..2f273950 100644 --- a/tos/platforms/telosa/.platform +++ b/tos/platforms/telosa/.platform @@ -27,7 +27,6 @@ push( @includes, qw( %T/chips/at45db %T/chips/msp430 %T/chips/msp430/adc12 - %T/chips/msp430/clock %T/chips/msp430/pins %T/chips/msp430/timer %T/chips/msp430/usart diff --git a/tos/platforms/telosb/.platform b/tos/platforms/telosb/.platform index 816de3fd..5fab8f26 100644 --- a/tos/platforms/telosb/.platform +++ b/tos/platforms/telosb/.platform @@ -26,7 +26,6 @@ push( @includes, qw( %T/chips/cc2420/transmit %T/chips/cc2420/unique %T/chips/msp430 - %T/chips/msp430/clock %T/chips/msp430/adc12 %T/chips/msp430/dma %T/chips/msp430/pins diff --git a/tos/platforms/tinynode/.platform b/tos/platforms/tinynode/.platform index a6050ac4..818c7a83 100644 --- a/tos/platforms/tinynode/.platform +++ b/tos/platforms/tinynode/.platform @@ -19,7 +19,6 @@ push( @includes, qw( %T/chips/msp430 %T/chips/msp430/adc12 - %T/chips/msp430/clock %T/chips/msp430/dma %T/chips/msp430/pins %T/chips/msp430/timer diff --git a/tos/platforms/tmicore/.platform b/tos/platforms/tmicore/.platform index 3cd16861..3cd5e01a 100755 --- a/tos/platforms/tmicore/.platform +++ b/tos/platforms/tmicore/.platform @@ -9,7 +9,6 @@ push( @includes, qw( %T/chips/msp430 %T/chips/msp430/adc12 %T/chips/msp430/clock2 - %T/chips/msp430/clock %T/chips/msp430/dma %T/chips/msp430/pins %T/chips/msp430/timer