EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Watchdog interval timer problem

Started by "Robert J. Wilson" August 7, 2006
Hi folks,

I need to use the Watchdog timer for the main polling loop, Timer A
and B have other fuctions. Unfortuantely, I've not been able to get it
to function as an interval timer versus a Power on Reset trigger. The
code gets considerably more complex if I have to overload the A/B timers.

The debugger shows the timer vector is initialized in flash and we do
get one, but only one, NMI interrupt. But I've run out of flags to test:

static int wdt_cnt=0;
static int nmi_cnt=0;

void main(void)
{
WDTCTL = WDTPW + WDTTMSEL ; // Puts in interval time mode
//
// Ordinary flashing LED as background
//
P1DIR |= 0x01; // Set P1.0 to output direction

for (;;)
{
unsigned int i; // volatile to prevent optimization
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR

i = 60000; // Loop Delay
do i--;
while (i != 0);
}
}

// 0xFFF4 Watchdog Timer
#pragma vector=WDT_VECTOR
__interrupt void wdt_vector(void)
{
wdt_cnt +=1; // Count ISR
if ( wdt_cnt > 30000 )
{
wdt_cnt = 0;
}
}
// 0xFFFC Non-maskable
#pragma vector=NMI_VECTOR
__interrupt void nmi_vector(void)
{
nmi_cnt +=1; // Count ISR
if ( nmi_cnt > 30000 )
{
nmi_cnt = 0;
}
}

I'm using the IAR kickstart package with an eZ430-F2013. Ideas?

Bob Wilson

Beginning Microcontrollers with the MSP430

You probably figured it out already. When the WDT is in the
timer mode, you need to enable both the WDTIE and GIE in
order to get interrupts.

IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
_BIS_SR(GIE); //GIE bit is always in SR register

I do not know why you got NMI interrupt, I did not.
--- In m..., "Robert J. Wilson"
wrote:
>
> Hi folks,
>
> I need to use the Watchdog timer for the main polling loop, Timer A
> and B have other fuctions. Unfortuantely, I've not been able to get
it
> to function as an interval timer versus a Power on Reset trigger.
The
> code gets considerably more complex if I have to overload the A/B
timers.
>
> The debugger shows the timer vector is initialized in flash and we
do
> get one, but only one, NMI interrupt. But I've run out of flags to
test:
>
> static int wdt_cnt=0;
> static int nmi_cnt=0;
>
> void main(void)
> {
> WDTCTL = WDTPW + WDTTMSEL ; // Puts in interval time mode
> //
> // Ordinary flashing LED as background
> //
> P1DIR |= 0x01; // Set P1.0 to output
direction
>
> for (;;)
> {
> unsigned int i; // volatile to prevent optimization
> P1OUT ^= 0x01; // Toggle P1.0 using
exclusive-OR
>
> i = 60000; // Loop Delay
> do i--;
> while (i != 0);
> }
> }
>
> // 0xFFF4 Watchdog Timer
> #pragma vector=WDT_VECTOR
> __interrupt void wdt_vector(void)
> {
> wdt_cnt +=1; // Count ISR
> if ( wdt_cnt > 30000 )
> {
> wdt_cnt = 0;
> }
> }
> // 0xFFFC Non-maskable
> #pragma vector=NMI_VECTOR
> __interrupt void nmi_vector(void)
> {
> nmi_cnt +=1; // Count ISR
> if ( nmi_cnt > 30000 )
> {
> nmi_cnt = 0;
> }
> }
>
> I'm using the IAR kickstart package with an eZ430-F2013. Ideas?
>
> Bob Wilson
>
--- In m..., "old_cow_yellow"
wrote:
>
> You probably figured it out already. When the WDT is in the
> timer mode, you need to enable both the WDTIE and GIE in
> order to get interrupts.
>
> IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
> _BIS_SR(GIE); //GIE bit is always in SR register
>
> I do not know why you got NMI interrupt, I did not.

THANKS!! That did it.

Bob Wilson
--- In m..., "old_cow_yellow"
wrote:
>
> You probably figured it out already. When the WDT is in the
> timer mode, you need to enable both the WDTIE and GIE in
> order to get interrupts.
>
> IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
> _BIS_SR(GIE); //GIE bit is always in SR register
>
> I do not know why you got NMI interrupt, I did not.

I thought I'd tried each before but not the combination. I had been
working on the hypothsis that it was possibly an interrupt priority
problem.

I thought the POR interrupt was at priority 31, the highest. So I was
trying to code assembler statements to fix up the stack and allow an
RETI to dismiss the initial POR interrupt. But since the watchdog
timer interrupts, priority 26, are being delivered, I'm scratching my
head, again. The 'main()' routine is obviously running at a lower
priority.

Is there any way to read out the current "Priority"? It doesn't seem
to be defined in the SR register.

BTW, thanks again! It was the combination that had me confused.

Bob Wilson
The TI documents are somewhat confusing. MSP430 CPU hardware does not
support multiple priority levels.

The SR register includes a global interrupt enable (GIE) bit. Each
interrupt source has an individual interrupt flag IFG and an
individual interrupt enable bit IE. For "maskable" interrupts, when
an event sets IFG, an interrupt request will be generated only when
the GIE and the individual IE are both set. For "(non)-Maskable"
interrupts, GIE has no effect and only the individual IE is required.

The interrupt priority levels described in TI documents are relevant
only when two or more different interrupt sources make requests at
the same time. Under this circumstance, the interrupt with highest
priority is accepted; all others are still pending.

When an interrupt is accepted, current SR (which includes GIE) and
the PC are pushed to the stack. GIE itself is cleared and the
interrupt vector is copied to PC. When a RETI instruction is
executed, the SR and PC are popped from the stack.

POR (or Reset) is not really an interrupt. It copies the vector at
0xFFFE-0FFFF to PC and sets some other registers to certain fixed
values. Nothing is pushed into the stack. Thus do not use RETI!

"(non)-maskable interrupt"? NMI? POR? PUR? TATJTCY (they are there
just to confuse you).

--- In m..., "Robert J. Wilson"
wrote:
>
> --- In m..., "old_cow_yellow"
> wrote:
> >
> > You probably figured it out already. When the WDT is in the
> > timer mode, you need to enable both the WDTIE and GIE in
> > order to get interrupts.
> >
> > IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
> > _BIS_SR(GIE); //GIE bit is always in SR register
> >
> > I do not know why you got NMI interrupt, I did not.
>
> I thought I'd tried each before but not the combination. I had been
> working on the hypothsis that it was possibly an interrupt priority
> problem.
>
> I thought the POR interrupt was at priority 31, the highest. So I
was
> trying to code assembler statements to fix up the stack and allow an
> RETI to dismiss the initial POR interrupt. But since the watchdog
> timer interrupts, priority 26, are being delivered, I'm scratching
my
> head, again. The 'main()' routine is obviously running at a lower
> priority.
>
> Is there any way to read out the current "Priority"? It doesn't seem
> to be defined in the SR register.
>
> BTW, thanks again! It was the combination that had me confused.
>
> Bob Wilson
>
Yes, the MSP430 does support multiple priority levels. If this
behaviour is required, enable the GIE bit at the start of each
interrupt service routine which can potentially be interrupted by a
higher-priority interrupt, since as you mention GIE is not set by
default in the "local" copy of the status register. If a higher
priority interrupt occurs whilst the first interrupt is in progress,
the higher priority interrupt will be vectored to and serviced by
it's interrupt service routine before returning to the first interrupt.

You can nest multiple interrupts (not just 2) in this manner, limited
only by depth of stack and number of priority levels available on the
particular MSP.

Hugh

At 03:02 PM 8/10/2006, you wrote:

The TI documents are somewhat confusing. MSP430 CPU hardware does not
support multiple priority levels.

The SR register includes a global interrupt enable (GIE) bit. Each
interrupt source has an individual interrupt flag IFG and an
individual interrupt enable bit IE. For "maskable" interrupts, when
an event sets IFG, an interrupt request will be generated only when
the GIE and the individual IE are both set. For "(non)-Maskable"
interrupts, GIE has no effect and only the individual IE is required.

The interrupt priority levels described in TI documents are relevant
only when two or more different interrupt sources make requests at
the same time. Under this circumstance, the interrupt with highest
priority is accepted; all others are still pending.

When an interrupt is accepted, current SR (which includes GIE) and
the PC are pushed to the stack. GIE itself is cleared and the
interrupt vector is copied to PC. When a RETI instruction is
executed, the SR and PC are popped from the stack.

POR (or Reset) is not really an interrupt. It copies the vector at
0xFFFE-0FFFF to PC and sets some other registers to certain fixed
values. Nothing is pushed into the stack. Thus do not use RETI!

"(non)-maskable interrupt"? NMI? POR? PUR? TATJTCY (they are there
just to confuse you).

--- In m..., "Robert J. Wilson"
wrote:
>
> --- In m..., "old_cow_yellow"
> wrote:
> >
> > You probably figured it out already. When the WDT is in the
> > timer mode, you need to enable both the WDTIE and GIE in
> > order to get interrupts.
> >
> > IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
> > _BIS_SR(GIE); //GIE bit is always in SR register
> >
> > I do not know why you got NMI interrupt, I did not.
>
> I thought I'd tried each before but not the combination. I had been
> working on the hypothsis that it was possibly an interrupt priority
> problem.
>
> I thought the POR interrupt was at priority 31, the highest. So I
was
> trying to code assembler statements to fix up the stack and allow an
> RETI to dismiss the initial POR interrupt. But since the watchdog
> timer interrupts, priority 26, are being delivered, I'm scratching
my
> head, again. The 'main()' routine is obviously running at a lower
> priority.
>
> Is there any way to read out the current "Priority"? It doesn't seem
> to be defined in the SR register.
>
> BTW, thanks again! It was the combination that had me confused.
>
> Bob Wilson
>
It depends on how you look at this.

"MSP430 does support multiple priority levels" : this statement is both right and wrong.
The way it was described below this is true.
Interrupts of a lower priority WILL be vectored however as soon as the current interrupt(s) are
done (even INSIDE a higher priority interrupt !!) - unless it's an interrupt that you need to
clear explicitly - even though it was vectored.
I think that's what "old cow" meant....

"MSP430 does NOT support multiple priority levels" is correct as well.
On the MSP430 the interrupts are fixed in priority, and when enabled they will always be executed.
As above - and what the original thread was about - this means that you can NEVER prevent a lower
priority interrupt from vectoring with a higher priority one..
Ie. The NMI won't stop a watchdog interrupt from executing if it is enabled , despite the lower
priority.

As the previous poster pointed out, the priority level of interrupts is IRRELEVANT until there are
multiple interrupts pending, and an arbitration takes place.

Maybe you can compare it with an ARM core.
If an interrupt is given to the INT controller, and its priority is set higher than (or equal to)
a new interrupt that is pending, then the new interrupt is masked....

To do this on an MSP430 you would have to disable the IE bit in all interrupts that are lower
priority.....
Therefore the MSP430 does NOT support multiple priorities IMO.

B regards,
Kris

-----Original Message-----
From: m... [mailto:m...] On Behalf Of Hugh Molesworth
Sent: Friday, 11 August 2006 11:10 AM
To: m...
Subject: [msp430] Re: Watchdog interval timer problem

Yes, the MSP430 does support multiple priority levels. If this
behaviour is required, enable the GIE bit at the start of each
interrupt service routine which can potentially be interrupted by a
higher-priority interrupt, since as you mention GIE is not set by
default in the "local" copy of the status register. If a higher
priority interrupt occurs whilst the first interrupt is in progress,
the higher priority interrupt will be vectored to and serviced by
it's interrupt service routine before returning to the first interrupt.

You can nest multiple interrupts (not just 2) in this manner, limited
only by depth of stack and number of priority levels available on the
particular MSP.

Hugh

At 03:02 PM 8/10/2006, you wrote:

The TI documents are somewhat confusing. MSP430 CPU hardware does not
support multiple priority levels.

The SR register includes a global interrupt enable (GIE) bit. Each
interrupt source has an individual interrupt flag IFG and an
individual interrupt enable bit IE. For "maskable" interrupts, when
an event sets IFG, an interrupt request will be generated only when
the GIE and the individual IE are both set. For "(non)-Maskable"
interrupts, GIE has no effect and only the individual IE is required.

The interrupt priority levels described in TI documents are relevant
only when two or more different interrupt sources make requests at
the same time. Under this circumstance, the interrupt with highest
priority is accepted; all others are still pending.

When an interrupt is accepted, current SR (which includes GIE) and
the PC are pushed to the stack. GIE itself is cleared and the
interrupt vector is copied to PC. When a RETI instruction is
executed, the SR and PC are popped from the stack.

POR (or Reset) is not really an interrupt. It copies the vector at
0xFFFE-0FFFF to PC and sets some other registers to certain fixed
values. Nothing is pushed into the stack. Thus do not use RETI!

"(non)-maskable interrupt"? NMI? POR? PUR? TATJTCY (they are there
just to confuse you).

--- In m..., "Robert J. Wilson"
wrote:
>
> --- In m..., "old_cow_yellow"
> wrote:
> >
> > You probably figured it out already. When the WDT is in the
> > timer mode, you need to enable both the WDTIE and GIE in
> > order to get interrupts.
> >
> > IE1 |= WDTIE; //for F2013, WDTIE bit is in IE1
> > _BIS_SR(GIE); //GIE bit is always in SR register
> >
> > I do not know why you got NMI interrupt, I did not.
>
> I thought I'd tried each before but not the combination. I had been
> working on the hypothsis that it was possibly an interrupt priority
> problem.
>
> I thought the POR interrupt was at priority 31, the highest. So I
was
> trying to code assembler statements to fix up the stack and allow an
> RETI to dismiss the initial POR interrupt. But since the watchdog
> timer interrupts, priority 26, are being delivered, I'm scratching
my
> head, again. The 'main()' routine is obviously running at a lower
> priority.
>
> Is there any way to read out the current "Priority"? It doesn't seem
> to be defined in the SR register.
>
> BTW, thanks again! It was the combination that had me confused.
>
> Bob Wilson
>
Thanks! This helps a lot. My last, multiple priority interrupt system
was a VAX and I was acutely sensitive to the role of interrupt
priorities. I'd had to debug someones code who blocked all interrupts
in a device driver with a logic analyzer on the backplane.

If I don't enable GIE in the ISR, they are blocked and I can service
the interrupts FIFO. If I enable it, then time critical, higher
priority interrupts can preempt the current ISR. This is a simple rule
and would make a great addition to the M430 documentation or coding
guidelines.

I'm making good progress on one of my projects and am now working on
the low-power modes. If I get stuck, I'll ask for help but once I get
it working, I'll share the code with my thanks to my helpers. Unlike
some, I don't believe programing should stand on the toes of those who
came before us.

Bob Wilson

--- In m..., "Microbit" wrote:
>
> It depends on how you look at this.
>
> "MSP430 does support multiple priority levels" : this statement is
both right and wrong.
> The way it was described below this is true.
> Interrupts of a lower priority WILL be vectored however as soon as
the current interrupt(s) are
> done (even INSIDE a higher priority interrupt !!) - unless it's an
interrupt that you need to
> clear explicitly - even though it was vectored.
> I think that's what "old cow" meant....
>
> "MSP430 does NOT support multiple priority levels" is correct as well.
> On the MSP430 the interrupts are fixed in priority, and when enabled
they will always be executed.
> As above - and what the original thread was about - this means that
you can NEVER prevent a lower
> priority interrupt from vectoring with a higher priority one..
> Ie. The NMI won't stop a watchdog interrupt from executing if it is
enabled , despite the lower
> priority.
>
> As the previous poster pointed out, the priority level of interrupts
is IRRELEVANT until there are
> multiple interrupts pending, and an arbitration takes place.
>
> Maybe you can compare it with an ARM core.
> If an interrupt is given to the INT controller, and its priority is
set higher than (or equal to)
> a new interrupt that is pending, then the new interrupt is masked....
>
> To do this on an MSP430 you would have to disable the IE bit in all
interrupts that are lower
> priority.....
> Therefore the MSP430 does NOT support multiple priorities IMO.
>
> B regards,
> Kris
>
> -----Original Message-----
> From: m... [mailto:m...] On
Behalf Of Hugh Molesworth
> Sent: Friday, 11 August 2006 11:10 AM
> To: m...
> Subject: [msp430] Re: Watchdog interval timer problem
>
> Yes, the MSP430 does support multiple priority levels. If this
> behaviour is required, enable the GIE bit at the start of each
> interrupt service routine which can potentially be interrupted by a
> higher-priority interrupt, since as you mention GIE is not set by
> default in the "local" copy of the status register. If a higher
> priority interrupt occurs whilst the first interrupt is in progress,
> the higher priority interrupt will be vectored to and serviced by
> it's interrupt service routine before returning to the first interrupt.
>
> You can nest multiple interrupts (not just 2) in this manner, limited
> only by depth of stack and number of priority levels available on the
> particular MSP.
>
> Hugh
>
> At 03:02 PM 8/10/2006, you wrote:
>
> The TI documents are somewhat confusing. MSP430 CPU hardware does not
> support multiple priority levels.
>
> The SR register includes a global interrupt enable (GIE) bit. Each
> interrupt source has an individual interrupt flag IFG and an
> individual interrupt enable bit IE. For "maskable" interrupts, when
> an event sets IFG, an interrupt request will be generated only when
> the GIE and the individual IE are both set. For "(non)-Maskable"
> interrupts, GIE has no effect and only the individual IE is required.
>
> The interrupt priority levels described in TI documents are relevant
> only when two or more different interrupt sources make requests at
> the same time. Under this circumstance, the interrupt with highest
> priority is accepted; all others are still pending.
>
> When an interrupt is accepted, current SR (which includes GIE) and
> the PC are pushed to the stack. GIE itself is cleared and the
> interrupt vector is copied to PC. When a RETI instruction is
> executed, the SR and PC are popped from the stack.
>
> POR (or Reset) is not really an interrupt. It copies the vector at
> 0xFFFE-0FFFF to PC and sets some other registers to certain fixed
> values. Nothing is pushed into the stack. Thus do not use RETI!
>
> "(non)-maskable interrupt"? NMI? POR? PUR? TATJTCY (they are there
> just to confuse you).

Bob Wilson

Memfault Beyond the Launch