Jump to content
yyrkoon

msp430G2553 WDT

Recommended Posts

I'm currently searching, and reading on the G2553's watch dog, and so far have not been able to find a decent read with C example code on how to service the watchdog timer. I know probably 90% example code shows how to disable it, but that's not what I need.

 

Does anyone have a good link or three hopefully with C example code ?

 

EDIT:

 

Oh and right. I'm using Energia's gcc, but an Energia example would be fine too.

Share this post


Link to post
Share on other sites

Last time I checked Energia repurposes the WDT for its own purposes.  * It has been a while though so who knows *

Ah, well, I was afraid of that.

 

I found one TI slide pdf, and the title of the file was "all about timers" where the watchdog section was simply disabling the WDT heh.

Share this post


Link to post
Share on other sites

This is what I did in CCS to count pulses from a flow sensor and trigger a flow ok output when good, comments are not correct but cannot be bothered to fix them now...

 

The watchdog interrupt flag is cleared automatically when the interrupt is serviced.

 

WDT_MDLY_8 is defined as ((0x5A00)+(0x0010)+(0x0008)+(0x0001)) in CCS.

//
// C02 Laser engraver coolant control module
//
// v1.0 / 2015-07-06 / Io Engineering / Terje
//
//

#include <msp430.h> 

#define I2CADDRESS 0x47

#define FLOWPULSE BIT0	// P1
#define	SCL	BIT6		// P1
#define SDA	BIT7		// P1

#define FAN0 BIT0	// P2.0
#define FAN1 BIT1	// P2.1
#define PMP0 BIT2	// P2.2
#define AIR0 BIT3	// P2.3
#define PMPOK BIT5	// P2.5
#define SPARE BIT4	// P2.4

#define FLOWCOUNT 100

volatile int flowTimer = FLOWCOUNT;	    // 400ms delay

void initI2C (void) {

	P1SEL  |= (SCL|SDA);                      // Assign I2C pins to USCI_B0
	P1SEL2 |= (SCL|SDA);                      // Assign I2C pins to USCI_B0

	IE2 &= ~UCB0TXIE;                         // Disable TX interrupt
	UCB0CTL1 |= UCSWRST;                      // Enable SW reset
	UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
	UCB0I2COA = I2CADDRESS;                   // Set own address
	UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
	IE2 |= UCB0RXIE|UCB0TXIE;                 // Enable RX interrupt

}

void main(void)
{

	DCOCTL = 0;

	WDTCTL = WDT_MDLY_8;					// 8ms

	DCOCTL = CALDCO_1MHZ;					// Set DCO for 1MHz using
	BCSCTL1 = CALBC1_1MHZ;					// calibration registers

	P1SEL |= FLOWPULSE;
	P1SEL2 = 0;
	P1REN = ~(FLOWPULSE|SDA|SCL);			// Pull down unused inputs

	P2DIR |= (FAN0|FAN1|PMP0|AIR0|PMPOK|SPARE);
	P2OUT &= ~(FAN0|FAN1|PMP0|AIR0|PMPOK|SPARE);

	P3DIR = 0xFF; 							// Set P3 to outputs
	P3OUT = 0xFF; 							// and set high

	initI2C();

	TACTL = TACLR|TASSEL_0|MC_2; //+ID0+ID1;            // SMCLK/8, Clear TA

	IE1 |= WDTIE;

	_EINT();                                  // Enable interrupts

	while(1)                                  // Loop forever
	{
		LPM0;
	}

}

#pragma vector=WDT_VECTOR
__interrupt void WATCHDOG(void)
{
	if(!flowTimer--) {
		flowTimer = FLOWCOUNT;
		if(TAR > 12)
			P2OUT |= PMPOK;
		else
			P2OUT &= ~PMPOK;
		TAR = 0;
	}
}

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{

	int data, swmask, i = AIR0;

	if(IFG2 & UCB0RXIFG) {

		data   = UCB0RXBUF;
		swmask = data >> 4;

		while(i) {
			if(swmask & i) {
				if(data & i)
					P2OUT |= i;
				else
					P2OUT &= ~i;
			}
			i = i >> 1;
		}

	}
}

#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
	UCB0STAT &= ~(UCSTPIFG + UCSTTIFG);       // Clear interrupt flags
}

Share this post


Link to post
Share on other sites

So at this very moment I'm trying to figure out if it is possible to service the watchdog through it's interrupt. i.e. can you wait for the interrupt to fire, and then clear the watchdog status then, or would the MCU go into PUC first ?

 

I was thinking that perhaps since I do need another timer, that I could service the watchdog through that interrupt, but . . . yeah I'm still learning.

Share this post


Link to post
Share on other sites

 

This is what I did in CCS to count pulses from a flow sensor and trigger a flow ok output when good, comments are not correct but cannot be bothered to fix them now...

 

The watchdog interrupt flag is cleared automatically when the interrupt is serviced.

 

WDT_MDLY_8 is defined as ((0x5A00)+(0x0010)+(0x0008)+(0x0001)) in CCS.

//
// C02 Laser engraver coolant control module
//
// v1.0 / 2015-07-06 / Io Engineering / Terje
//
//

#include <msp430.h> 

#define I2CADDRESS 0x47

#define FLOWPULSE BIT0	// P1
#define	SCL	BIT6		// P1
#define SDA	BIT7		// P1

#define FAN0 BIT0	// P2.0
#define FAN1 BIT1	// P2.1
#define PMP0 BIT2	// P2.2
#define AIR0 BIT3	// P2.3
#define PMPOK BIT5	// P2.5
#define SPARE BIT4	// P2.4

#define FLOWCOUNT 100

volatile int flowTimer = FLOWCOUNT;	    // 400ms delay

void initI2C (void) {

	P1SEL  |= (SCL|SDA);                      // Assign I2C pins to USCI_B0
	P1SEL2 |= (SCL|SDA);                      // Assign I2C pins to USCI_B0

	IE2 &= ~UCB0TXIE;                         // Disable TX interrupt
	UCB0CTL1 |= UCSWRST;                      // Enable SW reset
	UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
	UCB0I2COA = I2CADDRESS;                   // Set own address
	UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
	IE2 |= UCB0RXIE|UCB0TXIE;                 // Enable RX interrupt

}

void main(void)
{

	DCOCTL = 0;

	WDTCTL = WDT_MDLY_8;					// 8ms

	DCOCTL = CALDCO_1MHZ;					// Set DCO for 1MHz using
	BCSCTL1 = CALBC1_1MHZ;					// calibration registers

	P1SEL |= FLOWPULSE;
	P1SEL2 = 0;
	P1REN = ~(FLOWPULSE|SDA|SCL);			// Pull down unused inputs

	P2DIR |= (FAN0|FAN1|PMP0|AIR0|PMPOK|SPARE);
	P2OUT &= ~(FAN0|FAN1|PMP0|AIR0|PMPOK|SPARE);

	P3DIR = 0xFF; 							// Set P3 to outputs
	P3OUT = 0xFF; 							// and set high

	initI2C();

	TACTL = TACLR|TASSEL_0|MC_2; //+ID0+ID1;            // SMCLK/8, Clear TA

	IE1 |= WDTIE;

	_EINT();                                  // Enable interrupts

	while(1)                                  // Loop forever
	{
		LPM0;
	}

}

#pragma vector=WDT_VECTOR
__interrupt void WATCHDOG(void)
{
	if(!flowTimer--) {
		flowTimer = FLOWCOUNT;
		if(TAR > 12)
			P2OUT |= PMPOK;
		else
			P2OUT &= ~PMPOK;
		TAR = 0;
	}
}

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{

	int data, swmask, i = AIR0;

	if(IFG2 & UCB0RXIFG) {

		data   = UCB0RXBUF;
		swmask = data >> 4;

		while(i) {
			if(swmask & i) {
				if(data & i)
					P2OUT |= i;
				else
					P2OUT &= ~i;
			}
			i = i >> 1;
		}

	}
}

#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
	UCB0STAT &= ~(UCSTPIFG + UCSTTIFG);       // Clear interrupt flags
}

Thanks for the reply. Correct me if I'm wrong, but you're not using the watchdog. So there is nothing to service in your code. The watchdog is configured as an interval timer instead. . .

Share this post


Link to post
Share on other sites

I *HAVE* to use the watchdog as a watchdog, and not an interval timer. So if the processor hangs for any reason at power up, the watchdog will reset the MCU.

Share this post


Link to post
Share on other sites

OK so this question of mine has been answered . . .

 

In the case of the MSP430, the watchdog interrupt is the same as the reset vector, so a watchdog interrupt will  reset the device.

 

Share this post


Link to post
Share on other sites

Sorry about misunderstanding, I was thinking you needed to service a watchdog timer interrupt rather than avoiding a PUC (Power-Up Clear) by clearing it before it expires.

 

 

The user must setup, halt, or clear the WDT+ prior to the expiration of the initial reset interval or another PUC will be generated.

Share this post


Link to post
Share on other sites

Sorry about misunderstanding, I was thinking you needed to service a watchdog timer interrupt rather than avoiding a PUC (Power-Up Clear) by clearing it before it expires.

no problem, probably my fault since undoubtedly my terminology is going to suck being newb to the G2553 WDT. But yes, I need the WDT active to reset the MCU if it ever locks up, hangs, or whatever.

Share this post


Link to post
Share on other sites

Quick demo here, description is pretty much in the comments. But it toggles an LED 10 times, and then delays for 3 seconds with the LED off, before the WDT resets the board. Where the code start all over again.

#include <msp430g2553.h>

int main(void) {
        int count = 0;
        WDTCTL = WDTPW | WDTHOLD;       // stop watchdog timer

        P1DIR = 0x01;                   // set up bit 0 of P1 as output
        P1OUT = 0x00;                   // intialize bit 0 of P1 to 0

        while(count++ < 10) {           // loop 10 times
                P1OUT ^= 0x01;          // toggle bit 0 of P1
                __delay_cycles(100000); // delay for a while
        }

        P1OUT &= ~BIT0;                 // Clear bit 0( turn off LED )
        __delay_cycles(3000000);        // Delay 3 seconds

        if (IFG1 & WDTIFG) {
                IFG1 &= ~WDTIFG;        // Clear WDT interrupt if set
        }

        WDTCTL = WDTPW + WDTCNTCL;      // Enable WDT

        return 0;
}

Share this post


Link to post
Share on other sites

This( below ) is probably closer to how the WDT is meant to be used. But I do have a quesiton if anyone may know. How can one put the MCU in low power mode if we're constantly kicking the dog ? ~32ms is not a whole lot of time using fSMCLK, and fACLK is only available if you have an external crystal soldered on right ?

#include <msp430g2553.h>

int main(void) {

        WDTCTL = WDTPW + WDTHOLD;       // stop watchdog timer

        P1DIR = 0x01;                   // set up bit 0 of P1 as output
        P1OUT = 0x00;                   // intialize bit 0 of P1 to 0

        int count = 1;

        WDTCTL = WDTPW | WDTCNTCL;      // Enable WDT

        while(count++) {
                __delay_cycles(10000);
                WDTCTL = WDTPW | WDTCNTCL;

                if( count > 100){
                        count = 1;
                        P1OUT ^= 0x01;
                }
        }

        return 0;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×