Part Number: MSP430F5310
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();
}
}