Hello freinds,
Having looked around for almost 2 days for getting some intro about the bootloading process, I would first elaborate a little about what I have understood about the entire thing.
Having referred to a plethora of forum threads, this is what I conclude.
Basically, the ARM7 executes in 3 different modes viz. boot mode, user flash mode and user ram mode. On reset, the core always is in boot mode and executes the boot loader.Now the boot block which is normally resident in the top 64 bytes in user flash gets remapped into the top 64 bytes of the onchip 2GB memory, if I understood correctly. Now heres my first question: If the boot block gets remapped to the top 64 bytes of on-chip memory, then does it mean that the reset vector is reset at location 0 relative to this address?..
If im correct on this one, does it mean that the 'LDR pc,reset_addr' which is usally the very first instruction in the startup file does(or is supposed to do) a short jump to reset addr which should be the very first word of my bootloader right?..the boot loeader should then do all the hardware initializations alongwith the allocation of various stacks for different operating modes including the user mode. It then does have to map the vectors back into the user RAM and load the OS image into the ram as well right? Now this is where things go haywire in my mind: 1. In one of the forum threads here, they said the startup file may use absolute addresses only whereas the manual says that once the MEMMAP register has been assigned a certain value, then based on this value, the core will automatically assume a certain base and accordingly calculate the addresses of the various interrupt vectors. Could someone please clarify what will it actually do?
2. Now how do I tell the linker that I would like to 'install' a given bootloader at a certain location. And how do I decidew where my bootloader should be. I plan to use U boot and while there is enough documentation to get started, I would be pleased if someone could get me straight on this one. I mean the bootloader should be able to boot the system automatically on startup. So I should be ideally placing it in non volatile flash right. Please give me some pointers on this one since these kind of things are bugging me a lot. The documentation on the UBoot website talks about the canyonlands board while I am using a local made board whch uses the LPC2129.If what I wrote above is indeed what it is actually done on the LPC2100s then I might have to specify an absolute address in the very first instruction which typically causes the jump to the reset handler. oh by the way im using uvision4
Keen to get things started, but Im still lost in this huge pile of information scattered in bits and pieces. May be I should get used to the real world now.
Keen to hear from you guys.
Hi there per. A very happy new year to you. Thank you for being so explanatory to a beginner. As again I have some more questions. Each of these questions now becomes more specific as I (hopefully) move closer inch by inch to my goal of getting my own bootloader to work with the LPC2129 chip.
Here it goes: 1. You said that I need to place the interrupt table at the start of flash "for the secondary bootloader". So when the chip comes out of reset, the primary bootloader (is it what they call bootmonitor?) will cause the instruction at address 0x0 to be executed. Having read notes AN10254,AN10404 which describes the initial steps to be taken to execute a given interrupt, I have some specific questions about it. The note typically has 3 files, one for the table, one containing the startup code and the 3rd C file which contains the ISR for the timer interrupt. To me the 1st two are of interest. a)The 1st file,which should be linked to 0x0. It contains in the very first line,a jump to the start of the startup code.b)2nd file contains startup code which enables the interrupts and sets up the stack pointer for the various modes.Were the interrupts disabled to begin with? If yes, then how did the reset interrupt cause the jump to reset vector?
2. The note further explains the changes required to enable the code from SRAM. Now the manual says that the SRAM is mapped from 0x4000 0000.Thus in the words of the note, "linker should be linked such that the 1st file should be linked to 0x4000 0000.The relevant interrupt vectors should lie between 0x4000 003F.The other files are linked within the code itself and can lie in SRAM.Also the interrupt vectors have to be remapped to SRAM. Using the MEMAP register and configuring it for User RAM mode could achieve this.
int main() { ... . /* Initialize MEMAP */ MEMAP=0x2; ... . } " Now some more questions: Now when my processor comes out of reset, the 1st stage bootloader will again take the core to the address 0x0. a)Since I link the vector table to 0x4000 0000, does it mean that core will "automatically be taken to 0x4000 0000 without worrying about what might be present at 0x0?" b)we are actually writing to the MEMMAP register inside the C code here.I mean isn't the C code the very last in the complete sequence? Doesn't the C code already reside in the user ram due to the linking? So the mere fact that the C code is being executed automatically implies we are already running from the on chip ram isn't it? Then why do we need to explicitly write to MEMMAP in the C code?
3. A person on this forum asked a question regarding the place where the nxp bootloader resides (http://www.keil.com/forum/docs/thread14333.asp).He specifically wanted to know where exactly are the interrupts "copied to" when MEMMAP = 00.I think that the interrupts table for the nxp bootloader is distinct from the table which my stage 2 bootloader may use.It is what you told me in our earlier discussions, right?
4. In the thread http://www.keil.com/forum/docs/thread10212.asp, rodrigo describes problems he faced while remmapping the vectors to the application code once he jumps into the application.Now he has a secondary bootloader which he uses to load the application code from usb connection. Am I right to conclude that his secondary bootloader is at 0x4000? He has a codeinit.s file which he links at 0x0. This file is the one which will be "called upon" by the primary factory supplied bootloader after reset right? Then this file contains a direct jump to absolute address 0x4000 where the secondary bootloader is resident. am I right on that one?
5. Is it possible for code to be run directly from FLASH or do they need to be copied into RAM? Assuming my application (which could be an OS image for that matter) is to be run from RAM, then the bootloader has to run from FLASH or it will corrupt the RAM contents right? On a side note,I suppose one would need external RAM for running an OS as the onchip 16KB ram is not enough.
6. The thread 's not necessary to remappe the vectors in RAM.The bootloader and the firmware could init their VIC at the beginning of their execution to handle their ISR." Could you kindly explain?
7. I understand that scatter files are a way to let the linker (or is it the download tool rather?) know where to put a given section of the code written using say a typical IDE like Uvision from keil, isn't it? However to have the intended effect the "use memory from target dialog" checkbox must be de-selected. Could you elaborate a little on what effect does de-selecting this does?
8. Could you point me to a comprehensive review of all these mapping and remapping concepts? The material is so very scattered. Its rather a nightmarish situation. If I am allowed to ask, what strategy did u apply to get a grip on these concepts when u were just starting out?
Keen to hear from you and once again God Jul!!
Sorry, I don't have time to try and follow up all the links in your post, so I will have to assume/guess the contents of them :)
1) First off - there is no "reset interrupt". Reset isn't a normal interrupt. It is a hardcoded feature of the processor that sets processor registers etc in a known state. One of these registers is the PC.
When the processor boots, it will map in the interrupt table of the primary boot loader (caused by the reset of all registers - including the bits that defines interrupt table mapping).
When the NXP boot loader has done whatever it does, it will map back the original interrupt table stored at address 0, and then jump to the start address.
2) The flash memory can't be modified on the fly. And since the processor is always looking for the interrupt table at address 0 (which is flash) there has to be support for some type of mapping.
When your code starts (either a secondary boot loader or a main application) that interrupt table mapping is straight through, i.e. the interrupt table stored at address 0 of the flash will be visible at the same address. So when building a secondary boot loader, you would configure it similarly to a normal application that gets directly started from the NXP startup code.
If you do want a secondary boot loader, then the application (which is then step three in the startup sequence) must be able to replace the interrupt vectors at address 0. The way to do that, is to store the vectors at a suitable location in flash (basically wherever you want). You then copy these vectors to the dedicated RAM area mentioned (the copy should either be performed by the secondary boot loader, or by the application). When the vectors has been copied into RAM, the remap feature is used to "overlay" this RAM block on top of address 0 of the flash. So the ARM core will still think that there is an interrupt vector table at address 0. But in reality, this table is in RAM.
When building a project, you can specify two addresses for a code block. One address where the code/data is expected to be stored in flash. One address corresponding to the address where the code/data is expected to be found when running the application.
3) Yes, the chip can have three (or some variants four) different mappings for the interrupt vectors. But one of these mappings are unofficial, and not documented. It is the mapping used for the NXP boot loader. You do not need to know where that table is located, unles you are going to try to reverse-engineer their code.
4) No. His secondary boot loader starts from address 0. This seondary boot loader may then (since it is your code) locate the application wherever you want in the flash. But you must reserve the start of RAM for a copy of the interrupt vector table, since the ARM can not make use of a vector table at a random location.
5) If you do not use a secondary boot loader, then your application can run fully from flash. If you do use a secondary boot loader, then your appliation can run fully from flash, with the exception that you need to make use of the initial RAM addresses for copying and remapping the interrupt table, so that the ARM core can find the entry points to your application.
6) You should initialize the interrupt vector table. The vector table is needed as first step. The VIC is a second step to extend a single interrupt into multiple, prioritized, interrupt sources.
7) The scatter file is for the linker.
For simple memory configurations, you use the IDE to specify memory regions. Whenever you change the settings, the IDE will regenerate a scatter file. For more complex configurations, the IDE will not be able to let you specify the configuration. So you have to turn off the auto-generation of a scatter file, and create one by hand - or take one generated by the IDE, and extend it.
8) Sorry. No can help. I read everything I could find. Then did trial-and-error attempts. Keil should add more information and examples for their scatter-load functionality. Including information about situations when the scatter file will produce correct mappings, but the Keil startup code + RTL code will not be able to handle. If you need access to specific memory regions in the first part of the memory - close above the interrupt vector table - then the linker can create solutions that will fail to boot. The variable initialization code in the runtime library has limitations that are not fully (or at all?) documented. As long as all startup code is allowed to be stored directly after the vector table, all seems to be ok.
I don't know much about this. But would like to try to give you a short/simple answer.
1. You can always execute your codes from the 4G (32 bits) memory addresses. For X86, the 4G (32 bits) memory addresses are mainly for DRAM. For MCU, the 4G (32 bits) memory addresses can be Flash/ROM or SRAM. So, your code can be executed from the Internal (On Chip) Flash.
2. The ARM7TDMI processor has 7 operating modes, with 8 interrupt vectors (Exceptions). The addresses of the 8 interrupt vectors are fixed, can NOT be changed. But the memory addresses can be remapped.
3. After the On Chip (First) boot-loader finishes its work, and YOUR code start. It must start from address 0x0000-0000. And if you need to remap the memory addresses, Your code has to do the remapping work.
4. Every time an IRQ (ex: UART or Timer) happens, the ARM core goes to the address 0x0000-0018.
5. Every time an FIQ happens, the ARM core goes to the Address 0x0000-001C.
6. Your boot-loader (Second) starts from address 0x0000-0000, after Your boot-loader finished its work, your application starts from somewhere, so your application does not have its own interrupt vectors, because 0x0000-0000 is occupied by Your boot-loader. And YOUR code need to handle such a problem.
I didn't notice Per's latest post, until I finished my posting.
Imagine that, Your boot-loader (Second) does not support UART; but your application has to support UART.
When your application is running, and an UART IRQ happens, the ARM core goes to the address 0x0000-0018 looking for the UART support. So the content of 0x0000-0018 must point to the correct UART ISR.
About point 6. the secondary bootloader should run with memory mapping = User Flash Mode. The Application loaded by secondary bootloader should run with memory mapping = User RAM Mode: so the Interrupt vectors of application are re-mapped to Static RAM without conflict with the secondary bootloader Interrupt vectors; How described on manual ...interrupt vectors, continue to appear in their original location in addition to the re-mapped address (ram mode).