Hi All, I am not an expert on ARM yet but an average guy for uC.
I am trying to get hands on with LPC2148 and plan to use it in next project.
One wonderful thing that I came across (I come form a background where we use 8051/mega16 uC) is USB IAP. So without any UART/Serial cable, I can flash program just by using USB cable.
Did some changes like 1. generating bin file (using fromelf --bin ....) and 2. changing IROM1 from 0x0 to 0x2000
to make program work with IAP.
I tasted some program and those worked very well.
But the issue is arising when I try to use Timer0 interrupt. I see controller getting stuck somewhere just after 1st int.
I checked with "Use Memory Layout with Target Dialog" selected and de-selected both. Nothing worked.
This has something to do with vector table but I am not able to make out what?
Any help on this would be appreciated.
Remember, I just made 3 above mentioned changes after creating new project. If there is anything else, please let me know.
Interrupts must be disabled during IAP (see user manual). You need to get your chip into privileged mode (use a SWI) to call "__disable_irq". This site explains how to do that, as well as different user manuals.
Thanks Tamir Michael for quick turn-around.
So in simple words, I cannot use interrupts(any interrupt like Timer, External, etc..) in the program if it is loaded via IAP. Is that correct?
(Sorry for my words. Actually too much of technical confuses me.)
I am using IAP available at Keil's site only. I did read that interrupts are not used but then I thought that I was for IAP's program. i.e. bootloadr itself.
I didn't know that the program that I load via IAP cannot have interrupt.
Any work around?
Thanks, Urvish.
Thanks Per and Tamir.
Now I unserstood. When program is being copied via IAP it cannot handle int. But once IAP is done copying and control of CPU is handed over the program we have loaded, it can handle interrupt.
But as earlier IVT was at different place (mostly earlier location of ROM), it needed to be relocated. (As IAP is in ROM location 0x0 to Ox2000.) IVT will be after 0x2000.
Thanks again for being good teacher.
Don't forget to actually reset the chip using the watchdog rather than to simply jump to the address of the newly flash binary.
Sorry for being a little dumb here. But, I am actually using a ready hex file provided by the vendor of the board (mostly AN10711 based) for USB IAP programmer.
I have no control over the code of IAP.
IAP works like this... While power up, if I keep P0.15 low, it enters IAP mode, if I keep it high, it jumps directly to user program mode (starting from 0x2000).
Will it still be possible for me to use interrupts or I should have the code of IAP to use interrupt.
The limitations above apply to the bootloader (see AN10711). The bootloader should disable interrupts while flashing your program. You have full control over IAP - you have the bootloader source as well, not?
I think you misunderstood the issue. I have 2 programs now.
1. USB_IAP.hex : loaded at location 0x0:0x1FFF 2. my_prog.bin : loaded from 0x2000:0x2100 via IAP.
Now my_prog.bin has already been loaded via IAP.
Now, when I reset the board, first IAP will run, but as entry to bootloader is not asserted, it will jump to my_prog.bin.
Now, my_prog.bin is using timer interrupt. So, when my_prog.bin is running, (and IAP is not running), will I be able to use interrupt?
I checked the Startup.s file and couldn't figure out much. I do not have code for USB_IAP.hex. I have code of my_prog.bin.
Now, what changes will I have to make to make interrupt of my_prog.bin work.
Per, your inputs will be much appreciated. Tamir, thanks to being with me on this.
Urvish Gohil => Now, what changes will I have to make to make interrupt of my_prog.bin work.
Per => A program that is loaded at a different place need to remap the interrupt vector table. There are settings in the startup file to do this - copying the interrupt vector table into RAM and remap to that address. Without remapping, the processor would search for an interrupt handler within your boot loader code.
On the Startup file of my_prog.bin: Set Options-> Asm-> Conditional Assembly Control Symbols: RAM_INTVEC REMAP RAM_MODE
And check what RAM_INTVEC REMAP RAM_MODE will do for you.
Thanks John for that wonderful and easy explanation. While I did get what Per said, but didn't know how to do it.
Right now I do not have access to the board. Will post here the my observation as soon as I get it(Hope to keep some smileys than).
Hi John, I just tried adding "RAM_INTVEC REMAP RAM_MODE" but it didn't worked.
Here is what I tried. 1. I just wrote a prog in keil which toggles 2 port pins. 1st by a while loop, 2nd by timer. 2. Without adding anything I simulated it in keil. (IROM1 still from 0x0, No remapping) 3. This works well and I see both of the port pins toggling.
Now I made a simple change of Adding "RAM_INTVEC REMAP RAM_MODE". I recompiled the code and simulated. Here, I saw that, as soon as int is occurred, LPC jumps to "LDR PC, [PC, #-0x0FF0]", but does not move from that point.
Moreover, I see words REMAP and RAM_MODE in Startup.s but not the RAM_INTVEC. I am using Startup.s provided by keil only.
KEIL has quite a lot startup.s/LPCooxx.s You need another startup.s like this: rtime.felk.cvut.cz/.../lpc21xx-boot
+# Memory Mapping (when Interrupt Vectors are in RAM) + .equ MEMMAP, 0xE01FC040 /* Memory Mapping Control */ +.ifdef RAM_INTVEC + LDR R0, =MEMMAP + MOV R1, #2 + STR R1, [R0] +.endif
I think what I have is exactly this only.
; Memory Mapping (when Interrupt Vectors are in RAM) MEMMAP EQU 0xE01FC040 ; Memory Mapping Control IF :DEF:REMAP LDR R0, =MEMMAP IF :DEF:EXTMEM_MODE MOV R1, #3 ELIF :DEF:RAM_MODE MOV R1, #2 ELSE MOV R1, #1 ENDIF STR R1, [R0] ENDIF
By defining REMAP and RAM_MODE, this will do exactly what your code snippets does with RAM_INTVEC.
In the Startup.s that I am using, what shown above is the only place where REMAP and RAM_MODE is used. There are no other defines.
I guess your startup.s is very like this one:
forum.sparkfun.com/viewtopic.php
If so, you need to figure out how it accomplishes what Per told you.
And, I don't think you can easily simulate USB_IAP.hex + my_prog.bin, it would be easier to run them on the real hardware.
Are you using this: ics.nxp.com/.../ ==> Boot Loader V2.12 for LPC213x and LPC214x (Apr 12, 2007) And it does not provide source code for bootloader (USB_IAP.hex)?
Take a look at this: it is for LPC23xx. http://www.keil.com/forum/13707/
See if you can debug your my_prog.bin like the below. After all of that, I start my Debug Session. The Disassembly Window shows the Machine Code/ASM Code of the Bootloader (without the Source Code). Then, the Bootloader jumps to my application. So that, I get the state while the Bootloader just finishes its work, and pass the control to my application. I can observe the CPSR and the R13/SP of Supervisor Mode etc, to see if the solutions works properly.
John, I did try the changes on hardware also. Yes, you are correct that simulation cannot be always correct.
BTW, I didn't find this connected to this issue. "Are you using this:
USB_IAP.hex is going to be the secondary bootloader which resides in 128k flash. And, as far as I understand, the link you gave is for primary bootloader which is by default by NXP.
Here is what I am using "">www.nxp.com/search
BTW, Right now I am looking at "http://www.keil.com/forum/13707/" which you gave. Though this tread is for different uC and App Not is also different (AN10759), I think the idea should be same.
Thanks for the pointer. Will have a look at it and post the conclusion here.
Meanwhile, if there is something new, I would be glad to take it.
www.nxp.com/.../LPC2000_Series_Secondary_Bootloader.zip
The above link is not for USB_IAP either. I am sorry.
www.sparkfun.com/.../94
LPC2148 USB Bootloader Tutorial by zagGrad | August 04, 2008 | 17 comments
This link should provide everything you need, except it may not be designed for your hardware, and it is not for KEIL toolchain.
.if (RAM_MODE==0) /* Relocate .data section (Copy from ROM to RAM) */ LDR R1, =_etext LDR R2, =_data LDR R3, =_edata CMP R2, R3 BEQ DataIsEmpty LoopRel: CMP R2, R3 LDRLO R0, [R1], #4 STRLO R0, [R2], #4 BLO LoopRel DataIsEmpty: .endif
www.embeddedrelated.com/.../39585.php
Copying Interrupt vector table to RAM
It is for IAR toolchain.
(9) LDMIA r8!,{r0-r7} ; Load Vectors (10) STMIA r9!,{r0-r7} ; Store Vectors (11) LDMIA r8!,{r0-r7} ; Load secondary vector table (12) STMIA r9!,{r0-r7} ; Store secondary vector table ; Setup Memory Mapping Control to remap the RAM vector area (13) LDR r0,=LPC231X_MEMMAP (14) MOV r1,#2 ; MEMMAP to User RAM mode (15) STRNE r1,[r0,#0] ; Remap Memory, if not remapped already
John, From the other link you gave me (http://www.keil.com/forum/13707/) I found this.
; Copy Exception Vectors to Internal RAM --------------------------------------- RAM_BASE EQU 0x40000000 IF :DEF:RAM_INTVEC ADR R8, Vectors ; Source LDR R9, =RAM_BASE ; Destination LDMIA R8!, {R0-R7} ; Load Vectors STMIA R9!, {R0-R7} ; Store Vectors LDMIA R8!, {R0-R7} ; Load Handler Addresses STMIA R9!, {R0-R7} ; Store Handler Addresses ENDIF
I think this was missing from my Startup.s This also supports your defines "RAM_INTVEC REMAP RAM_MODE".
Giving it a try now.
Hi John, Something good, something bad... I told you about the link from where I got USB_IAP.hex. (originally Memory.hex) which is USB based secondary bootloader.
Link : www.nxp.com/search
Here, with the code of USB bootloader, there is a sample code as well for user program. I used it and copied it over the board (with some modification for my board) (project name : blinky)
And VOILA, It worked.
Now, I am trying to figure out the changes between two.
John, A really strange thing is going on. After the Blinky worked well. I moved back to my earlier project and flash it. It just worked. I'm not sure how.
Even after spending some good, I couldn't figure out the issue.
So I decided to start a new project in keil and just copied the C file from the earlier version (Remember, this file was never touched in the whole process).
I made sure that Startup.s is original only (original of Keil, without RAM_INTVEC).
The only changes I made was to change IROM1 from 0x0 to 0x2000 and added Run Cmd to generate .bin.
NO ADDITION OF REMAP, RAM_MODE or RAM_INTVEC.
And, it worked.
Now, I am totally confused about what is going on.
Just to be careful about data in RAM, I re-plugged the power supply as well. Still it worked.
Did that Blinky made some changes?
I am planning to order one more of the same board. So will check this issue on that also. Till then, do you have some experiments which I should be trying on this board?
It is possible.
=== Flash === Bootloader Vector -> Both Bootloader and Application use this Vector Bootloader PROGRAM Bootloader PROGRAM Bootloader PROGRAM Bootloader PROGRAM Bootloader PROGRAM Bootloader ISR PROGRAM -> Both Bootloader and Application use this ISR ============= Application PROGRAM Application PROGRAM Application PROGRAM Application PROGRAM Application PROGRAM Application PROGRAM
One of the bootloaders you have tried, provided a usable ISR PROGRAM. If you did not erase this usable ISR PROGRAM, every Applications work fine.
LPC2148 seems quite old. LPC23xx/LPC24xx seem a little old. It is now LPC17xx. (LPC13xx?)
I think you are right.
So, in short, If 1. I get a new board (or completely erase the flash) 2. Program the USB Bootloader 3. Copy the newly working binary (not the Blinky)
it will not work immediately. I will need to run blinky once to make it running :)
LPC2148 may be old. But til now I was using AVR (8-bit) controllers. So I planned to move a level up so that next projects can be better.
And, to get familier with the uC, I got this Development board at very good rate. "">www.nex-robotics.com/.../arm7-lpc2148-development-board.html"
This will ramp up the development time.
I surely have a look at LPC17xx/13xx. But now as I have started with this, I plan to understand it properly. So the jump to 17/13xx would be easier.
BTW, thanks for suggestion.
Exception Vectors -> ARM design Vectored Interrupt Controller -> NXP design One of the Exception Vectors is linked to Vectored Interrupt Controller.
LPC21xx / LPC23xx -> ARM7 -> VIC LPC17xx (LPC13xx?) -> ARM Cortex-M -> NVIC
ARM7 is very different from Cortex-M; and due to the foundry process etc, Cortex-M might be cheaper than ARM7. But of course, different projects have different considerations, LPC2148 might still be the best choice for your projects. (When will NXP terminate LPC21xx?)
View all questions in Keil forum