int iBSP430bc2TrimToMCLK_ni (unsigned long mclk_Hz) { volatile sBSP430hplTIMER * tp = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE); const int MAX_ITERATIONS = 16 * 256; int rv = -1; unsigned long aclk_Hz; int iter = 0; const int SAMPLE_PERIOD_ACLK = 10; unsigned char bcsctl3; unsigned int target_tsp; if (! tp) { return -1; } bcsctl3 = BCSCTL3; if (0 != iBSP430clockConfigureACLK_ni(eBSP430clockSRC_XT1CLK_OR_VLOCLK)) { return -1; } aclk_Hz = ulBSP430clockACLK_Hz_ni(); target_tsp = (SAMPLE_PERIOD_ACLK * mclk_Hz) / aclk_Hz; tp->ctl = TASSEL_2 | MC_2 | TACLR; /* SELM = DCOCLK; DIVM = /1 */ BCSCTL2 &= ~(SELM_MASK | DIVM_MASK); while (iter++ < MAX_ITERATIONS) { unsigned int freq_tsp; freq_tsp = uiBSP430timerCaptureDelta_ni(BSP430_TIMER_CCACLK_PERIPH_HANDLE, BSP430_TIMER_CCACLK_ACLK_CCIDX, CM_2, BSP430_TIMER_CCACLK_ACLK_CCIS, SAMPLE_PERIOD_ACLK); if (freq_tsp == target_tsp) { configuredMCLK_Hz = mclk_Hz; rv = 0; break; } if (target_tsp < freq_tsp) { /* DCO too fast. Decrement modulator; if underflowed, * decrement RSEL */ if (0xFF == --DCOCTL) { --BCSCTL1; } } else { /* DCO too slow. Increment modulator; if overflowed, * increment RSEL */ if (0 == ++DCOCTL) { ++BCSCTL1; } } } tp->ctl = 0; BCSCTL3 = bcsctl3; return rv; }
void main () { #if (BSP430_CONSOLE - 0) const char * help; unsigned long smclk_Hz; unsigned long aclk_Hz; #endif /* BSP430_CONSOLE */ /* First thing you do in main is configure the platform. */ vBSP430platformInitialize_ni(); /* If we support a console, dump out a bunch of configuration * information. */ #if (BSP430_CONSOLE - 0) (void)iBSP430consoleInitialize(); cputtext("\nclocks " __DATE__ " " __TIME__ "\n"); cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_LFXT1: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_LFXT1, 10); cputtext("\nBSP430_CLOCK_LFXT1_STABILIZATION_DELAY_CYCLES: "); cputul(BSP430_CLOCK_LFXT1_STABILIZATION_DELAY_CYCLES, 10); cputtext("\nBSP430_PLATFORM_BOOT_LFXT1_DELAY_SEC: "); cputu(BSP430_PLATFORM_BOOT_LFXT1_DELAY_SEC, 10); cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_CLOCKS: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_CLOCKS, 10); #if defined(__MSP430_HAS_BC2__) #if (configBSP430_BC2_TRIM_TO_MCLK - 0) cputtext("\nconfigBSP430_BC2_TRIM_TO_MCLK: 1"); #else /* configBSP430_BC2_TRIM_TO_MCLK */ cputtext("\nconfigBSP430_BC2_TRIM_TO_MCLK: 0"); #endif /* configBSP430_BC2_TRIM_TO_MCLK */ #if (BSP430_BC2_TRIM_TO_MCLK - 0) cputtext("\nBSP430_BC2_TRIM_TO_MCLK: 1"); #else /* BSP430_BC2_TRIM_TO_MCLK */ cputtext("\nBSP430_BC2_TRIM_TO_MCLK: 0"); #endif /* BSP430_BC2_TRIM_TO_MCLK */ #endif /* BC2 */ #if defined(__MSP430_HAS_UCS__) || defined(__MSP430_HAS_UCS_RF__) #if (configBSP430_UCS_TRIM_DCOCLKDIV - 0) cputtext("\nconfigBSP430_UCS_TRIM_DCOCLKDIV: 1"); #else /* configBSP430_UCS_TRIM_DCOCLKDIV */ cputtext("\nconfigBSP430_UCS_TRIM_DCOCLKDIV: 0"); #endif /* configBSP430_UCS_TRIM_DCOCLKDIV */ #if (BSP430_UCS_TRIM_DCOCLKDIV - 0) cputtext("\nBSP430_UCS_TRIM_DCOCLKDIV: 1"); #else /* BSP430_UCS_TRIM_DCOCLKDIV */ cputtext("\nBSP430_UCS_TRIM_DCOCLKDIV: 0"); #endif /* BSP430_UCS_TRIM_DCOCLKDIV */ #endif /* UCS */ cputtext("\nBSP430_CLOCK_PUC_MCLK_HZ: "); cputul(BSP430_CLOCK_PUC_MCLK_HZ, 10); cputtext("\nBSP430_CLOCK_NOMINAL_MCLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_MCLK_HZ, 10); cputtext("\nBSP430_CLOCK_LFXT1_IS_FAULTED_NI(): "); cputu(BSP430_CLOCK_LFXT1_IS_FAULTED_NI(), 10); cputtext("\nBSP430_CLOCK_NOMINAL_VLOCLK_HZ: "); cputu(BSP430_CLOCK_NOMINAL_VLOCLK_HZ, 10); cputtext("\nBSP430_CLOCK_NOMINAL_XT1CLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_XT1CLK_HZ, 10); #if defined(BSP430_CLOCK_NOMINAL_XT2CLK_HZ) cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_XT2: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_XT2, 10); cputtext("\nBSP430_CLOCK_XT2_IS_FAULTED_NI(): "); cputu(BSP430_CLOCK_XT2_IS_FAULTED_NI(), 10); cputtext("\nBSP430_CLOCK_NOMINAL_XT2CLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_XT2CLK_HZ, 10); #endif /* BSP430_CLOCK_NOMINAL_XT2CLK_HZ */ cputtext("\nulBSP430clockMCLK_Hz_ni(): "); cputul(ulBSP430clockMCLK_Hz_ni(), 10); cputtext("\nBSP430_PLATFORM_BOOT_SMCLK_DIVIDING_SHIFT: "); cputi(BSP430_PLATFORM_BOOT_SMCLK_DIVIDING_SHIFT, 10); cputtext("\nulBSP430clockSMCLK_Hz_ni(): "); smclk_Hz = ulBSP430clockSMCLK_Hz_ni(); cputul(smclk_Hz, 10); cputtext("\nBSP430_PLATFORM_BOOT_ACLK_DIVIDING_SHIFT: "); cputi(BSP430_PLATFORM_BOOT_ACLK_DIVIDING_SHIFT, 10); cputtext("\nulBSP430clockACLK_Hz_ni(): "); aclk_Hz = ulBSP430clockACLK_Hz_ni(); cputul(aclk_Hz, 10); #if (BSP430_TIMER_CCACLK - 0) if (1000000UL <= aclk_Hz) { cputtext("\nUnable to use high-speed ACLK for differential timing of SMCLK"); } else { do { const unsigned int SAMPLE_PERIOD_ACLK = 10; volatile sBSP430hplTIMER * tp = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE); unsigned int cc_delta; unsigned long aclk_rel_smclk_Hz; unsigned long smclk_rel_aclk_Hz; if (! tp) { cputtext("\nUnable to access configured CCACLK timer"); break; } /* Capture the SMCLK ticks between adjacent ACLK ticks */ tp->ctl = TASSEL_2 | MC_2 | TACLR; cc_delta = uiBSP430timerCaptureDelta_ni(BSP430_TIMER_CCACLK_PERIPH_HANDLE, BSP430_TIMER_CCACLK_ACLK_CCIDX, CM_2, BSP430_TIMER_CCACLK_ACLK_CCIS, SAMPLE_PERIOD_ACLK); tp->ctl = 0; if (-1 == cc_delta) { cputtext("\nCCACLK measurement failed"); break; } cputchar('\n'); cputu(SAMPLE_PERIOD_ACLK, 10); cputtext(" ticks of ACLK produced "); cputu(cc_delta, 10); cputtext(" ticks of SMCLK"); cputtext("\nComparison with measured values:"); cputtext("\n SMCLK (Hz) (if measured ACLK correct): "); smclk_rel_aclk_Hz = (cc_delta * aclk_Hz) / SAMPLE_PERIOD_ACLK; cputul(smclk_rel_aclk_Hz, 10); cputtext(" (error "); cputl(smclk_rel_aclk_Hz - smclk_Hz, 10); cputtext(" = "); cputl(1000 * labs(smclk_rel_aclk_Hz - smclk_Hz) / smclk_Hz, 10); cputtext(" kHz/MHz)"); cputtext("\n ACLK (Hz) (if measured SMCLK correct): "); aclk_rel_smclk_Hz = SAMPLE_PERIOD_ACLK * smclk_Hz / cc_delta; cputul(aclk_rel_smclk_Hz, 10); cputtext(" (error "); cputl(aclk_rel_smclk_Hz - aclk_Hz, 10); cputtext(" = "); cputl(1000 * labs(aclk_rel_smclk_Hz - aclk_Hz) / aclk_Hz, 10); cputtext(" Hz/kHz)"); } while (0); } #else /* BSP430_TIMER_CCACLK */ cputtext("\nNo CCACLK timer available for ACLK/SMCLK comparison"); #endif /* BSP430_TIMER_CCACLK */ cputchar('\n'); #if defined(__MSP430_HAS_BC2__) cputtext("\nBC2: DCO "); cputu(DCOCTL, 16); cputtext(" CTL1 "); cputu(BCSCTL1, 16); cputtext(" CTL2 "); cputu(BCSCTL2, 16); cputtext(" CTL3 "); cputu(BCSCTL3, 16); #endif #if defined(__MSP430_HAS_FLL__) || defined(__MSP430_HAS_FLLPLUS__) cprintf("\nFLL: SCF QCTL %02x I0 %02x I1 %02x ; CTL0 %02x CTL1 %02x CTL2 %02x\n", SCFQCTL, SCFI0, SCFI1, FLL_CTL0, FLL_CTL1, #if defined(FLL_CTL2_) FLL_CTL2 #else /* FLL_CTL2 */ ~0 #endif /* FLL_CTL2 */ ); #endif /* FLL/PLUS */ #if defined(__MSP430_HAS_UCS__) || defined(__MSP430_HAS_UCS_RF__) cputtext("\nBSP430_UCS_FLL_SELREF: " #if SELREF__XT2CLK <= BSP430_UCS_FLL_SELREF "XT2CLK" #elif SELREF__REFOCLK <= BSP430_UCS_FLL_SELREF "REFOCLK" #else /* BSP430_UCS_FLL_SELREF */ "XT1CLK" #endif /* BSP430_UCS_FLL_SELREF */ ); cprintf("\nUCS RSEL %d DCO %d MOD %d:" "\n CTL0 %04x CTL1 %04x CTL2 %04x CTL3 %04x" "\n CTL4 %04x CTL5 %04x CTL6 %04x CTL7 %04x", 0x1F & (UCSCTL1 / DCORSEL0), 0x1F & (UCSCTL0 / DCO0), 0x1F & (UCSCTL0 / MOD0), UCSCTL0, UCSCTL1, UCSCTL2, UCSCTL3, UCSCTL4, UCSCTL5, UCSCTL6, UCSCTL7); #endif /* UCS */ #if defined(__MSP430_HAS_CS__) || defined(__MSP430_HAS_CS_A__) cprintf("\nCS %s : RSEL %d DCOFSEL %d:" "\n CTL0 %04x CTL1 %04x CTL2 %04x CTL3 %04x" "\n CTL4 %04x CTL5 %04x CTL6 %04x" "\n FRCTL0 %04x", #if (BSP430_CS_IS_FR57XX - 0) "FR57xx" #endif #if (BSP430_CS_IS_FR58XX - 0) "FR58xx" #endif "", !!(DCORSEL & CSCTL1), 0x07 & (CSCTL1 / DCOFSEL0), CSCTL0, CSCTL1, CSCTL2, CSCTL3, CSCTL4, CSCTL5, CSCTL6, FRCTL0); #endif /* CS */ #endif /* BSP430_CONSOLE */ if (0 == iBSP430platformConfigurePeripheralPins_ni(BSP430_PERIPH_EXPOSED_CLOCKS, 0, 1)) { #if (BSP430_CONSOLE - 0) cputtext("\n\nClock signals exposed:\n "); help = NULL; #ifdef BSP430_PLATFORM_PERIPHERAL_HELP help = xBSP430platformPeripheralHelp(BSP430_PERIPH_EXPOSED_CLOCKS, 0); #endif /* BSP430_PLATFORM_PERIPHERAL_HELP */ if (NULL == help) { help = "Go look at the data sheet and source, because nobody told me where they are"; } cputtext(help); cputtext("\nStatus register LPM bits: "); cputu(__read_status_register() & BSP430_CORE_LPM_SR_MASK, 16); cputtext("\nIFG1 bits: "); #if defined(__MSP430_HAS_MSP430XV2_CPU__) cputu(SFRIFG1, 16); #else /* CPUX */ cputu(IFG1, 16); #endif /* CPUX */ cputtext(" with OFIFG "); cputu(OFIFG, 16); cputchar('\n'); #endif /* BSP430_CONSOLE */ /* Spin here with CPU active. In LPM0, MCLK is disabled. Other * clocks get disabled at deeper sleep modes; if you fall off the * bottom, you might end up in LPM4 with all clocks disabled. */ while (1) { vBSP430ledSet(0, -1); BSP430_CORE_WATCHDOG_CLEAR(); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ / 2); } } else { #if (BSP430_CONSOLE - 0) cputtext("\nFailed to expose clock signals\n"); #endif /* BSP430_CONSOLE */ } }
int hh10d_offs; int hh10d_sens; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nApplication starting\n"); BSP430_CORE_DELAY_CYCLES(10000); if (NULL == hh10d_port) { cprintf("\nERROR: No port HAL; did you enable configBSP430_HAL_%s?\n", xBSP430portName(APP_HH10D_PORT_PERIPH_HANDLE) ?: "whatever"); return; } /* Initialize the state information used in the HH10D ISR */ hh10d.freq_timer = xBSP430hplLookupTIMER(APP_HH10D_TIMER_PERIPH_HANDLE); hh10d.uptime_ccidx = APP_HH10D_UPTIME_CC_INDEX; uptime_Hz = ulBSP430uptimeConversionFrequency_Hz_ni(); hh10d.sample_duration_utt = uptime_Hz; cprintf("HH10D I2C on %s at %p, bus rate %lu Hz, address 0x%02x\n", xBSP430serialName(APP_HH10D_I2C_PERIPH_HANDLE) ?: "UNKNOWN", i2c, ulBSP430clockSMCLK_Hz_ni() / APP_HH10D_I2C_PRESCALER, APP_HH10D_I2C_ADDRESS); #if BSP430_PLATFORM_PERIPHERAL_HELP cprintf("HH10D I2C Pins: %s\n", xBSP430platformPeripheralHelp(APP_HH10D_I2C_PERIPH_HANDLE, BSP430_PERIPHCFG_SERIAL_I2C)); #endif /* BSP430_PLATFORM_PERIPHERAL_HELP */ cprintf("Monitoring HH10D on %s.%u using timer %s\n", xBSP430portName(APP_HH10D_PORT_PERIPH_HANDLE) ?: "P?", bitToPin(APP_HH10D_PORT_BIT), xBSP430timerName(APP_HH10D_TIMER_PERIPH_HANDLE) ?: "T?");
void main () { volatile sBSP430hplTIMER * const timer_hpl = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE); unsigned int outclk; unsigned int last_outclk; unsigned int cctl; hBSP430halPORT const inclk_port_hal = hBSP430portLookup(BSP430_TIMER_CCACLK_CLK_PORT_PERIPH_HANDLE); hBSP430halPORT const cc_port_hal = hBSP430portLookup(APP_CC_PORT_PERIPH_HANDLE); hBSP430halPORT const outclk_port_hal = hBSP430portLookup(APP_OUTCLK_PORT_PERIPH_HANDLE); hBSP430halPORT const trigger_port_hal = hBSP430portLookup(APP_TRIGGER_PORT_PERIPH_HANDLE); vBSP430platformInitialize_ni(); vBSP430unittestInitialize(); cprintf("timer_scs_test: " __DATE__ " " __TIME__ "\n"); if (NULL == timer_hpl) { cprintf("ERROR: Unable to get timer HPL access\n"); return; } if (NULL == inclk_port_hal) { cprintf("ERROR: Unable to get INCLK port access\n"); return; } if (NULL == cc_port_hal) { cprintf("ERROR: Unable to get CC0 port access\n"); return; } if (NULL == outclk_port_hal) { cprintf("ERROR: Unable to get OUTCLK port access\n"); return; } if (NULL == trigger_port_hal) { cprintf("ERROR: Unable to get TRIGGER port access\n"); return; } cprintf("Please connect OUTCLK at %s.%u to %s INCLK at %s.%u\n", xBSP430portName(APP_OUTCLK_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_OUTCLK_PORT_BIT), xBSP430timerName(BSP430_TIMER_CCACLK_PERIPH_HANDLE), xBSP430portName(BSP430_TIMER_CCACLK_CLK_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_TIMER_CCACLK_CLK_PORT_BIT)); cprintf("Please connect TRIGGER at %s.%u to %s CCI0%c at %s.%u\n", xBSP430portName(APP_TRIGGER_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_TRIGGER_PORT_BIT), xBSP430timerName(BSP430_TIMER_CCACLK_PERIPH_HANDLE), 'A' + (APP_CC_CCIS / CCIS0), xBSP430portName(APP_CC_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_CC_PORT_BIT)); /* OUTCLK: output low */ outclk = 0; BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) &= ~APP_OUTCLK_PORT_BIT; BSP430_PORT_HAL_HPL_DIR(outclk_port_hal) |= APP_OUTCLK_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(outclk_port_hal) &= ~APP_OUTCLK_PORT_BIT; /* TRIGGER: output low */ BSP430_PORT_HAL_HPL_OUT(trigger_port_hal) &= ~APP_TRIGGER_PORT_BIT; BSP430_PORT_HAL_HPL_DIR(trigger_port_hal) |= APP_TRIGGER_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(trigger_port_hal) &= ~APP_TRIGGER_PORT_BIT; /* INCLK: input peripheral function */ BSP430_PORT_HAL_HPL_SEL(inclk_port_hal) &= ~BSP430_TIMER_CCACLK_CLK_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(inclk_port_hal) |= BSP430_TIMER_CCACLK_CLK_PORT_BIT; /* CC0: input peripheral function */ BSP430_PORT_HAL_HPL_DIR(cc_port_hal) &= ~APP_CC_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(cc_port_hal) |= APP_CC_PORT_BIT; cprintf("P4: DIR %04x SEL %04x\n", P4DIR, P4SEL); #define CLEAR_CAPTURE() do { \ timer_hpl->cctl[APP_CCIDX] &= ~CCIFG; \ timer_hpl->ccr[APP_CCIDX] = 0; \ } while (0) #define ASSERT_CLOCK_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) & APP_OUTCLK_PORT_BIT); \ } while (0) #define ASSERT_CLOCK_LOW() do { \ BSP430_UNITTEST_ASSERT_FALSE(BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) & APP_OUTCLK_PORT_BIT); \ } while (0) #define ASSERT_CCI_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCI & timer_hpl->cctl[APP_CCIDX]); \ } while (0) #define ASSERT_CCI_LOW() do { \ BSP430_UNITTEST_ASSERT_FALSE(CCI & timer_hpl->cctl[APP_CCIDX]); \ } while (0) #define ASSERT_INTERNAL_TRIGGER_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIS_3 == (CCIS_3 & timer_hpl->cctl[APP_CCIDX])); \ } while (0) #define ASSERT_INTERNAL_TRIGGER_LOW() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIS_2 == (CCIS_3 & timer_hpl->cctl[APP_CCIDX])); \ } while (0) #define ASSERT_NO_CAPTURE() do { \ BSP430_UNITTEST_ASSERT_FALSE(CCIFG & timer_hpl->cctl[APP_CCIDX]); \ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0, timer_hpl->ccr[APP_CCIDX]); \ } while (0) #define ASSERT_YES_CAPTURE() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIFG & timer_hpl->cctl[APP_CCIDX]); \ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(timer_hpl->r, timer_hpl->ccr[APP_CCIDX]); \ } while (0) /* Capture asynchronously on falling edge from TRIGGER. */ timer_hpl->ccr[APP_CCIDX] = 0; timer_hpl->cctl[APP_CCIDX] = CM_2 | APP_CC_CCIS | SCCI | CAP; timer_hpl->cctl[APP_CCIDX] = CM_3 | APP_CC_CCIS | SCCI | CAP; cprintf("%u: Timer: R %04x CTL %04x CCR %04x CCTL %04x\n", __LINE__, timer_hpl->r, timer_hpl->ctl, timer_hpl->ccr[APP_CCIDX], timer_hpl->cctl[APP_CCIDX]); /* Count upwards. */ timer_hpl->ctl = TASSEL_0 | MC_2 | TACLR; /* Validate that we can control the clock input. */ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 0); ASSERT_CLOCK_LOW(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 1); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); /* Verify that we can control the trigger, and that asynchronous * captures work. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); if (CM0 & timer_hpl->cctl[APP_CCIDX]) { ASSERT_YES_CAPTURE(); if (! (CM1 & timer_hpl->cctl[APP_CCIDX])) { CLEAR_CAPTURE(); } } else { ASSERT_NO_CAPTURE(); } ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Advance the clock. Make sure no capture occurred. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); /* Now turn on synchronous capture */ timer_hpl->cctl[APP_CCIDX] |= SCS; /* Advance the clock. Make sure no capture occurred */ cctl = timer_hpl->cctl[APP_CCIDX]; last_outclk = outclk; ASSERT_CLOCK_LOW(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); ASSERT_NO_CAPTURE(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); ASSERT_NO_CAPTURE(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk+1, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(cctl, timer_hpl->cctl[APP_CCIDX]); /* Do this again to make really sure no capture occurred. */ HALF_TICK_OUTCLK(); ASSERT_NO_CAPTURE(); HALF_TICK_OUTCLK(); ASSERT_NO_CAPTURE(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk+2, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(cctl, timer_hpl->cctl[APP_CCIDX]); /* F1) CCI rises then falls while CLK remains low. CCIFG remains low. When CLK rises the counter is incremented but CCIFG remains low. CCIFG is set only when CLK falls. */ /* CLK is low. */ ASSERT_CLOCK_LOW(); /* Check that external triggers with sync async do not trigger when * clock does not advance. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* F2) CCI rises then falls while CLK remains high. CCIFG remains low. When CLK falls CCIFG is set. */ /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Check that external triggers with sync async do not trigger when * clock does not advance. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Now test it with internal toggles. First, asynchronous: */ timer_hpl->cctl[APP_CCIDX] = CM_3 | CCIS_2 | SCCI | CAP; ASSERT_NO_CAPTURE(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_CCI_LOW(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_CCI_HIGH(); ASSERT_INTERNAL_TRIGGER_HIGH(); ASSERT_YES_CAPTURE(); CLEAR_CAPTURE(); HALF_TRIGGER(); ASSERT_CCI_HIGH(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_CCI_LOW(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Now synchronous */ timer_hpl->cctl[APP_CCIDX] |= SCS; ASSERT_NO_CAPTURE(); ASSERT_INTERNAL_TRIGGER_LOW(); INTERNAL_HALF_TRIGGER(); ASSERT_INTERNAL_TRIGGER_HIGH(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_NO_CAPTURE(); /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); cprintf("%u: Timer: R %04x CTL %04x CCR %04x CCTL %04x\n", __LINE__, timer_hpl->r, timer_hpl->ctl, timer_hpl->ccr[APP_CCIDX], timer_hpl->cctl[APP_CCIDX]); vBSP430unittestFinalize(); }
void main () { volatile sBSP430hplTIMER * const hpl = xBSP430hplLookupTIMER(BSP430_PERIPH_TA0); unsigned long ta0_Hz; unsigned int delta_ta0; const struct sLPMconfig * lcp = lpm_configs; const struct sLPMconfig * const elcp = lpm_configs + sizeof(lpm_configs)/sizeof(*lpm_configs); vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); TA0CTL = TASSEL_1 | MC_2 | TACLR; ta0_Hz = ulBSP430timerFrequency_Hz_ni(BSP430_PERIPH_TA0); #if 0 /* This sequence eliminates the wakeup delay on the MSP430F5438A. * The ramifications of doing this are to be found in the Power * Management Module and Supply Voltage Supervisor chapter of the * 5xx/6xx Family User's Guide, in the section "SVS and SVM * Performance Modes and Wakeup Times". * * Also check MCU errata related to the PMM. THere are several that * appear relevant when changing the module from its power-up * state. */ PMMCTL0_H = PMMPW_H; #if 1 /* This variant works */ SVSMLCTL &= ~(SVSLE | SVMLE); #else /* This appears to have no effect, though it should work. */ SVSMLCTL |= SVSLFP; #endif PMMCTL0_H = !PMMPW_H; #endif BSP430_CORE_ENABLE_INTERRUPT(); cputs("\n\nTimer LPM wake delay test\n"); delta_ta0 = ta0_Hz / 4; cprintf("TA0 is at %lu Hz; sleep time %u ticks\n", ta0_Hz, delta_ta0); cprintf("Standard mode SR is %04x\n", __read_status_register()); cprintf("SR bits: SCG0 %04x ; SCG1 %04x\n", SCG0, SCG1); cprintf("LPM exit from ISRs clears: %04x\n", BSP430_CORE_LPM_EXIT_MASK); cputs("LPMx CCR0 CAP0 Delta0 CCR1 CAP1 Delta1 SR"); while (lcp < elcp) { unsigned int tar; cprintf("%s: ", lcp->tag); BSP430_CORE_DISABLE_INTERRUPT(); ta0r = 0; hpl->cctl[0] = CCIE; tar = uiBSP430timerAsyncCounterRead_ni(hpl); hpl->ccr[0] = tar + delta_ta0; BSP430_CORE_LPM_ENTER_NI(lcp->lpm_bits); cprintf("%5u %5u %5u ", hpl->ccr[0], ta0r, ta0r-hpl->ccr[0]); BSP430_CORE_DISABLE_INTERRUPT(); ta0r = 0; hpl->cctl[1] = CCIE; tar = uiBSP430timerAsyncCounterRead_ni(hpl); hpl->ccr[1] = tar + delta_ta0; BSP430_CORE_LPM_ENTER_NI(lcp->lpm_bits); cprintf("%5u %5u %5u ", hpl->ccr[1], ta0r, ta0r-hpl->ccr[1]); cprintf("%04x\n", __read_status_register()); ++lcp; } cprintf("Done\n"); }