PikeOS Topics

This appendix describes topics that are specific to the GNAT for PikeOS, a cross-development ARINC-653 system provided by SYSGO.

Kernel Configuration for PikeOS

There are two possible ways to configure a PikeOS kernel:

  • SYSGO’s set of command-line tools: pikeos-cloneproject, pikeos-configure, etc.
  • CODEO, a visually-oriented Integrated Development Environment based on the Eclipse framework.

In the following sections, we will explain how to use these tools to build a PikeOS kernel so that Ada applications can be run on it. The procedures will mostly use CODEO; to know more about PikeOS kernel configuration, refers to the PikeOS user manual Installing and Using PikeOS.

In order to debug any application on target, a partition should run a tool called muxa. muxa provides several development services, such as a target console, and some debug channels that can be connected to AdaCore’s debugger.

This will be illustrated by a simple scenario. The following instructions should help you build a simple kernel integration project in which Ada application can be run.

Creating a PikeOS kernel integration project

Make sure that you have all PikeOS tools in your PATH; then launch CODEO. In CODEO, create a new project by going to File => New => Project....

This should open the New project wizard. Expand CODEO => PikeOS and select Integration Project. Click on Next. Give a project name and choose a workspace, then continue.

In the project templates, select devel-pikeos; it contains a project pre-configured with the major development features. Then click on Next.

You may then select qemu for target board. QEMU is a simulator provided with CODEO that allows you to easily run a PikeOS kernel on host; this will be useful in the context of this short tutorial. When this is done, click on Finish. This will open the PikeOS Project Configurator; this is a visual editor for the configuration file project.xml.conf.

Note that you could also have a created this project from the command line with the command:

$ pikeos-cloneproject /opt/pikeos-3.3/demos-integration/devel-pikeos new_project

PikeOS maximum priority setting

You should now have a basic integration project; you can then configure it for Ada Ravenscar applications.

In order to run Ada tasking applications on a PikeOS process, you should make sure that this process can handle 240 priority levels. To do so, in the Project Explorer, double-click on vmit.xml. This will open the Topology View.

In this Topology View, in PartitionTable, expand Partition => pikeos => ProcessList, then click on ProcessEntry => Proc_pikeos. In its attribute, change MaxPrio to 240.

Then click on Partition => pikeos. CODEO warns you about the fact that the process Proc_pikeos has a greater priority than its partitions; so upgrade the maximum priority for the partition as well. Set MaxPrio to 242. Then save your modifications.

PikeOS interrupts

Please read comments in pikeos-cert-app.c runtime file for guidance on using interrupts.

PikeOS muxa configuration

As explained earlier, console and debugging functionnalities are provided by a component called muxa that comes in two parts: one running on target, one running on host. This section will focus on how to configure your kernel integration project in order to include this component on target. How to run the host part will be explained latter in this chapter (in section Debugging an Ada application on PikeOS).

In the previously-created integration project in CODEO, double-click on project.xml.conf in the Project Explorer, to open the PikeOS Project Configuration. Expand pikeos => service and click on muxa. This will open a panel Configuration Options: muxa. Change the settings to match your host/target configuration. In our case, as we are building a kernel for QEMU, the following values will do:

  • mode: networkfp
  • Device: eth0:/0
  • HostIP: IP address of your host;
  • HostPort: port used by the host muxa; say, 1501;
  • TargetIP: IP of the target as seen from target; say, 10.0.2.1 for QEMU;
  • TargetPort: Port on which the target muxa is listening; say, 1500;
  • GatewayIP: IP of the gateway from target; say, 10.0.2.2 for QEMU;
  • ConfigPort: Port of muxa‘s back office; say, 1550.

You can also change these settings from the command line, with the command

$ pikeos-configure --editor

In order to have debug support for your particular user application, you will also need to make sure that it has access to the whole file system of the muxa partition. This is handled in the Topology View. To access to it, click on vmit.xml in the Project Explorer. Then, expand Root->Default => PartitionTable and go your user partition: in this example, it is named Partition -> pikeos. Expand this node, then the node FileAccessList and check that a node muxa:/* has all access rights (Stat, Read. Write, Read-Write). If not, you may add it by right-clicking on FileAccessList and selecting Add.

Your kernel integration project is now properly configured to host an Ada application. The following section will tell you how to build such an application and how to link it to the kernel.

Building an Ada application on PikeOS

This section will give a basic example to illustrate how an Ada application targeting PikeOS can be built. Consider the following Ada program, to be copied in a file named hello.adb:

with GNAT.IO; use GNAT.IO;

procedure Hello is
begin
   Put_Line ("Hello from Ada!");
end Hello;

On X86 PikeOS, you can then build the Ada program and link it against this global handler with this command:

$ i586-sysgo-pikeos-gnatmake --RTS=ravenscar-full -g hello.adb

A similar command would be used on other CPUs; only the prefix of the toolchain would change (e.g. powerpc-sysgo-pikeos-gnatmake). In the rest of this tutorial, we will use i586-sysgo-pikeos; adapting it to your platform is just a matter of changing the prefix.

This will generate a file hello. You should then add this executable to your kernel integration project. Using the project created in the previous section Kernel Configuration for PikeOS, here is how you would do: you would copy hello into the directory target/, rename it to pikeos (as it is the name of the user application as specified in this project) and use make boot to link all pieces together:

$ cp hello *<integration project dir>*/target/pikeos
$ cd *<integration project dir>*
$ source ./PikeOS.sh
$ make boot

A file will be created: boot/pikeos-qemu-x86-qemu; this is a PikeOS kernel running your simple Ada application. How to run it on QEMU will be explained in the next section.

Running an Ada application on PikeOS

PikeOS and CODEO are integrated with a simulator called QEMU. This can be a simple way to run and test a PikeOS application.

In the previous sections, we have seen how to create a PikeOS kernel targeted to this simulator, embedding a simple Ada application. make boot should give the proper command to run QEMU. e.g. on x86:

$ /opt/pikeos-3.3/share/qemu/bin/qemu -m 32 \
  -cdrom ./boot/pikeos-qemu-x86-qemu -net none
PikeOS (C) Copyright 1998-2013 SYSGO AG, Germany
[...]
Hello from Ada!

or, on ppc:

$ /opt/pikeos-3.4/share/qemu/bin/qemu-system-ppc \
  -M prep_bare -nographic -no-reboot \
  -kernel ./boot/pikeos-qemu-ppc-qemu -net none
PikeOS (C) Copyright 1998-2013 SYSGO AG, Germany
[...]
Hello from Ada!

Debugging an Ada application on PikeOS

Any application that should be debugged on PikeOS should call a routine named init_gdbstub at the early stages of its execution. To do so with GNAT, the simplest way will be to recompile the entry code of your Ada application. This entry point is a file named pikeos-cert-app.c in the GNAT run-time library; the path to the GNAT run-time library is given by i586-sysgo-pikeos-gnatls -v. After copying it in your source directory, you can recompile it with the following command:

$ i586-sysgo-pikeos-gcc -c -DDEBUG pikeos-app.c -I$PIKEOS_TARGET_FILES/include/

Note the presence of an option -DDEBUG; it enables the gdbstub hook. After compiling it, you can link it to your application; in the case of our hello example, this build command would be:

$ i586-sysgo-pikeos-gnatmake --RTS=ravenscar-full -f -g hello.adb \
  -largs pikeos-cert-app.o -lgdbstub -ldebug

Note that you should also link against libgdbstub.a and libdebug.a using the options -lgdbstub -ldebug. You can then recopy it in the integration project that we created in the previous sections and relink the kernel:

$ cp hello <integration project dir>/target/pikeos
$ cd <integration project dir>
$ source ./PikeOS.sh
$ make boot

To run this on QEMU, specify several options to configure the network support properly, using the option -net and -redir; these options are documented in the usage message of QEMU that you can get by doing qemu --help. In our example, a proper setting would be:

$ /opt/pikeos-3.3/share/qemu/bin/qemu -m 32 \
  -net nic -net user -redir udp:1500:10.0.2.1:1500 \
  -cdrom boot/pikeos-qemu-x86-qemu

Or, on ppc:

$ /opt/pikeos-3.4/share/qemu/bin/qemu-system-ppc -M prep_bare \
  -nographic -no-reboot -kernel boot/pikeos-qemu-ppc-qemu \
  -net nic -net user -redir udp:1500:10.0.2.1:1500

The next step is to launch the host muxa. Run it in your kernel integration project (replacing <host> by the actual name of your host machine):

$ muxa --type eth --host <host>:1550 --eth-host 0.0.0.0:1501 \
  --eth-target <host>:1500

You can then connect to it at <host>:1550 and configure your console and debug channels. For example, to get a console:

$ telnet <host> 1550
Ok: Connected to server.
muxa> lsn
Ok: Channel list, target supports 16 channels.
0  pikeos/Proc_pikeos/dbg
       Host:free      Port:0      Target:open     (Uid:0x000,0x0016,0x0000)
4  Monitor
       Host:free      Port:0      Target:open     (Uid:0x000,0x0004,0x0000)
5  mon_con
       Host:free      Port:0      Target:open     (Uid:0x000,0x0004,0x0008)
6  traceserver
       Host:free      Port:0      Target:open     (Uid:0x000,0x0005,0x0000)

muxa> connect mon_con
Ok: connected
help
PikeOS Monitor Command Shell v1.0
Available commands:
   help                  Help on command
   sysinfo               Info on system
   lsp                   List partition names
   pinfo                 Info on a Partition
   lsc                   List channels
   cinfo                 Info on a channel
   lsq                   List Queuing ports of a partition
   qinfo                 Info on a queuing port
   lss                   List sampling ports of a partition
   sinfo                 Info on a sampling port
   lse                   List processes of a partition
   einfo                 Info on a process
   lsm                   List memory requirements of a partition
   minfo                 Info on a memory requirement
   preboot               Reboot a Partition
   phalt                 Halts a Partition
   treset                Resets the target with the specified mode.
   kinfo                 Info on kernel structures
   ps                    Show Tasks/Threads

Type help name to find out more about the command name.

PikeOS# lsp
 id name    partd fctid lctid mprio mode
  1 service   1.5     2    21   102 COLD_START
  2 pikeos    1.6    22    22   242 COLD_START
PikeOS# pinfo pikeos
operating mode:      COLD_START
num_kpages:          8
free_kpages:         3
flags:               0
max prio:            242
part daemon:         1.6
first child task:    22
last child task:     22
proc count:          1
queuing port count:  0
sampling port count: 0
max. open files:     32
open files:          1
cookie:              0

To connect the application gdbstub to an host port, in order to debug your application:

$ telnet <host> 1550
Ok: Connected to server.
muxa> lsn
Ok: Channel list, target supports 16 channels.
0  pikeos/Proc_pikeos/dbg
       Host:free      Port:0      Target:open     (Uid:0x000,0x0016,0x0000)
4  Monitor
       Host:free      Port:0      Target:open     (Uid:0x000,0x0004,0x0000)
5  mon_con
       Host:connected Port:1550   Target:open     (Uid:0x000,0x0004,0x0008)
6  traceserver
       Host:free      Port:0      Target:open     (Uid:0x000,0x0005,0x0000)

muxa> connect 1551 pikeos/Proc_pikeos/dbg
Ok: Connected channel

You can then connect the debugger to <host>:1551 using GDB’s remote protocol, either from GPS or from the command line:

(gdb) file hello
(gdb) target remote <host>:1551
Remote debugging using <host>:1551
0x08011d84 in gdbarch_breakpoint ()
(gdb) l hello.adb:2
1       with GNAT.IO; use GNAT.IO;
2
3       procedure Hello is
4       begin
5          Put_Line ("Hello from Ada!");
6       end;
(gdb) b 5
Breakpoint 1 at 0x80101da: file hello.adb, line 5.
(gdb) c
Continuing.

Breakpoint 1, hello () at hello.adb:5
5          Put_Line ("Hello from Ada!");

For further information about debugging with GNAT, refer to the GNAT User’s Guide for Native Platforms and to the GDB User’s Manual.

Using the APEX Run-Time Library on PikeOS

With the Zero Footprint run-time library GNAT for PikeOS provides a APEX binding to be used with the corresponding PikeOS personality. This section describes how to use it.

PikeOS APEX Kernel Configuration

The same configuration as Kernel Configuration for PikeOS should work, with the following addition: an APEX partition will need an additional set of memory pools named _APEX_KMEM_, _APEX_HEAP_POOL_, _APEX_STACK_POOL_. To create them in CODEO, open vmit.xml and expand Root -> Default => PartitionTable and go your user partition: in our example, Partition -> pikeos. Under this node, right-click MemoryRequirementList and choose Add. You will have to do it for the three memory pools mentioned above; in each case, modify the newly added memory pool as follow:

  • _APEX_KMEM_: change the name to _APEX_KMEM_ and the type to VM_MEM_TYPE_KMEM; set the size so that the kernel has enough memory space to create the tasks of your application (e.g. 0x00200000);
  • _APEX_HEAP_POOL_: change the name to _APEX_HEAP_POOL_ and the type to VM_MEM_TYPE_RAM; set the size to the heap size that your application needs to run properly (e.g. 0x00400000); enable isPool;
  • _APEX_STACK_POOL_: change the name to _APEX_STACK_POOL_ and the type to VM_MEM_TYPE_RAM; set the size to the stack size that your application needs to run properly (e.g. 0x00400000); enable isPool;

Then save your project and rebuild with make boot (from the command line or by a right-click on target boot in panel Make targets).

Building an Ada Application for PikeOS APEX

This section will show how to build a simple APEX application. It contains only simple APEX process that prints hello:

with Apex_Types; use Apex_Types;
with Apex_Partitions; use Apex_Partitions;
with tasking; use tasking;

procedure Hello is
   Set_Partition_Result : Return_Code_Type;
begin
   Create_Processes;
   Set_Partition_Mode (Normal, Set_Partition_Result);
end Hello;

--

package Tasking is

   procedure Create_Processes;

end Tasking;

--

with GNAT.IO;         use GNAT.IO;
with Apex_Types;      use Apex_Types;
with Apex_Processes;  use Apex_Processes;
with Apex_Partitions; use Apex_Partitions;

package body Tasking is

   procedure Process is
   begin
      Put_Line ("In process!");
      Stop_Self;
   end Process;

   function Get_Partition_Status return Partition_Status_Type is
      Part_Stat : Partition_Status_Type;
      RC        : Return_Code_Type;
   begin
      Get_Partition_Status (Part_Stat, RC);
      return Part_Stat;
   end Get_Partition_Status;

   procedure Create_Processes is
      Part_Stat : Partition_Status_Type := Get_Partition_Status;
      Attr      : constant Process_Attribute_Type :=
                    (Name => (others => 'a'),
                     Entry_Point => System_Address_Type (Process'Address),
                     Stack_size => 16#800#,
                     Base_Priority => 10,
                     Period => Part_Stat.Period,
                     Time_Capacity => Part_Stat.Period - 1,
                     Deadline => Hard);
      RC        : Return_Code_Type;
      Id        : Process_Id_Type;
   begin
      Create_Process (Attr, Id, RC);
      Start (Id, RC);
   end Create_Processes;

end Tasking;

To build this hello world program, you may copy it into one file and use i586-sysgo-pikeos-gnatchop to break it into several Ada units:

$ i586-sysgo-pikeos-gnatchop -w hello.ada

splitting hello.ada into:
hello.adb
tasking.ads
tasking.adb

You can then create a project that imports the APEX binding in a file p.gpr:

with "apex";

project P is
   for Main use ("hello.adb");
end P;

Invoking gprbuild will build the APEX application.

$ gprbuild --target=i586-sysgo-pikeos -Pp --RTS=zfp -XBINDING=apex_zfp -XPLATFORM=i586-sysgo-pikeos -XRUNTIME=zfp
i586-sysgo-pikeos-gcc -c -g hello.adb
i586-sysgo-pikeos-gcc -c -g tasking.adb
gprbind hello.bexch
i586-sysgo-pikeos-gnatbind hello.ali
i586-sysgo-pikeos-gcc -c b__hello.adb
i586-sysgo-pikeos-gcc hello.o -L/opt/pikeos-3.3/target/x86/i586/apex/lib -uMAIN -lapex -lxt -o hello

Debugging an Ada Application for PikeOS APEX

To debug an Ada Application using the APEX interface, the procedure is the same as the one described previously in Debugging an Ada application on PikeOS. Refer to this section for a detailed example.

A set of differences is worth mentioning: the entry code to recompile should now be found in a file named pikeos-apex-app.c in the binding; the path to the GNAT run-time library is given by

$ i586-sysgo-pikeos-gnat ls -Pp --RTS=zfp -XBINDING=apex_zfp \
   -XPLATFORM=i586-sysgo-pikeos  -XRUNTIME=zfp apex_types.ads

After copying it in your source directory, you can recompile it with a few changes to your project file:

  • Make sure that C is in the list of languages for this project;
  • Add -DDEBUG and -I$PIKEOS_TARGET_FILES/apex/include/ to the C compilation options;
  • Add -lgdbstub, -lapex_d, -lxt_d to the link options (these should be added as leading switches to override the default link options; because of circular dependencies between apex and xt the first two options should be listed twice).

In our example, the project will therefore be as follow:

with "apex";

project P is
   for Languages use ("Ada", "C");

   for Main use ("hello.adb");

   Pikeos_Target_Files := external ("PIKEOS_TARGET_FILES");

   package Compiler is
      for Default_Switches ("Ada") use ("-g");

      for Default_Switches ("C") use
        ("-g", "-I" & Pikeos_Target_Files & "/apex/include", "-DDEBUG");
   end Compiler;

   package Linker is
      for Leading_Switches ("Ada") use ("-lapex_d", "-lxt_d", "-lgdbstub",
                                        "-lapex_d", "-lxt_d");
   end Linker;
end P;

The example can then be built with the same command as in the previous section. Note that this is a case where project scenario variables can be used to differentiate between debug and production mode:

with "apex";

project P is
   type Mode_Type is ("DEBUG", "PRODUCTION");

   Mode : Mode_Type := external ("MODE", "DEBUG");

   for Languages use ("Ada", "C");

   for Main use ("hello.adb");

   Pikeos_Target_Files := external ("PIKEOS_TARGET_FILES");

   package Compiler is
      case Mode is
         when "PRODUCTION" =>
            for Default_Switches ("C") use
              ("-I" & Pikeos_Target_Files & "/apex/include");

         when "DEBUG" =>
            for Default_Switches ("Ada") use ("-g");

            for Default_Switches ("C") use
              ("-g", "-I" & Pikeos_Target_Files & "/apex/include", "-DDEBUG");
      end case;
   end Compiler;

   package Linker is
      case Mode is
         when "PRODUCTION" =>
            null;
         when "DEBUG" =>
            for Leading_Switches ("Ada") use
              ("-lapex_d", "-lxt_d", "-lgdbstub", "-lapex_d", "-lxt_d");
      end case;
   end Linker;
end P;

For more information about scenario variables, please refer to the “GNAT Project Manager” chapter in the GNAT User’s Guide for Native Platforms.