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