Startup-gen User’s Guide
About startup-gen
startup-gen
generates startup files (crt0 and linker script) based on
properties of the target device such as: architecture, memory layout, number of
interrupts.
One of the goals of this tool is to make it easier to start developing on micro-controllers by providing the basic elements of a Board Support Package (BSP).
The target device properties are provided inside a GNAT Project file (see Input format) and the output files are generated from templates in the template-parser format (see Custom templates).
Usage
To use startup-gen
you need a GNAT Project file that contains the target
device properties (see Input format).
Here is an example of project file:
project Spec is
package Device_Configuration is
for CPU_Name use "cortex-m4f";
for Number_Of_Interrupts use "25";
for Main_Stack_Size use ("4K");
for Memories use ("flash", "sram");
for Boot_Memory use "flash";
for Main_Stack_Memory use "sram";
for Main_Stack_Size use "8K";
-- flash
for Mem_Kind ("flash") use "ROM";
for Address ("flash") use "16#08000000#";
for Size ("flash") use "1024K";
-- sram
for Mem_Kind ("sram") use "RAM";
for Address ("sram") use "16#20000000#";
for Size ("sram") use "128K";
end Device_Configuration;
end Spec;
The following command line switches are available:
-l ARG Name of the generated linker script.
-s ARG Name of the generated startup code.
-X ARG Specify an external reference for Project Files.
-P ARG Name of the project file with the device configuration.
–print-tags Print the tags available in templates.
Here is an example of startup-gen
command:
$ startup-gen -P spec.gpr -l link.ld -s crt0.S
This command will generate a linker script in the file link.ld
and a crt0
in the file crt0.S
based on the target properties provided in spec.gpr
.
The -P
switch is required. The linker script and/or crt0 will be generated
only if respectively the -l
and/or -s
switches are provided.
Input format
The properties of the target device must be provided in a
Device_Configuration
package inside a GNAT Project file.
Here are the attributes supported by startup-gen
:
Architecture and CPU
for CPU_Name use ("<STRING>");
This attribute (optional if a supported run-time is defined) specifies the name of the target CPU. It is used, for instance, to determine the default templates that will be used for output generation.
for Float_Handling use "<soft|hard>";
This attribute is optional and specifies whether the floating point support is provided by the CPU/hardware (hard
) or by the compiler/software (soft
). It is used, for instance, to determine whether the Floating Point Unit (FPU) is initialized in thecrt0
. Note that you can decide to not use hardware floating point even if the target device has an FPU.
Memory
for Memories use (<LIST_OF_STRINGS>);
This attribute specifies the list of memory banks of the device, e.g.("flash", "sram", "dtcm")
. For each bank of this list, theKind
,Address
andSize
attributes are required.
for Boot_Memory use "<BANK_NAME>";
This attribute specifies the memory bank from which the program will start. It can be a ROM bank if the program is written to a non-volatile memory such as flash, or a RAM bank if the program is loaded by a debugger or a bootloader.
for Mem_Kind (<BANK_NAME>) use "<ROM|RAM>";
This attribute specifies the kind of memory<BANK_NAME>
, eitherROM
(read-only) orRAM
. This attribute is used to determine what linker sections will be allocated to the bank. For instance a.data
or.bss
cannot be allocated in read-only memory.
for Address (<BANK_NAME>) use "<VALUE>";
This attribute specifies the base address of the memory bank.<VALUE>
is a string containing an Ada or C numeric literal, e.g.16#08000000#
or0x08000000
.
for Size (<BANK_NAME>) use "<VALUE>";
This attribute specifies the size of the memory bank.<VALUE>
is a string containing a numeric literal. Multiplier suffixK
andM
are supported, e.g.16K
.
for Main_Stack_Size use "<VALUE>";
This attribute specifies the size of the main program stack statically allocated in the linker script. The value is a string containing a numeric literal. Multiplier suffixK
andM
are supported, e.g.16K
for Main_Stack_Memory use "<BANK_NAME>";
This attribute specifies the memory bank where the the main program stack is statically allocated in the linker script. The bank must be a RAM bank.
Interrupts
for Number_Of_Interrupts use "<VALUE>";
This attribute specifies the number of interrupt lines on the device. The value is a string containing a numeric literal. Depending on the architecture, this value can be used to create a trap vector in thecrt0
.
for Interrupt("<ID>") use "<NAME>";
This attribute specifies a name for an interrupt.<ID>
is a numeric literal representing the interrupt id (starts at zero).<NAME>
is a string that will be used to declare assembly symbols for instance. Therefore the name must be a valid assembly symbol name.
Templates
for Startup_Template use "<PATH>";
This attribute specifies a path to a custom template file used to control startup (crt0
) generation (see Custom Templates).
for Linker_Template use "<PATH>";
This attribute specifies a path to a custom template file used to control linker script generation (see Custom Templates).
for User_Tag ("<TAG_NAME>") use "<TAG_VALUE>";
This attribute specifies a user defined tag to be used in templates. It can be used control optional features in templates or provide extra values that are not generated by startup-gen.
Advanced Topics
Scenario Variables
startup-gen
supports the use of scenario variables
in the input project file.
These can be used in multiple ways, here are some examples:
Select boot memory
project Prj is
type Boot_Mem is ("flash", "sram");
Boot : Boot_Mem := external ("BOOT_MEM", "flash");
package Device_Configuration is
for Memories use ("flash", "sram");
for Boot_Memory use Boot;
-- [...]
end Device_Configuration;
end Prj;
$ startup-gen -P prj.gpr -l link.ld -s crt0.S -XBOOT_MEM=flash
$ startup-gen -P prj.gpr -l link.ld -s crt0.S -XBOOT_MEM=sram
Select boards with different device configuration
project Prj is
type Board_Kind is ("dev_board", "production_board");
Board : Board_Kind := external ("BOARD", "dev_board");
package Device_Configuration is
for Memories use ("flash", "sram");
case Board is
when "dev_board" =>
for Size ("sram") use "256K";
when "production_board" =>
for Size ("sram") use "128K";
end case;
-- [...]
end Device_Configuration;
end Prj;
$ startup-gen -P prj.gpr -l link.ld -s crt0.S -XBOARD=dev_board
$ startup-gen -P prj.gpr -l link.ld -s crt0.S -XBOARD=production_board
Custom Templates
You can provide your own templates for startup and linker script files using
the Startup_Template
and Linker_Template
attributes (see Templates).
The output files are generated using the template-parser library, you can therefore refer to this documentation to write your templates.
To see the list of predefined tags available for your templates, use the
--print-tags
command line switch.
For instance:
$ startup-gen -P spec.gpr --print-tags
--- Template tags ---
BOOT_FROM_ROM => TRUE
BOOT_MEM => ("flash")
BOOT_MEM_ADDR => ("0x8000000")
BOOT_MEM_SIZE => ("0x100000")
MAIN_RAM => ("sram")
MAIN_RAM_ADDR => ("0x20000000")
MAIN_RAM_SIZE => ("0x20000")
RAM_REGION => ("ccm")
RAM_ADDR => ("0x10000000")
RAM_SIZE => ("0x10000")
ROM_REGION => ()
ROM_ADDR => ()
ROM_SIZE => ()
MAIN_STACK_SIZE => ("0x1000")
MAIN_STACK_REGION => ("ccm")
INTERRUPT_NAME => ()
INTERRUPT_ID => ()
---------------------
[...]
Example of project using a generic Light Ada run-time and startup-gen
For this example we will use STM32F4-Discovery development board from STmicroelectronics. The board is equipped with an ARM Cortex-M4F microcontroller.
The sources of this example can be found in: <install_directory>/share/examples/startup-gen/startup-gen-stm32f4
Board specifications
To begin with we need to know the specification of the board and microcontroller. We will need:
The name of the CPU core architecture (ARM Cortex-M4F in our case)
Base address and size of memory banks (flash, RAM, etc.)
The number of interrupts
You can get the information from the vendor documentation or product page.
The project file
The project file will require some specific fields:
The list of languages must contain ASM_CPP, because we will compile the startup code (crt0) written in assembly language.
The run-time should be set to light-cortex-m4f because we are using an ARM Cortex-M4F microcontroller
The linker script must be specified as a linker option
The board specifications in a Device_Configuration
Here is what the project file looks like:
project Hello is
for Languages use ("Ada", "ASM_CPP"); -- ASM_CPP to compile the startup code
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Main use ("hello.adb");
for Target use "arm-eabi";
-- generic Light run-time compatible with our MCU
for Runtime ("Ada") use "light-cortex-m4f";
package Linker is
-- Linker script generated by startup-gen
for Switches ("Ada") use ("-T", Project'Project_Dir & "/src/link.ld");
end Linker;
package Device_Configuration is
-- Name of the CPU core on the STM32F407
for CPU_Name use "ARM Cortex-M4F";
for Float_Handling use "hard";
-- Number of interrupt lines on the STM32F407
for Number_Of_Interrupts use "82";
-- List of memory banks on the STM32F407
for Memories use ("SRAM", "FLASH", "CCM");
-- Specify from which memory bank the program will load
for Boot_Memory use "FLASH";
-- Allocate the main stack in CCM with 8K size
for Main_Stack_Memory use "CCM";
for Main_Stack_Size use "8K";
-- Specification of the SRAM
for Mem_Kind ("SRAM") use "ram";
for Address ("SRAM") use "0x20000000";
for Size ("SRAM") use "128K";
-- Specification of the FLASH
for Mem_Kind ("FLASH") use "rom";
for Address ("FLASH") use "0x08000000";
for Size ("FLASH") use "1024K";
-- Specification of the CCM RAM
for Mem_Kind ("CCM") use "ram";
for Address ("CCM") use "0x10000000";
for Size ("CCM") use "64K";
end Device_Configuration;
end Hello;
Generate the linker script and startup-code with startup-gen
Once the project file is ready we can use startup-gen to generate the linker script and startup code.
To do this use the following command line:
$ startup-gen -P hello.gpr -l src/link.ld -s src/crt0.S
This means that startup-gen will create a linker script in src/link.ld and a startup code in src/crt0.S
Build
We can now build our project:
$ gprbuild -P hello.gpr
You can also open this project in GNATstudio and build it from there.
Running on the GNATemulator
You can now run the example on GNATemulator:
$ arm-eabi-gnatemu --board=STM32F4 obj/hello