EmbDev.net

Forum: ARM programming with GCC/GNU tools LPC2103 - GCC (Winarm) - Crashes when using Thumb Interwork


von John Dominey (Guest)


Rate this post
useful
not useful
Hi,
I'm developing an application in C for the NXP LPC2103 which uses
interrupts (VIC) and works fine using just ARM code. However I'm almost
out of code space and am trying to use THUMB. Enabling -mthumb-interwork
(rather than -mno-thumb-interwork), without even building a file in
THUMB, causes the processor to hang when it encounters an interrupt. Not
enabling interrupts at startup cures this problem, but the application
relies on them heavily. Optimisation is -0s (size), the program won't
fit in any other mode.

My interrupt enabling/disabling routines are:

inline unsigned enableIRQ(void)
{
  unsigned _cpsr;

  _cpsr = asm_get_cpsr();
  asm_set_cpsr(_cpsr & ~IRQ_MASK);
  return _cpsr;
}

inline unsigned disableIRQ(void)
{
  unsigned _cpsr;

  _cpsr = asm_get_cpsr();
  asm_set_cpsr(_cpsr | IRQ_MASK);
  return _cpsr;
}

I think it's the actual getting into/out of the ISRs which is causing it
to fall over.

I'm using the latest version of Winarm (20060606). I've tried using
Yagarto as well, with exactly the same problem.

Can anyone suggest what's going wrong? I've been trying to get to the
bottom of this for a while, and it's now getting urgent!

P.S. I'm not very familiar with ARM assembly yet.

Thanks, John.

von Martin Thomas (Guest)


Rate this post
useful
not useful
John Dominey wrote:
> Hi,
> I'm developing an application in C for the NXP LPC2103 which uses
> interrupts (VIC) and works fine using just ARM code. However I'm almost
> out of code space and am trying to use THUMB. Enabling -mthumb-interwork
> (rather than -mno-thumb-interwork), without even building a file in
> THUMB, causes the processor to hang when it encounters an interrupt. Not
> enabling interrupts at startup cures this problem, but the application
> relies on them heavily. Optimisation is -0s (size), the program won't
> fit in any other mode.
>
> My interrupt enabling/disabling routines are:
>
> inline unsigned enableIRQ(void)
> {
>   unsigned _cpsr;
>
>   _cpsr = asm_get_cpsr();
>   asm_set_cpsr(_cpsr & ~IRQ_MASK);
>   return _cpsr;
> }
>
> inline unsigned disableIRQ(void)
> {
>   unsigned _cpsr;
>
>   _cpsr = asm_get_cpsr();
>   asm_set_cpsr(_cpsr | IRQ_MASK);
>   return _cpsr;
> }
>
> I think it's the actual getting into/out of the ISRs which is causing it
> to fall over.
>
> I'm using the latest version of Winarm (20060606). I've tried using
> Yagarto as well, with exactly the same problem.
>
> Can anyone suggest what's going wrong? I've been trying to get to the
> bottom of this for a while, and it's now getting urgent!
>
> P.S. I'm not very familiar with ARM assembly yet.
>
> Thanks, John.

There is a known problem with interwork, interrupts and optimization. It
has been discussed in in different forums/mailing-lists. A rather easy
approach to work around this is to declare the functions with the
"nacked" attribute and use entry- and exit-macros. It's not elegant or
portable but works. The example lpc2106_uart_irq (based on code from
Bill Knight) demonstrates this method. Another appraoch is an
assembler-wrapper, for LPC it's demonstrated in the gcc-port of the
LPC213x/4x driver-examples available in WinARM (update versions on my
web-pages). Also see the various gcc-Ports of AT91SAM7 examples, the
wrapper can be included easily, no knowledge in ARM assembly needed.

Martin Thomas

von John Dominey (Guest)


Rate this post
useful
not useful
Thanks - it works!!!!
I'm not sure what to do about the exception handlers like

void SWI_Routine   (void)  _attribute_ ((interrupt("SWI")));
void UNDEF_Routine (void)  _attribute_ ((interrupt("UNDEF")));

How do you make these "nacked" while still telling the compiler that
they're SWI and UNDEF interrupts? Do you still need to use ISR_ENTRY()
and ISR_EXIT()?
I know these interrupts should never be encountered, and I intend to
reset the  processor when they are, but how should it be done?

Thanks again,
John

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
John Dominey wrote:
> Thanks - it works!!!!
> I'm not sure what to do about the exception handlers like
>
> void SWI_Routine   (void)  _attribute_ ((interrupt("SWI")));
> void UNDEF_Routine (void)  _attribute_ ((interrupt("UNDEF")));
>
> How do you make these "nacked" while still telling the compiler that
> they're SWI and UNDEF interrupts? Do you still need to use ISR_ENTRY()
> and ISR_EXIT()?
> I know these interrupts should never be encountered, and I intend to
> reset the  processor when they are, but how should it be done?
>
> Thanks again,
> John

I have not used the macros for anything else but "normal" interrupts.
But if you are going to reset the processor anyway macros my not be
needed at all. The needed "prologs" for the other interrupt-sources are
documented in the technical reference. For SWI you might get an idea
from my SWI-examples which use "wrappers".

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.