EmbeddedRelated.com
Forums

LPC2378 and watchdog

Started by remsilicon July 17, 2007
Hi,

The erratasheet of the LPC2378 explain that feed the watchdog cause a
reset, so how use the watchdog with the LPC2378 ???
:s
Thanks

An Engineer's Guide to the LPC2100 Series

--- In l..., "remsilicon" wrote:
>
> Hi,
>
> The erratasheet of the LPC2378 explain that feed the watchdog cause
a
> reset, so how use the watchdog with the LPC2378 ???
> :s
> Thanks
>
This is what I do...It seems to work OK, is this correct ???

void WDTFeed( void )
{
//Per LPC2378 Erratsheet :
//
//Problem : "After writing 0xAA to WDFEED, any APB register
access other than writing 0x55
// to WDFEED may cause an immediate reset."
//
//Workaround : "Avoid APB accesses in the middle of the feed
sequence.
// This implies that interrupts and the GPDMA should be
disabled while feeding
// the Watchdog."
//
//APB: "All Pereferals Bus"
unsigned long current_interrupt_status;

//(JP) This seems to work
VICProtection = 0; //allow access to vic in
user mode
current_interrupt_status = VICIntEnable ; //Save a copy of the
currently enabled interrupts
VICIntEnClr = current_interrupt_status; //Clears all that were
active

WDFEED = 0xAA; // Feeding sequence that does not
want to be interrupted after this statement !!!!!
WDFEED = 0x55;

VICIntEnable = current_interrupt_status; //Restore the interrupts

}
I was having a problem with the watchdog in the LPC236x where it
would continuously reset the part even though it was being fed often
enough. An engineer at NXP alerted me to an undocumented "feature"
of the watchdog timer: Do not feed it more than once every 35us. I
modified my code to make sure this doesn't happen, and it is working
fine now. I am told that this requirement should appear in the next
version of the documentation.
--- In l..., "jap136542"
wrote:
>
> --- In l..., "remsilicon" wrote:
> >
> > Hi,
> >
> > The erratasheet of the LPC2378 explain that feed the watchdog
cause
> a
> > reset, so how use the watchdog with the LPC2378 ???
> > :s
> >
> >
> > Thanks
> >
> This is what I do...It seems to work OK, is this correct ???
>
> void WDTFeed( void )
> {
> //Per LPC2378 Erratsheet :
> //
> //Problem : "After writing 0xAA to WDFEED, any APB register
> access other than writing 0x55
> // to WDFEED may cause an immediate reset."
> //
> //Workaround : "Avoid APB accesses in the middle of the feed
> sequence.
> // This implies that interrupts and the GPDMA should
be
> disabled while feeding
> // the Watchdog."
> //
> //APB: "All Pereferals Bus"
> unsigned long current_interrupt_status;
>
> //(JP) This seems to work
> VICProtection = 0; //allow access to vic
in
> user mode
> current_interrupt_status = VICIntEnable ; //Save a copy of the
> currently enabled interrupts
> VICIntEnClr = current_interrupt_status; //Clears all that
were
> active
>
> WDFEED = 0xAA; // Feeding sequence that does not
> want to be interrupted after this statement !!!!!
> WDFEED = 0x55;
>
> VICIntEnable = current_interrupt_status; //Restore the
interrupts
>
> }
>
So you disabled all interrupts ???
I will try this right now :)

--- In l..., "jap136542" wrote:
>
> --- In l..., "remsilicon" wrote:
> >
> > Hi,
> >
> > The erratasheet of the LPC2378 explain that feed the watchdog cause
> a
> > reset, so how use the watchdog with the LPC2378 ???
> > :s
> >
> >
> > Thanks
> >
> This is what I do...It seems to work OK, is this correct ???
>
> void WDTFeed( void )
> {
> //Per LPC2378 Erratsheet :
> //
> //Problem : "After writing 0xAA to WDFEED, any APB register
> access other than writing 0x55
> // to WDFEED may cause an immediate reset."
> //
> //Workaround : "Avoid APB accesses in the middle of the feed
> sequence.
> // This implies that interrupts and the GPDMA should be
> disabled while feeding
> // the Watchdog."
> //
> //APB: "All Pereferals Bus"
> unsigned long current_interrupt_status;
>
> //(JP) This seems to work
> VICProtection = 0; //allow access to vic in
> user mode
> current_interrupt_status = VICIntEnable ; //Save a copy of the
> currently enabled interrupts
> VICIntEnClr = current_interrupt_status; //Clears all that were
> active
>
> WDFEED = 0xAA; // Feeding sequence that does not
> want to be interrupted after this statement !!!!!
> WDFEED = 0x55;
>
> VICIntEnable = current_interrupt_status; //Restore the interrupts
>
> }
>
jap136542 wrote:
>
> --- In lpc2000@yahoogroups .com ,
> "remsilicon" wrote:
> >
> > Hi,
> >
> > The erratasheet of the LPC2378 explain that feed the watchdog cause
> a
> > reset, so how use the watchdog with the LPC2378 ???
> This is what I do...It seems to work OK, is this correct ???
>
Disabling the interrupt seems to be a great idea since the LPC family
don't have atomic instructions (afaik). But how can your application
coop with the missing interrupts? I guess that if an interrupt occur in
the middle of your disabled phase, then you simply miss those out?
Right? The VIC doesn't remember the interrupt when you enable it again
or does it?

Regards Jan
--- In l..., Jan Thersen wrote:
>
> jap136542 wrote:
> >
> > --- In lpc2000@yahoogroups .com
40yahoogroups.com>,
> > "remsilicon" wrote:
> > >
> > > Hi,
> > >
> > > The erratasheet of the LPC2378 explain that feed the watchdog
cause
> > a
> > > reset, so how use the watchdog with the LPC2378 ???
> >
> >
> > This is what I do...It seems to work OK, is this correct ???
> >
> Disabling the interrupt seems to be a great idea since the LPC
family
> don't have atomic instructions (afaik). But how can your
application
> coop with the missing interrupts? I guess that if an interrupt
occur in
> the middle of your disabled phase, then you simply miss those out?
> Right? The VIC doesn't remember the interrupt when you enable it
again
> or does it?
>
> Regards Jan
>

All ARM (assembler) instructions are atomic. The issue is if an
interrupt happens in the middle of a sequence on instructions. That's
why you should disable them when doing the feed sequence (which can't
be done with a single instruction).

One of the main functions of the VIC is to priorise multiple
interrupts. If a lower priority interrupt is pending when a higher
level one is bein serviced (or interrupts to the core disabled), it
will pass the interrupt through to the core once it becomes the
highest priority current interrupt (when interrupts are re-enabled or
all higher priority interrupts have been serviced), provided the
interrupt source has not been removed. As most (all?) peripheral
sources don't remove the source of the interrupt until explicitely
told to do so my software, there is no problem.

That's a pretty long way of saying: "no, you don't miss the
interrupt" and "yes, the VIC does remember".

Brendan
At 09:42 PM 7/17/2007 +0000, jap136542 wrote:
>This is what I do...It seems to work OK, is this correct ???
>
>void WDTFeed( void )
>{
> //Per LPC2378 Erratsheet :
> //
> //Problem : "After writing 0xAA to WDFEED, any APB register
>access other than writing 0x55
> // to WDFEED may cause an immediate reset."
> //
> //Workaround : "Avoid APB accesses in the middle of the feed
>sequence.
> // This implies that interrupts and the GPDMA should be
>disabled while feeding
> // the Watchdog."
> //
> //APB: "All Pereferals Bus"
> unsigned long current_interrupt_status;
>
> //(JP) This seems to work
> VICProtection = 0; //allow access to vic in
>user mode
> current_interrupt_status = VICIntEnable ; //Save a copy of the
>currently enabled interrupts
> VICIntEnClr = current_interrupt_status; //Clears all that were
>active
>
> WDFEED = 0xAA; // Feeding sequence that does not
>want to be interrupted after this statement !!!!!
> WDFEED = 0x55;
>
> VICIntEnable = current_interrupt_status; //Restore the interrupts
>
>}

A couple of points to consider
- That doesn't disable the FIQ so it potentially leaves a rather large hole.
- Not a likely occurrence since it would be rather ugly programming
practice but there is at least one potential race condition in the VIC
disable above if an interrupt occurs between the lines.
- I'd disable interrupts via the processor's status register rather than
the VIC. If nothing else it will disable all sources simultaneously.

Robert

http://www.aeolusdevelopment.com/

From the Divided by a Common Language File (Edited to protect the guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live.... we
currently have stock."
--- In l..., Robert Adsett
wrote:
>
> At 09:42 PM 7/17/2007 +0000, jap136542 wrote:
> >This is what I do...It seems to work OK, is this correct ???
> >
> >void WDTFeed( void )
> >{
> > //Per LPC2378 Erratsheet :
> > //
> > //Problem : "After writing 0xAA to WDFEED, any APB register
> >access other than writing 0x55
> > // to WDFEED may cause an immediate reset."
> > //
> > //Workaround : "Avoid APB accesses in the middle of the feed
> >sequence.
> > // This implies that interrupts and the GPDMA
should be
> >disabled while feeding
> > // the Watchdog."
> > //
> > //APB: "All Pereferals Bus"
> > unsigned long current_interrupt_status;
> >
> > //(JP) This seems to work
> > VICProtection = 0; //allow access to
vic in
> >user mode
> > current_interrupt_status = VICIntEnable ; //Save a copy of the
> >currently enabled interrupts
> > VICIntEnClr = current_interrupt_status; //Clears all that
were
> >active
> >
> > WDFEED = 0xAA; // Feeding sequence that does not
> >want to be interrupted after this statement !!!!!
> > WDFEED = 0x55;
> >
> > VICIntEnable = current_interrupt_status; //Restore the
interrupts
> >
> >}
>
> A couple of points to consider
> - That doesn't disable the FIQ so it potentially leaves a rather
large hole.
> - Not a likely occurrence since it would be rather ugly
programming
> practice but there is at least one potential race condition in the
VIC
> disable above if an interrupt occurs between the lines.
> - I'd disable interrupts via the processor's status register
rather than
> the VIC. If nothing else it will disable all sources
simultaneously.
>
> Robert
>
> http://www.aeolusdevelopment.com/
>
> From the Divided by a Common Language File (Edited to protect the
guilty)
> ME - "I'd like to get Price and delivery for connector Part # XXXXX"
> Dist./Rep - "$X.XX Lead time 37 days"
> ME - "Anything we can do about lead time? 37 days seems a bit
high."
> Dist./Rep - "that is the lead time given because our stock is
live.... we
> currently have stock."
>
Thanks for the feedback Robert,

I took this as a nudge for me to go do more reading in the "Arm
System Developers Guide", and also some reading on Keil's web page:
http://www.keil.com/support/docs/3229.htm
...and am now using a SWI to set and clear F & I as suggested.

I'm doing this, FOR NOW, because I'm still running in user mode. I'm
running in user mode because I'm still a bit intimidated by Keil's
LPC2300.s I see a stack being set up for user mode, but no set up
for system mode. ????? ;^o

Here's a snippet from LPC2300.s:

<>
; Setup Stack for each mode

LDR R0, =Stack_Top

; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size

; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size

; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size

; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size

; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size

; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
<>
Question 1) : Why are all modes except system covered ??

Question 2) : What changes would one make to lpc2300.s to run
correctly in system mode ??

After yesterdays readings it seems that system mode is what I want.
(easier access to CPSR) (this is a soft-realtime, dedicated
application, Frequent diagnostics(RAM, FLASH CRCs, others), all
interrupt driven, no opperating system)
Thanks in advance...
JP