EmbDev.net

Forum: ARM programming with GCC/GNU tools Slow running code - PLL or ARM/Thumb mode?


Author: Randall Aiken (randallaiken)
Posted on:

Rate this post
0 useful
not useful
I have a weird problem.  I am using WinARM with a Philips LPC2124, and
am getting very slow operation, nowhere near the 60MHz PLL-enabled
performance I expect.

I made a simple program to blink an LED attached to one of the port
pins.  It blinks the LED three times, then configures the PLL for 60MHz
operation (using an external 12MHz crystal), and blinks the LED three
more times.

If I compile the code in Keil, it blinks at a moderate speed the first
three times, then much faster the second three times, as expected.

If I then compile the exact same code in WinArm, the LED blinks very
slowly the first three times, then faster the second three times, but
neither are anywhere near as fast as the Keil-compiled code.

This would indicate to me that my PLL setup code is indeed functional,
because the second set of blinks is indeed faster than the first set
(which should be the default startup speed with no PLL enabled).
However, the code running so much slower concerns me.

The delay loop is a simple loop as follows, which I call with a value of
200000 in between blinks:

void delay(unsigned long value)
{
  volatile unsigned long loop;
   for ( loop = value ; loop > 0 ; loop--);

}

I am beginning to suspect that I may be somehow running in thumb mode as
opposed to ARM mode.   The makefile has the following statements, which
I assume should compile in ARM mode:

# List C source files here. (C dependencies are automatically
generated.)
SRC =
# List C source files here which must be compiled in ARM-Mode.
# use file-extension c for "c-only"-files
SRCARM = main.c
# List Assembler source files here.
ASRC =
# List Assembler source files here which must be assembled in ARM-Mode..
ASRCARM = crt0.S

Is there anything else that needs to be done to insure ARM-mode
compilation?

Otherwise, is there anything that needs to be set in the makefile or
crt0.S file to set the operating frequency?

Any help on this strange problem is greatly appreciated.

Thanks,

Randall Aiken

Author: Randall Aiken (randallaiken)
Posted on:

Rate this post
0 useful
not useful
Well, I found part of the problem - the Keil compiler initializes the
memory accelerator module (MAM) in their automatically-generated
startup.s file.  I took it out of there and put the initialization in
main.c, and now the Keil and WinARM are much closer, but the Keil still
looks to be about twice as fast.

Any other ideas would be welcomed!

Randall Aiken

Author: Jim Kaz (ancaritha)
Posted on:

Rate this post
0 useful
not useful
Randall Aiken wrote:
>I took it out of there and put the initialization in
> main.c, and now the Keil and WinARM are much closer, but the Keil still
> looks to be about twice as fast.

I ran across a problem once that made me think I was running much slower
than I actually was; for loops.  I calculated how long each instruction
would take, an executed a for loop to try and estimate my speed.  On
WinArm, I noticed it was actually about 10 times slower than I had
estimated it to be.  This may be a function of the GCC compiler, the
optimization level I was running at (1) and who knows what else.  Its
entirely possible that the Keil compiler is optimizing the for loop
different than GCC (perhaps a difference between thumb and arm mode), so
that although you are actually running at 60 MHz, the Keil codes faster
for loop makes it look like you are going fast.

Then again, you may have messed up initialization in WinArm :)

I suggest you post your start up file where you initialize clock stuff.
I've never used any LPC processors, but I'm sure someone else here has
and may be able to help you.

Author: Randall Aiken (randallaiken)
Posted on:

Rate this post
0 useful
not useful
Jim Kaz wrote:
> I ran across a problem once that made me think I was running much slower
> than I actually was; for loops.  I calculated how long each instruction
> would take, an executed a for loop to try and estimate my speed.  On
> WinArm, I noticed it was actually about 10 times slower than I had
> estimated it to be.  This may be a function of the GCC compiler, the
> optimization level I was running at (1) and who knows what else.  Its
> entirely possible that the Keil compiler is optimizing the for loop
> different than GCC (perhaps a difference between thumb and arm mode), so
> that although you are actually running at 60 MHz, the Keil codes faster
> for loop makes it look like you are going fast.
>
> Then again, you may have messed up initialization in WinArm :)
>
> I suggest you post your start up file where you initialize clock stuff.
> I've never used any LPC processors, but I'm sure someone else here has
> and may be able to help you.


After a bit more thought late last night, I came to the same conclusion.
Today I am going to write a routine that just toggles a pin in an
infinite loop.  I'll stick the oscilloscope on the pin and measure the
frequency.  This will take the delay loop and any optimization out of
the equation (I think!).  If nothing else, it will tell me exactly what
the frequency difference is.

Thanks!

Randall Aiken

Author: Randall Aiken (randallaiken)
Posted on:

Rate this post
0 useful
not useful
Now it gets interesting...

I put in the following code:

  while(1)
  {
    IOCLR0 |= P0_STATUS_LED_o;
    IOSET0 |= P0_STATUS_LED_o;
  }


The Keil compiler executes this at a 1.44MHz toggle rate.

The WinArm compiler executes the same routine at a 1.58MHz toggle rate,
so it is actually faster than Keil!

So, I guess it is indeed a loop optimization problem, although I would
have thought the above code would have run at the same speed regardless
of the compiler.

Thanks!

Randall Aiken

Author: Martin Thomas (mthomas) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Randall Aiken wrote:
> Now it gets interesting...
>
> I put in the following code:
>
>   while(1)
>   {
>     IOCLR0 |= P0_STATUS_LED_o;
>     IOSET0 |= P0_STATUS_LED_o;
>   }
>
>
> The Keil compiler executes this at a 1.44MHz toggle rate.

Try to use RealView, it's the compiler (better toolchain) RV-MDK from
Keil uses "behind" the uVision IDE.

> The WinArm compiler executes the same routine at a 1.58MHz toggle rate,
> so it is actually faster than Keil!

There is no WinARM compiler. The WinARM package just includes a
precompiled GNU cross-compiler for ARM. Try to use "arm-elf-gcc Version
x.x.x"

> So, I guess it is indeed a loop optimization problem, although I would
> have thought the above code would have run at the same speed regardless
> of the compiler.

For GNU you can output the assembler-code the compiler generates or
create a disassembly from the elf-file (objdump "lss-file"). IRC
RealView also creates elf-binaries so you can objdump this too and
compare the assembly-code and see which kind of optimization has been
done. I think there is also an option in uVision to enable
assembler-listings

When looking at code for RealView or the IAR EWARM toolchain I sometimes
think that both have some kind of "forgotten volatile protection" which
might decrease speed since values are updated in RAM too and not only in
a core-register. But this is just speculation, the (dis)assembly will
show the difference.

Martin Thomas

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.