You should have Arm Development Studio installed and your license configured. Refer to the Arm Development Studio install guide for more information.
Alternatively you can install Arm Compiler for Embedded and Arm Fixed Virtual Platforms (FVP) individually.
See Prepare Docker image for Arm embedded development for an example Docker image containing all these tools.
The FVP_Base_AEMvA
Architecture Envelope Model is used to execute the code. This is a generic Arm Architecture platform, implementing 4 processors.
This Learning Path assumes some knowledge of Armv8-A Architecture . If you need more background, Architecture Exploration Tools provide an overview of the instruction set and registers.
Start with a simple C program, and use the armclang
compiler and armlink
linker tools to compile and generate an executable image.
Use your favorite editor to create a new source file called hello.c
with the following contents:
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
This command invokes the compiler to compile hello.c
for the Armv8-A architecture and generate an ELF object file hello.o
:
armclang -c -g --target=aarch64-arm-none-eabi -march=armv8-a hello.c
The options used in this command are:
-c
tells the compiler to stop after compiling to object code. The link step to create the final executable will be performed later.-g
tells the compiler to include debug information in the image.--target=aarch64-arm-none-eabi
tells the compiler to target AArch64
code (rather than AArch32
).-march=armv8-a
explicitly selects the architecture version. Alternatively you can specify a particular processor with -mcpu
.The default memory map used by the linker does not match the memory map of the FVP.
You must specify a memory map that matches the target. The Arm linker feature scatter-loading is used.
Create a file scatter.txt
with the following contents:
ROM_LOAD 0x00000000 0x00010000
{
ROM_EXEC +0x0 0x10000
{
* (InRoot$$Sections)
* (+RO)
}
RAM_EXEC 0x04000000 0x10000
{
* (+RW, +ZI)
}
ARM_LIB_STACKHEAP 0x04010000 EMPTY 0x10000 {}
}
and link the image using the scatter file.
armlink --scatter=scatter.txt hello.o -o hello.axf
The statements in the scatter file define the different regions of memory and their purpose. The following defines a load region
, starting at address 0x0, and of size 0x10000 bytes. A load region
is an area of memory that contains the image file at reset before execution starts (typically defining the Flash memory addresses of a real system).
ROM_LOAD 0x00000000 0x00010000
{...}
Within the load region
define execution region(s)
, where the code/data will be located at run-time:
ROM_EXEC +0x0 0x10000
{
* (InRoot$$Sections)
* (+RO)
}
An execution region is called a root region
if it has the same load-time and execute-time address. The initial entry point of an image must be in a root region, as this is executed before scatterloading can occur to relocate that code. You can use the InRoot$$Sections
section name to ensure the appropriate C library code for scatterloading is in this section (useful when there are multiple code regions).
In the scatter file, all read-only (RO
) code/data (including the entry point __main()
) is placed in the ROM_EXEC
root region.
RAM_EXEC 0x04000000 0x10000
{
* (+RW, +ZI)
}
RAM_EXEC
contains any read-write (RW
) or zero-initialised (ZI
) data. Because this has been located at a different address (0x04000000, in SRAM), it is not a root region.
Region names (such as ROM_LOAD
, ROM_EXEC
, and RAM_EXEC
above) are arbitrary. However there are
reserved names
for the Stack and Heap regions. This example uses a single region (ARM_LIB_STACKHEAP
) for both.
ARM_LIB_STACKHEAP 0x04010000 EMPTY 0x10000{}
0x04010000
and grows upwards.0x04020000
(0x04010000 + 0x10000
) and grows downwards.EMPTY
as there are no explicit sections to locate there.You can now run the executable image hello.axf
from the command line using the Fixed Virtual Platform (FVP).
FVP_Base_AEMvA -a hello.axf
The code starts at the default entry point, __main()
in the Arm libraries. These libraries perform a number of setup activities, including:
The code executes on the FVP, and the message “Hello World!” appears on screen 4 times, as the same code is executed on each of the 4 processors in the model.
Hello World!
Hello World!
Hello World!
Hello World!
The FVP can be configured so that only one processor is running at start up.
FVP_Base_AEMvA -a hello.axf -C pctl.startup=0.0.0.1
In this case, only one instance of the output is shown:
Hello World!
In the next section you will learn how to manage this in software.