LEON3 Topics

This appendix describes topics relevant to GNAT for bareboard LEON3.

Supported Processors and Run-Time Libraries

GNAT for bareboard LEON3 supports the LEON3 and LEON4 processor families. The following uniprocessor run-time libraries are pre-built:

  • light-leon3

  • light-tasking-leon3

  • embedded-leon3

The following multiprocessor run-time libraries are pre-built:

  • light-tasking-leon3-smp

  • embedded-leon3-smp

All pre-built run-time libraries include the necessary low-level hardware startup and initialization functionality required to run applications on LEON3 and LEON4 processor families.

Getting Started

Developing with GNAT for bareboard LEON3 is similar to native GNAT development, with two important differences. First, when building for a bareboard target, you need to specify both the target processor and the run-time library. This can be defined in a project file (either directly or via the project properties dialog in GNAT Studio) or on the command line. For details on how to specify the target and run-time library for your project, see Introduction to GNAT for Cross Platforms. For LEON3 and LEON4 processors the target ‘leon3-elf’ needs to be specified.

For example, the following project file fragment shows both the target and the run-time library specified via their respective attributes. In this example, the LEON3 target and the ‘Zero Foot Print’ LEON3 run-time library is specified:

project Demo is
   ...
   for Runtime ("Ada") use "light-leon3";
   for Target use "leon3-elf";
   ...
end Demo;

The second difference is how programs are run and debugged. This is dependent on your setup and the tools you use. In many cases, GNAT Studio can be used to debug your program. See Debugging for details.

Executing and Debugging on Emulators

The program compiled by the toolchain can be executed using GNATemulator or Gaisler’s TSIM. GNATemulator can execute or debug with the program either directly from the command line or from within GNAT Studio.

Within GNAT Studio, the program can be run on the emulator using the Run with Emulator toolbar button or the Build/Emulator->Run with Emulator menu entry. As the program executes, it will display its output, if any, in the leon3-elf-gnatemu view. Alternatively, GNATemulator can run the program from the command line:

$ leon-elf-gnatemu main

To debug a program from within GNAT Studio, click on the Debug with Emulator toolbar button. This will launch the emulator along with a gdb remote debugging session connected to the emulator. Debugging the program through GNAT Studio is similar to debugging a native program. Alternatively from the command line, launch GNATemulator using the -g debugger switch:

$ leon-elf-gnatemu -g main

The debugger can then be launched directly from the command line or from GNAT Studio. Before loading the program to debug, GDB must connect to the simulator using the remote protocol and the required IP port (by default localhost:1234).

$ leon3-elf-gdb main
(gdb) target remote localhost:1234
   ...
(gdb) continue
   ...
(gdb) detach
   ...

Further information about GNATemulator can be found in GNATemulator Documentation

Executing and Debugging on Hardware Platforms

The compiler generates ELF executables that can be loaded onto the target board using the GRMON debug monitor or tools provided by your board supplier.

Debugging LEON3 programs with GDB is done through the remote target capability provided by GRMON debug monitor. This functionality is activated by launching the GRMON monitor with the -gdb switch or using the GRMON gdb command:

$ grmon -gdb

From the grmon window the program can be loaded with:

grmon> load main

It is important to load the program through the GRMON as it will initialize the .data and .bss sections.

GDB may now be started from GNAT Studio or the command line. By default, GRMON listens on port 2222 for GDB``connections. From GNAT Studio, you may configure in the project settings the remote connection details so GNAT Studio can automatically connect to ``GRMON. From the command line:

$ leon-elf-gdb main
(gdb) target remote monnitor_address:2222
(gdb) <insert your breakpoints here>

To resume the execution, we first need to set the PC to the start address and then resume from there. This can be done in a single command:

(gdb) jump start

This part assumes that the entry point is a function named “start”, which is the case for the pre-built runtimes we provide with GNAT Pro. If you are building your own version of the runtime, the name of the entry point is found via the “ENTRY” statement in the linker script. See for instance the linker script leon3-elf/lib/gnat/embedded-leon3/ld/leon.ld in your GNAT Pro install for an example of such script.

SMP Support

The “embedded-leon3-smp” and “light-tasking-leon3-smp” runtime libraries support symmetric multi-processing (SMP) and are pre-configured to support two processors. Processors are numbered beginning at one, therefore applications can assign tasks to either CPU #1 or CPU #2.

The number of processors supported can be increased by changing the value of Max_Number_Of_CPUs in package System.BB.Board_Parameters and then rebuilding the runtime library.

Per the Ada language standard (RM D.13/11), under the Ravenscar profile all tasks execute on a single processor unless the application explicitly uses aspect “CPU” to assign tasks to processors. (This is due to the No_Dynamic_CPU_Assignment restriction.) Therefore, CPU #1 is used by default.

All runtime and library unit elaboration is done on CPU #1. After that code completes CPU #2 is started. Note that the configuration pragma Partition_Elaboration_Policy (RM H.6) can be used, as usual, to control how library unit elaboration is performed regarding task activations and interrupt handler attachment, but a single processor is used nonetheless.

The implementation of delay statements is such that the resulting timer interrupt always goes to CPU #1, then to CPU #2 (via software interrupt) if that’s where the task requesting the delay is located. Thus there will be some overhead in that case.

Adapting the Run-Time System

There may be some variations among the different boards. The RAM and ROM sizes can be modified via the a custom linker script while other properties including clock speed and multiprocessor support requires modifying the LEON3 BSP sources and rebuilding the run-time library. For the latter see Customized Bareboard Run-Time Libraries for instructions on how to perform these modifications.

The default linker script located at leon3-elf/lib/gnat/<runtime_library>/ld/leon.ld defines the size of memory in the system and the default stack size. If these parameters need to be adapted a local copy of this script can be created and modified:

  • Memory size: the _RAM_SIZE and _PROM_SIZE variables defines the size of the RAM and ROM memory installed on the board respectively. The memory map also needs tailoring when _RAM_SIZE is changed.

    MEMORY
    {
      ram (rwx) : ORIGIN = 0x40000000, LENGTH = New_Length
    }
    
  • Default stack size for the environment task is set through _STACK_SIZE variable. This variable can be overridden at the command line without creating a new linker script, see Environment Task Primary Stack Size for further information.

The new linker script can be selected by setting the environment variable LDSCRIPT to the path of the script or alternatively passed on the command line to gprbuild:

gprbuild -P prj.gpr -XLDSCRIPT=my_system.ld

User specific hardware initialization can be performed before the elaboration of Ada code through the __gnat_hw_initialize procedure. By default, this procedure returns immediately. It can be replaced by providing your own version of this procedure. As the procedure is called before memory initialization, it should be written in assembly. Routine calls are possible as long as there is no window overflow. Finally, be sure that your routine is linked in the executable (double check with objdump). If needed, force the link when using gprbuild by using a 'globl pseudo assembly instruction, like this:

with System.Machine_Code;

   System.Machine_Code.Asm(".globl __gnat_hw_initialize",
                           Volatile => True);

LEON3FT RETT Restart Errata

All of the LEON3 run-times implement the workaround #1 of the LEON3FT RETT Restart Errata (GRLIB-TN-0018). Please refer to the Gaisler documentation for more information about the triggering of the errata. If the errata is not applicable to your project, the workaround can be disabled by commenting out the definition of the LEON3_ERRATA_GRLIB_TN_0018 macro in the crt0.S source file of the run-time, and then recompiling the run-time.

Console Output

UART 1 is used as the target console.