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-02-28 by milind_pd
Attachments
- No local attachments were found for this message.