EmbeddedRelated.com
Forums

LPCUSB VCOM IRQ + LPC2148 + Crossworks

Started by darkcobrax February 6, 2007
--- In l..., "Michael Anton" wrote:
> Another workaround, is to just disable optimization for your
> interrupt code, but enable optimization for everything else.
> But, I'm not sure how you would do this in Crossworks. It is not
> hard to if using a GCC makefile.

This worked! And it's a workaround I can live with. I moved the ISR
to a file by itself, and Crossworks has a 'properties' window that
lets you set optimization on a file-by-file basis.

All my problems using LPCUSB seem to be solved. I'll go stress-test
it now to make sure. :)

Thanks again to everyone who helped me through this!

An Engineer's Guide to the LPC2100 Series

> I just tried it, and it didn't solve the problem. But I'll remember
> those functions - as you said, it's a lot easier. Thanks!

You of course still need a proper assembler stub to call your C
function for this to work. I am not sure if they are included in
CrossWorks. This stub saves the registers used by the called C
function (R0-R3, IP, and LR).

Here is what I use to call an interrupt routine:



This will fetch the interrupt handler address from the VIC.
If anyone has a better method of doing this, I'm open to
suggestions, especially since I'm and ARM assembler newbie.

Mike
--- In l..., "Michael Anton" wrote:
> You of course still need a proper assembler stub to call your C
> function for this to work. I am not sure if they are included in
> CrossWorks. This stub saves the registers used by the called C
> function (R0-R3, IP, and LR).

Though I'm satisfied with the other workaround, I went ahead and tried
this in combination with your prior suggestion. Same deal - works
fine as long as optimization is off. There may be some other
difference in play between your setup and mine.

> This will fetch the interrupt handler address from the VIC.
> If anyone has a better method of doing this, I'm open to
> suggestions, especially since I'm and ARM assembler newbie.

I've seen two stubs other than yours - one in Crossworks, and one Paul
Knight sent me. I can't tell you which is best since I'm a complete
asm newb, but all produced identical results for me. Let me know if
you want me to post them.
>
> Though I'm satisfied with the other workaround, I went ahead
> and tried
> this in combination with your prior suggestion. Same deal - works
> fine as long as optimization is off. There may be some other
> difference in play between your setup and mine.
>
> > This will fetch the interrupt handler address from the VIC.
> > If anyone has a better method of doing this, I'm open to
> > suggestions, especially since I'm and ARM assembler newbie.
>
> I've seen two stubs other than yours - one in Crossworks, and
> one Paul
> Knight sent me. I can't tell you which is best since I'm a complete
> asm newb, but all produced identical results for me. Let me know if
> you want me to post them.
>

I forgot to mention that you do need to change the interrupt vector
to branch to this stub, or it won't change a thing.

Here is a more complete snippet, starting with the interrupt
jump table:



Replace the line two lines up (it should be something similar in your code)
with:



Then include the stub below, after the FIQ branch (or perhaps the FIQ
routine if it is in assembler):



I suspect in all of the cases you tried, that the stub was not
actually used.

Mike
--- In l..., "Michael Anton" wrote:
> I forgot to mention that you do need to change the interrupt vector
> to branch to this stub, or it won't change a thing.

D'OH! That could be important, yes.. :)

I did a quick test by butchering the built-in Crossworks IRQ stub,
which is what I had been replacing with other stubs. The interrupts
continued working. You are correct, I never really changed a thing.

Your files look very different than mine. Fortunately, I recognized
the 'ldr pc, [pc, #-0xFF0]' command. The Crossworks docs say:

"You need to have the instruction 'ldr pc, [pc, #-0xFF0]' located at
the IRQ exception vector for vectored interrupts to work. To do this
make sure you have the preprocessor definition
VECTORED_IRQ_INTERRUPTS defined when you compile the
Philips_LPC210X_Startup.s file."

This define was actually the *first* thing I'd added trying to get
LPCUSB to work. Without it, the interrupt function as declared by
Bertrik with '__attribute__ ((interrupt("IRQ")))' didn't work at
all. I hunted down the conditional compile for this define, and
guess what it has if you *don't* define this?

A jump to the Crossworks IRQ stub. D'OH again!

So I removed the define, positively verified that the default
Crossworks IRQ stub is being used, and removed '__attribute__
((interrupt("IRQ")))' from the interrupt declaration.

The interrupt routine is now working with optimizations on!

Strangely, this broke something in my own, non-interrupt code. I'll
save this issue for later, it's break time. Three days of debugging
only to learn I'd taken a wrong turn at the beginning. At least it
was a scenic and educational route!
--- In l..., "Michael Anton" wrote:
> You of course still need a proper assembler stub to call your C
> function for this to work. I am not sure if they are included in
> CrossWorks. This stub saves the registers used by the called C
> function (R0-R3, IP, and LR).
>
> Here is what I use to call an interrupt routine:
>
> stmfd SP!,{R0-R3,IP,LR} // Save critical registers on the stack
> ldr R0,VICVectAddr // Address of the VICVectAddr register
> ldr R0,[R0] // Read the VICVectAddr register to get the interrupt
> handler address
> ands R0,R0 // Check if the adress is zero, and set flags
> movne LR,PC // Save the PC in the link register so we can return
> bxne R0 // Branch to the interrupt handler
> ldr R0,VICVectAddr // Address of the VICVectAddr register
> str R0,[R0] // Update the VIC priority hardware
> ldmfd SP!,{R0-R3,IP,LR} // Restore the stack
> subs PC,LR,#4 // Return from routine
>
> VICVectAddr: .word 0xFFFFF030
>
> This will fetch the interrupt handler address from the VIC.
> If anyone has a better method of doing this, I'm open to
> suggestions, especially since I'm and ARM assembler newbie.
>
> Mike
>

Mike,

An alternative stub is below (no doubt the formatting will be messed
up making it difficult to read, but you should get the idea). It's
slightly longer, but has the following advantages:

- nested interrupts, where a higher priority interrupt can interrupt
the ISR), are supported

- interrupts are disabled for an absolute minimum of time (6
instructions into the ISR), rather than the whole ISR

- the main ISR code can be coded as a standard 'C' function, with no
special keywords and pragmas (and can by in Thumb if required),
removing problems with portability and bugs in these features in some
compilers

- stack space is optimised slightly: the IRQ stack is minimal (4
words) and no extra safety margin is needed

Brendan