Execute In Place (XIP)
While an embedded system starts-up from no power, the first code it
will execute has to come from a non-volatile memory source e.g.
Flash or ROM.
Usually there shall be a 'bootloader' program which will do the
bare-minimum to get the system up and running.
When a system is booting, it has no-ram available, hence no stack available,
hence no memory available to store program variables. So the first
code a processor runs must do things entirely using the processor
registers. The first code the processor executes also executes from
where it is. That is to say it is 'executed-in-place' (XIP). It must
not attempt to modify anything in the program itself, as this code
may be in ROM, and the code cannot be self-modifying.
Due to the above considerations, the first program that a
processor executes after power-up is usually written in assembly
language, as the execution of a c-program almost always
requires a 'stack'
to be setup in Read/Write memory (RAM) to store variables, and at
startup or power-up RAM may not be available. Tutorial 2 shows how
the variables are stored on to the stack at the time of program
execution.
One of the things that the boot-loader would do is to make the
system RAM available for use. It can then relocate the code from
flash into this ram, and then jump to the RAM to execute this copied
or relocated code.
And yes, for all XIP code the load region = execution region, that
is to say that XIP code is stored in the root region. Remember 'root
region' by definition is the region where the load addresses are =
execute addresses. (see below to understand Load/Execute
regions)
Other applications of XIP:
Apart from the boot-loader code, XIP is also gaining popularity in
embedded world to execute programs other than boot code directly
from the Flash. NOR flash can be accessed randomly unlike NAND,
hence NOR flash is the obvious choice for such XIP storage and
in-place execution code. This helps save the on-chip ram area, which
in turn can be cost-effective. The execution will of course will
slower than RAM execution, however for many embedded applications it
brings about cost advantages, and offers adequate performance.
Load Region Vs
Execute Region:
In a typical embedded system, all the program & data is stored
in some Non-volatile memory when the system is powered off. However
some of the data or code may be moved into system SRAM (volatile
mem), before it is executed (if code) or before it is used (if
data), when the system is powered-ON.
When a user compiles and 'links' a program, an 'image' of that
program is produced. This is a binary executable file which the
system can execute.
The binary 'image' is typically divided into 'Read-Only' segment,
which contains the code & read-only data and 'Read-Write'
segment, which contains data, which can be initialized or zero
initialized or even Un-initialized.
Usually the 'Read-Only' segment can even be placed into ROM (as
opposed to flash), and does not have a requirement to be moved from
where it is in the memory. it is 'executed from where it is' i.e. it
is executed in place.
While the 'Read-Write' segment must be moved into system's
Read/Write memory e.g. SRAM before execution begins.
Hence for certain parts of the code, the memory location where that
part resides when the system is powered off is the same when the
system is powered ON.
But
For certain parts of the code, the memory location where that part
resides when the system in powered off is different to the memory
location where that part is moved to, upon power ON.
So who moves the code?
The linker will add the code into the program which the processor
will execute, and move those parts of the code, which are required
to be moved into system's SRAM at power-up.
Now these sections of code have different address at 'load' time,
which is in NVM than at 'execution' time, which is typically
somewhere in the SRAM.
So the program image can have parts for which the 'Load Region =
Execute Region', and this part of the code is 'Executed-In-Place'
XIP.
For certain other parts of the code the 'Load Region is not equal to
Execute Region', and this part of the code is not executed-in-place.
Example:
A user has its application code, he compiles and links it to produce
binary executable called 'image.bin'. The 'image.bin' is 14,246
Bytes.
That means the system must have at least that amount of NVM
available for the user to fit its binary image in the system.
Then the system will have some SRAM (say 16KB, which is quite
generous in this case), and this is at location 0x2000_0000 and
0x2000_3FFF.
Now the permanent address of the image file 'image.bin' is will be
in the NVM and will occupy the memory addresses 0x0000_0000 to
0x0000_37A6 in the system.
Hence the load address for this whole of the binary is from
0x0000_0000 to 0x0000_37A6. This can be an NVM (Flash) or can even
be ROM.
But before this can be executed, as a bare minimum requirement
- Stack memory should be setup.
- The r/w data e.g variables must be moved to R/W memory
The system's R/W memory (say a total of 16 KB SRAM is available in
the system) is somewhere else in the memory map, and say it is from
0x2000_0000 to 0x2000_3FFF (16KB).
Hence certain regions from the 'image.bin' will be moved to the
memory location somewhere in between 0x2000_0000 and 0x2000_3FFF.
And the stack pointer will be setup to have some memory reserved for
'stack' which will also reside between 0x2000_0000 and 0x2000_3FFF.
Hence for certain section(s) of the 'image.bin' file, the load
address = execution address, and it remains permanent, and is
between 0x0000_0000 and 0x0000_37A6. This is also the XIP ,
Execute-in-Place Region of the 'image.bin'.
Whereas for certain section(s) of the 'image.bin' file, the load
address was somewhere in between 0x0000_0000 to 0x0000_37A6, and the
execution address somewhere in between 0x2000_0000 and 0x2000_3FFF.
i.e. for these sections, the Load Address is not equal to their
execution address.
Let us take another example where the Load
address is not the same as execution address:
The user has a critical function written in C. The image file that
contains this function is placed in NVM. However the user wants this
function to be moved into a SRAM which is very close to the
processor for fast execution.
Now this function has 2 memory addresses.
1. Load Address : Where the function resides in NVM memory, when the
system is powered off
2. Execution Address : Where the function resides in SRAM memory,
when the system is up and running.
Again for this function the Load Address is different to its
Execution address.
Hence this code will not be XIP (Executed-in-Place)
Conclusion:
Certain code in a binary image can be executed from where it is in
memory. This code never 'moves' into another region of the memory
and has permanent address. When this code is executed, it is
executed from where it is, this is called Execute-In-Place (XIP)
So how does the user specifies where the
image regions should be placed at execution time?
There are 2 mechanisms.
Click Here to Make Comments or ask Questions
<=
PREV : Embedded C Fundamentals
Next =>
Scatter Loading
SITE HOME