Forums

Do not over-feed the Watchdog (?)

Started by Danish Ali April 3, 2006
Can someone point me to a definitive / application reference for the Watchdog
circuit used in the LPC2xxx - )one that is better than the user manual for
LPC2292)

I recently started trying to use the watchdog in the LPC2292.
Knowing no better, I decided to feed the watchdog once every time
I went round my event loop. I was careful to disable* interrupts before
writing 0xAA and 0x55 to WDFEED, and then re-enable the interrupts
afterwards. But I could not get the watchdog to behave - it would cause
interrupts no matter what (long) duration I set for the period (for
debugging I did not enable the reset, and I placed a
breakpoint in a Watchdog interrupt routine).
Typical periods I tried were around 1 to 10 seconds, with the PCLK at
60 MHz.

*using the macros provided in Crossworks. Note also that my spurious
interrupt routine merely writes to VICVectAddr and returns.

But if I placed a breakpoint in my event loop, and (from the debugger)
said "continue" before the watchdog timed out, the watchdog would not
interrupt.

My main event loop is pretty tight - it mostly looks to see if data have
arrived in buffers (put there by peripheral interrupt-service-routines).
Only when enough data are available will time-consuming calculations
be performed.

Seeing that the system did work if I placed a manual delay between
watchdog feeds, I tried only feeding the watchdog once every keyboard
scan (polled from a timer flag in the event loop, no faster than once
every ten milliseconds). This seemed to work fine, and continues to
work now I have enabled the watchdog reset.
And the watchdog does cause a reset if I deliberately enter an endless
loop.

Does this fit with the experience of others?
What constitutes over-feeding of the watchdog? Is it documented anywhere?
(It is possible that I do not understand what is going on).
I invite comments.

Regards,
Danish

Yahoo! Groups Links

An Engineer's Guide to the LPC2100 Series

Danish Ali wrote:

>Seeing that the system did work if I placed a manual delay between
>watchdog feeds, I tried only feeding the watchdog once every keyboard
>scan (polled from a timer flag in the event loop, no faster than once
>
>
That is suspicious! I would look very carefully at the assembly
language being generated by the compiler to ensure what I said in C
actually is being done in assembler (opcode level). Never assume.

TomW

--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------

Yahoo! Groups Links
--- In l..., Tom Walsh wrote:
>
> Danish Ali wrote:
>
> >Seeing that the system did work if I placed a manual delay between
> >watchdog feeds, I tried only feeding the watchdog once every keyboard
> >scan (polled from a timer flag in the event loop, no faster than once
> >
> >
> That is suspicious! I would look very carefully at the assembly
> language being generated by the compiler to ensure what I said in C
> actually is being done in assembler (opcode level). Never assume.
>
Hi Tom,
Good point, particularly as I hadn't included any source code
let alone the resulting assembly code.

When you view my watchdog feed routine, note that I do not
have anything set up to cause a FIQ. (I have not yet decided
which of my interrupt routines should be fast).

I don't have the hardware to hand (it is on its way back from
a trade show in Germany) where the system seemed to work. But
I had nothing hanging off the diagnostics port so I don't
know that for sure.

Regards,
Danish

The C source code is:

void Watchdog_Feed(void) {
/* This code DOES NOT WORK if FIQ is used */
/* read IRQ status. If it is enabled, disable it
feed watchdog
restore IRQ status */
int irqStat;
asm volatile (
" mrs r0, cpsr\n"
" mov %0,r0\n" : "=r" (irqStat) : : "r0" );
/* bit 7 of cpsr is set to disable IRQ */
if (128 & ~irqStat)
__ARMLIB_disableIRQ();
asm volatile (
"WDFEED = 0xE0000008\n"
" LDR r0, =WDFEED\n"
" MOV r1,#0xAA\n"
" MOV r2,#0x55\n"
" STRB r1,[r0]\n"
" STRB r2,[r0]\n" : : : "r0", "r1", "r2");
if (128 & ~irqStat)
__ARMLIB_enableIRQ();
}

with the crossworks IRQ enable and disable routines being:
<__ARMLIB_enableIRQ>:
E92D0001 stmfd sp!, {r0}
E10F0000 mrs r0, cpsr
E3C00080 bic r0, r0, #0x00000080
E12FF000 msr cpsr_cxsf, r0
E8BD0001 ldmfd sp!, {r0}
E12FFF1E bx lr
<__ARMLIB_disableIRQ>:
E92D0001 stmfd sp!, {r0}
E10F0000 mrs r0, cpsr
E3800080 orr r0, r0, #0x00000080
E12FF000 msr cpsr_cxsf, r0
E8BD0001 ldmfd sp!, {r0}
E12FFF1E bx lr

The full disassembly of Watchdog_Feed is:
void Watchdog_Feed(void) {
E1A0C00D mov r12, sp
E92DD800 stmfd sp!, {r11-r12, lr-pc}
E24CB004 sub r11, r12, #0x00000004
E24DD004 sub sp, sp, #0x00000004
int irqStat;
asm volatile (
E10F0000 mrs r0, cpsr
E1A03000 mov r3, r0
E50B3010 str r3, [r11, #-16]
" mrs r0, cpsr\n"
" mov %0,r0\n" : "=r" (irqStat) : : "r0" );
if (128 & ~irqStat)
E51B3010 ldr r3, [r11, #-16]
E1E03003 mvn r3, r3
E2033080 and r3, r3, #0x00000080
E3530000 cmp r3, #0x00000000
0A000000 beq 0x000033E8
__ARMLIB_disableIRQ();
EB001A7D bl 0x00009DE0 <__ARMLIB_disableIRQ>
asm volatile (
E3A0028E mov r0, #0xE0000008
E3A010AA mov r1, #0x000000AA
E3A02055 mov r2, #0x00000055
E5C01000 strb r1, [r0]
E5C02000 strb r2, [r0]
" MOV r1,#0xAA\n"
" MOV r2,#0x55\n"
" STRB r1,[r0]\n"
" STRB r2,[r0]\n" : : : "r0", "r1", "r2");
if (128 & ~irqStat)
E51B3010 ldr r3, [r11, #-16]
E1E03003 mvn r3, r3
E2033080 and r3, r3, #0x00000080
E3530000 cmp r3, #0x00000000
0A000000 beq 0x00003414
__ARMLIB_enableIRQ();
EB001A6C bl 0x00009DC8 <__ARMLIB_enableIRQ>
}
E24BD00C sub sp, r11, #0x0000000C
E89D6800 ldmfd sp, {r11, sp-lr}
E12FFF1E bx lr

Yahoo! Groups Links