Reply by wouter van ooijen May 5, 20072007-05-05
> FIQs are primarily needed to support very high priority interrupts
> that are handled imediately. If you ever disable them, the latency of
> the handler is unknown, which as I said obviates one of the main
> reasons for using them (predictable worst case performance).

only if you disable them *at a time when they are needed*. DMA (to use
the canonical example) is not needed while it is being set up.

> I see no reason to use an FIQ when a high-priority IRQ can be
> used in its place.

You are right of course, but note the word "can". For very special
purposes (which is what FIQ is for) you can't use an IRQ because you
need the banked registers.

Wouter van Ooijen

-- -------
Van Ooijen Technische Informatica: www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: www.voti.nl/hvu

An Engineer's Guide to the LPC2100 Series

Reply by Darcy Williams April 28, 20072007-04-28
Hi Richard,

What a can of worms :) I like that little solution. I can't see it
saving many instructions but I suppose if you see the need to do it,
an extra instruction or three makes a difference! I'm happy playing
around with 8051 assembler, but the times I've looked through ARM
assembler I'm just stunned with the number of ways each instruction
can be used.

As this product is so simple, I think I'll just stay with the remapped
vectors in SRAM... but I'm also going to need to make a different
boot monitor for a product at work so I'll definitely save this
discussion for later reference.

Thanks for the help!
Darcy
--- In l..., Richard Duits wrote:
>
> Hi Darcy,
>
> Looks like a lot of LPC users have given this a lot of thought. I kept
> things a lot simpler than the other replies I read.
>
> For the Software Interrupt vector (SWI instruction) I use a fixed
> address in the application sectors.
>
> The IRQ address is loaded directly from the VIC.
>
> For the FIQ the "MOV PC, R12" is used. Before using the FIQ you can
call
> a assembly function to set the R12 in the FIQ register bank. R12
will be
> preserved by an IRQ function implemented in C or an assembly function
> can leave another address in R12 depending on the state of the hardware
> at the end of the interrupt. I used this for a high priority ADC
> interrupt to remember wich ADC channel was selected. This saved me a
> "switch (adc_channel) { .... }" like construct at the start of the FIQ.
>
> The other exceptions are handled by the custom boot loader. They
usually
> just reset the device, but they can be used to dump the registers to a
> serial port.
>
> This way it is usually not needed to remap the vectors to SRAM.
>
> Regards,
> Richard.
>
Reply by Brendan Murphy April 28, 20072007-04-28
--- In l..., "jayasooriah" wrote:

> Every time someone does not agree with you, you accuse them of missing
> the point. This is why I dont like to respond to your posts.
>

Apologies, your statement:

FIQ, then the same should apply to disabling IRQ /END QUOTE>

had led me to believe you didn't understand the point I was making, as
it makes little sense in the context of that point.

> There is little point in you repeating yourself. Those of use who
> understand DMA appreciate that this function on is better served by
> FIQ than IRQ because of the alternate register bank that can hold
> buffer pointers and transfer counts.
>

A good point, in that FIQ have other advantages over IRQs other than
deterministic worst-case response times.

Again, personally I'd either code the DMA FIQ so that it would work
correctly without being disabled, or relegate it to a high-priority IRQ
and forgo the use of the banked registers, which have fairly minimal
time savings in any case.

By the way, I had thought I'd made it clear that I'm not asking you or
anyone else to agree with me; all I was doing was pointing out there
was an alternative approach.

We've both made our points, so unless you have some other relevant
technical issue to raise, I suggest we end this.

Brendan
Reply by jayasooriah April 28, 20072007-04-28
--- In l..., "Brendan Murphy"
wrote:
>
> --- In l..., "jayasooriah" wrote:
> > If it is true that one "loses the benefits of FIQ" by disabling FIQ,
> > then the same should apply to disabling IRQ. Clearly it is not
> true.
>
> I rather think you've missed the point. If you need to have an
> interrupt that needs on occasion to be disabled, just define it as an
> IRQ.
>
> > Off the cuff, one example is when FIQ is used in a manner similar to
> > DMA, but for peripherals that do not support DMA. You *must*
> suspend
> > this "DMA" handled by FIQ handler when you fiddle with the buffers.
>
> To use your example, I'd simply use the highest priority IRQ to
> handle the DMA and enable and disable it as required.
>
> >
> > There are many examples of this kind of use. The FIQ and IRQ bits
> are
> > independent in the PSR precisely for this purpose.
>
> FIQs are primarily needed to support very high priority interrupts
> that are handled imediately. If you ever disable them, the latency of
> the handler is unknown, which as I said obviates one of the main
> reasons for using them (predictable worst case performance).
>
> I see no reason to use an FIQ when a high-priority IRQ can be used in
> its place.
>

Every time someone does not agree with you, you accuse them of missing
the point. This is why I dont like to respond to your posts.

There is little point in you repeating yourself. Those of use who
understand DMA appreciate that this function on is better served by
FIQ than IRQ because of the alternate register bank that can hold
buffer pointers and transfer counts.

Jaya
Reply by Tom Walsh April 28, 20072007-04-28
jayasooriah wrote:
>
> --- In lpc2000@yahoogroups .com ,
> Tom Walsh wrote:
> > ========= begin IRQ ===========> > __irq:
> > stmfd sp!,{lr} // save return address.
> > mrs lr,spsr // save status reg.
> > stmfd sp!,{r4-r5,lr} // save work regs and status reg.
> > ldr r4,=VICVectAddr // get ISR address from vic.
> > ldr r5,[r4]
> > msr cpsr_c,#MODE_ SVC // Supervisor Mode and re-enable
> > interrupts.
> > stmfd sp!,{r0-r3,r12, lr} // save work registers and
> return on
> > stack.
> > mov lr,pc // set return to common exit of ISR.
> > mov pc,r5 // execute the proper ISR handler.
> > ldmfd sp!,{r0-r3,r12, lr} // restore work regs and return.
> > msr cpsr_c,#MODE_ IRQ|I_BIT // switch back to IRQ mode,
> > interrupt off.
> > ldr r4,=VICVectAddr // ack the interrupt.
> > mov r5,#0xff
> > str r5,[r4] // touch VIC to update priorities.
> > ldmfd sp!,{r4-r5,lr} // restore work regs and IRQ return.
> > msr spsr_cxsf,lr // restore spsr of irq mode.
> > ldmfd sp!,{lr} // restore return address.
> > subs pc,lr,#0x4 // do the return from IRQ interrupt.
> > ======== snip ============ ====>
> For the benefit of those who are looking at abstracting a general
> purpose re-entrant IRQ handler from the above solution, I like to
> point out that the above solution assumes FIQ is always enabled on
> entry into IRQ handler.
>

Heh, I forgot to mention, the FIQ exception is not used in my system.
That is a good point though, I should be careful of that and setup some
vector in the external RAM so that a future runtime app could use the FIQ...

TomW
--
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net http://cyberiansoftware.com http://openzipit.org
"Windows? No thanks, I have work to do..."
----------------
Reply by Brendan Murphy April 28, 20072007-04-28
--- In l..., "jayasooriah" wrote:
> If it is true that one "loses the benefits of FIQ" by disabling FIQ,
> then the same should apply to disabling IRQ. Clearly it is not
true.

I rather think you've missed the point. If you need to have an
interrupt that needs on occasion to be disabled, just define it as an
IRQ.

> Off the cuff, one example is when FIQ is used in a manner similar to
> DMA, but for peripherals that do not support DMA. You *must*
suspend
> this "DMA" handled by FIQ handler when you fiddle with the buffers.

To use your example, I'd simply use the highest priority IRQ to
handle the DMA and enable and disable it as required.

>
> There are many examples of this kind of use. The FIQ and IRQ bits
are
> independent in the PSR precisely for this purpose.

FIQs are primarily needed to support very high priority interrupts
that are handled imediately. If you ever disable them, the latency of
the handler is unknown, which as I said obviates one of the main
reasons for using them (predictable worst case performance).

I see no reason to use an FIQ when a high-priority IRQ can be used in
its place.
Reply by jayasooriah April 28, 20072007-04-28
--- In l..., "Brendan Murphy"
wrote:
> However, to my mind if you ever disable FIQs, you loose one of the
> benefits of using them: a predictable latency with the worst case
> response of standard overhead plus maximum instruction length. If you
> disable them, you have an unknown upper bound on the response time.
> There's little difference between having something as the highest
> priority IRQ interrupt and an FIQ in this situation (assuming you
> support nested interrupts). If you take the approach of never
> disabling FIQs, things are somewhat simpler (in particular you don't
> have to worry about the ARM's quirks relating to enabling/disabling
> IRQ/FIQs).

If it is true that one "loses the benefits of FIQ" by disabling FIQ,
then the same should apply to disabling IRQ. Clearly it is not true.
If you could not think of a scenario where this is necessary you could
just ask an open question.

Off the cuff, one example is when FIQ is used in a manner similar to
DMA, but for peripherals that do not support DMA. You *must* suspend
this "DMA" handled by FIQ handler when you fiddle with the buffers.

There are many examples of this kind of use. The FIQ and IRQ bits are
independent in the PSR precisely for this purpose.

> Before jumping down my throat, Jaya, I'm simply suggesting this
> approach as an alternative: it's not a criticism of what you say
> (which as I mention, I'd tend to agree with in general).

I trust pointing out that your "alternative approach" is based on
false premises does not tantamount to "jumping down your throat".

> Brendan

Jaya
Reply by Brendan Murphy April 28, 20072007-04-28
--- In l..., "jayasooriah" wrote:
>
> For the benefit of those who are looking at abstracting a general
> purpose re-entrant IRQ handler from the above solution, I like to
> point out that the above solution assumes FIQ is always enabled on
> entry into IRQ handler.
>
> In general this is not true and I find it useful useful to de-couple
> as much as possible exception handling routines from each other so
as
> to avoid problems later on that are very hard to debug. So I would
> preserve the FIQ bit rather than clear (or set) based on apriori
> assumptions.
>

In the general case, this is of course true: best not make any
assumptions about the rest of the system, and to always restore it to
the state you left it.

However, to my mind if you ever disable FIQs, you loose one of the
benefits of using them: a predictable latency with the worst case
response of standard overhead plus maximum instruction length. If you
disable them, you have an unknown upper bound on the response time.
There's little difference between having something as the highest
priority IRQ interrupt and an FIQ in this situation (assuming you
support nested interrupts). If you take the approach of never
disabling FIQs, things are somewhat simpler (in particular you don't
have to worry about the ARM's quirks relating to enabling/disabling
IRQ/FIQs).

Before jumping down my throat, Jaya, I'm simply suggesting this
approach as an alternative: it's not a criticism of what you say
(which as I mention, I'd tend to agree with in general).

Brendan
Reply by Richard Duits April 28, 20072007-04-28
Hi Darcy,

Looks like a lot of LPC users have given this a lot of thought. I kept
things a lot simpler than the other replies I read.

For the Software Interrupt vector (SWI instruction) I use a fixed
address in the application sectors.

The IRQ address is loaded directly from the VIC.

For the FIQ the "MOV PC, R12" is used. Before using the FIQ you can call
a assembly function to set the R12 in the FIQ register bank. R12 will be
preserved by an IRQ function implemented in C or an assembly function
can leave another address in R12 depending on the state of the hardware
at the end of the interrupt. I used this for a high priority ADC
interrupt to remember wich ADC channel was selected. This saved me a
"switch (adc_channel) { .... }" like construct at the start of the FIQ.

The other exceptions are handled by the custom boot loader. They usually
just reset the device, but they can be used to dump the registers to a
serial port.

This way it is usually not needed to remap the vectors to SRAM.

Regards,
Richard.

Darcy Williams schreef:
> I'm using an LPC2138/2148 with Rowley CrossWorks and GCC 4.1.1
>
> Essentially, I have a boot monitor in the first two sectors of flash
> that checks the primary application image against another
> application image, and if required copies the upgrade over the
> primary application.
>
> Addr: 0x0000 0000 - 0x0000 1FFF (sect: 0 - 1) - Custom boot monitor
> Addr: 0x0000 4000 - 0x0001 FFFF (sect: 4 - 10) - Primary Application
> Addr: 0x0002 0000 - 0x0003 FFFF (sect: 11 - 14) - Upgrade Image
>
> The boot monitor then performs a jump to the primary application,
> using the method:
>
> typedef void (*func_ptr)(void);
>
> func_ptr func = (void*)0x4000;
> func();
> The primary application then reconfigures the device, trashing all
> the memory used by the boot monitor - reconfiguring stack sizes and
> all that jazz. After jumping to the application, interrupts no
> longer function. I had a suspicion this would be the case before
> starting on this, but wasn't totally sure of that until I got this
> far.
>
> I think my solutions are along the lines of...
> a) Have the primary application place it's interrupt vectors in RAM
> and configure MEMMAP to RAM mode.
> b) Configure the boot monitor interrupt vectors to jump ahead into
> the vectors of the application (i'm unsure about how suitable this
> is). Interrupts are NOT used by the boot monitor.
>
> There are bound to be other people that have implemented similar
> solutions, are there any pros/cons to each method?
> Is this a reasonable method in which to implement a boot monitor
> (not to be confused with the boot loader of course)?
>
> Is there a better way to jump to the main application?
>
> Thanks very much
> Cheers
> Darcy
>
>
Reply by jayasooriah April 28, 20072007-04-28
--- In l..., Tom Walsh wrote:
> ========= begin IRQ ===========> __irq:
> stmfd sp!,{lr} // save return address.
> mrs lr,spsr // save status reg.
> stmfd sp!,{r4-r5,lr} // save work regs and status reg.
> ldr r4,=VICVectAddr // get ISR address from vic.
> ldr r5,[r4]
> msr cpsr_c,#MODE_SVC // Supervisor Mode and re-enable
> interrupts.
> stmfd sp!,{r0-r3,r12,lr} // save work registers and
return on
> stack.
> mov lr,pc // set return to common exit of ISR.
> mov pc,r5 // execute the proper ISR handler.
> ldmfd sp!,{r0-r3,r12,lr} // restore work regs and return.
> msr cpsr_c,#MODE_IRQ|I_BIT // switch back to IRQ mode,
> interrupt off.
> ldr r4,=VICVectAddr // ack the interrupt.
> mov r5,#0xff
> str r5,[r4] // touch VIC to update priorities.
> ldmfd sp!,{r4-r5,lr} // restore work regs and IRQ return.
> msr spsr_cxsf,lr // restore spsr of irq mode.
> ldmfd sp!,{lr} // restore return address.
> subs pc,lr,#0x4 // do the return from IRQ interrupt.
> ======== snip ================
For the benefit of those who are looking at abstracting a general
purpose re-entrant IRQ handler from the above solution, I like to
point out that the above solution assumes FIQ is always enabled on
entry into IRQ handler.

In general this is not true and I find it useful useful to de-couple
as much as possible exception handling routines from each other so as
to avoid problems later on that are very hard to debug. So I would
preserve the FIQ bit rather than clear (or set) based on apriori
assumptions.

> It is a somewhat complex system to intially setup, however, once done,
> it is easy to use. The trick is the management of the stack(s). At
> first I thought that I could simply use a single (SYS) stack, this
> proved to be complex, the use of two stack "realms" simplified
things a lot.

In general one cannot avoid having a separate stack for each kind of
exception, but the trick I found is to switch to the working (SYS/USR)
stack as soon as practicable, so as to keep the size of the peripheral
stacks trivially small.

Jaya