EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Software crash with FIQ

Started by Wyss Markus July 6, 2006
Hello

Normaly, when there is a problem with my LPC2148 it takes me some
effort to solve it - at the end it works. There is a lot of
documentation out there, and a lot of information in this LPC2000
group. Now I find myself lost :) Hopefuly someone can help me...

I want to scan a analog signal with a 10kHz rate with the ADC1.
For this I use the timer1 match.0 which triggers the conversion.
That the trigger signal has physicaly to be set at the port pin
(P0.12) is another story (I would've liked to use it as a GPIO).

I have a lot of other IRQ handlers, and a RTOS IRQ time tick.
For some reasons I can't reenable IRQ interrupt in some handlers.
So it is natural, that some ADC triggers get lost during such an
other handler is working (IRQ disabled). So I decided to change
this ADC handler to FIQ.

All works fine as long as I use the ADC handler as IRQ, except that
ADC triggers get lost. When I change to FIQ, other IRQ handlers are
interrupted as expected, and no trigger is lost.

But after a while there is a strange behavior. After a while means,
that IRQ handlers and FIQ handler are processed several times,
and then (in one case) there are data abort exeptions.

I checked the following points to be correct :
- Stack pointer initialization for User/System-, IRQ- and FIQ-mode
- Stack size for User/System-, IRQ- and FIQ-mode
- FIQ prologue and epilogue
- Clear interrupt flag
- Only one FIQ handler

Here the simplified code for the ADC handler:
#define VIC_FIQ_PROLOGUE() \
__asm__ __volatile__( " sub lr, lr, #4 \n" \
" stmfd sp!, {r0-r6,lr} \n");

#define VIC_FIQ_EPILOGUE() \
__asm__ __volatile__( " ldmfd sp!, {r0-r6,pc}^ \n");
unsigned int value;

void fiq_handler(void) __attribute__((naked));
void fiq_handler(void)
{
VIC_FIQ_PROLOGUE();
DIO_PIEPSER_HIGH(); // Set Port bit (for Debug purposes)
value = AD1GDR; // Clear interrupt flag

DIO_PIEPSER_LOW(); // Clear Port bit (for Debug purposes)
VIC_FIQ_EPILOGUE();
}
(By the way: only reading of the AD1GDR register clears the
interrupt flag. The LPC2184 has for every AD-channel its own
result register whith a DONE flag. Reading the corresponding
registers, does not clear the interrupt flag.)

Any suggestions?
Thank's for help.

Markus

An Engineer's Guide to the LPC2100 Series

On a LPC2292 not all match signals need to be connected to a external
pin to trigger the adc. This will probably the same on other LPC2xxx chips.

I noticed you do not save R7 in your VIC_FIQ_PROLOGUE macro. Is this
because it is not used in the FIQ handler? You do not need to save
R8-R12 because those are banked registers in FIQ mode.
Richard.
Wyss Markus wrote:
>
> Hello
>
> Normaly, when there is a problem with my LPC2148 it takes me some
> effort to solve it - at the end it works. There is a lot of
> documentation out there, and a lot of information in this LPC2000
> group. Now I find myself lost :) Hopefuly someone can help me...
>
> I want to scan a analog signal with a 10kHz rate with the ADC1.
> For this I use the timer1 match.0 which triggers the conversion.
> That the trigger signal has physicaly to be set at the port pin
> (P0.12) is another story (I would've liked to use it as a GPIO).
>
> I have a lot of other IRQ handlers, and a RTOS IRQ time tick.
> For some reasons I can't reenable IRQ interrupt in some handlers.
> So it is natural, that some ADC triggers get lost during such an
> other handler is working (IRQ disabled). So I decided to change
> this ADC handler to FIQ.
>
> All works fine as long as I use the ADC handler as IRQ, except that
> ADC triggers get lost. When I change to FIQ, other IRQ handlers are
> interrupted as expected, and no trigger is lost.
>
> But after a while there is a strange behavior. After a while means,
> that IRQ handlers and FIQ handler are processed several times,
> and then (in one case) there are data abort exeptions.
>
> I checked the following points to be correct :
> - Stack pointer initialization for User/System-, IRQ- and FIQ-mode
> - Stack size for User/System-, IRQ- and FIQ-mode
> - FIQ prologue and epilogue
> - Clear interrupt flag
> - Only one FIQ handler
>
> Here the simplified code for the ADC handler:
>
> #define VIC_FIQ_PROLOGUE() \
> __asm__ __volatile__( " sub lr, lr, #4 \n" \
> " stmfd sp!, {r0-r6,lr} \n");
>
> #define VIC_FIQ_EPILOGUE() \
> __asm__ __volatile__( " ldmfd sp!, {r0-r6,pc}^ \n");
>
> unsigned int value;
>
> void fiq_handler(void) __attribute__((naked));
> void fiq_handler(void)
> {
> VIC_FIQ_PROLOGUE();
> DIO_PIEPSER_HIGH(); // Set Port bit (for Debug purposes)
> value = AD1GDR; // Clear interrupt flag
>
> DIO_PIEPSER_LOW(); // Clear Port bit (for Debug purposes)
> VIC_FIQ_EPILOGUE();
> }
>
> (By the way: only reading of the AD1GDR register clears the
> interrupt flag. The LPC2184 has for every AD-channel its own
> result register whith a DONE flag. Reading the corresponding
> registers, does not clear the interrupt flag.)
>
> Any suggestions?
> Thank's for help.
>
> Markus
>

--- In l..., "Wyss Markus" wrote:
>
> Hello
>
> Normaly, when there is a problem with my LPC2148 it takes me some
> effort to solve it - at the end it works. There is a lot of
> documentation out there, and a lot of information in this LPC2000
> group. Now I find myself lost :) Hopefuly someone can help me...
>
> I want to scan a analog signal with a 10kHz rate with the ADC1.
> For this I use the timer1 match.0 which triggers the conversion.
> That the trigger signal has physicaly to be set at the port pin
> (P0.12) is another story (I would've liked to use it as a GPIO).
>
> I have a lot of other IRQ handlers, and a RTOS IRQ time tick.
> For some reasons I can't reenable IRQ interrupt in some handlers.
> So it is natural, that some ADC triggers get lost during such an
> other handler is working (IRQ disabled). So I decided to change
> this ADC handler to FIQ.
>
> All works fine as long as I use the ADC handler as IRQ, except that
> ADC triggers get lost. When I change to FIQ, other IRQ handlers are
> interrupted as expected, and no trigger is lost.
>
> But after a while there is a strange behavior. After a while means,
> that IRQ handlers and FIQ handler are processed several times,
> and then (in one case) there are data abort exeptions.
>
> I checked the following points to be correct :
> - Stack pointer initialization for User/System-, IRQ- and FIQ-mode
> - Stack size for User/System-, IRQ- and FIQ-mode
> - FIQ prologue and epilogue
> - Clear interrupt flag
> - Only one FIQ handler
>
> Here the simplified code for the ADC handler:
> #define VIC_FIQ_PROLOGUE() \
> __asm__ __volatile__( " sub lr, lr, #4 \n" \
> " stmfd sp!, {r0-r6,lr} \n");
>
> #define VIC_FIQ_EPILOGUE() \
> __asm__ __volatile__( " ldmfd sp!, {r0-r6,pc}^ \n");
> unsigned int value;
>
> void fiq_handler(void) __attribute__((naked));
> void fiq_handler(void)
> {
> VIC_FIQ_PROLOGUE();
> DIO_PIEPSER_HIGH(); // Set Port bit (for Debug purposes)
> value = AD1GDR; // Clear interrupt flag
>
> DIO_PIEPSER_LOW(); // Clear Port bit (for Debug purposes)
> VIC_FIQ_EPILOGUE();
> }
> (By the way: only reading of the AD1GDR register clears the
> interrupt flag. The LPC2184 has for every AD-channel its own
> result register whith a DONE flag. Reading the corresponding
> registers, does not clear the interrupt flag.)
>
> Any suggestions?
> Thank's for help.
>
> Markus
>

What you're doing (multiple interrupt sources happenening together)
is (or should be!) fairly straightforward.

If I were you I'd:

- get rid of the "attribute" and "asm" stuff
- read the example in the PDF document in gcc_and_ucossii.zip in the
Files section of the group on how to set up mutiple interrupts safely
- have everything as IRQ, using the priority mechanism in the VIC to
sort out if one source needs a higher priority
- test each interrupt separately before putting everything together

By the way, it's a bit unclear how you are actually triggering the
ADC conversion: you really need a hardware start with no software
intervention to ensure no jitter is present.

Brendan

To Richard
----------

> On a LPC2292 not all match signals need to be connected to a
> external pin to trigger the adc. This will probably the same on
> other LPC2xxx chips.

o.k. I will check that.

> I noticed you do not save R7 in your VIC_FIQ_PROLOGUE macro. Is this
> because it is not used in the FIQ handler? You do not need to save
> R8-R12 because those are banked registers in FIQ mode.

As far as I know, Register R0..R6 have to be saved. The registers
R7..R14 are banked. Anyway - I checked that during debuging.
I stored all regs (R0..R12) to be sure this is not my problem.
The behavior was the same.
To Brendan
----------

> If I were you I'd:
>
> - get rid of the "attribute" and "asm" stuff

All IRQ handlers are done that way in my application. Except the FIQ
handler. During my first steps with the FIQ I've done it also this way.
And then I got trouble with different compiler optimization options.
I found some discussions here in this group about that topic.
First I'd like to bring it up to run this way, and will try to do it
like you suggest afterwards.
> - read the example in the PDF document in gcc_and_ucossii.zip in the
> Files section of the group on how to set up mutiple interrupts safely

I already read this doc. Very interesting. In fact some code snippets I
used are from there.

> - have everything as IRQ, using the priority mechanism in the VIC to
> sort out if one source needs a higher priority

This is another solution. But why reenable interrupts when there is a
nice solution with FIQ? Reenable interrupts gives some overhead to the
prologue and epilogue of every handler.

The behavior looks like a stack overflow or like not all needed registers
are saved and restored correctly. It is a bit hard to debug this problem
because I have a debugger with no trace capability. When I put a
breakpoint in the abort handler I can examine the link register. This
shows
me the instruction that caused the exception. But (for me) not enough
information to localize the problem.
--- In l..., "Wyss Markus" wrote:
>
> All IRQ handlers are done that way in my application. Except the FIQ
> handler. During my first steps with the FIQ I've done it also this
way.
> And then I got trouble with different compiler optimization options.
> I found some discussions here in this group about that topic.
> First I'd like to bring it up to run this way, and will try to do it
> like you suggest afterwards.

If you have it working one way, I'd leave it!

My reason for suggesting the alternative approach is that it is much
simpler to prove correct. Once you have the correct prologue and
epilogue code in assembler (a few lines), writing interrupt handlers
is very simple. The code is there, so why not use it?

As it is, you should really check the assembler o/p from the compiler
to verify it's doing what you think (as regards attribute naked and
in-line assembler etc.). Sounds like a whole lot of trouble to me...

> > - read the example in the PDF document in gcc_and_ucossii.zip in
the
> > Files section of the group on how to set up multiple interrupts
safely
>
> I already read this doc. Very interesting. In fact some code
snippets I
> used are from there.

Check out the example in section 3.10. If you don't want to support
interrupt nesting, you can leave out the instructions to change mode
and re-enable. The key thing is however that it allows you to code
the handler in regular `C'.

> This is another solution. But why re-enable interrupts when there
is a
> nice solution with FIQ? Re-enable interrupts gives some overhead to
the
> prologue and epilogue of every handler.

The overhead is negligible. Having two classes of interrupts can
cause other problems. Generally, FIQ is used for "extra special, must
handle right now" type interrupts (e.g. power is failing, time
critical event happened). Using it as a general purpose higher
priority interrupt can get quite tricky with disabling/enabling
interrupts etc.

>
> The behavior looks like a stack overflow or like not all needed
registers
> are saved and restored correctly. It is a bit hard to debug this
problem
> because I have a debugger with no trace capability. When I put a
> breakpoint in the abort handler I can examine the link register.
This
> shows
> me the instruction that caused the exception. But (for me) not
enough
> information to localize the problem.
>

Imagine if you didn't have a debugger!

Seriously, one handy trick to test for stack overflow is to fill each
stack area with a specific value (e.g. 0xaaaaaaaa for SVC stack,
0xbbbbbbbb for IRS stack etc.) at the start, and look at it
afterwards to see if someone's gone wild and overflowed the stack.

Hope some of this helps.

Brendan.

Take a look at http://www.arm.com/pdfs/DVI0027B_7_R3.pdf page 11.
You will see that the banked registers start at R8.

Richard.
Wyss Markus wrote:
>
> To Richard
> ----------
>
> > I noticed you do not save R7 in your VIC_FIQ_PROLOGUE macro. Is this
> > because it is not used in the FIQ handler? You do not need to save
> > R8-R12 because those are banked registers in FIQ mode.
>
> As far as I know, Register R0..R6 have to be saved. The registers
> R7..R14 are banked. Anyway - I checked that during debuging.
> I stored all regs (R0..R12) to be sure this is not my problem.
> The behavior was the same.
>

--- In l..., Richard Duits wrote:
>
> Take a look at http://www.arm.com/pdfs/DVI0027B_7_R3.pdf page 11.
> You will see that the banked registers start at R8.
>
> Wyss Markus wrote:
> > As far as I know, Register R0..R6 have to be saved. The registers
> > R7..R14 are banked.

I have seen more than a few (not just students) making the same
incorrect assumption relating to R7 and FIQ interrupts.

I traced the culprit to a document published by Philips and Hitex
explaining LPC programming but the reference skips my mind. Anyone?

Perhaps a note to the authors pointing out the error is appropriate.

Jaya

You have x-ray vision, Jaya.

The tome in question is "The Insider's Guide to Philips ARM7-Based
Microcontrollers" by Trevor Martin. The diagrams and text on page 12-13
all refer to the FIQ exception banking R7-R14 (should be R8-R14 as you
pointed out).

A small error but still a great book.

Cheers,
Jim Lynch
--- In l..., "lynchzilla" wrote:
>
> You have x-ray vision, Jaya.
>
> The tome in question is "The Insider's Guide to Philips ARM7-Based
> Microcontrollers" by Trevor Martin. The diagrams and text on page 12-13
> all refer to the FIQ exception banking R7-R14 (should be R8-R14 as you
> pointed out).
>
> A small error but still a great book.
>
> Cheers,
> Jim Lynch

I saw one too many programmers falling into the same trap, so I looked
for the cause and found it. By the way the next relese of this
document will have this fixed I am told.

Jaya
Hello Jim,

Just curious, did this fix the problem or are you still looking for a
solution?

Richard.

jayasooriah wrote:
>
> --- In l... ,
> "lynchzilla" wrote:
> >
> > You have x-ray vision, Jaya.
> >
> > The tome in question is "The Insider's Guide to Philips ARM7-Based
> > Microcontrollers" by Trevor Martin. The diagrams and text on page 12-13
> > all refer to the FIQ exception banking R7-R14 (should be R8-R14 as you
> > pointed out).
> >
> > A small error but still a great book.
> >
> > Cheers,
> > Jim Lynch
>
> I saw one too many programmers falling into the same trap, so I looked
> for the cause and found it. By the way the next relese of this
> document will have this fixed I am told.
>
> Jaya
>
>


Memfault Beyond the Launch