msp430clockm.nc

来自「tinyos最新版」· NC 代码 · 共 286 行

NC
286
字号
//$Id: MSP430ClockM.nc,v 1.11 2004/09/28 18:19:55 cssharp Exp $/* "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 <cssharp@eecs.berkeley.edu>includes MSP430Timer;module MSP430ClockM{  provides interface StdControl;  provides interface MSP430ClockInit;  uses interface MSP430Compare as ACLKCompare;  uses interface MSP430TimerControl as ACLKControl;}implementation{  MSP430REG_NORACE(IE1);  MSP430REG_NORACE(TACTL);  MSP430REG_NORACE(TAIV);  MSP430REG_NORACE(TBCTL);  MSP430REG_NORACE(TBIV);  volatile norace uint16_t m_dco_curr;  volatile norace uint16_t m_dco_prev;  volatile norace uint8_t m_aclk_count;  enum  {    ACLK_CALIB_PERIOD = 128,    ACLK_KHZ = 32,    TARGET_DCO_KHZ = 4096, // prescribe the cpu clock rate in kHz    TARGET_DCO_DELTA = (TARGET_DCO_KHZ / ACLK_KHZ) * ACLK_CALIB_PERIOD,  };  command void MSP430ClockInit.defaultInitClocks()  {    // 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 & (RSEL2|RSEL1|RSEL0));    // 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 = 2; set the divisor of SCLK to 4    // .DCOR = 0; select internal resistor for DCO    BCSCTL2 = DIVS1;    // 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.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);  }  async event void ACLKCompare.fired()  {    if( m_aclk_count > 0 )    {      m_dco_prev = m_dco_curr;      m_dco_curr = TAR;      if( m_aclk_count > 1 )	call ACLKCompare.setEventFromPrev( ACLK_CALIB_PERIOD );      m_aclk_count--;    }  }  void set_calib( int calib )  {    BCSCTL1 = (BCSCTL1 & ~0x07) | ((calib >> 8) & 0x07);    DCOCTL = calib & 0xff;  }  void test_calib( int calib )  {    set_calib( calib );    m_aclk_count = 2;    call ACLKCompare.setEventFromNow( ACLK_CALIB_PERIOD );  }  uint16_t busywait_delta()  {    while( m_aclk_count != 0 ) { }    return m_dco_curr - m_dco_prev;  }  uint16_t test_calib_busywait_delta( int calib )  {    test_calib( calib );    return busywait_delta();  }  // busyCalibrateDCO: DESTRUCTIVE TO ALL TIMERS  void busyCalibrateDCO()  {    // --- variables ---    int calib;    int step;    // --- setup ---    // destructive: force all clocks and timers into a default state    // (using TimerA2 with ACLK as its source this didn't work, wth)    m_aclk_count = 0;    TACTL = TASSEL1 | MC1; // source SMCLK, continuous mode, everything else 0    TBCTL = TBSSEL0 | MC1;    CLR_FLAG( IE1, OFIE );    BCSCTL1 = XT2OFF | RSEL2;    BCSCTL2 = 0;    TACCTL0 = 0;    TACCTL1 = 0;    TACCTL2 = 0;    TBCCTL0 = 0;    TBCCTL1 = 0;    TBCCTL2 = 0;    TBCCTL3 = 0;    TBCCTL4 = 0;    TBCCTL5 = 0;    TBCCTL6 = 0;    SET_FLAG( TBCTL, TBIE ); // enable timer b interrupts    call ACLKControl.setControlAsCompare();    call ACLKControl.enableEvents();    // --- calibrate ---    // Binary search for RSEL,DCO,DCOMOD.    // It's okay that RSEL isn't monotonic.    for( calib=0,step=0x800; 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;    }    // --- restore ---    // disable Timer A and A2    TACTL = 0;    TBCTL = 0;    TBCCTL2 = 0;  }  void garnishedBusyCalibrateDCO()  {    bool do_dint;    do_dint = !are_interrupts_enabled();    eint();    busyCalibrateDCO();    if(do_dint)      dint();  }      command result_t StdControl.init()  {    // Reset timers and clear interrupt vectors    TACTL = TACLR;    TAIV = 0;    TBCTL = TBCLR;    TBIV = 0;    garnishedBusyCalibrateDCO();    atomic    {      signal MSP430ClockInit.initClocks();      signal MSP430ClockInit.initTimerA();      signal MSP430ClockInit.initTimerB();    }    return SUCCESS;  }  command result_t StdControl.start()  {    atomic    {      startTimerA();      startTimerB();    }    return SUCCESS;  }  command result_t StdControl.stop()  {    atomic    {      stopTimerB();      stopTimerA();    }    return SUCCESS;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?