Yahoo Groups archive

Lpc2000

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

Message

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