Hi there,
I am trying to run a fairly simple piece of code to pulse an IO every 100mS and then go into LPM3.
But every time I run it, a watchdog reset occurs.. The code is attached..
has anybody any suggestions as to what I may be doing wrong here? I am tearing my hair out :-(
static volatile uint8_t kick_watchdog = 0; /** Brief: kernel timer isr, uses timer0 a0, @param[in] @param[in] @return */ void __attribute__((interrupt)) hal_timer0_a0_isr(void) { _bic_SR_register_on_exit(0xF0); if (kick_watchdog) { WDTCTL = WDTPW + WDTSSEL0 + WDTCNTCL + WDTIS__32K; // password, aclk, clear counter, /32768 kick_watchdog = 0; } } /** Brief: Delay in microseconds. Times are approx. @param[in] uint16_t delay - in microseconds @param[in] none @return none */ void __attribute__((optimize("O0"))) hal_delay_us(uint16_t delay_us) { uint8_t i; for(;delay_us;delay_us--) { i = 2; while(!i--) { __asm volatile(" nop\n"); __asm volatile(" nop\n"); __asm volatile(" nop\n"); } } } /** Brief: main entry point into code Clock setup: - MCLK is the master clock and runs at 24mHZ MCLK is sourced from the DCOCLK The DCOCLK runs at 24mHz from the FLL VCORE the core voltage must be set to its highest level, level 3 - SMCLK is Sub Master clock and runs at 12Mhz This clock is used as the source clock for the UART and ... The SMCLK is sourced from the DCOCLK with a /2 divider i.e. 24Mhz/2 = 12Mhz - ACLK is the auxcillary clock and runs at 32768Hz and is used as a source clock for low power timers such as timer A0. ACLK is sourced from XT1CLK. XT1CLK is an external 32768Hz Crystal connected to P5.4 and P5.5. This allows timers to run in low power modes */ void hal_init(void) { // ------------------------------------- // Set up MCLK, DCOCLK = 24Mhz // Core voltage must be set to highest level to support 24Mhz // Vcore will be set to level3, but core voltage can only be changed one level at a time (see errata) // so we will iterate from level 1 to 3 until level 3 reached for (uint8_t level = 1; level <= 3; level++) { PMMCTL0_H = PMMPW_H; // Open PMM registers for write by writing the password SVSMHCTL = SVSHE | SVSHRVL0 * level | SVMHE | SVSMHRRL0 * level; // Set SVS/SVM high side new level SVSMLCTL = SVSLE | SVMLE | SVSMLRRL0 * level; // Set SVM low side to new level while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled PMMIFG &= ~(SVMLVLRIFG | SVMLIFG); // Clear already set flags PMMCTL0_L = PMMCOREV0 * level; // Set VCore to new level // Wait till new level reached if ((PMMIFG & SVMLIFG)) while ((PMMIFG & SVMLVLRIFG) == 0); SVSMLCTL = SVSLE | SVSLRVL0 * level | SVMLE | SVSMLRRL0 * level; // Set SVS/SVM low side to new level PMMCTL0_H = 0x00; // Lock PMM registers for write access } __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL4 = SELM__DCOCLK; // Select the MCLK source, MCLK = DCOCLK UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_7; // Select DCO range 50MHz operation // Set DCO Multiplier for 24MHz // (N + 1) * FLLRef = Fdco // (731 + 1) * 32768 = 24MHz // Set FLL Div = fDCOCLK/2 // Enable the FLL control loop UCSCTL2 = FLLD_0 | 731; __bic_SR_register(SCG0); // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 25 MHz / 32,768 Hz ~ 750k MCLK cycles for DCO to settle // this delay is about 85mS far in excess of the ~35mS that is required for (uint32_t delay = 0; delay < 100000; delay++); // ------------------------------------- // Set up SMCLK, DCOCLK/2 = 12Mhz // Select the SMCLK source, SMCLK = DCOCLK/2 UCSCTL4 |= SELS__DCOCLK; UCSCTL5 = DIVS__2; // ------------------------------------- // Setup ACLK - 32Khz XT1 // Select the ACLK source, ACLK = XT1CLK // Select XT1 Mode on P5.4 & P5.5 UCSCTL4 |= SELA__XT1CLK; P5SEL |= BV(4) | BV(5); // Wait for the XTAL to stabilize, and fault flags to clear // clear DCO, XT2 & XT1 oscillator fault flags. If these bits are set, the OFIFG flag is also set. while ((SFRIFG1 & OFIFG)) { UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG); SFRIFG1 &= ~OFIFG; } // reduce drive strength to XT1, set to max by default UCSCTL6 &= ~(XT1DRIVE_3); // ------------------------------------- // GPIO setup // PORT 1 GPIO P1SEL = 0b00000000; // set pin mode, 0=gpio 1=alt P1DIR = 0b11000001; // set direction, 0=input 1=output P1REN = 0b00001110; // Pullup or pulldown resistor enabled, 0=pull disabled 1=pull enabled P1OUT = 0b00001110; // Set IO state for output 0=low 1=high, or, set pull resistor mode fot input 0=pulldown 1=pullup // PORT 5 GPIO P5SEL = 0b00110000; // set pin mode, 0=gpio 1=alt P5DIR = 0b11001111; // set direction, 0=input 1=output P5REN = 0b00000000; // Pullup or pulldown resistor enabled, 0=pull disabled 1=pull enabled P5OUT = 0b00000011; // Set IO state for output 0=low 1=high, or, set pull resistor mode fot input 0=pulldown 1=pullup // led on, for short time to indicate power up P5OUT &= ~0x02; for (uint8_t i = 250; i > 0; i--) hal_delay_us(1000); P5OUT |= 0x02; // Enable the watchdog WDTCTL = WDTPW + WDTSSEL0 + WDTCNTCL + WDTIS__32K; // password, aclk, clear counter, /32768 // Setup and start timer0 a0, interrupt every 100mS TA0CCTL0 = CCIE; // CCR0 interrupt enabled TA0CCR0 = 3277; // CCR0 is loaded with 3277, aclk=32Khz => 1/32Khz = ~30.5uS + 3277 = ~100ms TA0CTL = TASSEL_1 | MC_1 | TACLR; // ACLK, upmode, clear TAR // enable interrupts _enable_interrupts(); // into main loop while (1) { // set watchdog flag, picked up in ISR kick_watchdog = 1; // Pulse output P1OUT |= 0x01; hal_delay_us(5); P1OUT &= ~0x01; hal_delay_us(2); // into low power mode, wake in 100ms __bis_SR_register(LPM3_bits + GIE); __no_operation(); } }