EmbeddedRelated.com
Forums

How to Execute Flash Code in RAM (LPC2888)

Started by Sait Izmit June 3, 2008
Dear all,

I am working with LPC2888 (ARM7TDMI). I have a firmware running on it. I
download the firmware to flash and execute from there. However, I have a
function, which I want to execute in RAM in order to make it faster. I am
using the RVCT 3.0 ARM compiler. After reading couple of posts, I councluded
that the best way to do that is using the scatter loading file.

I have 1 Mb flash at 1x10400000 and 64 kb SRAM at 0x400000. Vectortable
stores ISR adresses and priorities. The fast routine I want to execute is in
fast.o and this is the scatter I am trying to use.

L_ROM 0x10400000 { ; load region
E_ROM 0x10400000 {
* (RESET, +First)
* (+RO)
}

RAM 0x00401000 {
fast.o (+RO)
*.* ( +ZI, +RW )
}

VECTORTABLE 0x0040E800 {
vectortable.o (+ZI)
}

}

I download the code and start executing. When the program calls the function
inside fast.o, I end up in memory location 0x401000. The problem is there is
no code there. All the memory values around 0x401000 are all 0x00. Which
means that the linker adds a call to direct the code to RAM but the code is
not copied there for execution. My first question is if what I am trying to
do is possible? and if yes, how?

I read the available documentation in uVision3 - "Linker and Utilities
Guide" but in all the examples given there no .RO data is assigned to RAM
for execution.

Can someone please help?

Kind Regards

An Engineer's Guide to the LPC2100 Series

Hi,

I can't exactly say what's wrong with your scatter file (it's too
early for me today), but I enclose my own scatter file contents for
our secondary stage bootloader, which does execute in RAM. I only
remember, that I've played around a (very) long time to set it up,
but I'm unsure now, if I could explain what I've done in the meantime ...

Hope that helps,
Herbert

LR_IROM1 0x00000000 0x00004000 { ; load region size_region
ER_IROM1 0x00000000 0x00004000 { ; load address = execution address
*.o (RESET, +First)
.ANY (*)
}
CODE_PROTECTION 0x1FC FIXED 4 {
bl_crp.o (*)
}
DATA_INFO 0x200 FIXED { ; load region size_region
bl_datainfo_abs.o (*)
}

ER_IROM2 +0 0x00004000 {
*(InRoot$$Sections)
* (+RO)
endofprog_rv.o (*, +Last)
.ANY(*)
}

RW_IRAM1 0x40000000 32 { ; RW data
vectors.o (*)
}

RW_IRAM2 0x40000020 0x00003FE0 { ; RW data
bl_main_loop.o (+RO)
bl_timer.o (+RO)
squafer.o (+RO)
; secdata.o (+RO) ; no executable code here for bootloader
bl_datainfo.o (+RO)
helper.o (+RO)
bl_dispatch.o (+RO)
commio.o (+RO)
queue.o (+RO)
hardware.o (+RO)
flashio.o (+RO)
flashio_ram.o (+RO)
irq.o (+RO)
checkmem.o (+RO)
serial.o (+RO)
uread4.o (+RO) ; "inline" used by the compiler
uwrite4.o (+RO) ; "inline" used by the compiler
callvia.o (+RO) ; "inline" used by the compiler
switch8.o (+RO) ; "inline" used by the compiler
; memory.o (+RO) ; no executable code here for bootloader
* (+RW +ZI)
}
}

LR_IROM3 0x00003F00 0x00000100 { ; load region size_region
ER_IROM3 0x00003F00 0x00000100 { ; load address = execution address
secdata_abs.o (*)
}
}

-------
At 18:02 03.06.2008 +0200, you wrote:
>Dear all,
>
>I am working with LPC2888 (ARM7TDMI). I have a firmware running on it. I
>download the firmware to flash and execute from there. However, I have a
>function, which I want to execute in RAM in order to make it faster. I am
>using the RVCT 3.0 ARM compiler. After reading couple of posts, I councluded
>that the best way to do that is using the scatter loading file.
>
>I have 1 Mb flash at 1x10400000 and 64 kb SRAM at 0x400000. Vectortable
>stores ISR adresses and priorities. The fast routine I want to execute is in
>fast.o and this is the scatter I am trying to use.
>
>L_ROM 0x10400000 { ; load region
> E_ROM 0x10400000 {
> * (RESET, +First)
> * (+RO)
> }
>
> RAM 0x00401000 {
> fast.o (+RO)
> *.* ( +ZI, +RW )
> }
>
> VECTORTABLE 0x0040E800 {
> vectortable.o (+ZI)
> }
>
>}
>
>I download the code and start executing. When the program calls the function
>inside fast.o, I end up in memory location 0x401000. The problem is there is
>no code there. All the memory values around 0x401000 are all 0x00. Which
>means that the linker adds a call to direct the code to RAM but the code is
>not copied there for execution. My first question is if what I am trying to
>do is possible? and if yes, how?
>
>I read the available documentation in uVision3 - "Linker and Utilities
>Guide" but in all the examples given there no .RO data is assigned to RAM
>for execution.
>
>Can someone please help?
>
>Kind Regards
>
>
Morning
This is pretty interesting stuff, I am investigating the same issue

What would be wrong with doing something like:

#define ATTR_RUN_FROM_RAM __attribute__ ((section (".fast")))

void runFasterer( void ) ATTR_RUN_FROM_RAM;

Under Crossworks...In that Rowley have done it all for me ?
Or have I once again completely missunderstood ?

Regards
Jim ( Active Reading ( UK ))
Hi Jim,

> Morning
> This is pretty interesting stuff, I am investigating the same issue
>
> What would be wrong with doing something like:
>
> #define ATTR_RUN_FROM_RAM __attribute__ ((section (".fast")))
>
> void runFasterer( void ) ATTR_RUN_FROM_RAM;
>
> Under Crossworks...In that Rowley have done it all for me ?
> Or have I once again completely missunderstood ?

As copying .fast to RAM is done in the common startup code, that is indeed
all you need to do.

http://ccgi.rowley.co.uk/support/faq.php?do=article&articleid1

Regards,

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Thanks for the input so far!

Herbert, I can not see much difference about the way we define the
scatter files.

Jim and Paul, I tried to define the attribute however the code runs
from FLASH. But Paul's reply made me curious if I am doing something
wrong with my startup.s file. Because I just use an example startup.s
file I never changed it. So my question is if startup.s is
responsible for copying the code from flash to RAM? Because I believe
that my scatter file is ok. Here is the startup.s file I have:
;*********************************************************************
*********
;
; File name: Startup.s
; ----------
;
;*********************************************************************
*********

;/* <<< Use Configuration Wizard in Context Menu
>>> */
; INCLUDE Regs.inc

IMPORT main
IMPORT FIQ_Handler_User_Init, WEAK ;from FIQHandler.s
IMPORT FIQ_Handler_User, WEAK ;from FIQHandler.s
;============================================================================;
; Definitions and Macros
;
;============================================================================
; Value of Mode Bits M[4..0] of CPSR

Mode_USR EQU 0x10 ;User Mode
Mode_FIQ EQU 0x11 ;FIQ Mode
Mode_IRQ EQU 0x12 ;IRQ Mode
Mode_SVC EQU 0x13 ;Supervisor Mode
Mode_ABT EQU 0x17 ;Abort Mode
Mode_UND EQU 0x1B ;Undefined instruction Mode
Mode_SYS EQU 0x1F ;System Mode

I_Bit EQU 0x80 ;IRQ disable bit
F_Bit EQU 0x40 ;FIQ disable bit
; - Flash Marker -----------------
----------

; Area Definition for Flash User Program Valid Marker

; UNCOMMENT FOR FLASH PROGRAMMING !!!
AREA |.ARM.__AT_0x104FF800|, CODE, READONLY
ARM

DCD 0xAA55AA55

;---------------------------------
---------
; Stack sizes, stack top addresses.
; USR/SYS stack size doesn't have to be defined, because it simply
uses
; the remaining memory between the other dedicated stack and the
heap.
;---------------------------------
---------

;// Stack Configuration (Stack Sizes in Bytes)
;// Undefined Mode <0x0-0xFFFFFFFF:8>
;// Supervisor Mode <0x0-0xFFFFFFFF:8>
;// Abort Mode <0x0-0xFFFFFFFF:8>
;// Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
;// Interrupt Mode <0x0-0xFFFFFFFF:8>
;// User/System Mode <0x0-0xFFFFFFFF:8>
;//

UND_Stack_Size EQU 0x00000000
SVC_Stack_Size EQU 0x00000080
ABT_Stack_Size EQU 0x00000000
FIQ_Stack_Size EQU 0x00000100
IRQ_Stack_Size EQU 0x00000100
USR_Stack_Size EQU 0x00000400

Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size +
ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size +
USR_Stack_Size)

AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size

Stack_Top EQU Stack_Mem + Stack_Size

;// Heap Configuration
;// Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;//

Heap_Size EQU 0x00000200

AREA HEAP, NOINIT, READWRITE, ALIGN=3
Heap_Mem SPACE Heap_Size

;============================================================================;
; Start of executable code.
; This area 'Startup' must be linked as the very first module in
; the executable region 'ROM'.
;
;============================================================================ AREA RESET, CODE, READONLY

PRESERVE8
CODE32

IMPORT Undefined_Handler
IMPORT SWI_Handler
IMPORT Prefetch_Handler
IMPORT Abort_Handler
IMPORT IRQ_Handler
; IMPORT FIQ_Handler

LDR PC,Reset_Handler_Address ;offset 0x00
LDR PC,Undefined_Handler_Address ;offset 0x04
LDR PC,SWI_Handler_Address ;offset 0x08
LDR PC,Prefetch_Handler_Address ;offset 0x0C
LDR PC,Abort_Handler_Address ;offset 0x10
NOP ;offset 0x14
LDR PC,IRQ_Handler_Address ;offset 0x18
; LDR PC,FIQ_Handler_Address ;offset 0x1C
LDR PC,=FIQ_Handler_User
;offset 0x1C
Reset_Handler_Address DCD Reset_Handler
Undefined_Handler_Address DCD Undefined_Handler
SWI_Handler_Address DCD SWI_Handler
Prefetch_Handler_Address DCD Prefetch_Handler
Abort_Handler_Address DCD Abort_Handler
IRQ_Handler_Address DCD IRQ_Handler
;FIQ_Handler_Address DCD FIQ_Handler
;FIQ_Handler b FIQ_Handler
;============================================================================; This is were we are just after reset.
; The ARM is in SVC (Supervisor) mode.
;============================================================================Reset_Handler

; Setup Stack for each mode

LDR R0, =Stack_Top

; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size

; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size

; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size

; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size

; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size

; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SYS
MOV SP, R0
SUB SL, SP, #USR_Stack_Size

;---------------------------------
---------
; Switch to FIQ mode and call the initialization function for the
; FIQ interrupt handler (if it exists)
;---------------------------------
---------

;Switch to FIQ mode (IRQ and FIQ still disabled)
;
MOV R0, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MSR CPSR_c, R0

LDR R0,=FIQ_Handler_User_Init
MOVS R0,R0
BLNE FIQ_Handler_User_Init

;============================================================================; Switch to user mode and do a global interrupt enable in ARM CPU.
; Then jump to C main code.
;============================================================================
;Go to USR mode and enable IRQ and FIQ interrupts in ARM
;
MOV R1, #Mode_USR
MSR CPSR_c, R1

;Now jump to C main code.
;C_main in ARM mode.
;
LDR R0,=main
BX R0

SwitchToArm

;Should the main function ever return, we restart the CPU
;
B Reset_Handler
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY

IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap

LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
END
Kind Regards,

Sait
Hi,

> Thanks for the input so far!
>
> Herbert, I can not see much difference about the way we define the
> scatter files.
>
> Jim and Paul, I tried to define the attribute however the code runs
> from FLASH. But Paul's reply made me curious if I am doing something
> wrong with my startup.s file. Because I just use an example startup.s
> file I never changed it. So my question is if startup.s is
> responsible for copying the code from flash to RAM? Because I believe
> that my scatter file is ok. Here is the startup.s file I have:

Code copying is done by the CrossWorks startup code; sorry if Jim's/my
comments did not make the context clear.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
What about PIC? Or this is enabled by default?

On Wed, Jun 4, 2008 at 11:51 AM, Paul Curtis wrote:
> Hi,
>
>> Thanks for the input so far!
>>
>> Herbert, I can not see much difference about the way we define the
>> scatter files.
>>
>> Jim and Paul, I tried to define the attribute however the code runs
>> from FLASH. But Paul's reply made me curious if I am doing something
>> wrong with my startup.s file. Because I just use an example startup.s
>> file I never changed it. So my question is if startup.s is
>> responsible for copying the code from flash to RAM? Because I believe
>> that my scatter file is ok. Here is the startup.s file I have:
>
> Code copying is done by the CrossWorks startup code; sorry if Jim's/my
> comments did not make the context clear.
>
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Hi,

> What about PIC? Or this is enabled by default?

There is no PIC requirement.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
Hi,

I assume you mean "there is no PIC requirement in this particular
case", right? Because in general I assume that you need some sort of
PIC if you're moving code around.

Thanks,
Bogdan

On Wed, Jun 4, 2008 at 11:54 AM, Paul Curtis wrote:
> Hi,
>
>> What about PIC? Or this is enabled by default?
>
> There is no PIC requirement.
>
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Hi,

> I assume you mean "there is no PIC requirement in this particular
> case", right? Because in general I assume that you need some sort of
> PIC if you're moving code around.

You only need PIC if you don't know, in advance, where the code will
execute. In this case there is no PIC requirement because you know the code
will run from a known place in RAM (the linker chooses it), it's just a
matter of getting the RAM filled with the right instructions--that's what
the startup code does for you.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors