pdrosihn,
I'm not sure what you mean by:
Quote:
What would be reallly very useful would be if you could convert one of your example demos for the SDK, the SWIM would be best, so that it can be burned to Flash and run. Then send it to me/ post as a download.
mainly because I don't know what
SWIM refers to.
However, I will try and explain what is happening when you adjust the virtual addresses of the ELF file.
The first thing you need to understand is how the LogicLoader
loads a file. To properly load and run an ELF formatted executable, LoLo performs the following steps:
- Looks at the program's start address.
- Based on that address, determines if the program is going to start execution from flash or RAM.
If the program's start address is in RAM:
For each section in the ELF file:
- Remove the section header.
- Copy the section's data to its proper location in RAM.
If the program's start address is in flash:
For each section in the ELF file:
- Remove the section header.
- Adjust the starting address of the section to some place in RAM.
- Copy the section's data to this location in RAM.
The end result of the above steps is that your program is now a raw binary image sitting someplace in the system's RAM. It has been stripped of any and all ELF file format headers. It has also been stripped of any debug symbols or other unecessary information. Therefore, it is a snapshot of how the program looks when it is executing in memory.
The second thing you need to understand is why the LogicLoader needs to copy a flash image into RAM first. The reason this is necessary is that programming flash memory is inherently slow. Flash memory needs to be unlocked and erased before programming. Unlocking and erasing blocks of flash takes time. The time it takes is so long that the LogicLoader would drop bytes coming in over the serial port while it was trying to do this, thus corrupting your program image. That is why you need to use a seperate
burn command after loading a program destined for flash memory.
The third thing you need to understand is that NOR flash devices (such as the ones on our SDK kits) are capable of what is known as eXecute In Place (XIP). This means that programs can execute directly out of the flash device. This is as oppossed to needing to be loaded into RAM by some other program (like an operating system), or copying themselves into RAM (like our little sample application does). Because of this feature of NOR Flash, the LogicLoader doesn't make
any assumptions about the program you just burned into flash. It doesn't care what this program does, or where it executes from (does it copy itself out to RAM, or eXecute In Place from the flash). The LogicLoader just knows that the starting address of the program was in Flash, so it "cached" it into RAM first and then let the user decide if he/she wants to burn it into flash or not.
Finally, we get to your original question concerning what happens when we adjust the virtual addresses in the ELF file. Our sample application is linked to execute out of RAM. But, we don't want to download it each and every time we want to run it, so we actually want to store it in flash. So, to do this, we need to accomplish two things:
- Write startup code that will relocate our program from flash to RAM so that the branches will work.
- Fake out the LogicLoader so that it thinks that our program is going to start in flash.
To do this, we adjust the virtual addresses within the ELF file.
This does
not change the way the program was linked. For instance, if the address of function
foo() gets linked to 0xC0008000 and
main() calls
foo(), that instruction is still going to branch to the address 0xC0008000. Therefore, the code for
foo() had better be existing at 0xC0008000. That is what the startup code does. It copies the code out of flash memory into RAM so it is re-located to its proper runtime location.
This
does change the start address within the ELF file's header. Thus, when LoLo loads the ELF file, it will look at the start address and assume that this program is going to start in flash.
The reason this all works is that the startup code contains
no branches. Thus, if LoLo burns the program into flash, the program can safely run through the entire assembly language
startup() function without trouble. However, the relocation needs to happen before
startup jumps to
main(). This is because
main() is going to be located at some RAM address, because that is how we linked and located the file.
Summary:
- The sample program is linked to run from RAM. So all addresses in the program (such as the addresses of functions, or global variables) will point to someplace in RAM.
- We adjust the start address reported in the ELF header to point to someplace in flash.
- LogicLoader reads the adjusted start address and determines that this is a flash address.
- LogicLoader "caches" the program in stripped binary form someplace in RAM.
- LogicLoader lets you burn this program into flash.
- When you start this program, you jump to its first instruction which has been burned into flash.
- Before the program accesses any global variables, or calls any functions, it copies its code and data sections into RAM.
- When the program jumps to main() it is actually jumping to an address in RAM.
- It can do the above because it copied all of the code for main() (and all other functions) into RAM before it jumped there.
Hope this helps,
--mikee