Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

relocating code in RAM with lpc2106.

relocating code in RAM with lpc2106.

2005-02-27 by Milind Deshpande

Hi,

I am a newbie doing firmware development on LPC2106 and using couple of interrupts for UART0 and TIMER1. The interrupts work fine when the code resides in flash. 

However when I try to put the code in RAM for debug, the interrupts no longer work and so I cannot do any debug on UART0.

 

When putting the code in FLASH I am linking the code as below:

Code: 0x00000000 i.e. whole 128K for code.

Ram: 0x40000000 i.e. whole 64k for data.

Register E01FC040 = 0x0;

 

When putting the code in RAM I am linking the code as below:

Code: 0x40000000 i.e. 48K for Code

Ram: 0x4000C000 i.e. 15K for Data.

Register E01FC040 = 0x2;

 

The LPC manual does not say anything else for relocating the code in RAM, so I am not sure what is going wrong with my settings. Could someone please explain or let me know if I need to do any further settings to get the interrupts working in RAM.

Thanks in advance.

 

Regards

Milind


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

[Non-text portions of this message have been removed]

RS485 bootloader ?

2005-02-27 by Lasse Madsen

Hi all,

Has any one seen or made an open source serial boot loader for the LPC21xx?
I'm particularly looking for a bootloader that enables me to use RS485 in
the same way as the internal Philips RS232 bootloader.

Suggestions, hints and comments are welcome.

Best regards
Lasse Madsen

Re: [lpc2000] relocating code in RAM with lpc2106.

2005-02-28 by Hong Jiang

Milind Deshpande <milind_pd@...> wrote:

Hi,

I am a newbie doing firmware development on LPC2106 and using couple of interrupts for UART0 and TIMER1. The interrupts work fine when the code resides in flash. 

However when I try to put the code in RAM for debug, the interrupts no longer work and so I cannot do any debug on UART0.



When putting the code in FLASH I am linking the code as below:

Code: 0x00000000 i.e. whole 128K for code.

Ram: 0x40000000 i.e. whole 64k for data.

Register E01FC040 = 0x0;



When putting the code in RAM I am linking the code as below:

Code: 0x40000000 i.e. 48K for Code

Ram: 0x4000C000 i.e. 15K for Data.

Register E01FC040 = 0x2;



The LPC manual does not say anything else for relocating the code in RAM, so I am not sure what is going wrong with my settings. Could someone please explain or let me know if I need to do any further settings to get the interrupts working in RAM.

Thanks in advance.



Regards

Milind

---------------------------------------------

You should remap the interrupt vector table from 0x00000000 to 0x40000000,then your program will run in the ram as well as in the flash.
__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

[Non-text portions of this message have been removed]



Yahoo! Groups SponsorADVERTISEMENT


---------------------------------
Yahoo! Groups Links

   To visit your group on the web, go to:
http://groups.yahoo.com/group/lpc2000/
  
   To unsubscribe from this group, send an email to:
lpc2000-unsubscribe@yahoogroups.com
  
   Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 





---------------------------------
Do You Yahoo!?
150万曲MP3疯狂搜,带您闯入音乐殿堂
美女明星应有尽有,搜遍美图、艳图和酷图
1G就是1000兆,雅虎电邮自助扩容!

[Non-text portions of this message have been removed]

Re: [lpc2000] relocating code in RAM with lpc2106.

2005-02-28 by 42Bastian Schick

Hong Jiang <smartpite@...> schrieb am Mon, 28 Feb 2005 09:20:19 
+0800 (CST):

Hong, check your email program to have correct quoting.

> You should remap the interrupt vector table from 0x00000000 to 
> 0x40000000,then your program will run in the ram as well as in the flash.

He does set it correctly.

-- 
42Bastian Schick

Re: [lpc2000] relocating code in RAM with lpc2106.

2005-02-28 by 42Bastian Schick

Milind Deshpande <milind_pd@...> schrieb am Sun, 27 Feb 2005 
14:55:41 -0800 (PST):

> Code: 0x40000000 i.e. 48K for Code
>
> Ram: 0x4000C000 i.e. 15K for Data.
>
> Register E01FC040 = 0x2;

When do you write the MEMMAP register ? Before or after downloading ?


-- 
42Bastian Schick

Re: relocating code in RAM with lpc2106.

2005-02-28 by mannem_sri

Hi All,

I am also facing the same problem.

I am trying to run the interrupts from SRAM and i have set that 
MEMMAP register also.

But the interrupts are not working.

I am getting the interrupt but it's not going to SRAM vector table..

Please help me.

Thanks in advance.

Regards,
-Srinivas.

--- In lpc2000@yahoogroups.com, 42Bastian Schick <bastian42@m...> 
wrote:
> Milind Deshpande <milind_pd@y...> schrieb am Sun, 27 Feb 2005 
> 14:55:41 -0800 (PST):
> 
> > Code: 0x40000000 i.e. 48K for Code
> >
> > Ram: 0x4000C000 i.e. 15K for Data.
> >
> > Register E01FC040 = 0x2;
> 
> When do you write the MEMMAP register ? Before or after 
downloading ?
Show quoted textHide quoted text
> 
> 
> -- 
> 42Bastian Schick

Re: relocating code in RAM with lpc2106.

2005-02-28 by milind_pd

I am writing to the MEMMAP register after download. The actual 
command is the first line of my main() routine which was done as per 
Ashling guide.

Milind

--- In lpc2000@yahoogroups.com, 42Bastian Schick <bastian42@m...> 
wrote:
> Milind Deshpande <milind_pd@y...> schrieb am Sun, 27 Feb 2005 
> 14:55:41 -0800 (PST):
> 
> > Code: 0x40000000 i.e. 48K for Code
> >
> > Ram: 0x4000C000 i.e. 15K for Data.
> >
> > Register E01FC040 = 0x2;
> 
> When do you write the MEMMAP register ? Before or after 
downloading ?
Show quoted textHide quoted text
> 
> 
> -- 
> 42Bastian Schick

Re: relocating code in RAM with lpc2106.

2005-02-28 by kennethwada

Hello Milind;

Let us say...

You are attempting to do a very advanced thing with the LPC2xxx chip. 
This is emminently doable though.

In general, you need to do the following:

Define your startup vector:
'the following is a code snippet from one of my projects'

AREA    INTVECT, 'CODE_IVEC', READONLY, ALIGN=2  // READONLY, ALIGN=4 
bytes
        RSEG  INTVECT
PUBLIC  __startup
__startup       PROC    CODE32

// Pre-defined interrupt handlers that may be directly 
// overwritten by C interrupt functions
EXTERN CODE32 (Undef_Handler?A)
EXTERN CODE32 (SWI_Handler?A)
EXTERN CODE32 (PAbt_Handler?A)
EXTERN CODE32 (DAbt_Handler?A)
EXTERN CODE32 (IRQ_Handler?A)
EXTERN CODE32 (FIQ_Handler?A)

// Exception Vectors
// Mapped to Address 0.
// Absolute addressing mode must be used.

vectors:        LDR     PC,Reset_Addr         
                LDR     PC,Undef_Addr
                LDR     PC,SWI_Addr
                LDR     PC,PAbt_Addr
                LDR     PC,DAbt_Addr
                NOP                            /* Reserved Vector */
;               LDR     PC,IRQ_Addr
                LDR     PC,[PC, #-0x0FF0]      /* Vector from 
VicVectAddr */
                LDR     PC,FIQ_Addr

Reset_Addr:     DD      Reset_Handler
Undef_Addr:     DD      Undef_Handler?A
SWI_Addr:       DD      SWI_Handler?A
PAbt_Addr:      DD      PAbt_Handler?A
DAbt_Addr:      DD      DAbt_Handler?A
                DD      0                      /* Reserved Address */
IRQ_Addr:       DD      IRQ_Handler?A
FIQ_Addr:       DD      FIQ_Handler?A
ENDP

As you can see, this vector consumes exactly 64 bytes of code!

Next, you need to relocate, (at runtime), your 64 byte interrupt 
vector table that you created above.

Do this as follows:

Reset_Handler:  
     .... ; <--- some startup code here, (usually PINSEL programming)

/*****
    Relocate interrupt vectors to internal RAM
***/
    MEMMAP  EQU   0xE01FC040              ; interrupt memory map 
register

    LDR     R1,=__startup
    MOV     R0,#0x40000000
    MOV     R2,#0x10

copyLoop:
    LDMIA   R1!,{R3}
    STMIA   R0!,{R3}
    SUBS    R2,R2,#0x0001
    BNE     copyLoop

    LDR     R0,=MEMMAP
    MOV     R1,#0x02
    STR     R1, [R0]

In your 'C' code, you need to define your vectors such that they 
reside in RAM. The Keil compiler has a real nifty way to do this via 
the following LINKER directive:

CLASSES (ERAM       (0x40000040-0x40001FFF))

This places all code that has been defined to store in flash, and 
execute in RAM to be loaded at runtime into the RAM area.

That is, for every subroutine you define with the following Keil 
modifier:

void my_interrupt_service (void) __irq __ram;

This __irq and __ram modifier does two things:
__irq compiles the subroutine as a service vector using ARM 
instructions.

__ram places the entire subroutine into the ERAM segment that will 
automatically get loaded into flash by the nifty Keil tool.

in lieu of the Keil tool, you must be able find a way relocate,
(copy) 
your service vectors into ram at run time.

whew!

hope this helps;
Ken Wada

Re: relocating code in RAM with lpc2106.

2005-02-28 by milind_pd

Hi Ken,
Is it imperative that I have to set the MEMMAP register to 0x2 
value, before I brach off to main()? From your code it seems that 
way. Here is the snippet from my code. Let me know if you see 
anything funky here.

Milind

/* Export list */
.global       handle_uart0
.global       handle_tmr0

/*#define ARM_RDP_MONITOR 0x01*/
/*#define ARM_RDI_MONITOR 0x01*/

/* Define some hardware locations */
.equ VICVecAddr, 0xfffff030                    /* Address of 
VICVectAddr register */
            
/********************************************************************
*          Exception vector table - common to all ARM-based 
systems           *
******************************************************************** 
* Common to all ARM-based systems.  Table entries just jump to 
handlers using full 32-bit addressing. 
****************************************/
_int_vectors:

        ldr     pc, do_reset_addr     
        ldr     pc, do_undefined_instruction_addr
        ldr     pc, do_software_interrupt_addr
        ldr     pc, do_prefetch_abort_addr
        ldr     pc, do_data_abort_addr
/*        .long 	0xB9205F88     		/* ARM-reserved 
vector */
        nop
        ldr     pc, [pc, #-0xff0]       /* set PC (currently 0x18) 
to VicVectAddr (0xFFFFF030) by - 0xFF0 */
        ldr     pc, do_fiq_addr

do_reset_addr:                  .long   do_reset
do_undefined_instruction_addr:  .long   do_undefined_instruction
do_software_interrupt_addr:     .long   do_software_interrupt
do_prefetch_abort_addr:         .long   do_prefetch_abort
do_data_abort_addr:             .long   do_data_abort
do_fiq_addr:                    .long   do_fiq

/********************************************************************
*                 Yet to be implemented exceptions 
*********************************************************************
* Just fall through to reset exception handler for now 
********************************************************************/
                                                                     
       
do_undefined_instruction:
do_software_interrupt:
do_prefetch_abort:
do_data_abort:
do_fiq:

/********************************************************************
*                            System reset handler 
********************************************************************/
do_reset:

        /* Set stack pointers for all modes used (supervisor, IRQ 
and FIQ) */
        ldr     sp, =__stack_svc            /* set supervisor mode 
stack pointer */
                                           
        msr     cpsr_c, #0xd2	             /* enter IRQ mode, with 
interrupts disabled */
                                                      
        ldr     sp, =__stack_irq            /* set IRQ mode stack 
pointer */
                                                      
        mov     lr, #0x0	                  /* clear out other 
IRQ shadow register */
                                                      
        msr     cpsr_c, #0xd1	             /* enter FIQ mode, with 
interrupts disabled */
                                                      
        ldr     sp, =__stack_fiq            /* set FIQ mode stack 
pointer */
                   
                                           
        /* Clear uninitialized data section (bss) */
        ldr     r4, =__start_bss            /* First address*/      
        ldr     r5, =__end_bss              /* Last  address*/      
        mov     r6, #0x0                                
                                                    
loop_zero:  
        str     r6, [r4]                                
        add     r4, r4, #0x4                            
        cmp     r4, r5                                  
        blt     loop_zero
    
        /* Copy initialized data sections from ROM into RAM */
        ldr     r4, =_fdata                 /* destination address 
*/      
        ldr     r5, =_edata                 /* Last  address*/      
        ldr     r6, =_etext                 /* source address*/      
        cmp     r4, r5                                  
        beq     skip_initialize
    
loop_initialise:
        ldr     r3, [r6]
        str     r3, [r4]                                
        add     r4, r4, #0x4
        add     r6, r6, #0x4
        cmp     r4, r5                                  
        blt     loop_initialise
        
skip_initialize:
       
              
#if !defined(ARM_RDP_MONITOR) && !defined(ARM_RDI_MONITOR)
        mov     r0, #0              /*  no arguments  */
        mov     r1, #0              /*  no argv either */
#else
        /* Need to set up standard file handles */
        bl      initialise_monitor_handles
#endif  
              
        /* Enable interrupts, enter supervisor mode and branch to 
start of 'C' code */
        
        msr     cpsr_c, #0x13	    /* I=0 F=0 T=0 MODE=supervisor */
        bl      main

/********************************************************************
**********
*                         Interrupt 
exceptions                                *
*********************************************************************
*********/

handle_uart0:
        stmfd   r13!, {r12, r14}         /* save r12 & r14 */
        mrs     r12, spsr                /* save the spsr  */
        stmfd   r13!, {r12}              
        msr     cpsr_c, #0x93            /* switch to sys mode */
        stmfd   r13!, {r0-r3, r14}       /* save sys mode registers 
*/
        msr     cpsr_c, #0x13            /* enable interrupts */
        bl      uartInterrupt            /* go handle the interrupt 
*/
        msr     cpsr_c, #0x93            /* disable interrupts */
        ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
registers */
        msr     cpsr_c, #0x92            /* switch back to irq mode 
*/
        ldmfd   r13!, {r12}              /* restore spsr */
        msr     spsr_cxsf, r12
        ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
        stmfd   r13!, {r0-r1}            /* save r0 & r1 */
        ldr     r0, =VICVecAddr          /* update VIC */
        mov     r1, #0xff
        str     r1, [r0]
        ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
        subs    pc, lr, #0x4             /* return from teh 
interrupt */

handle_tmr0:
        stmfd   r13!, {r12, r14}         /* save r12 & r14 */
        mrs     r12, spsr                /* save the spsr  */
        stmfd   r13!, {r12}              
        msr     cpsr_c, #0x93            /* switch to sys mode */
        stmfd   r13!, {r0-r3, r14}       /* save sys mode registers 
*/
        msr     cpsr_c, #0x13            /* enable interrupts */
        bl      tmrInterrupt             /* go handle the interrupt 
*/
        msr     cpsr_c, #0x93            /* disable interrupts */
        ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
registers */
        msr     cpsr_c, #0x92            /* switch back to irq mode 
*/
        ldmfd   r13!, {r12}              /* restore spsr */
        msr     spsr_cxsf, r12
        ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
        stmfd   r13!, {r0-r1}            /* save r0 & r1 */
        ldr     r0, =VICVecAddr          /* update VIC */
        mov     r1, #0xff
        str     r1, [r0]
        ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
        subs    pc, lr, #0x4             /* return from teh 
interrupt */


/*
 * End of startup code
 */

.size   _int_vectors,.-_int_vectors;

--- In lpc2000@yahoogroups.com, "kennethwada" <kwada@a...> wrote:
> 
> Hello Milind;
> 
> Let us say...
> 
> You are attempting to do a very advanced thing with the LPC2xxx 
chip. 
> This is emminently doable though.
> 
> In general, you need to do the following:
> 
> Define your startup vector:
> 'the following is a code snippet from one of my projects'
> 
> AREA    INTVECT, 'CODE_IVEC', READONLY, ALIGN=2  // READONLY, 
ALIGN=4 
> bytes
>         RSEG  INTVECT
> PUBLIC  __startup
> __startup       PROC    CODE32
> 
> // Pre-defined interrupt handlers that may be directly 
> // overwritten by C interrupt functions
> EXTERN CODE32 (Undef_Handler?A)
> EXTERN CODE32 (SWI_Handler?A)
> EXTERN CODE32 (PAbt_Handler?A)
> EXTERN CODE32 (DAbt_Handler?A)
> EXTERN CODE32 (IRQ_Handler?A)
> EXTERN CODE32 (FIQ_Handler?A)
> 
> // Exception Vectors
> // Mapped to Address 0.
> // Absolute addressing mode must be used.
> 
> vectors:        LDR     PC,Reset_Addr         
>                 LDR     PC,Undef_Addr
>                 LDR     PC,SWI_Addr
>                 LDR     PC,PAbt_Addr
>                 LDR     PC,DAbt_Addr
>                 NOP                            /* Reserved Vector 
*/
> ;               LDR     PC,IRQ_Addr
>                 LDR     PC,[PC, #-0x0FF0]      /* Vector from 
> VicVectAddr */
>                 LDR     PC,FIQ_Addr
> 
> Reset_Addr:     DD      Reset_Handler
> Undef_Addr:     DD      Undef_Handler?A
> SWI_Addr:       DD      SWI_Handler?A
> PAbt_Addr:      DD      PAbt_Handler?A
> DAbt_Addr:      DD      DAbt_Handler?A
>                 DD      0                      /* Reserved Address 
*/
> IRQ_Addr:       DD      IRQ_Handler?A
> FIQ_Addr:       DD      FIQ_Handler?A
> ENDP
> 
> As you can see, this vector consumes exactly 64 bytes of code!
> 
> Next, you need to relocate, (at runtime), your 64 byte interrupt 
> vector table that you created above.
> 
> Do this as follows:
> 
> Reset_Handler:  
>      .... ; <--- some startup code here, (usually PINSEL 
programming)
> 
> /*****
>     Relocate interrupt vectors to internal RAM
> ***/
>     MEMMAP  EQU   0xE01FC040              ; interrupt memory map 
> register
> 
>     LDR     R1,=__startup
>     MOV     R0,#0x40000000
>     MOV     R2,#0x10
> 
> copyLoop:
>     LDMIA   R1!,{R3}
>     STMIA   R0!,{R3}
>     SUBS    R2,R2,#0x0001
>     BNE     copyLoop
> 
>     LDR     R0,=MEMMAP
>     MOV     R1,#0x02
>     STR     R1, [R0]
> 
> In your 'C' code, you need to define your vectors such that they 
> reside in RAM. The Keil compiler has a real nifty way to do this 
via 
Show quoted textHide quoted text
> the following LINKER directive:
> 
> CLASSES (ERAM       (0x40000040-0x40001FFF))
> 
> This places all code that has been defined to store in flash, and 
> execute in RAM to be loaded at runtime into the RAM area.
> 
> That is, for every subroutine you define with the following Keil 
> modifier:
> 
> void my_interrupt_service (void) __irq __ram;
> 
> This __irq and __ram modifier does two things:
> __irq compiles the subroutine as a service vector using ARM 
> instructions.
> 
> __ram places the entire subroutine into the ERAM segment that will 
> automatically get loaded into flash by the nifty Keil tool.
> 
> in lieu of the Keil tool, you must be able find a way relocate,
> (copy) 
> your service vectors into ram at run time.
> 
> whew!
> 
> hope this helps;
> Ken Wada

Re: relocating code in RAM with lpc2106.

2005-02-28 by kennethwada

no; It is not imperative to set MEMMAP=0x2 as I did with the example. 
You need to do this MEMMAP=2 at any time AFTER relocating your 
vectors, and BEFORE starting up the interrupts, (startup via VIC 
register setup).

By the way, I noticed throughout your code, this switching to/from 
USER mode, and disabling/enabling interrupts in your vectors.

If you are currently processing an exception, the silicon 
automatically switches the process to:
--> ARM format
--> SYSTEM mode

If you do not allow nesting of interrupts, (generally not recommended 
to nest), then you do not need to do this (enabling/disabling 
interrupts inside a vector). In general, you should not nest 
interrupts in the ARM, for concern in regards to corrupting the SPSR 
(shadow of CPSR) register. If you do the nesting, then you need to 
define a shadow of a shadow! This gets really complicated.

In general, I have found no need to enable/disable interrupts. I have 
done all atomic and monitor style operations using a pseudo-semaphore 
technique that exploits the ARM SWI hardware. This is very nice, and 
very much like the INT86 instruction that those Intel architectures 
have. TI also supports hardware like this on their very fine DSP 
cores!

You really ought to avoid enabling/disabling interrupts because of the 
ARM cache vs. interrupt issues. This is a very dangerous area to 
tread. I know most users hear are probably doing this a lot, and 
probably see no problem with doing this. In fact, I believe this is 
precisely the reason why Philips, in their users manual, writes 3-4 
paragraphs on this, (spurious interrupts concerns).

I have worked many years with fully pipelined/cached architectures, 
and one of the most difficult, (to prove, and to quantify) problems 
with these architectures is cache pipeline vs asynchronous events, 
(ie. enabling/disabling exceptions).

You really ought to let the ARM silicon do what it is really good at, 
(resynchronizing itself), and leave the coding up to you.

The problem with this is, we embedded engineers, for many years are 
used to non-pipelined cached architectures, and are not familiar with 
some of the advanced interrupt techniques of the more modern 
architectures. Once you learn this stuff, it is not hard to get very 
nice reliable and robust systems cranked out.

Ken Wada

--- In lpc2000@yahoogroups.com, "milind_pd" <milind_pd@y...> wrote:
> 
> Hi Ken,
> Is it imperative that I have to set the MEMMAP register to 0x2 
> value, before I brach off to main()? From your code it seems that 
> way. Here is the snippet from my code. Let me know if you see 
> anything funky here.
> 
> Milind
> 
> /* Export list */
> .global       handle_uart0
> .global       handle_tmr0
> 
> /*#define ARM_RDP_MONITOR 0x01*/
> /*#define ARM_RDI_MONITOR 0x01*/
> 
> /* Define some hardware locations */
> .equ VICVecAddr, 0xfffff030                    /* Address of 
> VICVectAddr register */
>             
> 
/********************************************************************
> *          Exception vector table - common to all ARM-based 
> systems           *
> ******************************************************************** 
> * Common to all ARM-based systems.  Table entries just jump to 
> handlers using full 32-bit addressing. 
> ****************************************/
> _int_vectors:
> 
>         ldr     pc, do_reset_addr     
>         ldr     pc, do_undefined_instruction_addr
>         ldr     pc, do_software_interrupt_addr
>         ldr     pc, do_prefetch_abort_addr
>         ldr     pc, do_data_abort_addr
> /*        .long 	0xB9205F88     		/* ARM-reserved 
> vector */
>         nop
>         ldr     pc, [pc, #-0xff0]       /* set PC (currently 0x18) 
> to VicVectAddr (0xFFFFF030) by - 0xFF0 */
>         ldr     pc, do_fiq_addr
> 
> do_reset_addr:                  .long   do_reset
> do_undefined_instruction_addr:  .long   do_undefined_instruction
> do_software_interrupt_addr:     .long   do_software_interrupt
> do_prefetch_abort_addr:         .long   do_prefetch_abort
> do_data_abort_addr:             .long   do_data_abort
> do_fiq_addr:                    .long   do_fiq
> 
> 
/********************************************************************
> *                 Yet to be implemented exceptions 
> 
*********************************************************************
> * Just fall through to reset exception handler for now 
> 
********************************************************************/
>                                                                      
>        
> do_undefined_instruction:
> do_software_interrupt:
> do_prefetch_abort:
> do_data_abort:
> do_fiq:
> 
> 
/********************************************************************
> *                            System reset handler 
> 
********************************************************************/
> do_reset:
> 
>         /* Set stack pointers for all modes used (supervisor, IRQ 
> and FIQ) */
>         ldr     sp, =__stack_svc            /* set supervisor mode 
> stack pointer */
>                                            
>         msr     cpsr_c, #0xd2	             /* enter IRQ mode, with 
> interrupts disabled */
>                                                       
>         ldr     sp, =__stack_irq            /* set IRQ mode stack 
> pointer */
>                                                       
>         mov     lr, #0x0	                  /* clear out other 
> IRQ shadow register */
>                                                       
>         msr     cpsr_c, #0xd1	             /* enter FIQ mode, with 
> interrupts disabled */
>                                                       
>         ldr     sp, =__stack_fiq            /* set FIQ mode stack 
> pointer */
>                    
>                                            
>         /* Clear uninitialized data section (bss) */
>         ldr     r4, =__start_bss            /* First address*/      
>         ldr     r5, =__end_bss              /* Last  address*/      
>         mov     r6, #0x0                                
>                                                     
> loop_zero:  
>         str     r6, [r4]                                
>         add     r4, r4, #0x4                            
>         cmp     r4, r5                                  
>         blt     loop_zero
>     
>         /* Copy initialized data sections from ROM into RAM */
>         ldr     r4, =_fdata                 /* destination address 
> */      
>         ldr     r5, =_edata                 /* Last  address*/      
>         ldr     r6, =_etext                 /* source address*/      
>         cmp     r4, r5                                  
>         beq     skip_initialize
>     
> loop_initialise:
>         ldr     r3, [r6]
>         str     r3, [r4]                                
>         add     r4, r4, #0x4
>         add     r6, r6, #0x4
>         cmp     r4, r5                                  
>         blt     loop_initialise
>         
> skip_initialize:
>        
>               
> #if !defined(ARM_RDP_MONITOR) && !defined(ARM_RDI_MONITOR)
>         mov     r0, #0              /*  no arguments  */
>         mov     r1, #0              /*  no argv either */
> #else
>         /* Need to set up standard file handles */
>         bl      initialise_monitor_handles
> #endif  
>               
>         /* Enable interrupts, enter supervisor mode and branch to 
> start of 'C' code */
>         
>         msr     cpsr_c, #0x13	    /* I=0 F=0 T=0 MODE=supervisor 
*/
>         bl      main
> 
> 
/********************************************************************
> **********
> *                         Interrupt 
> exceptions                                *
> 
*********************************************************************
Show quoted textHide quoted text
> *********/
> 
> handle_uart0:
>         stmfd   r13!, {r12, r14}         /* save r12 & r14 */
>         mrs     r12, spsr                /* save the spsr  */
>         stmfd   r13!, {r12}              
>         msr     cpsr_c, #0x93            /* switch to sys mode */
>         stmfd   r13!, {r0-r3, r14}       /* save sys mode registers 
> */
>         msr     cpsr_c, #0x13            /* enable interrupts */
>         bl      uartInterrupt            /* go handle the interrupt 
> */
>         msr     cpsr_c, #0x93            /* disable interrupts */
>         ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
> registers */
>         msr     cpsr_c, #0x92            /* switch back to irq mode 
> */
>         ldmfd   r13!, {r12}              /* restore spsr */
>         msr     spsr_cxsf, r12
>         ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
>         stmfd   r13!, {r0-r1}            /* save r0 & r1 */
>         ldr     r0, =VICVecAddr          /* update VIC */
>         mov     r1, #0xff
>         str     r1, [r0]
>         ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
>         subs    pc, lr, #0x4             /* return from teh 
> interrupt */
> 
> handle_tmr0:
>         stmfd   r13!, {r12, r14}         /* save r12 & r14 */
>         mrs     r12, spsr                /* save the spsr  */
>         stmfd   r13!, {r12}              
>         msr     cpsr_c, #0x93            /* switch to sys mode */
>         stmfd   r13!, {r0-r3, r14}       /* save sys mode registers 
> */
>         msr     cpsr_c, #0x13            /* enable interrupts */
>         bl      tmrInterrupt             /* go handle the interrupt 
> */
>         msr     cpsr_c, #0x93            /* disable interrupts */
>         ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
> registers */
>         msr     cpsr_c, #0x92            /* switch back to irq mode 
> */
>         ldmfd   r13!, {r12}              /* restore spsr */
>         msr     spsr_cxsf, r12
>         ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
>         stmfd   r13!, {r0-r1}            /* save r0 & r1 */
>         ldr     r0, =VICVecAddr          /* update VIC */
>         mov     r1, #0xff
>         str     r1, [r0]
>         ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
>         subs    pc, lr, #0x4             /* return from teh 
> interrupt */
> 
> 
> /*
>  * End of startup code
>  */
> 
> .size   _int_vectors,.-_int_vectors;
> 
> --- In lpc2000@yahoogroups.com, "kennethwada" <kwada@a...> wrote:
> > 
> > Hello Milind;
> > 
> > Let us say...
> > 
> > You are attempting to do a very advanced thing with the LPC2xxx 
> chip. 
> > This is emminently doable though.
> > 
> > In general, you need to do the following:
> > 
> > Define your startup vector:
> > 'the following is a code snippet from one of my projects'
> > 
> > AREA    INTVECT, 'CODE_IVEC', READONLY, ALIGN=2  // READONLY, 
> ALIGN=4 
> > bytes
> >         RSEG  INTVECT
> > PUBLIC  __startup
> > __startup       PROC    CODE32
> > 
> > // Pre-defined interrupt handlers that may be directly 
> > // overwritten by C interrupt functions
> > EXTERN CODE32 (Undef_Handler?A)
> > EXTERN CODE32 (SWI_Handler?A)
> > EXTERN CODE32 (PAbt_Handler?A)
> > EXTERN CODE32 (DAbt_Handler?A)
> > EXTERN CODE32 (IRQ_Handler?A)
> > EXTERN CODE32 (FIQ_Handler?A)
> > 
> > // Exception Vectors
> > // Mapped to Address 0.
> > // Absolute addressing mode must be used.
> > 
> > vectors:        LDR     PC,Reset_Addr         
> >                 LDR     PC,Undef_Addr
> >                 LDR     PC,SWI_Addr
> >                 LDR     PC,PAbt_Addr
> >                 LDR     PC,DAbt_Addr
> >                 NOP                            /* Reserved Vector 
> */
> > ;               LDR     PC,IRQ_Addr
> >                 LDR     PC,[PC, #-0x0FF0]      /* Vector from 
> > VicVectAddr */
> >                 LDR     PC,FIQ_Addr
> > 
> > Reset_Addr:     DD      Reset_Handler
> > Undef_Addr:     DD      Undef_Handler?A
> > SWI_Addr:       DD      SWI_Handler?A
> > PAbt_Addr:      DD      PAbt_Handler?A
> > DAbt_Addr:      DD      DAbt_Handler?A
> >                 DD      0                      /* Reserved Address 
> */
> > IRQ_Addr:       DD      IRQ_Handler?A
> > FIQ_Addr:       DD      FIQ_Handler?A
> > ENDP
> > 
> > As you can see, this vector consumes exactly 64 bytes of code!
> > 
> > Next, you need to relocate, (at runtime), your 64 byte interrupt 
> > vector table that you created above.
> > 
> > Do this as follows:
> > 
> > Reset_Handler:  
> >      .... ; <--- some startup code here, (usually PINSEL 
> programming)
> > 
> > /*****
> >     Relocate interrupt vectors to internal RAM
> > ***/
> >     MEMMAP  EQU   0xE01FC040              ; interrupt memory map 
> > register
> > 
> >     LDR     R1,=__startup
> >     MOV     R0,#0x40000000
> >     MOV     R2,#0x10
> > 
> > copyLoop:
> >     LDMIA   R1!,{R3}
> >     STMIA   R0!,{R3}
> >     SUBS    R2,R2,#0x0001
> >     BNE     copyLoop
> > 
> >     LDR     R0,=MEMMAP
> >     MOV     R1,#0x02
> >     STR     R1, [R0]
> > 
> > In your 'C' code, you need to define your vectors such that they 
> > reside in RAM. The Keil compiler has a real nifty way to do this 
> via 
> > the following LINKER directive:
> > 
> > CLASSES (ERAM       (0x40000040-0x40001FFF))
> > 
> > This places all code that has been defined to store in flash, and 
> > execute in RAM to be loaded at runtime into the RAM area.
> > 
> > That is, for every subroutine you define with the following Keil 
> > modifier:
> > 
> > void my_interrupt_service (void) __irq __ram;
> > 
> > This __irq and __ram modifier does two things:
> > __irq compiles the subroutine as a service vector using ARM 
> > instructions.
> > 
> > __ram places the entire subroutine into the ERAM segment that will 
> > automatically get loaded into flash by the nifty Keil tool.
> > 
> > in lieu of the Keil tool, you must be able find a way relocate,
> > (copy) 
> > your service vectors into ram at run time.
> > 
> > whew!
> > 
> > hope this helps;
> > Ken Wada

Re: relocating code in RAM with lpc2106.

2005-03-01 by milind_pd

Hello Everyone,
Thanks for your help. Actual problem was not my code but non-erasure 
of RAM at Power ON. With Ashling tools and Ashling Eval board,I need 
to do a hard reset from Pathfinder and then load the application. 
Just Power ON reset is not sufficient. 
Thanks for all the inputs.

Milind
--- In lpc2000@yahoogroups.com, "kennethwada" <kwada@a...> wrote:
> 
> no; It is not imperative to set MEMMAP=0x2 as I did with the 
example. 
> You need to do this MEMMAP=2 at any time AFTER relocating your 
> vectors, and BEFORE starting up the interrupts, (startup via VIC 
> register setup).
> 
> By the way, I noticed throughout your code, this switching to/from 
> USER mode, and disabling/enabling interrupts in your vectors.
> 
> If you are currently processing an exception, the silicon 
> automatically switches the process to:
> --> ARM format
> --> SYSTEM mode
> 
> If you do not allow nesting of interrupts, (generally not 
recommended 
> to nest), then you do not need to do this (enabling/disabling 
> interrupts inside a vector). In general, you should not nest 
> interrupts in the ARM, for concern in regards to corrupting the 
SPSR 
> (shadow of CPSR) register. If you do the nesting, then you need to 
> define a shadow of a shadow! This gets really complicated.
> 
> In general, I have found no need to enable/disable interrupts. I 
have 
> done all atomic and monitor style operations using a pseudo-
semaphore 
> technique that exploits the ARM SWI hardware. This is very nice, 
and 
> very much like the INT86 instruction that those Intel 
architectures 
> have. TI also supports hardware like this on their very fine DSP 
> cores!
> 
> You really ought to avoid enabling/disabling interrupts because of 
the 
> ARM cache vs. interrupt issues. This is a very dangerous area to 
> tread. I know most users hear are probably doing this a lot, and 
> probably see no problem with doing this. In fact, I believe this 
is 
> precisely the reason why Philips, in their users manual, writes 3-
4 
> paragraphs on this, (spurious interrupts concerns).
> 
> I have worked many years with fully pipelined/cached 
architectures, 
> and one of the most difficult, (to prove, and to quantify) 
problems 
> with these architectures is cache pipeline vs asynchronous events, 
> (ie. enabling/disabling exceptions).
> 
> You really ought to let the ARM silicon do what it is really good 
at, 
> (resynchronizing itself), and leave the coding up to you.
> 
> The problem with this is, we embedded engineers, for many years 
are 
> used to non-pipelined cached architectures, and are not familiar 
with 
> some of the advanced interrupt techniques of the more modern 
> architectures. Once you learn this stuff, it is not hard to get 
very 
> nice reliable and robust systems cranked out.
> 
> Ken Wada
> 
> --- In lpc2000@yahoogroups.com, "milind_pd" <milind_pd@y...> wrote:
> > 
> > Hi Ken,
> > Is it imperative that I have to set the MEMMAP register to 0x2 
> > value, before I brach off to main()? From your code it seems 
that 
> > way. Here is the snippet from my code. Let me know if you see 
> > anything funky here.
> > 
> > Milind
> > 
> > /* Export list */
> > .global       handle_uart0
> > .global       handle_tmr0
> > 
> > /*#define ARM_RDP_MONITOR 0x01*/
> > /*#define ARM_RDI_MONITOR 0x01*/
> > 
> > /* Define some hardware locations */
> > .equ VICVecAddr, 0xfffff030                    /* Address of 
> > VICVectAddr register */
> >             
> > 
> /******************************************************************
**
> > *          Exception vector table - common to all ARM-based 
> > systems           *
> > 
******************************************************************** 
> > * Common to all ARM-based systems.  Table entries just jump to 
> > handlers using full 32-bit addressing. 
> > ****************************************/
> > _int_vectors:
> > 
> >         ldr     pc, do_reset_addr     
> >         ldr     pc, do_undefined_instruction_addr
> >         ldr     pc, do_software_interrupt_addr
> >         ldr     pc, do_prefetch_abort_addr
> >         ldr     pc, do_data_abort_addr
> > /*        .long 	0xB9205F88     		/* ARM-reserved 
> > vector */
> >         nop
> >         ldr     pc, [pc, #-0xff0]       /* set PC (currently 
0x18) 
> > to VicVectAddr (0xFFFFF030) by - 0xFF0 */
> >         ldr     pc, do_fiq_addr
> > 
> > do_reset_addr:                  .long   do_reset
> > do_undefined_instruction_addr:  .long   do_undefined_instruction
> > do_software_interrupt_addr:     .long   do_software_interrupt
> > do_prefetch_abort_addr:         .long   do_prefetch_abort
> > do_data_abort_addr:             .long   do_data_abort
> > do_fiq_addr:                    .long   do_fiq
> > 
> > 
> /******************************************************************
**
> > *                 Yet to be implemented exceptions 
> > 
> 
*********************************************************************
> > * Just fall through to reset exception handler for now 
> > 
> 
********************************************************************/
> 
>                                                                    
  
> >        
> > do_undefined_instruction:
> > do_software_interrupt:
> > do_prefetch_abort:
> > do_data_abort:
> > do_fiq:
> > 
> > 
> /******************************************************************
**
> > *                            System reset handler 
> > 
> 
********************************************************************/
> > do_reset:
> > 
> >         /* Set stack pointers for all modes used (supervisor, 
IRQ 
> > and FIQ) */
> >         ldr     sp, =__stack_svc            /* set supervisor 
mode 
> > stack pointer */
> >                                            
> >         msr     cpsr_c, #0xd2	             /* enter IRQ 
mode, with 
> > interrupts disabled */
> >                                                       
> >         ldr     sp, =__stack_irq            /* set IRQ mode 
stack 
> > pointer */
> >                                                       
> >         mov     lr, #0x0	                  /* clear out other 
> > IRQ shadow register */
> >                                                       
> >         msr     cpsr_c, #0xd1	             /* enter FIQ 
mode, with 
> > interrupts disabled */
> >                                                       
> >         ldr     sp, =__stack_fiq            /* set FIQ mode 
stack 
> > pointer */
> >                    
> >                                            
> >         /* Clear uninitialized data section (bss) */
> >         ldr     r4, =__start_bss            /* First 
address*/      
> >         ldr     r5, =__end_bss              /* Last  
address*/      
> >         mov     r6, #0x0                                
> >                                                     
> > loop_zero:  
> >         str     r6, [r4]                                
> >         add     r4, r4, #0x4                            
> >         cmp     r4, r5                                  
> >         blt     loop_zero
> >     
> >         /* Copy initialized data sections from ROM into RAM */
> >         ldr     r4, =_fdata                 /* destination 
address 
> > */      
> >         ldr     r5, =_edata                 /* Last  
address*/      
> >         ldr     r6, =_etext                 /* source 
address*/      
> >         cmp     r4, r5                                  
> >         beq     skip_initialize
> >     
> > loop_initialise:
> >         ldr     r3, [r6]
> >         str     r3, [r4]                                
> >         add     r4, r4, #0x4
> >         add     r6, r6, #0x4
> >         cmp     r4, r5                                  
> >         blt     loop_initialise
> >         
> > skip_initialize:
> >        
> >               
> > #if !defined(ARM_RDP_MONITOR) && !defined(ARM_RDI_MONITOR)
> >         mov     r0, #0              /*  no arguments  */
> >         mov     r1, #0              /*  no argv either */
> > #else
> >         /* Need to set up standard file handles */
> >         bl      initialise_monitor_handles
> > #endif  
> >               
> >         /* Enable interrupts, enter supervisor mode and branch 
to 
> > start of 'C' code */
> >         
> >         msr     cpsr_c, #0x13	    /* I=0 F=0 T=0 
MODE=supervisor 
> */
> >         bl      main
> > 
> > 
> /******************************************************************
**
> > **********
> > *                         Interrupt 
> > exceptions                                *
> > 
> 
*********************************************************************
> > *********/
> > 
> > handle_uart0:
> >         stmfd   r13!, {r12, r14}         /* save r12 & r14 */
> >         mrs     r12, spsr                /* save the spsr  */
> >         stmfd   r13!, {r12}              
> >         msr     cpsr_c, #0x93            /* switch to sys mode */
> >         stmfd   r13!, {r0-r3, r14}       /* save sys mode 
registers 
> > */
> >         msr     cpsr_c, #0x13            /* enable interrupts */
> >         bl      uartInterrupt            /* go handle the 
interrupt 
> > */
> >         msr     cpsr_c, #0x93            /* disable interrupts */
> >         ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
> > registers */
> >         msr     cpsr_c, #0x92            /* switch back to irq 
mode 
> > */
> >         ldmfd   r13!, {r12}              /* restore spsr */
> >         msr     spsr_cxsf, r12
> >         ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
> >         stmfd   r13!, {r0-r1}            /* save r0 & r1 */
> >         ldr     r0, =VICVecAddr          /* update VIC */
> >         mov     r1, #0xff
> >         str     r1, [r0]
> >         ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
> >         subs    pc, lr, #0x4             /* return from teh 
> > interrupt */
> > 
> > handle_tmr0:
> >         stmfd   r13!, {r12, r14}         /* save r12 & r14 */
> >         mrs     r12, spsr                /* save the spsr  */
> >         stmfd   r13!, {r12}              
> >         msr     cpsr_c, #0x93            /* switch to sys mode */
> >         stmfd   r13!, {r0-r3, r14}       /* save sys mode 
registers 
> > */
> >         msr     cpsr_c, #0x13            /* enable interrupts */
> >         bl      tmrInterrupt             /* go handle the 
interrupt 
> > */
> >         msr     cpsr_c, #0x93            /* disable interrupts */
> >         ldmfd   r13!, {r0-r3, r14}       /* restore sys mode 
> > registers */
> >         msr     cpsr_c, #0x92            /* switch back to irq 
mode 
> > */
> >         ldmfd   r13!, {r12}              /* restore spsr */
> >         msr     spsr_cxsf, r12
> >         ldmfd   r13!, {r12, r14}         /* restore r12 & r14 */
> >         stmfd   r13!, {r0-r1}            /* save r0 & r1 */
> >         ldr     r0, =VICVecAddr          /* update VIC */
> >         mov     r1, #0xff
> >         str     r1, [r0]
> >         ldmfd   r13!, {r0-r1}            /* restore r0 & r1 */
> >         subs    pc, lr, #0x4             /* return from teh 
> > interrupt */
> > 
> > 
> > /*
> >  * End of startup code
> >  */
> > 
> > .size   _int_vectors,.-_int_vectors;
> > 
> > --- In lpc2000@yahoogroups.com, "kennethwada" <kwada@a...> wrote:
> > > 
> > > Hello Milind;
> > > 
> > > Let us say...
> > > 
> > > You are attempting to do a very advanced thing with the 
LPC2xxx 
> > chip. 
> > > This is emminently doable though.
> > > 
> > > In general, you need to do the following:
> > > 
> > > Define your startup vector:
> > > 'the following is a code snippet from one of my projects'
> > > 
> > > AREA    INTVECT, 'CODE_IVEC', READONLY, ALIGN=2  // READONLY, 
> > ALIGN=4 
> > > bytes
> > >         RSEG  INTVECT
> > > PUBLIC  __startup
> > > __startup       PROC    CODE32
> > > 
> > > // Pre-defined interrupt handlers that may be directly 
> > > // overwritten by C interrupt functions
> > > EXTERN CODE32 (Undef_Handler?A)
> > > EXTERN CODE32 (SWI_Handler?A)
> > > EXTERN CODE32 (PAbt_Handler?A)
> > > EXTERN CODE32 (DAbt_Handler?A)
> > > EXTERN CODE32 (IRQ_Handler?A)
> > > EXTERN CODE32 (FIQ_Handler?A)
> > > 
> > > // Exception Vectors
> > > // Mapped to Address 0.
> > > // Absolute addressing mode must be used.
> > > 
> > > vectors:        LDR     PC,Reset_Addr         
> > >                 LDR     PC,Undef_Addr
> > >                 LDR     PC,SWI_Addr
> > >                 LDR     PC,PAbt_Addr
> > >                 LDR     PC,DAbt_Addr
> > >                 NOP                            /* Reserved 
Vector 
> > */
> > > ;               LDR     PC,IRQ_Addr
> > >                 LDR     PC,[PC, #-0x0FF0]      /* Vector from 
> > > VicVectAddr */
> > >                 LDR     PC,FIQ_Addr
> > > 
> > > Reset_Addr:     DD      Reset_Handler
> > > Undef_Addr:     DD      Undef_Handler?A
> > > SWI_Addr:       DD      SWI_Handler?A
> > > PAbt_Addr:      DD      PAbt_Handler?A
> > > DAbt_Addr:      DD      DAbt_Handler?A
> > >                 DD      0                      /* Reserved 
Address 
> > */
> > > IRQ_Addr:       DD      IRQ_Handler?A
> > > FIQ_Addr:       DD      FIQ_Handler?A
> > > ENDP
> > > 
> > > As you can see, this vector consumes exactly 64 bytes of code!
> > > 
> > > Next, you need to relocate, (at runtime), your 64 byte 
interrupt 
> > > vector table that you created above.
> > > 
> > > Do this as follows:
> > > 
> > > Reset_Handler:  
> > >      .... ; <--- some startup code here, (usually PINSEL 
> > programming)
> > > 
> > > /*****
> > >     Relocate interrupt vectors to internal RAM
> > > ***/
> > >     MEMMAP  EQU   0xE01FC040              ; interrupt memory 
map 
> > > register
> > > 
> > >     LDR     R1,=__startup
> > >     MOV     R0,#0x40000000
> > >     MOV     R2,#0x10
> > > 
> > > copyLoop:
> > >     LDMIA   R1!,{R3}
> > >     STMIA   R0!,{R3}
> > >     SUBS    R2,R2,#0x0001
> > >     BNE     copyLoop
> > > 
> > >     LDR     R0,=MEMMAP
> > >     MOV     R1,#0x02
> > >     STR     R1, [R0]
> > > 
> > > In your 'C' code, you need to define your vectors such that 
they 
> > > reside in RAM. The Keil compiler has a real nifty way to do 
this 
> > via 
> > > the following LINKER directive:
> > > 
> > > CLASSES (ERAM       (0x40000040-0x40001FFF))
> > > 
> > > This places all code that has been defined to store in flash, 
and 
> > > execute in RAM to be loaded at runtime into the RAM area.
> > > 
> > > That is, for every subroutine you define with the following 
Keil 
> > > modifier:
> > > 
> > > void my_interrupt_service (void) __irq __ram;
> > > 
> > > This __irq and __ram modifier does two things:
> > > __irq compiles the subroutine as a service vector using ARM 
> > > instructions.
> > > 
> > > __ram places the entire subroutine into the ERAM segment that 
will 
Show quoted textHide quoted text
> > > automatically get loaded into flash by the nifty Keil tool.
> > > 
> > > in lieu of the Keil tool, you must be able find a way relocate,
> > > (copy) 
> > > your service vectors into ram at run time.
> > > 
> > > whew!
> > > 
> > > hope this helps;
> > > Ken Wada

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.