EmbeddedRelated.com
Forums
Memfault Beyond the Launch

LPC2103 Rev A Watchdog Timer and Vectored IRQ - not functional?

Started by ftsol1962 July 31, 2009
Sorry if this has been visited before, but my searches haven't turned it up. I am using the IAR WorkBench 5.4 (Kickstart Edition)

Basically I want to have the WatchDog operate in INT mode, not RESET,
so that I can do some housekeeping in the interrupt routine before system reset. I want to use IRQ Vector 0 so the WatchDog INT takes
priority over all other IRQs in the system. I am running the PLL @ 4X multiplier with external oscillator @ 14.7456 MHz, and MAM=1,
MAMTIM=3; Operating in USerFlash mode.

Now, the problem:
I configure the VIC to enable WatchDog Ints, have them generate IRQ, and configure VICVectAddr0 register with the address of my watchdog
ISR function, and Enable the VICVectCntl0 for the WatchDog Int (VICVectCntl0 = 0x20) as follows:

unsigned long temp;
temp = VICIntSelect; // Get current IRQ/FIQ int settings
temp = temp & ~(0x00000001); // Make WatchDog int IRQ
VICIntSelect = temp;
temp = VICIntEnable;
temp |= 0x00000001; // Enable WDOG Timer Int generation
VICIntEnable = temp;
VICVectCtl0 = (unsigned long) 0x0020; //WDOG Vect Enable
VICVectAddr0 = (unsigned long)WatchDog_Interrupt;

I then configure the Watchdog and start it.

The WatchDog_Interrupt function @ 0x3d8:
__irq __nested __arm void WatchDog_Interrupt()
{
VICIntEnableClear = (unsigned long)0x00000001;
WatchDogIntcount +=1;
WDMOD = 0x00;
//
// Do cleanup stuff here before reset or exit
//
VICVectAddr = (unsigned long) 0x00;
}

Problem is:
1. WatchDog underflows and sets the WDINT; It *appears* that the IRQ
is generated, but the the Vector taken is the default one
(VICDefVectADDR=0x00) instead of my isr @(0x3d8) even though I
can see by placing a breakpoint @main that VICVectAddr=0x3d8 when
the program restarts !?
2. IF I set the VICDefVectAddr = 0x3d8 (my watchdog ISR) then it is
called instead of taking the Reset vector (0), so I believe that
something odd is happening with the VIC and the WDog Vector
processing, but cannot figure out what.

Any assistance is appreciated!

An Engineer's Guide to the LPC2100 Series

I assume from context that you're using the "Insider's Guide" trick in the IRQ startup vector? Like

_vectors: ldr PC, Reset_Addr
ldr PC, Undef_Addr
ldr PC, SWI_Addr
ldr PC, PAbt_Addr
ldr PC, DAbt_Addr
.word 0xb9205f80 /* Reserved Vector (holds Philips ISP checksum) */
ldr PC, [PC,#-0xFF0] /* see page 71 of "Insiders Guide" by Trevor Martin */
ldr PC, FIQ_Addr

If not, you must have a default IRQ routine that jumps to the location given in VICVectAddr.

This question gives me a chance to ask the group one of my own:

When I'm using this technique, it appears to me that the performance of IRQ is the same as FIQ? Of course, you can get one level of nesting for free by configuring your highest priority interrupt as FIQ. But it looks like the number of machine cycles required will be the same. Is this true, or is there an advantage to FIQ that I've not understood?

-Hugh

--- In l..., "ftsol1962" wrote:
>
> Sorry if this has been visited before, but my searches haven't turned it up. I am using the IAR WorkBench 5.4 (Kickstart Edition)
>
> Basically I want to have the WatchDog operate in INT mode, not RESET,
> so that I can do some housekeeping in the interrupt routine before system reset. I want to use IRQ Vector 0 so the WatchDog INT takes
> priority over all other IRQs in the system. I am running the PLL @ 4X multiplier with external oscillator @ 14.7456 MHz, and MAM=1,
> MAMTIM=3; Operating in USerFlash mode.
>
> Now, the problem:
> I configure the VIC to enable WatchDog Ints, have them generate IRQ, and configure VICVectAddr0 register with the address of my watchdog
> ISR function, and Enable the VICVectCntl0 for the WatchDog Int (VICVectCntl0 = 0x20) as follows:
>
> unsigned long temp;
> temp = VICIntSelect; // Get current IRQ/FIQ int settings
> temp = temp & ~(0x00000001); // Make WatchDog int IRQ
> VICIntSelect = temp;
> temp = VICIntEnable;
> temp |= 0x00000001; // Enable WDOG Timer Int generation
> VICIntEnable = temp;
> VICVectCtl0 = (unsigned long) 0x0020; //WDOG Vect Enable
> VICVectAddr0 = (unsigned long)WatchDog_Interrupt;
>
> I then configure the Watchdog and start it.
>
> The WatchDog_Interrupt function @ 0x3d8:
> __irq __nested __arm void WatchDog_Interrupt()
> {
> VICIntEnableClear = (unsigned long)0x00000001;
> WatchDogIntcount +=1;
> WDMOD = 0x00;
> //
> // Do cleanup stuff here before reset or exit
> //
> VICVectAddr = (unsigned long) 0x00;
> }
>
> Problem is:
> 1. WatchDog underflows and sets the WDINT; It *appears* that the IRQ
> is generated, but the the Vector taken is the default one
> (VICDefVectADDR=0x00) instead of my isr @(0x3d8) even though I
> can see by placing a breakpoint @main that VICVectAddr=0x3d8 when
> the program restarts !?
> 2. IF I set the VICDefVectAddr = 0x3d8 (my watchdog ISR) then it is
> called instead of taking the Reset vector (0), so I believe that
> something odd is happening with the VIC and the WDog Vector
> processing, but cannot figure out what.
>
> Any assistance is appreciated!
>
h...@sbcglobal.net wrote:
> When I'm using this technique, it appears to me that the performance of
> IRQ is the same as FIQ? Of course, you can get one level of nesting for
> free by configuring your highest priority interrupt as FIQ. But it looks
> like the number of machine cycles required will be the same. Is this
> true, or is there an advantage to FIQ that I've not understood?

When a few cycles matters, you can't beat the FIQ. A couple of cycles
may be saved, as the address is read from the memory rather than from
the VIC through slow busses - depends of course on where your vectors
are. Few more cycles can be saved if the handler is coded in place, in
other words, it starts from the address of the vector. Biggest saving
comes from the fact that you have seven banked registers for the FIQ
handler. So, if you can do the thing in two instructions (extreme case),
then a FIQ handler can be made with roughly 50% overhead. IRQ handler
must read the vector, save registers, load variables, update variables
and restore registers. For a couple instructions main matter the
overhead can be in the order of 500%.

Of course, if the main thing in the handler is many lines of C code,
then the overhead is negligible and there may be no other reasons to use
FIQ than the easy two level nesting as you said.

--

Timo

You are correct, I am using the LDR PC,[PC,#-0xFF00] instruction at
memory location 0x18 (or rather, this is what I am trying to get the thing to do). If I put just a single IRQ_Handler() branch instruction at that location instead, I do of course, end up in the IRQ_Handler() function I write. If I do this, the very first read of VICVectAddr register does appear to give me the configured address of my WatchDog_Interrupt() routine (subsequent reads while in the IRQ_Handler do not). While I suppose that I could have the IRQ_Handler do an inline assembly branch to my WatchDog_Interrupt() or any other interpt service routine in this manner, it rather slows down the process and doesn't make use of the Vectored Intrpt Controller function, IMHO. Why the LDR PC,... instruction @ 0x18 doesn't seem to get the thing to branch to the configured WatchDog_Interrupt() address to begin with is the problem/mystery.

Do I have to have the chip in supervisor (not system) mode or something subtle like that?

--- In l..., "hsutherland2@..." wrote:
>
> I assume from context that you're using the "Insider's Guide" trick in the IRQ startup vector? Like
>
> _vectors: ldr PC, Reset_Addr
> ldr PC, Undef_Addr
> ldr PC, SWI_Addr
> ldr PC, PAbt_Addr
> ldr PC, DAbt_Addr
> .word 0xb9205f80 /* Reserved Vector (holds Philips ISP checksum) */
> ldr PC, [PC,#-0xFF0] /* see page 71 of "Insiders Guide" by Trevor Martin */
> ldr PC, FIQ_Addr
>
> If not, you must have a default IRQ routine that jumps to the location given in VICVectAddr.
>
> This question gives me a chance to ask the group one of my own:
>
> When I'm using this technique, it appears to me that the performance of IRQ is the same as FIQ? Of course, you can get one level of nesting for free by configuring your highest priority interrupt as FIQ. But it looks like the number of machine cycles required will be the same. Is this true, or is there an advantage to FIQ that I've not understood?
>
> -Hugh
>
> --- In l..., "ftsol1962" wrote:
> >
> > Sorry if this has been visited before, but my searches haven't turned it up. I am using the IAR WorkBench 5.4 (Kickstart Edition)
> >
> > Basically I want to have the WatchDog operate in INT mode, not RESET,
> > so that I can do some housekeeping in the interrupt routine before system reset. I want to use IRQ Vector 0 so the WatchDog INT takes
> > priority over all other IRQs in the system. I am running the PLL @ 4X multiplier with external oscillator @ 14.7456 MHz, and MAM=1,
> > MAMTIM=3; Operating in USerFlash mode.
> >
> > Now, the problem:
> > I configure the VIC to enable WatchDog Ints, have them generate IRQ, and configure VICVectAddr0 register with the address of my watchdog
> > ISR function, and Enable the VICVectCntl0 for the WatchDog Int (VICVectCntl0 = 0x20) as follows:
> >
> > unsigned long temp;
> > temp = VICIntSelect; // Get current IRQ/FIQ int settings
> > temp = temp & ~(0x00000001); // Make WatchDog int IRQ
> > VICIntSelect = temp;
> > temp = VICIntEnable;
> > temp |= 0x00000001; // Enable WDOG Timer Int generation
> > VICIntEnable = temp;
> > VICVectCtl0 = (unsigned long) 0x0020; //WDOG Vect Enable
> > VICVectAddr0 = (unsigned long)WatchDog_Interrupt;
> >
> > I then configure the Watchdog and start it.
> >
> > The WatchDog_Interrupt function @ 0x3d8:
> > __irq __nested __arm void WatchDog_Interrupt()
> > {
> > VICIntEnableClear = (unsigned long)0x00000001;
> > WatchDogIntcount +=1;
> > WDMOD = 0x00;
> > //
> > // Do cleanup stuff here before reset or exit
> > //
> > VICVectAddr = (unsigned long) 0x00;
> > }
> >
> > Problem is:
> > 1. WatchDog underflows and sets the WDINT; It *appears* that the IRQ
> > is generated, but the the Vector taken is the default one
> > (VICDefVectADDR=0x00) instead of my isr @(0x3d8) even though I
> > can see by placing a breakpoint @main that VICVectAddr=0x3d8 when
> > the program restarts !?
> > 2. IF I set the VICDefVectAddr = 0x3d8 (my watchdog ISR) then it is
> > called instead of taking the Reset vector (0), so I believe that
> > something odd is happening with the VIC and the WDog Vector
> > processing, but cannot figure out what.
> >
> > Any assistance is appreciated!
>

--- In l..., Timo wrote:
> When a few cycles matters, you can't beat the FIQ. A couple of cycles
> may be saved, as the address is read from the memory rather than from
> the VIC through slow busses - depends of course on where your vectors
> are. Few more cycles can be saved if the handler is coded in place, in
> other words, it starts from the address of the vector. Biggest saving
> comes from the fact that you have seven banked registers for the FIQ
> handler. So, if you can do the thing in two instructions (extreme case),
> then a FIQ handler can be made with roughly 50% overhead. IRQ handler
> must read the vector, save registers, load variables, update variables
> and restore registers. For a couple instructions main matter the
> overhead can be in the order of 500%.
>
> Of course, if the main thing in the handler is many lines of C code,
> then the overhead is negligible and there may be no other reasons to use
> FIQ than the easy two level nesting as you said.
>
> --
>
> Timo
>
I begin to see what you mean. There have been a couple of other threads discussing instruction timing. Quite an eye-opener for me when I began following the links, even though most of the info was available in the Tech Ref Manual. I guess I'd been thinking "Hey, its a RISC processor, right?..." I'm having second thoughts about that one-chip-logic-analyzer system I was dreaming about.

ftsol: Sorry, I can't see where the problem might be. (Once I get up to speed a bit more so I have specific questions to ask, a lot of them are going to be about how to catch interrupts and startup code with the debugger.)

--- In l..., "hsutherland2@..." wrote:

> I begin to see what you mean. There have been a couple of other threads discussing instruction timing. Quite an eye-opener for me when I began following the links, even though most of the info was available in the Tech Ref Manual. I guess I'd been thinking "Hey, its a RISC processor, right?..." I'm having second thoughts about that one-chip-logic-analyzer system I was dreaming about.

I don't know about a one chip logic analyzer but I do know about a 1 board system.

See http://www.sump.org/projects/analyzer/

It's based on the Digilent Inc Spartan 3 Starter Board
http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,519&Prod=S3BOARD

It works very well. I use it all the time.

Richard

Memfault Beyond the Launch