Yahoo Groups archive

Lpc2000

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

Message

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 
> 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

Attachments

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.