X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fmsp430%2Ftimer%2FMsp430ClockP.nc;h=7d081ab6edb1f3c0d25e5837274986d9891454b5;hb=aa4cce05c4de388b4451c7fc70bcceea95f88b7e;hp=55aaba33203581bdff602e1b62d393355f5fe05b;hpb=816c22929992f22955bffe07b387128922cbd0a5;p=tinyos-2.x.git diff --git a/tos/chips/msp430/timer/Msp430ClockP.nc b/tos/chips/msp430/timer/Msp430ClockP.nc index 55aaba33..7d081ab6 100644 --- a/tos/chips/msp430/timer/Msp430ClockP.nc +++ b/tos/chips/msp430/timer/Msp430ClockP.nc @@ -25,14 +25,13 @@ * @author Vlado Handziski */ -#include - #include "Msp430Timer.h" -module Msp430ClockP @safe() +generic module Msp430ClockP(uint16_t TARGET_DCO_KHZ, uint16_t ACLK_KHZ) @safe() { provides interface Init; provides interface Msp430ClockInit; + provides interface McuPowerOverride; } implementation { @@ -42,12 +41,25 @@ implementation 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, }; + async command mcu_power_t McuPowerOverride.lowestState() { + return MSP430_POWER_LPM3; + } command void Msp430ClockInit.defaultSetupDcoCalibrate() { @@ -63,20 +75,37 @@ implementation 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 & (RSEL2|RSEL1|RSEL0)); + 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 = 2; set the divisor of SCLK to 4 + // .DIVS = see below // .DCOR = 0; select internal resistor for DCO - BCSCTL2 = DIVS1; + // + // 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 ); @@ -159,7 +188,7 @@ implementation void set_dco_calib( int calib ) { - BCSCTL1 = (BCSCTL1 & ~0x07) | ((calib >> 8) & 0x07); + BCSCTL1 = (BCSCTL1 & ~RSELX) | ((calib >> 8) & RSELX); DCOCTL = calib & 0xff; } @@ -197,16 +226,16 @@ implementation // Binary search for RSEL,DCO,DCOMOD. // It's okay that RSEL isn't monotonic. - for( calib=0,step=0x800; step!=0; step>>=1 ) + 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 7 (0x0e0 in calib), then the 5-bit MODx is not useable, set it to 0 - if( (calib & 0x0e0) == 0x0e0 ) - calib &= ~0x01f; + // 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 ); }