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.
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.