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 WadaMessage
Re: relocating code in RAM with lpc2106.
2005-03-01 by milind_pd
Attachments
- No local attachments were found for this message.