How to get a function running in RAM (Lpc21xx+GnuArm)?

Started by arkeryd January 18, 2006
Hi,

I am using uVision3 ide together with GnuArm compiler on LPC21xx.

I need to have some interrupts enabled while using the IAP functions,
and therefore have to place some interrupt service routines in RAM.

I have been looking around in documents and example files, but have
not found any solid info on this yet.

Any example, or hint of how to achieve this would be much appreciated!

(I suppose reading the generic gnu linker manual would do it, but am
afraid that the info is not so straightforward... Maybe I am too
prejudicial?)

/ Dennis



An Engineer's Guide to the LPC2100 Series

--- In lpc2000@lpc2..., "arkeryd" <arkeryd@y...> wrote:

> I am using uVision3 ide together with GnuArm compiler on LPC21xx.
>
> I need to have some interrupts enabled while using the IAP
> functions, and therefore have to place some interrupt service
> routines in RAM.
>
> I have been looking around in documents and example files, but have
> not found any solid info on this yet.
>
> Any example, or hint of how to achieve this would be much
> appreciated!

Put it in the .data section, and the startup code should copy it from
flash to RAM, just like initialization values for initialized data.
You'll get some assembler warnings "Warning: ignoring changed section
attributes for .data" that I haven't found out how to silence. It
works for me.

void ramfunc (int i) __attribute__ ((section(".data")));
void ramfunc (int i)
{
/* ... */
}

You cannot call such functions directly from flash functions (or call
flash functions from RAM functions) because RAM and flash are further
apart than a BL instruction can reach. You can use calls through
function pointers instead.

Karl Olsen



For an example, see
ftp://ftp.analog.com/pub/MicroConverter/ADuC702xV1.1/ADuC702x/code/keilcodeexamples/GNU%20Tools/FuncRam/



IAR does this even simpler - use the __ramfunc declarator on the
function. It is all auto-magic.
In LPC, it doesn't matter - RAM and FLASH are essentially the same speed
(barring branches). But on other ARMs, Flash may be very slow, so
copying to RAM is important for critical routines.
_____

From: lpc2000@lpc2... [mailto:lpc2000@lpc2...] On Behalf
Of Karl Olsen
Sent: Wednesday, January 18, 2006 2:14 AM
To: lpc2000@lpc2...
Subject: [lpc2000] Re: How to get a function running in RAM
(Lpc21xx+GnuArm)?
--- In lpc2000@lpc2..., "arkeryd" <arkeryd@y...> wrote:

> I am using uVision3 ide together with GnuArm compiler on LPC21xx.
>
> I need to have some interrupts enabled while using the IAP
> functions, and therefore have to place some interrupt service
> routines in RAM.
>
> I have been looking around in documents and example files, but have
> not found any solid info on this yet.
>
> Any example, or hint of how to achieve this would be much
> appreciated!

Put it in the .data section, and the startup code should copy it from
flash to RAM, just like initialization values for initialized data.
You'll get some assembler warnings "Warning: ignoring changed section
attributes for .data" that I haven't found out how to silence. It
works for me.

void ramfunc (int i) __attribute__ ((section(".data")));
void ramfunc (int i)
{
/* ... */
}

You cannot call such functions directly from flash functions (or call
flash functions from RAM functions) because RAM and flash are further
apart than a BL instruction can reach. You can use calls through
function pointers instead.

Karl Olsen SPONSORED LINKS

Microprocessor
<http://groups.yahoo.com/gads?t=ms&k=Microprocessor&w1=Microprocessor&w2
=Microcontrollers&w3=Pic+microcontrollers&w451+microprocessor&c=4&s=9
3&.sig=tsVC-J9hJ5qyXg0WPR0l6g>

Microcontrollers
<http://groups.yahoo.com/gads?t=ms&k=Microcontrollers&w1=Microprocessor&
w2=Microcontrollers&w3=Pic+microcontrollers&w451+microprocessor&c=4&s
&.sig=DvJVNqC_pqRTm8Xq01nxwg>

Pic microcontrollers
<http://groups.yahoo.com/gads?t=ms&k=Pic+microcontrollers&w1=Microproces
sor&w2=Microcontrollers&w3=Pic+microcontrollers&w451+microprocessor&c
=4&s&.sig=TpkoX4KofDJ7c6LyBvUqVQ>

8051 microprocessor
<http://groups.yahoo.com/gads?t=ms&k51+microprocessor&w1=Microprocess
or&w2=Microcontrollers&w3=Pic+microcontrollers&w451+microprocessor&c=
4&s&.sig=1Ipf1Fjfbd_HVIlekkDP-A

_____

> .
_____


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

arkeryd wrote:
> Hi,
>
> I am using uVision3 ide together with GnuArm compiler on LPC21xx.
>
> I need to have some interrupts enabled while using the IAP functions,
> and therefore have to place some interrupt service routines in RAM.
>
> I have been looking around in documents and example files, but have
> not found any solid info on this yet.
>
> Any example, or hint of how to achieve this would be much appreciated!
>
> (I suppose reading the generic gnu linker manual would do it, but am
> afraid that the info is not so straightforward... Maybe I am too
> prejudicial?)

Also have a look at Martin Thomas' page, he has some example code for
the GNU toolchain at:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/#gcc_ramfunc

Regards,
Bertrik

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFDznqeETD6mlrWxPURAuHsAJ94n4hraaxhiu52wEvy53t6PMXA7wCfaJ0p
gPbx3rCWaJRIonrOWhp/XEk=
=O7Ui
-----END PGP SIGNATURE-----



Thanks to all who replied!

I ended up defining a section named ram_func in the .ld file similiar
to the example from analog electronics and added "__attribute__
((section(".ram_func")));" to the headers of each function I want to
have in ram.

This works fine, and for some reason unknown for me this avoids the
compiler warnings that arrise when just declaring "__atribute__
((section(".data")));". :-)

If anybody is interested, I did the changes listed further below
compared to the default .ld file for LPC2129.

Btw, if anybody knows how to calculate the "_ramfuncetext" value
without needing to explicitly specify "- 0x40000000", I would be glad
to know how!

/ Dennis ...

MEMORY
{
CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x0001E000
DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00003FE0
} /* Section Definitions */

SECTIONS
{

...

_etext = . ;
PROVIDE (etext = .);

/* .data section which is used for initialized data */

.data : AT (_etext)
{
_data = . ;
*(.data)
SORT(CONSTRUCTORS)
} >DATA
. = ALIGN(4);

_foo = . ;
_ramfuncetext = _foo - 0x40000000 + _etext;
PROVIDE (ramfuncetext = .);

.ram_func : AT (_ramfuncetext)
{
_ram_func = .;
*(.ram_func)
} >DATA
. = ALIGN(4);

...



Try this.

MEMORY
{
CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x0001E000
DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00003FE0
}

/* Section Definitions */
SECTIONS
{

...

_etext = . ;
PROVIDE (etext = .);

/* .data section which is used for initialized data */
.data : AT (_etext)
{
_data = . ;
*(.data)
. = ALIGN(4)
*(.ram_func)
SORT(CONSTRUCTORS)
} >DATA

... Regards
-Bill Knight
R O SoftWare


---- Original Message ----
From: "Dan Beadle" <dan.beadle@dan....>
To: <lpc2000@lpc2...>
Sent: Wednesday, January 18, 2006 5:28 PM
Subject: RE: [lpc2000] Re: How to get a function running in RAM
(Lpc21xx+GnuArm)?

> In LPC, it doesn't matter - RAM and FLASH are essentially the same
> speed (barring branches). But on other ARMs, Flash may be very slow,
> so copying to RAM is important for critical routines.

It also matters for LPC chips, not so much because of speed differences, but
because interrupt functions that can be called while the foreground program
does IAP calls to program/erase the flash, cannot be executed out of flash.

Karl Olsen