<<

GNAT User’s Guide Supplement for Cross Platforms Release 23.0w

AdaCore

Sep 29, 2021 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

2 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

GNAT, The GNU Ada Development Environment GNAT Pro Edition

Version 23.0w Date: Sep 29, 2021

AdaCore Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Foundation; with no Invariant Sections, with the Front-Cover Texts being “GNAT Reference Manual”, and with no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.

GNAT User’s Guide Supplement for Cross Platforms 3 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

4 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

CONTENTS

1 About This Guide 13 1.1 What This Guide Contains...... 13 1.2 What You Should Know before Reading This Guide...... 14 1.3 Related Information...... 14 1.4 Conventions...... 15

2 Introduction to GNAT for Cross Platforms 17 2.1 for Cross Platforms...... 17 2.2 Specifying the Target...... 17 2.3 Specifying the Run-Time ...... 18 2.4 GNAT /C++ for Cross Platforms...... 18 2.4.1 Supported C++ Version...... 18 2.4.2 Mixed-Language Programming using GNAT Exclusively...... 18

3 The Primary and Secondary Stacks 19 3.1 The Primary Stack...... 19 3.1.1 The Default Primary Stack Size...... 19 3.1.2 Per-Task Primary Stack Size...... 20 3.1.3 Environment Task Primary Stack Size...... 20 3.2 The Secondary Stack...... 21 3.2.1 Fixed Secondary Stack Allocation...... 21 3.2.2 Dynamic Secondary Stack Allocation...... 22 3.2.3 Disabling the Secondary Stack...... 22

4 Predefined Profiles 23 4.1 The Ravenscar Profiles...... 23 4.2 The Jorvik Profile...... 23 4.2.1 Number of Entries Per Protected Object...... 24 4.2.2 Number of Queued Callers per Entry...... 24 4.2.3 Entry Barriers...... 24 4.2.4 Relative Delay Statements...... 25 4.2.5 Additional Non-Tasking Restrictions Removed...... 25 No_Implicit_Heap_Allocations...... 25 No Dependence on Ada.Calendar...... 25

5 Predefined GNAT Pro Run-Times 27 5.1 Standard Run-Time...... 27 5.2 Embedded Run-Time...... 27 5.3 Light Run-Time...... 28 5.3.1 Allocator Support...... 29

GNAT User’s Guide Supplement for Cross Platforms 5 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

5.3.2 Certification...... 29 5.3.3 Excluding the Run-Time Library...... 30 5.3.4 Exceptions and the Last Chance Handler...... 31 5.4 Light-Tasking Run-Time...... 31 5.5 Specifying a Run-Time...... 32

6 The GNAT Configurable Run-Time Facility 33 6.1 Standard Run-Time...... 33 6.2 The Configurable Run-Time...... 33 6.3 Run-Time Libraries and Objects...... 34 6.3.1 GNAT Run-Time Library...... 34 6.3.2 C Library...... 35 6.3.3 Math Library...... 35 6.3.4 Internal GCC Library...... 35 6.3.5 Startup and Cleanup Code...... 36 6.4 Run-Time Dependencies in User Code...... 36 6.4.1 Explicit with Clauses...... 36 6.4.2 -Generated Calls to the GNAT Run-Time Library...... 36 6.4.3 Pragma Import...... 36 6.4.4 Back-End Generated Calls to Library Functions...... 37 6.5 How The Run Time Library Is Configured...... 37 6.5.1 Configuration Pragmas...... 37 6.5.2 Specification of Configuration Parameters...... 38 6.5.3 Restricting the Set of Run-Time Units...... 44 6.6 Naming the Run-Time Library...... 45 6.7 Creating a Configurable Run-Time Library...... 45

7 Support for Certified Systems 47 7.1 The Certification Philosophy...... 47 7.2 Using GNAT Pro Features Relevant to Certification...... 48 7.2.1 Exceptions...... 48 7.2.2 Allocators...... 50 7.2.3 Array and Record Assignments...... 51 7.2.4 Object-Oriented Programming...... 52 7.2.5 Functions Returning Unconstrained Objects...... 53 7.2.6 Controlling Implicit Conditionals and Loops...... 53 7.2.7 Controlling Use of Conditional Operators...... 55 7.2.8 Avoiding Elaboration Code...... 55 7.2.9 Removal of Deactivated Code...... 57 7.2.10 Traceability from to ...... 58 7.2.11 Optimization issues...... 59 7.2.12 Other useful features...... 59 7.2.13 Program Build Options...... 59 Compiler Switches...... 59 gnatbind Switches...... 60

A VxWorks Topics 61 A.1 Common VxWorks Topics...... 61 A.1.1 VxWorks Kernel Requirements...... 61 A.1.2 Executing a Program on VxWorks...... 62 Loading and Running the Program...... 62 Unloading the Program...... 62 A.1.3 Mixed-Language Programming on VxWorks using GNAT Exclusively...... 63 A.1.4 Mixed-Language Programming using the VxWorks C/C++ ...... 63

6 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

A.1.5 Interoperability with VxWorks C/C++ Compilers...... 63 A.1.6 ...... 63 Exception Integration Schemes...... 64 Exception Propagation Schemes...... 65 ZCX on VxWorks...... 66 Mixing Ada and C++ in Workbench...... 66 A.1.7 Kernel Configuration for VxWorks...... 68 A.1.8 Main Task Attributes and the Application Stub...... 68 A.1.9 Stack Overflow Checking on VxWorks...... 69 A.1.10 Interrupt Handling for VxWorks...... 70 A.1.11 Handling Issues for PowerPC Targets...... 78 Kernel Mode...... 78 RTPs...... 79 A.1.12 Calling exported Ada procedures from the VxWorks shell...... 79 A.1.13 Simulating Command Line Arguments for VxWorks...... 81 A.1.14 Traceback Support on VxWorks...... 82 Traceback Computation When Using Restricted Runtimes...... 82 A.1.15 Using addr2line on VxWorks...... 82 Differences between VxWorks and native platforms...... 82 Using -vxaddr2line...... 83 An example...... 83 A.1.16 Removal of Unused Code and Data...... 85 A.1.17 ...... 85 A.1.18 Frequently Asked Questions for VxWorks...... 86 A.2 Workbench / VxWorks 6.x Topics...... 87 A.2.1 Installing GNAT for VxWorks 6...... 87 A.2.2 Using GNAT for VxWorks 6...... 87 A.2.3 Building a VxWorks 6 Application...... 88 Building from Workbench...... 88 Building from GNAT Studio...... 88 RTPs and kernel modules...... 89 A.2.4 SMP Support...... 90 A.2.5 Using the VxWorks 6 Simulator...... 91 A.2.6 Debugging an Application on VxWorks 6...... 92 Using Workbench DFW...... 92 Using GNAT Studio and GDB...... 92 A.2.7 Known GNAT C++ Limitations on PowerPC VxWorks 6...... 94 A.3 Workbench / VxWorks 7 Topics...... 95 A.3.1 Using GNAT for VxWorks 7...... 95 A.3.2 Building a VxWorks 7 Application...... 95 Building a VxWorks 7 Application from Workbench...... 96 Building a VxWorks 7 Application from GNAT Studio...... 96 VxWorks 7 RTPs and kernel modules...... 96 A.3.3 VxWorks 7 SMP Support...... 98 A.3.4 Debugging an Application on VxWorks 7...... 98 A.3.5 Using VxSim on VxWorks 7...... 98 A.3.6 Known GNAT C++ Limitations on VxWorks 7...... 99 A.4 VxWorks 653 Topics...... 99 A.4.1 Introduction...... 99 A.4.2 Configuring a VxWorks 653 System...... 100 Application Configuration Files...... 100 Partition Makefiles...... 103 A.4.3 Running and Debugging Applications...... 104 VxWorks 653 System Setup...... 105

GNAT User’s Guide Supplement for Cross Platforms 7 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

Environment Setup...... 106 GNAT Studio Setup...... 106 Debugging a Partition...... 106 Debugging Multiple Partitions...... 107 System Mode Debugging...... 107 Commands Specific to VxWorks 653...... 107 A.4.4 Application Design Considerations...... 108 General Application Structure on VxWorks 653...... 108 The ARINC-653 APEX Binding...... 108 Selection of a Run-Time Profile...... 111 Replacement of the Default Last Chance Handler...... 111 Process-Level Health Monitoring Handler...... 112

B LynxOS-178 Topics 113 B.1 Getting Started...... 113 B.2 Kernel Configuration...... 114 B.3 Debugging...... 114 B.3.1 Debugging Example...... 115

C Bareboard Topics 117 C.1 Introduction...... 117 C.2 Bareboard Run-Time Libraries...... 117 C.2.1 Generic bareboard Light run-times...... 118 C.3 Getting Started with the Bareboard Toolchain...... 118 C.4 Minimizing Object Code and Data Sizes...... 119 C.5 Viewing Object Code and Data Sizes...... 119 C.6 Stacks...... 120 C.7 Character Input/Output...... 120 C.8 Floating-Point Support...... 121 C.9 Dynamic Memory Allocation...... 122 C.10 Bareboard Debugging...... 122 C.11 Non-Symbolic Traceback...... 122

D Customized Bareboard Run-Time Libraries 125 D.1 Rationale for A New Run-Time Library...... 126 D.1.1 Hardware Considerations...... 126 D.1.2 Software Considerations...... 126 D.2 The Run-Time Library Structure...... 127 D.3 Building A Run-Time Library...... 127 D.3.1 Building...... 127 D.3.2 Choosing the Location...... 128 D.4 Example: Creating An STM32F429 Run-Time...... 129 D.4.1 Initial Library Creation...... 129 D.4.2 Tailoring the Library...... 130 Changing Clock Frequency...... 130 Tailoring the Memory Layout...... 131 Selecting Scripts...... 132 Increased Heap Size...... 133 Configuring Interrupts...... 133 Interrupt Priorities...... 134 Startup Code...... 135 Floating-Point Co-processor...... 136 D.4.3 Augmenting the Library...... 136

E ARM-ELF Topics and Tutorial 139

8 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

E.1 Supported Processors and Run-Time Libraries...... 139 E.1.1 Generic core runtimes...... 139 E.1.2 runtimes...... 139 E.2 Getting Started...... 140 E.2.1 Getting Started with the STM32F429-Discovery...... 141 E.2.2 Host Setup...... 142 E.2.3 Opening the Led_Flasher Project...... 142 E.2.4 Building...... 143 E.2.5 Running the Program...... 143 E.2.6 Debugging the Program...... 143 Debugging Walkthrough...... 144 E.3 Changing Time Resolution...... 145 E.4 Target Restrictions...... 146 E.4.1 Task Priority Restriction...... 146 E.5 Debugging...... 146 E.5.1 Debugging with GNAT Studio...... 146 E.5.2 ST Microelectronics Discovery Kits...... 147 Automatic Board Reset For Debugging...... 148 Troubleshooting...... 149

F ARM AArch64-ELF Topics 151 F.1 Supported Processors and Run-Time Libraries...... 151 F.2 Getting Started with the UltraZed and GNAT...... 152 F.2.1 Preparation...... 152 GNAT installation...... 152 Hardware Platform Specification...... 152 F.2.2 Gnatbench Installation...... 152 F.2.3 Create an Ada Project...... 153 F.2.4 Run/Debug the Application...... 153 -based Debugging...... 153 On-board Debugging...... 154 F.3 Resources used by the runtime...... 154 F.4 Memory mapping...... 154 F.5 Boot...... 155 F.6 Debugging...... 155 F.6.1 Halting time when debugging...... 155 Xilinx Zynq Ultrascale+...... 155

G AVR-ELF Topics 157 G.1 Introduction to GNAT Pro for AVR-ELF...... 157 G.2 Compiler and Linker Flags for AVR-ELF...... 157 G.3 Getting Started...... 158 G.3.1 Getting started with GNATemu...... 158 G.3.2 Building...... 158 G.3.3 Running the Example...... 159 G.3.4 Debugging the Example...... 159

H LEON3 Topics 161 H.1 Supported Processors and Run-Time Libraries...... 161 H.2 Getting Started...... 161 H.3 Executing and Debugging on ...... 162 H.4 Executing and Debugging on Hardware Platforms...... 162 H.5 SMP Support...... 163 H.6 Adapting the Run-Time System...... 163

GNAT User’s Guide Supplement for Cross Platforms 9 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

H.7 LEON3FT RETT Restart Errata...... 164 H.8 Console Output...... 164

I RISC-V 32-Bit Topics and Tutorial 165 I.1 Supported Processors and Run-Time Libraries...... 165 I.1.1 Generic core runtimes...... 165 I.1.2 Microcontroller runtimes...... 165 I.2 Getting Started...... 166 I.2.1 Getting Started with GNATemulator...... 166 I.2.2 Creating a new Project...... 166 I.2.3 Building...... 167 I.2.4 Running the Program...... 167 I.2.5 Debugging the Program...... 167

J RISC-V 64-Bit Topics and Tutorial 169 J.1 Supported Processors and Run-Time Libraries...... 169 J.1.1 Generic core runtimes...... 169 J.1.2 Processor runtimes...... 169 J.2 Getting Started...... 170 J.2.1 Getting Started with GNATemulator...... 170 J.2.2 Creating a new Project...... 170 J.2.3 Building...... 171 J.2.4 Running the Program...... 171 J.2.5 Debugging the Program...... 171

K x86_64 ELF Topics 173 K.1 Supported Processors and Run-Time Libraries...... 173 K.1.1 Required CPU Features...... 173 K.1.2 Running a x86_64-elf Application...... 174 GNATemulator...... 174 Multiboot...... 174 LynxSecure...... 174 K.1.3 Serial I/O...... 175 K.1.4 Clock Speed...... 175 K.1.5 Interrupts...... 175 K.1.6 Memory Layout...... 176 K.2 Getting Started...... 176 K.2.1 Getting Started with GNATemulator...... 176 K.2.2 Creating a new Project...... 177 K.2.3 Building...... 177 K.2.4 Running the Program...... 177 K.2.5 Debugging the Program...... 177

L Cross Topics 179 L.1 Building a Cross Linux Application...... 179 L.2 Debugging an Application on Cross Linux...... 180

M PikeOS Topics 183 M.1 Kernel Configuration for PikeOS...... 183 M.1.1 Creating a PikeOS kernel integration project...... 183 M.1.2 PikeOS maximum priority setting...... 183 M.1.3 PikeOS interrupts...... 184 M.1.4 PikeOS muxa configuration...... 184 M.2 Building an Ada application on PikeOS...... 184 M.3 Running an Ada application on PikeOS...... 185

10 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

M.4 Debugging an Ada application on PikeOS...... 185

N iOS Topics 189 N.1 Prerequisites...... 189 N.2 Preparing Your Ada Project for Xcode Integration...... 189 N.3 Integrating Your Ada Project into Your App...... 190 N.4 Running Your App on Your iOS Device...... 190 N.5 Using the iOS Simulator...... 191 N.6 Debugging Your App on Your iOS Device...... 191 N.7 Debugging Ada on the iOS Simulator...... 191

O QNX Topics 193 O.1 Getting Started...... 193 O.2 Integration with Momentics...... 194

P GNU Free Documentation License 195

Index 201

GNAT User’s Guide Supplement for Cross Platforms 11 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

12 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER ONE

ABOUT THIS GUIDE

For ease of exposition, ‘GNAT Pro’ will generally be referred to simply as ‘GNAT’ in the remainder of this document. This guide describes the use of GNAT, a compiler and software development toolset for the full Ada , in a cross compilation environment. It supplements the information presented in the GNAT User’s Guide for Native Platforms. It describes the features of the compiler and tools, and details how to use them to build Ada applications that run on a target processor. GNAT implements Ada 95, Ada 2005 and Ada 2012, and it may also be invoked in Ada 83 compatibility mode. By default, GNAT assumes Ada 2012, but you can override with a compiler switch to explicitly specify the language version. (Please refer to the section Compiling Different Versions of Ada in the GNAT User’s Guide for Native Platforms for details on these switches.) Throughout this manual, references to ‘Ada’ without a year suffix apply to all Ada 95/2005/2012 versions of the language. This guide contains some information about using GNAT in any cross environment, but the main body of the document is a set of Appendices on topics specific to the various target platforms.

1.1 What This Guide Contains

This guide contains the following chapters: • Introduction to GNAT for Cross Platforms describes GNAT for cross platforms and the key concepts behind using GNAT in a cross environment. • The Primary and Secondary Stacks describes the purposes of the two stacks and how to set their sizes. • Predefined Profiles presents the different profiles (restricted feature sets). • Predefined GNAT Pro Run-Times presents the different run-time libraries provided by GNAT Pro. • The GNAT Configurable Run-Time Facility explains how to configure the GNAT run-time library or define a specific Ada feature profile based on application requirements. • Support for Certified Systems describes both the general philosophy and specific features that relate to the use of GNAT for software that has high assurance requirements, for example for safety or security. • VxWorks Topics presents information relevant to the various VxWorks targets for cross-compilation. • LynxOS-178 Topics presents information relevant to the LynxOS-178 targets for cross-compilation configura- tions. • Bareboard Topics describes how to build, load, and run programs on a target without requiring the services of an underlying kernel. • Customized Bareboard Run-Time Libraries presents information relevant to the customization of run-time libraries on bare-board targets.

GNAT User’s Guide Supplement for Cross Platforms 13 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• ARM-ELF Topics and Tutorial describes topics specific to the use of bareboard platforms supporting ARM processors and presents a tutorial on how to build Ada applications that will run on such platforms. • ARM AArch64-ELF Topics describes topics relevant to bareboard AArch64 and also presents a tutorial on building, running, and debugging an Ada application on this platform. • LEON3 Topics presents information relevant to the LEON3 targets for cross-compilation configurations. • RISC-V 32-Bit Topics and Tutorial describes topics relevant to GNAT for bareboard 32-bit RISC-V and also presents a tutorial on building, running, and debugging an Ada application on this platform. • RISC-V 64-Bit Topics and Tutorial describes topics relevant to GNAT for bareboard 64-bit RISC-V and also presents a tutorial on building, running, and debugging an Ada application on this platform. • x86_64 ELF Topics describes topics relevant to GNAT for bareboard 64 and also presents a tutorial on building, running, and debugging an Ada application on this platform. • Cross Linux Topics presents information relevant to the Cross Linux targets for cross-compilation configurations. • PikeOS Topics presents information relevant to PikeOS targets for cross-compilation configurations. • iOS Topics describes how to set up a project for deployment on iOS devices, how to use GNAT Pro for iOS to include Ada code in an app, and how to build and deploy the app on the iOS simulator. • QNX Topics presents information relevant to QNX targets for cross-compilation configurations.

1.2 What You Should Know before Reading This Guide

This user’s guide assumes a basic familiarity with the Ada 95 language, as described in the International Standard ISO/IEC-8652:1995, January 1995. It does not require knowledge of the new features introduced by Ada 2005, (officially known as ISO/IEC 8652:1995 with Technical Corrigendum 1 and Amendment 1) or the features added by Ada 2012. All Ada reference manuals are included in the GNAT documentation package. This user’s guide also assumes that you are familiar with the GNAT User’s Guide for Native Platforms, and that you know how to use GNAT on a native platform.

1.3 Related Information

For further information about Ada and related tools, please refer to the following documents: • Ada 95 Reference Manual, Ada 2005 Reference Manual, and Ada 2012 Reference Manual, which contain reference material for the several revisions of the Ada language standard. • GNAT Reference_Manual, which contains all reference material for the GNAT implementation of Ada. • Using GNAT Studio, which describes the GNAT Studio Integrated Development Environment. • GNAT Programming Studio Tutorial, which introduces the main GNAT Studio features through examples. • Debugging with GDB, for all details on the use of the GNU source-level debugger.

14 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

1.4 Conventions

Following are examples of the typographical and graphic conventions used in this guide: • Functions, utility program names, standard names, and classes. • Option flags • File names • Variables • Emphasis • [optional information or parameters] • Examples are described by text

and then shown this way.

• Commands that are entered by the user are shown as preceded by a prompt string consisting of the $ character followed by a space. • Full file names are shown with the ‘/’ character as the directory separator; e.g., parent-dir/subdir/ myfile.adb. If you are using GNAT on a Windows platform, please note that the ‘\’ character should be used instead.

Contents 15 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

16 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER TWO

INTRODUCTION TO GNAT FOR CROSS PLATFORMS

Cross platforms are where the compiler toolchain produces binaries for a target that is not the same as the host. For GNAT, there are two types of cross platforms: cross targets and bareboard targets. Cross targets are where the target has an embedded like VxWorks or Linux. Bareboard targets are those where the run-times do not depend on operating system services and can run directly on top of the processor. GNAT distinguishes the two kinds of targets because there differences between the two in workflow and customizability of the run-time libraries. The general workflow for GNAT for cross platforms is similar to GNAT for native platforms, primarily through the support provided through the GNAT project facility. To begin using GNAT with cross platforms, it’s important to understand the naming of the tools provided, and how to specify the target and run-time library in GNAT projects.

2.1 Toolchain for Cross Platforms

Most of the tools described in the GNAT User’s Guide for Native Platforms are available for use on cross platforms. The major difference is that the name of the cross tools includes the name of the target. For instance, the cross gcc tool is invoked as -gcc, where stands for the name of the cross target. Thus, in an environment configured for the target arm-elf, the gcc command is arm-elf-gcc. This convention allows the installation of a native and one or several cross-development environments on the same machine. An exception to this is the GPRbuild tools, which are not prefixed by target, as they are target-independent tools. The rest of this manual generally refers to the tools with their simple native names (e.g., gcc) when describing their generic functionality, and with their full cross names (e.g., -gcc) when describing their invocation. Note: Bareboard platforms no longer include the older -gnatmake builder. The newer multilingual builder GPRbuild is used instead. gnatmake is still available for real-time operating system targets (e.g., VxWorks).

2.2 Specifying the Target

When using the GNAT Project facility, there are two ways to specify the target to use: via the GPR project file or a command-line switch. The recommended approach is to specify the target within a project file using the Target attribute:

project Demo is ... for Target use "arm-eabi"; ... end Demo;

On the command line, you can use the –target switch to specify the run-time library. For example, the following shows an invocation of gprbuild for an ARM target:

GNAT User’s Guide Supplement for Cross Platforms 17 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

$ gprbuild --target=arm-eabi -P demo_leds.gpr

The names for the targets vary with the architecture of the intended platform, and are documented in their specific sections. Note that the names are reflected in the names of the cross-development versions of the AdaCore tools.

2.3 Specifying the Run-Time Library

The cross and bareboard compilers provide a set of run-time libraries offering subsets of the Ada language for different use cases. These run-time libraries differ by target and are documented in the corresponding target-specific sections They may be selected via an attribute in the project’s GPR project file or as a command-line switch to GPRbuild. The contents of a run-time library is located in a folder with that library name (see Customized Bareboard Run-Time Libraries for those files and directories). If the library is installed in the default compiler toolchain location, the library can be specified as a simple name. Otherwise, you must specify an absolute or relative to the named run-time library directory. The recommended approach is to specify the run-time library through the project file using the Runtime attribute: project Demo is ... for Runtime("Ada") use "embedded-tms570"; ... end Demo;

Note the inclusion of the language name as the index to the attribute. On the command line, you can use the –RTS= switch to specify the run-time library name.

2.4 GNAT C/C++ for Cross Platforms

2.4.1 Supported C++ Version

Unless explicitly documented otherwise for a given platform, the most recent version of C++ supported by GNAT is C++-17.

2.4.2 Mixed-Language Programming using GNAT Exclusively

For mixed Ada and C/C++ projects built using both GNAT (Ada) and GNAT C++, the GNAT (Ada) and GNAT C++ must have matching versions, and must both be installed at the same location. In that configuration, both GNATbench and GPRbuild may be used to build mixed Ada and C/C++ applications. When compiling a mixed-language project, GNATBench or GPRbuild will insert the relevant includes and switches automatically. For GPRbuild, the first C/C++ compiler on the path will be selected; consequently, to use GNAT C and/or GNAT C++ to compile C/C++ code, ensure that this compiler appears on the path before the VxWorks compilers, or select it explicitly using GPRconfig. The compiler selection happens automatically when using GNATBench.

18 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER THREE

THE PRIMARY AND SECONDARY STACKS

This chapter covers the primary and secondary stacks, explaining their purposes and how to control their sizes.

3.1 The Primary Stack

In GNAT, each user-defined task (if any) has a dedicated primary stack, as does the language-defined “environment task” that ultimately calls the main subprogram. At run time, this primary stack is used by the compiler-generated code for several purposes, including representing subprogram calls. Each subprogram call typically represents a new entry on the stack, popped when the call returns. In addition, the stack is used for subprogram calls to pass data for the parameters, including the results of calls to functions that return values of constrained types. The stack is used for other purposes as well.

3.1.1 The Default Primary Stack Size

Applications vary widely, including, for example, the depth to which subprograms call each other, so the required size of each primary stack is application dependent. Therefore, the default stack sizes provided by the implementation for the environment task and for application-defined tasks may or may not suffice. In GNAT the same default value is applied to both the environment task and to application-defined tasks. The default primary stack size is determined by the underlying operating system, or in the case of bareboard targets by the specific run-time library. For bareboard targets, the default stack size varies across specific platforms because different classes of target boards will have different ranges of RAM available. For example, the Stellaris LM3S board, with a Cortex-M3 MCU, has a default stack size of 2K in GNAT, whereas the STM32F4 targets have Cortex-M4 MCUs and a 4K default stack size. You can determine the default primary stack size for a given bareboard run-time library by examining the linker scripts used to lay out memory. These files are located in the run-time library’s (BSP) files. On the ARM STM32 targets, for example, in common-RAM.ld the following declaration appears near the top

_DEFAULT_STACK_SIZE=4 *1024; whereas for the LM3S (in lm3s-ram.ld) a different value is specified

_DEFAULT_STACK_SIZE=2 *1024;

In all cases the name is the same, only the name of the linker script file varies.

GNAT User’s Guide Supplement for Cross Platforms 19 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

3.1.2 Per-Task Primary Stack Size

The primary stack size for a task object can be specified either on the type declaration, if explicitly defined, or directly on the task object declaration. To do so, use the Storage_Size aspect (or pragma). For example, the following code defines a task type with a primary stack size of 20KB:

task type My_Task_Type with Storage_Size => 20 * 1024;

Every task object of that type will have that primary stack size. For an anonymously-typed task object:

task My_Task with Storage_Size => 20 * 1024;

That one task object will then have that primary stack size. If you want to have a task type that does not apply the same stack size to every object of the type, you can use a discriminant:

task type My_Task_Type(Primary_Stack: Positive) with Storage_Size => Primary_Stack;

Each task object will specify a value for the Primary_Stack discriminant, thereby defining the primary stack size for that individual object:

T1: My_Task_Type(Primary_Stack => 20 * 1024); T2: My_Task_Type(Primary_Stack =>4 * 1024);

3.1.3 Environment Task Primary Stack Size

The application environment task is “created” by the target environment. Therefore, everything required for the environment task’s execution, including the primary stack size, must be known before the application starts. For non-bareboard targets, refer to your operating system’s manual. For bareboard targets, the mechanism for specifying the environment task’s primary stack size is implementation- defined. In GNAT, there are two ways to do so: • Edit the default value in the linker script • Specify the default using a linker switch when building You can change the linker script to specify a different value for the _DEFAULT_STACK_SIZE symbol. The new default will be applied whenever the corresponding run-time library is linked with an application. The same default will be used in each build. If, however, you do not want to use the same default, even if you have changed the default in the run-time library, you can specify the different primary stack size using a linker switch. Thus the difference will be project-specific (or even invocation-specific) rather than specific to the individual run-time library. The linker switch is of the form "-Wl,--defsym=__stack_size=x" where X is is the number of bytes required. The value can be either in decimal or (with a leading “0x”). For example, to set a primary stack size of 20K bytes the switch would be, in decimal: "-Wl,--defsym=__stack_size=20480"

20 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

or, in hexadecimal: "-Wl,--defsym=__stack_size=0x5000" Note how the switch defines the __stack_size symbol, which is used inside the linker scripts (e.g., common-RAM.ld). If that symbol is defined the corresponding value is used instead of that of the default symbol. Although you can add the switch to an invocation of the builder on the command line (using the -largs switch), we suggest more permanently specifying it in the project file, like so:

package Linker is for Default_Switches("ada") use ("-Wl,--defsym=__stack_size=20480"); end Linker;

Note that there are no spaces anywhere within the string. However you specify it, if the primary stack size value is too large the builder will not create the image.

3.2 The Secondary Stack

GNAT returns objects from functions via registers (if small) or via the primary stack. For the latter, the caller of the function typically allocates space for the return object on its primary stack before the call. However, Ada allows functions to return objects of unconstrained types, for example unbounded array types such as String, and unconstrained discriminated record types. In this case the caller does not know the size of the returned object at the point of the call. To resolve this problem, GNAT provides each task with a secondary stack that objects of unconstrained types are returned on. On native and cross targets using the full run-time, the secondary stack by default is allocated dynamically on the heap. For cross and bareboard platforms, where stack sizes are fixed, secondary stacks are statically allocated and cannot grow at run time. In both cases the secondary stack is allocated independently from the primary stack.

3.2.1 Fixed Secondary Stack Allocation

Secondary stack allocation on Light, Light-Tasking and Embedded run-times is fixed as they do not permit dynamic allocation of memory by the run-time. For these targets, the secondary stack is allocated statically at bind time using the default size given by the System.Parameters.Runtime_Default_Sec_Stack_Size parameter. This default value can be changed using the gnatbind -D switch if a more suitable value is required. For example, to specify a default secondary stack size of 20KB for all tasks:

gnatbind-D20k main.ali

Like all gnatbind switches, the -D switch can be included in the binder section of a project file. The default secondary stack size can be overridden on a per-task basis if individual tasks have different secondary stack requirements. This is achieved through the Secondary_Stack_Size aspect that takes the size of the secondary stack in bytes. For example, to specify a 20KB secondary stack for the task A_Task:

task A_Task with Secondary_Stack_Size => 20 * 1024;

Contents 21 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

3.2.2 Dynamic Secondary Stack Allocation

Dynamic secondary stack allocation allows GNAT to size the secondary stack to the needs of each task at run time without input from the developer and is used by default on the full GNAT run-time used by native and many cross targets. The size the secondary stack can grow to is limited by the amount of free heap space on the target. The initial memory allocated to the secondary stack is governed by the parameter System.Parameters. Runtime_Default_Sec_Stack_Size and grows in increments of this value unless an object larger than this value needs to be placed on the stack. In this case, the stack will grow by the size of the object. The value of Runtime_Default_Sec_Stack_Size is suitable for nearly all applications, balancing the number of heap allocations required during the life of the stack against stack fragmentation. However, if the default allocation size is unsuitable, it can be modified via the gnatbind -D switch. Per-task increment sizes can also be specified via the Secondary_Stack_Size aspect:

task A_Task with Secondary_Stack_Size => 20 * 1024;

In certain circumstances there can be a performance benefit by increasing the default secondary stack size to reduce the number of memory allocations performed by the secondary stack. These situations include string operations within a loop that cause a string to grow on each iteration. In this case it is advised to set the secondary stack size for the task performing the operation (or the default secondary stack size) to the expected final size of the string in question.

3.2.3 Disabling the Secondary Stack

The secondary stack can be disabled by using pragma Restrictions (No_Secondary_Stack); This will cause an error to be raised at for each call to a function that returns an object of unconstrained type. When this restriction is in effect, Ada tasks (excluding the environment task) will not have their secondary stacks allocated.

22 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER FOUR

PREDEFINED PROFILES

GNAT Pro supports two language defined profiles: Ravenscar and Jorvik. These profiles provide subsets of Ada’s tasking capabilities suitable for embedded or certification applications. This section provides a brief introduction to these profiles.

4.1 The Ravenscar Profiles

The Ravenscar profile defines a subset of tasking features suitable for use in applications having extremely demanding requirements. The profile is a part of the Ada programming language and is defined by the language standard in section D.13 of the Real-Time Systems annex. The profile is intended to support four application domains: • hard real-time applications requiring predictability, • safety-critical applications requiring formal certification, • high-integrity applications requiring formal verification, and • embedded applications requiring small and low execution overhead. The resulting tasking subset is designed to be small enough to allow efficient and analyzable run-time libraries, but large enough to permit programming styles needed in practice for all these domains. For details of using the Ravenscar profile, including what the subset allows and excludes, see Guidance for the use of the Ada Ravenscar Profile in high integrity systems, ISO/IEC Technical Report 24718.

4.2 The Jorvik Profile

In addition to the Ravenscar tasking profile, GNAT supports the Jorvik (pronounced “yourvick”) profile, a new tasking profile in the Ada 202x language standard. Jorvik is the standardization of the older GNAT_Extended_Ravenscar profile. The latter profile name remains in GNAT as an alias to the Jorvik profile for compatibility with existing applications. The Jorvik profile relaxes certain Ravenscar profile restrictions in order to increase expressive power for applications in the hard real-time and domains. Applications exclusively in these two domains typically do not require the formal certification and verification analyses imposed by the other Ravenscar domains. As a result, the new profile allows an underlying tasking run-time library implementation that, although somewhat more complex, remains small and efficient. However, for those applications requiring the most rigorous forms of analysis, i.e., those required for certification, the Ravenscar profile remains the best choice.

GNAT User’s Guide Supplement for Cross Platforms 23 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

GNAT Pro provides a number of run-time libraries providing the Jorvik tasking subset, with differing subsets of the remaining sequential language supported. The following sections describe the Jorvik profile included in these run- times. Anything not specified as removed or altered from the Ravenscar profile remains unchanged in the Jorvik profile.

4.2.1 Number of Entries Per Protected Object

The Jorvik profile does not specify a value for Max_Protected_Entries. As a result, multiple entries per protected object are allowed. Note that this change also allows entry families to have more than one member.

4.2.2 Number of Queued Callers per Entry

The Jorvik profile does not specify Max_Entry_Queue_Length. As a result, multiple callers can be queued on any given protected entry, rather than only one at a time. Task entries remain disallowed. Note that any protected object containing protected entry declarations can specify, for each entry, the maximum number of callers allowed. This maximum number is checked at runtime, if specified, and can be used to compute a less pessimistic WCET off-line. Specification of the maximum value is optional. The maximum value is specified via the language standard aspect or pragma Max_Queue_Length applied to that entry. (Max_Queue_Length is defined independent of Jorvik.) The value must be a static (positive) integer value. For example: protected type P is

entry A(Item: Integer) with Max_Queue_Length =>2;

entry B(Item: Integer); pragma Max_Queue_Length(X); private ... end P;

4.2.3 Entry Barriers

The Jorvik profile does not specify Simple_Barriers. Instead, the new language-standard restriction “Pure_Barriers” is applied automatically. As a result, in addition to simple Boolean local variables, more complex Boolean expressions are allowed. However, these expressions are still limited in content so that side effects, exceptions, and recursion are impossible. Removing the possibility of side effects is important because the language does not specify the number of times a given barrier is evaluated. Allowing exceptions would complicate the implementation, whereas the goal is an efficient and predictable run-time library implementation that minimizes barrier evaluation cost. Specifically, “Pure_Barriers” allows the following: • References to components of the protected object • References to discriminants of the protected object • Numeric literals

24 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• Enumeration (and thus character) literals • Named numbers • Predefined relational operators • Predefined logical operators (“and”, “or”, “xor”, “not”) • Short-circuit control forms (“and then”, “or else”) • Membership tests • Conditional expressions • The Count attribute The list above is a general description intended to give an idea of the enhancements. Several of the above have restrictions. See the Ada 202x draft Reference Manual description for precise details (section D.7 “Tasking Restrictions” specifically.) Note that the Count attribute is allowed in the barriers for protected entries (and protected entry families), not just within entry bodies as in Ravenscar.

4.2.4 Relative Delay Statements

The Jorvik profile does not specify No_Relative_Delay. As a result, both relative and absolute delay statements are allowed. Although relative delay statements are not appropriate for expressing cyclic behavior, there are cases in which a relative delay has precisely the required semantics. For example, a relay may have a requirement that it not be actuated more than N times per second. A relative delay after each actuation directly implements that requirement.

4.2.5 Additional Non-Tasking Restrictions Removed

Some Ravenscar restrictions are not related to tasking and can be relaxed without affecting timing analysis and space/speed performance.

No_Implicit_Heap_Allocations

The Jorvik profile does not specify No_Implicit_Heap_Allocations. This restriction is in the standard Ravenscar profile for the sake of the other domains and need not be applied when focusing on real-time and embedded systems. (Note that users can specify this restriction in their application code if they want the restriction to apply.) Instead, the No_Implicit_Heap_Allocations restriction has been replaced by No_Implicit_Task_Allocations and No_Implicit_Protected_Object_Allocations.

No Dependence on Ada.Calendar

The Jorvik profile removes the restriction prohibiting use of the Ada.Calendar package. This restriction is present in standard Ravenscar because the Ada.Real_Time package has more appropriate semantics for real-time/embedded applications. However, not all usage of Ada.Calendar is unreasonable, for example time-stamping log messages.

Contents 25 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

26 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER FIVE

PREDEFINED GNAT PRO RUN-TIMES

The Standard GNAT Pro Ada run-time supports the full core Ada Language and numerous Appendixes as documented in the GNAT Reference Manual. While suitable for a large range of applications, there are certain applications and targets where the Standard GNAT Pro Ada run-time is not appropriate. This may be due to certification requirements, limitations of the underlying , or target specific restrictions. To address these needs, GNAT Pro provides additional predefined run-times suitable for applications and targets that can only utilize a subset of the Standard GNAT Pro Ada run-time. Depending on the capabilities of the target, GNAT Pro offers up to one of four different predefined run-time families: Light, Light-Tasking, Embedded and Standard. If required, these run-times may be customized further to meet your needs. See The GNAT Configurable Run-Time Facility for more details. This chapter presents the four predefined run-time families. For further details on the run-times supported on a particular target, please refer to the target’s Appendix for more details.

5.1 Standard Run-Time

The Standard run-time supports the core Ada Language and language Appendixes as documented in the GNAT Reference Manual. It is available for Operating System targets that can support the full capabilities of the language, for example: Linux, Windows, VxWorks and RTEMS. Depending on the target, there may be different variants of the Standard run-time to support different underlying Operating System libraries or execution environments. For example, on VxWorks there are different Standard run- time libraries for the Kernel and RTP execution environments. Please refer to the target specific appendixes for more details on the run-time libraries offered for your target.

5.2 Embedded Run-Time

The Embedded Run-Time provides a subset of the Standard Run-Time suitable for applications running on bare- metal systems and Real-Time Operating Systems that lack file I/O and networking support. It provides most of the functionality of the Standard run-time with the following limitations: • Tasking is restricted to the Jorvik and Ravenscar Profiles. • The only supported I/O is provided in the form of a simplified Ada.Text_IO package (suitable for serial communication). • No networking support. Ada or GNAT packages that depend on tasking outside of the Jorvik Profile or require file I/O and networking support are not included in the Embedded run-time.

GNAT User’s Guide Supplement for Cross Platforms 27 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

5.3 Light Run-Time

The Light run-time supports a non-tasking subset Ada suitable for certification and space-constrained embedded applications. It is provided on bare-metal, certifiable RTOSes and native targets (allowing embedded code to be tested on native platforms). The run-time provides support for: • Integer and fixed-point: – 32-bit targets: up to 64-bit types – 64-bit targets: up to 128-bit types • Floating point: – Single (IEEE binary32) and double (IEEE binary64) float support – 80-bit extended float support on – Support for floating-point attributes • Packed arrays with a component size of 1, 2, 4, 8, 16, 32, 64 bits. 128-bit packed arrays supported on 64-bit targets. • Packed arrays with static bounds whose sizes are 64-bit or less (128 bits and less on 64-bit platforms) • Assertions • Character runtime support: – Ada.Characters.Latin_1 and Ada.Characters.Handling – No support for Wide_Characters and Wide_Wide_Characters. • Ada.Numerics • Ada.Strings • Exception support limited to: – Locally handled exceptions – Last Chance Handler – (exception propagation is not supported) • Library-level tagged types • Simplified versions of Interfaces.C and it’s children • System.Bit_Ops • System.Compare_Array • Exponential operations • Foreign support • Support for ‘Image and ‘Value attributes for Scalar types • Type conversion support for Real types • Simplified Text_IO with no file I/O support • Allocators (but not Unchecked_Dellocation) • Secondary stack The following language restrictions are applied:

28 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

pragma Restrictions(No_Exception_Propagation); pragma Restrictions(No_Exception_Registration); pragma Restrictions(No_Implicit_Dynamic_Code); pragma Restrictions(No_Finalization); pragma Restrictions(No_Tasking);

While the Light Run-Time offers a wide range of functionality, applications will only include in it’s binary the run-time object files corresponding to features used by the application. This allows space-constrained embedded applications to subsets of the light run-time without having to use a customized run-time with unwanted packages removed.

5.3.1 Allocator Support

The Light run-time supports dynamic memory allocation on the heap via Ada’s allocators. However, deallocation is not supported and is implemented as a no-op, with the rationale being that with certifiable software dynamic memory allocation is performed at most once, at startup, so freeing the memory is unnecessary. This restriction allows a simple, efficient, and predictable behavior for memory allocation, and is a strategy implemented on certifiable operating systems. For bare-metal run-times, the allocation mechanism relies on the __heap_start and __heap_end symbols to delimit the memory area that can be allocated. These symbols are defined by the linker script used for the specific board being targeted. For operating-system-based run-times the heap routines are provided by the underlying operating- system. If required, the dynamic memory support can be replaced with application specific code (for example, to support memory deallocation). This is done by implementing the following functions in your application in Ada:

type Pointer is access Character; -- This is really a void pointer type, the result from -- Gnat_Malloc will always be maximally aligned.

function Gnat_Malloc(size: Interfaces.C.size_t) return Pointer; pragma Export(C, Gnat_Malloc, "__gnat_malloc"); procedure Gnat_Free(Ptr: Pointer); pragma Export(C, Gnat_Free, "__gnat_free");

or in C:

void *__gnat_malloc( size_t size); void __gnat_free( void *ptr);

5.3.2 Certification

The Light run-time is certifiable and certification evidence can be obtained by contacting AdaCore sales. If a limited number of run-time units are used by your application it is possible to certify these units as part of your application. You can produce a run-time that contains only these run-time units by customizing a Light-based run-time as documented in Customized Bareboard Run-Time Libraries

Contents 29 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

5.3.3 Excluding the Run-Time Library

In a certification context it may be required that no external library is linked with the final application image. This can be achieved by using the builder switch -nostdlib. GPRBuild will pass this switch to the binder and to the linker, resulting in the application not being linked with the run-time and compiler support libraries libgnat.a and libgcc.a. By excluding the run-time library, an application may not • Reference entities from run-time packages, for example Ada.External_Tag; • Use pragma Assert; • Use the following floating-point attributes: – Adjacent, – Ceiling, – Compose, – Copy_Sign, – Exponent, – Floor, – Fraction, – Leading_Part, – Machine, – Machine_Rounding, – Model, – Pred, – Remainder, – Rounding, – Scaling, – Succ, – Truncation, – Unbiased_Rounding (with nonstatic arguments), and – Valid (with any argument); • Use the secondary stack (this can be enforced by including pragma Restrictions(No_Secondary_Stack); and • Use of floating-point or other arithmetic operations that are too complex for and that therefore require calls to a support library.

30 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

5.3.4 Exceptions and the Last Chance Handler

The No_Exception_Propagation restriction is applied to applications using the Light run-time, disallowing the use of exception propagation within the application. This is done on the Light run-time to simplify run-time implementation and certification. While exception propagation is disallowed, language and user-defined exceptions can still be raised and handled locally within subprograms. Unhandled exceptions will result in the Last Chance Handler being called. The Last Chance Handler provides the ability for the application to safely shutdown or reset as a result of an unhandled exception; it is not possible for the application to resume after the Last Chance Handler is called. The Light run-time provides a default Last Chance Handler implementation that prints the exception name and the line number of the Ada source code that raised the exception. This handler can be replaced in your application by implementing an Ada procedure with the following procedure declaration:

procedure Last_Chance_Handler (Source_Location: System.Address; Line: Integer); pragma Export(C, Last_Chance_Handler, "__gnat_last_chance_handler");

Alternatively, the handler may be implemented in C using the following C function:

void __gnat_last_chance_handler( char *source_location, int line);

The Source_Location parameter is a C null-terminated string representing the source location of the raise statement, as generated by the compiler, or a zero-length string if pragma Suppress_Exception_Locations is used. The Line parameter, when nonzero, represents the line number in the source. When Line is zero, the line number information is provided in Source_Location itself. See Exceptions for details on providing an application-specific Last Chance Handler.

5.4 Light-Tasking Run-Time

The Light-Tasking run-time provides the functionality of the Light profile with additional support for Ravenscar tasking as defined by the Ravenscar Profile. It is offered on all bare-metal and certifiable RTOSes targets. Please refer to The Ravenscar Profiles for details about the capabilities offered under the Ravenscar Profile. For the non-tasking aspect of the Light-Tasking run-time the information in Light Run-Time applies, with the exception that the Light-Tasking run-time applies the following restrictions:

pragma Restrictions(No_Exception_Propagation); pragma Restrictions(No_Exception_Registration); pragma Restrictions(No_Implicit_Dynamic_Code); pragma Restrictions(No_Finalization); pragma Profile(Ravenscar);

Contents 31 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

5.5 Specifying a Run-Time

By default, GNAT Pro tools will use the Standard GNAT Pro run-time if supported on the target. In all other cases you will need to specify the name of the run-time library to gnatbind and other GNAT tools that needs to be aware of the run-time configuration. You choose a particular run-time through one of two approaches: • With the Runtime attribute in a project file (the recommended technique); or • With the --RTS= switch. For predefined run-times shipped with GNAT Pro, the value provided to the --RTS= switch or Runtime` attribute is the name of the chosen run-time library. Non-Standard run-times will include the run-time family in their name (e.g.: light) and may include a board or target specific identifier. Customized run-times can be referred to using the same approach if they are installed in the same location as the predefined run-times. Alternatively, you can use the the full or relative path to the folder containing the run-time library. For example, to use the Light-Tasking run-time for the ST STM32F4, you would add to your project file the following (note the necessary inclusion of the language name as index):

project Demo is ... for Runtime("Ada") use "light-tasking-stm32f4"; ... end Demo;

32 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER SIX

THE GNAT CONFIGURABLE RUN-TIME FACILITY

This chapter documents the configurable GNAT run-time facility. This facility enables versions of the GNAT run-time library to be created that only provide support for subsets of the Ada language for applications where run-time support for the full language is not appropriate or possible. This chapter is of interest to users who need to port the GNAT run-time to a new operating system or need to tailor one of the existing run-times to better suit their requirements.

6.1 Standard Run-Time

The standard GNAT run-time library provides all the features specified by the Ada Reference Manual and described in the GNAT Reference Manual. This run-time library is included on all native and most cross targets, and cannot be modified. If the compiler detects that the run-time library lacks interfaces for required language features, then the run-time library is considered to be improperly configured or installed, and an error message is given. Do note that when a program is statically linked against the standard GNAT run-time library, only the sections of the library required by that program will be included. Nevertheless, keep in mind that these sections may contain a significant amount of code that may not be directly required by the applications.

6.2 The Configurable Run-Time

The Configurable Run-Time capability allows the creation of customized run-time libraries that support only a subset of the full Ada language. There are several reasons for providing the ability to configure the GNAT run-time library: • The underlying operating system may not provide the necessary features to support particular aspects of the language. • For embedded systems with tight memory constraints, it permits finer control on the size of the run-time library than what the linker can achieve. This is achieved by removing components that are not used by that application or replacing them with components that are better suited for the target environment. • For certification applications where the run-time units are required to be certifiable, since the certification process may require significant resources, it is desirable to reduce this certification effort by minimizing the run-time. Using the configurable run-time capability, you can choose any level of support from the full run-time library to a minimal run-time that requires no run-time code at all. The units included in the library may be either a subset of the standard units provided with GNAT Pro, or they may be specially tailored to the application. Note that if you only require a subset of the Ada language and do not fit into the above scenarios, you can restrict the features of the language available to your application through the Restrictions pragma defined in the Ada Reference Manual.

GNAT User’s Guide Supplement for Cross Platforms 33 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

6.3 Run-Time Libraries and Objects

The GNAT run-time library implements the semantics of Ada that cannot be generated by the compiler alone or where it would not be feasible to. The complexity of the run-time library depends on features used and the operating capabilities. In addition to the GNAT run-time library, an Ada program may also link with the following additional libraries: • C library • Math library • Internal GCC library • Startup code GPRbuild and gnatlink automatically link these libraries and objects with the final executable, statically or dynamically depending on the target and compilation options. This behavior may be suppressed by specifying the -nodefaultlibs or -nostdlib linker options. The former switch causes the linker to not use the above libraries, while the latter switch will also not use the startup code. Be aware when either switch is used the compiler will still generate calls to functions in those libraries: it is your responsibility to provide implementations of these functions in this case. GNAT attempts to find these libraries and objects in several standard system directories plus any that are specified with the -L option or the LIBRARY_PATH . The gcc --print-search-dirs command prints the name of the configured installation directory and a list of program and library directories where gcc will search. The following sections define the contents and purpose of the various elements potentially included in an application’s executable.

6.3.1 GNAT Run-Time Library

The high abstraction level and expressiveness provided by the full Ada language requires a large run-time library. This library bridges the semantic gap between the high-level Ada constructs and the low-level C functions and representations available in the target system. Hence, the semantics of Ada constructs are expanded into calls to a collection of lower-level run-time constructions. An example of this is the implementation of Ada tasking. The GNAT run-time library comprises both C and Ada files. Ada packages within the GNAT run-time library implement the required Ada semantics. For native and cross targets, these Ada packages are built on top of the operating system services, typically provided through a C interface. The GNAT run-time library and user applications typically depend on the following set of libraries: • C Library (libc.a) for interfacing to operating system provided services such as the input/output system, , etc. • Math Library (libm.a) for everything related to the functionality specified in the Ada Numerics Annex. • Internal GCC Library (libgcc.a) for features such as integer and floating-point operations, and exception handling.

34 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

6.3.2 C Library

The C library is provided by the operating system and provides standard ANSI C functionality that is used by the GNAT run-time library: • Standard Utility Functions (stdlib.h) • Character Type Macros and Functions (ctype.h) • Input and Output (stdio.h) • Strings and Memory (string.h) • Wide Character Strings (wchar.h) • Signal Handling (signal.h) • Time Functions (time.h) • Locale (locale.h) For bareboard targets, there is an assumption that libc is not present. Consequently, they use modified run-time Ada packages that implemented the required functionality directly in Ada. Adapting GNAT to an operating systems that is missing any of the above will require you to either provide your own implementation of the missing routines or to modify the GNAT run-time library. This run-time modification may see the Ada packages relying on that function removed from the run-time library or replaced with an alternative non-libc-based implementation. The bareboard run-time libraries are an example of this. Note that if you chose not to link the GNAT run-time library and the C library (through the -nodefaultlibs or -nostdlib linker options) you may still need to provide implementations of the following routines:

Functionality Routines Basic memory operations memcpy, bcopy, memmove, memcmp Dynamic memory (heap) management malloc, free

6.3.3 Math Library

A complete IEEE math library is usually provided by libm.a, which includes functions that take float, double, and long-double parameters. Depending on the type used the function has a different extension. These extensions are named after their full-precision equivalents; i.e., sinf() is the single-precision version of the sin() function, and sinl() is the long-double variant. The reduced-precision functions run much faster than their IEEE-compliant double-precision counterparts, which can make some floating-point operations practical on hardware that is too weak for full double-precision computations.

6.3.4 Internal GCC Library

Internal GCC Library is a collection of internal that GCC uses to overcome shortcomings of particular machines, or to satisfy the special needs of some languages. For GNAT it provides support for numerical operations that cannot be performed natively in hardware (for example 64-bit integer arithmetic on a 32-bit processor) and exception handling. Refer to the GCC Internals manual for more information.

Contents 35 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

6.3.5 Startup and Cleanup Code

The startup and cleanup code are linked at the beginning and at the end of the executable. Their purpose is: • to provide the to the program. • to perform required program initialization (e.g., initialize hardware, reserve space for stack, zeroing the .bss section), • to bootstrap the rest of the application, and • to arrange the necessary ‘cleanup’ / finalization after program execution completes. For native and cross targets, the startup and cleanup code is typically provided by the operating system and are typically consist of assembly files named crt*.S (crt stands for ‘C Run Time’). For bareboard targets, the startup code is provided by the run-time library and may consist of a collection of assembly and Ada code. Refer to the target specific section for more details.

6.4 Run-Time Dependencies in User Code

6.4.1 Explicit with Clauses

The use of with clauses creates a dependence relationship between Ada units. This relationship is computed at compilation time and recorded in the ali file produced for each object. The final executable will contain all the objects corresponding to the units in the dependence closure of the main unit. This is the simplest and most common way of determining the required set of objects in the final application.

6.4.2 Compiler-Generated Calls to the GNAT Run-Time Library

When an Ada source file is compiled, the GNAT compiler expands high-level Ada abstractions into low-level primitives that can be converted directly into assembly. As part of this expansion, the compiler will generate calls to run-time routines that implement semantics that either rely on operating system support or that are more efficiently implemented via a run-time library. The expanded low-level representation of the original source code can be displayed in an Ada-like format using the -gnatD or -gnatG compiler switches.

6.4.3 Pragma Import

The Import aspect specifies that the designated entity is defined externally. This will cause the object file (and its dependencies) that contains the symbol to be incorporated with the program object file at link time. Be aware that using the Import aspect is not advised to import an Ada subprogram as the binder will not be able to know where this symbol comes from, and the elaboration code that the imported routine may require will not be called.

36 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

6.4.4 Back-End Generated Calls to Library Functions

The GCC back-end may generate ‘implicit’ calls to library subprograms for various reasons. Such calls are said to be implicit because they do not directly correspond to explicit subprogram invocations in the application source code. Implicit calls to library subprograms occur for several reasons: (a) Integer and floating-point operations. Some source operations require arithmetic support not available on the target hardware. (b) Run-time support for exception handling and trampolines. Some high-level constructs require low-level data structure management too complex to emit inline code for. (c) Basic memory operations. Some basic memory operations are too expensive to expand inline, e.g. large block copies or comparisons. For (a), what the compiler knows about the target hardware may depend on compilation options. For instance, -msoft-float triggers calls to library functions for floating-point operations even if the hardware has the necessary instructions available. Similarly, the -mcpu switch allows modifying the compiler’s default view of the target hardware. The functions to support (a) and (b) are located in libgcc.a, the GCC low-level run-time library built together with the compiler itself. The basic memory operations on the other hand are provided by the C library. Note that each toolchain is configured for a particular set of core cpus, and not all combinations of -mcpu or -msoft-float switches are supported. For instance, support for the e500v2 core requires a different toolchain than the default powerpc one.

6.5 How The Run Time Library Is Configured

There are three major mechanisms for tailoring the run-time library. • Use of Configuration Pragmas • Specification of Configuration Parameters • Restricting the Set of Run-Time Units These three mechanisms work together to provide a coherent run-time library that provides a well-defined subset. They allow the compiler to properly enforce the corresponding language subset, providing informative and appropriate messages if features not supported by the subset are used.

6.5.1 Configuration Pragmas

The Ada language provides configuration pragmas to constrain the language features available to a program or to specify a particular semantic behavior. While these pragmas can be specified on a per-program basis either in the program sources or in a *.adc file, they can also be specified on a run-time library basis if the run-time only supports a particular set of language features. This is achieved by placing the configuration pragmas at the start of the System package. The System package is implicitly with’ed by all packages, thus all units compiled against this run-time library will have these restrictions. The following list of configuration pragmas may be used:

pragma Detect_Blocking; pragma Discard_Names; pragma Locking_Policy(name); pragma Normalize_Scalars; (continues on next page)

Contents 37 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) pragma Queuing_Policy(name); pragma Task_Dispatching_Policy(name);

In addition, Restrictions pragmas may be used for all simple restrictions that are required to be applied consistently throughout a partition. GNAT supports all restrictions defined in the Ada Reference Manual and the implementation-defined restrictions contained within the GNAT Reference Manual. Refer to the run-time specification package s-rident.ads for a definitive list of supported restrictions. No other pragmas are allowed in package System (other than the pragma Pure for System itself which is always present).

6.5.2 Specification of Configuration Parameters

The private part of the System package defines a number of Boolean configuration switches, which control the support of specific language features. This section documents these switches.

------Run-Time Library Configuration ------

-- In configurable run-time mode, the system run-time may not support -- the full Ada language. The effect of setting this switch is to let -- the compiler know that it is not surprising (i.e. the system is not -- misconfigured) if run-time library units or entities within units are -- not present in the run-time.

Configurable_Run_Time: Boolean; -- Indicates that the system.ads file is for a configurable run-time -- -- This has some specific effects as follows -- -- The binder generates the gnat_argc/argv/envp variables in the -- binder file instead of being imported from the run-time library. -- If Command_Line_Args is set to False, then the -- generation of these variables is suppressed completely. -- -- The binder generates the gnat_exit_status variable in the binder -- file instead of being imported from the run-time library. If -- Exit_Status_Supported is set to False, then the -- generation of this variable is suppressed entirely. -- -- The routine __gnat_break_start is defined within the binder file -- instead of being imported from the run-time library. -- -- The variable __gnat_exit_status is generated within the binder file -- instead of being imported from the run-time library.

Suppress_Standard_Library: Boolean; -- If this flag is True, then the standard library is not included by -- default in the executable (see unit System.Standard_Library in file -- s-stalib.ads for details of what this includes). This is for example -- set True for the zero foot print case, where these files should not -- be included by default. -- (continues on next page)

38 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- This flag has some other related effects: -- -- The generation of global variables in the bind file is suppressed, -- with the exception of the priority of the environment task, which -- is needed by the Ravenscar run-time. -- -- The calls to __gnat_initialize and __gnat_finalize are omitted -- -- All finalization and initialization (controlled types) is omitted

Preallocated_Stacks: Boolean; -- If this flag is True, then the expander preallocates all task stacks -- at compile time. If the flag is False, then task stacks are not pre- -- allocated, and task stack allocation is the responsibility of the -- run-time (which typically delegates the task to the underlying -- operating system environment).

------Backend Arithmetic Checks ------

-- Divide and overflow checks are either done in the front end or -- back end. The front end will generate checks when required unless -- the corresponding parameter here is set to indicate that the back -- end will generate the required checks (or that the checks are -- automatically performed by the hardware in an appropriate form).

Backend_Divide_Checks: Boolean; -- Set True if the back end generates divide checks, or if the hardware -- checks automatically. Set False if the front end must generate the -- required tests using explicit expanded code.

Backend_Overflow_Checks: Boolean; -- Set True if the back end generates arithmetic overflow checks, or if -- the hardware checks automatically. Set False if the front end must -- generate the required tests using explicit expanded code.

------Control of Exception Handling ------

-- GNAT implements three methods of implementing exceptions:

-- Front-End Longjmp/Setjmp Exceptions

-- This approach uses longjmp/setjmp to handle exceptions. It -- uses less storage, and can often propagate exceptions faster, -- at the expense of (sometimes considerable) overhead in setting -- up an exception handler.

-- The generation of the setjmp and longjmp calls is handled by -- the front end of the compiler (this includes gigi in the case -- of the standard GCC back end). It does not use any back end -- support (such as the GCC3 exception handling mechanism). When -- this approach is used, the compiler generates special exception -- handlers for handling cleanups (AT-END actions) when an exception -- is raised. (continues on next page)

Contents 39 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

-- Back-End Zero Cost Exceptions

-- With this approach, the back end handles the generation and -- handling of exceptions. For example, the GCC3 exception handling -- mechanisms are used in this mode. The front end simply generates -- code for explicit exception handlers, and AT-END cleanup handlers -- are simply passed unchanged to the backend for generating cleanups -- both in the exceptional and non-exceptional cases.

-- As the name implies, this approach uses a table-based mechanism, -- which incurs no setup when entering a region covered by handlers -- but requires complex unwinding to walk up the call chain and search -- for handlers at propagation time.

-- Back-End Setjmp/Longjmp Exceptions

-- With this approach, the back end also handles the generation and -- handling of exceptions, using setjmp/longjmp to set up receivers and -- propagate. AT-END actions on exceptional paths are also taken care -- of by the back end and the front end doesn't need to generate -- explicit exception handlers for these.

-- Control of Available Methods and Defaults

-- The following switches specify whether we're using a front-end or a -- back-end mechanism and whether this is a zero-cost or a sjlj scheme.

-- The per-switch default values correspond to the default value of -- Opt.Exception_Mechanism.

ZCX_By_Default: Boolean; -- Indicates if zero cost scheme for exceptions

Frontend_Exceptions: Boolean; -- Indicates if we're using a front-end scheme for exceptions

------Duration Format ------

-- By default, type Duration is a 64-bit fixed-point type with a delta -- and small of 10**(-9) (i.e. it is a count in nanoseconds). This flag -- allows that standard format to be modified.

Duration_32_Bits: Boolean; -- If True, then Duration is represented in 32 bits and the delta and -- small values are set to 20.0*(10**(-3)) (i.e. it is a count in units -- of 20 milliseconds).

------Back-End Code Generation Flags ------

-- These flags indicate possible limitations in what the code generator -- can handle. They will all be True for a full run-time, but one or more -- of these may be false for a configurable run-time, and if a feature is (continues on next page)

40 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- used at the source level, and the corresponding flag is false, then an -- error message will be issued saying the feature is not supported.

Support_Aggregates: Boolean; -- In the general case, the use of aggregates may generate calls -- to run-time routines in the C library, including memset, memcpy, -- memmove, and bcopy. This flag is set to True if these routines -- are available. If any of these routines is not available, then -- this flag is False, and the use of aggregates is not permitted.

Support_Atomic_Primitives: Boolean; -- If this flag is True, then the back-end support GCC built-in atomic -- operations for memory model such as atomic load or atomic compare -- exchange (see the GCC manual for more information). If the flag is -- False, then the back-end doesn't provide this support. Note this flag is -- set to True only if the target supports all atomic primitives up to 64 -- bits. ??? To be modified.

Support_Composite_Assign: Boolean; -- The assignment of composite objects other than small records and -- arrays whose size is 64-bits or less and is set by an explicit -- size clause may generate calls to memcpy, memmove, and bcopy. -- If versions of all these routines are available, then this flag -- is set to True. If any of these routines is not available, then -- the flag is set False, and composite assignments are not allowed.

Support_Composite_Compare: Boolean; -- If this flag is True, then the back end supports bit-wise comparison -- of composite objects for equality, either generating inline code or -- calling appropriate (and available) run-time routines. If this flag -- is False, then the back end does not provide this support, and the -- front end uses component by component comparison for composites.

Support_Long_Shifts: Boolean; -- If True, the back end supports 64-bit shift operations. If False, then -- the source program may not contain explicit 64-bit shifts. In addition, -- the code generated for packed arrays will avoid the use of long shifts.

------Indirect Calls ------

Always_Compatible_Rep: Boolean; -- If True, the Can_Use_Internal_Rep flag (see Einfo) is set to False in -- all cases. This corresponds to the traditional code generation -- strategy. False allows the front end to choose a policy that partly or -- entirely eliminates dynamically generated trampolines.

------Control of Stack Checking ------

-- GNAT provides three methods of implementing exceptions:

-- GCC Probing Mechanism

-- This approach uses the standard GCC mechanism for (continues on next page)

Contents 41 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- stack checking. The method assumes that accessing -- storage immediately beyond the end of the stack -- will result in a trap that is converted to a storage -- error by the . This mechanism has -- minimal overhead, but requires complex hardware, -- operating system and run-time support. Probing is -- the default method where it is available. The stack -- size for the environment task depends on the operating -- system and cannot be set in a system-independent way.

-- GCC Stack-limit Mechanism

-- This approach uses the GCC stack limits mechanism. -- It relies on comparing the stack pointer with the -- values of a global symbol. If the check fails, a -- trap is explicitly generated. The advantage is -- that the mechanism requires no memory protection, -- but operating system and run-time support are -- needed to manage the per-task values of the symbol. -- This is the default method after probing where it -- is available.

-- GNAT Stack-limit Checking

-- This method relies on comparing the stack pointer -- with per-task stack limits. If the check fails, an -- exception is explicitly raised. The advantage is -- that the method requires no extra system dependent -- runtime support and can be used on systems without -- memory protection as well, but at the cost of more -- overhead for doing the check. This is the fallback -- method if the above two are not supported.

Stack_Check_Probes: Boolean; -- Indicates if the GCC probing mechanism is used

Stack_Check_Limits: Boolean; -- Indicates if the GCC stack-limit mechanism is used

-- Both flags cannot be simultaneously set to True. If neither -- is, the target independent fallback method is used.

Stack_Check_Default: Boolean; -- Indicates if stack checking is on by default

------Command Line Arguments ------

-- For most ports of GNAT, command line arguments are supported. The -- following flag is set to False for targets that do not support -- command line arguments (VxWorks and AAMP). Note that support of -- command line arguments is not required on such targets (RM A.15(13)).

Command_Line_Args: Boolean; -- Set False if no command line arguments on target. Note that if this -- is False in with Configurable_Run_Time set to True, then (continues on next page)

42 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- this causes suppression of generation of the argv/argc variables -- used to record command line arguments.

-- Similarly, most ports support the use of an exit status, but AAMP -- is an exception (as allowed by RM A.15(18-20))

Exit_Status_Supported: Boolean; -- Set False if returning of an exit status is not supported on target. -- Note that if this False in with Configurable_Run_Time -- set to True, then this causes suppression of the gnat_exit_status -- variable used to record the exit status.

------Main Program Name ------

-- When the binder generates the main program to be used to create the -- executable, the main program name is main by default (to match the -- usual Unix practice). If this parameter is set to True, then the -- name is instead by default taken from the actual Ada main program -- name (just the name of the child if the main program is a child unit). -- In either case, this value can be overridden using -M name.

Use_Ada_Main_Program_Name: Boolean; -- Set True to use the Ada main program name as the main name

------Boolean-Valued Floating-Point Attributes ------

-- The constants below give the values for representation oriented -- floating-point attributes that are the same for all float types -- on the target. These are all boolean values.

-- A value is only True if the target reliably supports the corresponding -- feature. Reliably here means that support is guaranteed for all -- possible settings of the relevant compiler switches (like -mieee), -- since we cannot control the user setting of those switches.

-- The attributes cannot dependent on the current setting of compiler -- switches, since the values must be static and consistent throughout -- the partition. We probably should add such consistency checks in future, -- but for now we don't do this.

-- Note: the compiler itself does not use floating-point, so the -- settings of the defaults here are not really relevant.

-- Note: in some cases, proper support of some of these floating point -- features may require a specific switch (e.g. -mieee on the Alpha) -- to be used to obtain full RM compliant support.

Denorm: Boolean; -- Set to False on targets that do not reliably support denormals

Machine_Rounds: Boolean; -- Set to False for targets where S'Machine_Rounds is False

(continues on next page)

Contents 43 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) Machine_Overflows: Boolean; -- Set to True for targets where S'Machine_Overflows is True

Signed_Zeros: Boolean; -- Set to False on targets that do not reliably support signed zeros

6.5.3 Restricting the Set of Run-Time Units

Many Ada language features generate implicit calls to the run-time library. For example, if we have the Ada procedure:

pragma Suppress(All_Checks); function Calc(X: Integer) return Integer is begin return X ** 4+X ** 52; end Calc;

Then the compiler will generate the following code (this is -gnatG output):

with system.system__exn_int;

function calc (x : integer) return integer is begin E1b : constant integer :=x * x; return integer (E1b * E1b+ integer(system__exn_int__exn_integer (x, 52))); end calc;

In the generated code, the compiler generates direct inlined code for X ** 4 (by computing (X ** 2) ** 2). But the computation of X ** 52 requires a call to the run-time routine System.Exn_Int.Exn_Integer (the double underlines in the -gnatG output represent dots in the name). The GNAT run-time library contains an appropriate package that provides this function:

-- Integer exponentiation (checks off)

package System.Exn_Int is .. index:: ``System.Exn_Int`` package

pragma Pure(Exn_Int);

function Exn_Integer (Left: Integer; Right: Natural) return Integer;

end System.Exn_Int;

For a configurable run-time library, the package System.Exn_Int may or may not be present. If not present, then the run-time library does not permit the use of exponentiation by large integer values, and an attempt to compile Calc will result in the following error message:

1. function Calc (X : Integer) return Integer is 2. begin 3. return X ** 4+X ** 52; | (continues on next page)

44 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) >>> construct not allowed in this configuration >>> entity"System.Exn_Int.Exn_Integer" not defined

4. end Calc;

The first line of the error message indicates that the construct is not provided in the library. The second line shows the exact entity that is missing. In this case, it is the entity Exn_Integer in package System.Exn_Int. This package is in file s-exnint.ads (you can use the command gnatkr system.exn_int.ads to determine the file name). If exponentiation is required, then this package must be provided, and must contain an appropriate declaration of the missing entity. There are two ways to accomplish this. Either the standard GNAT body can be copied and used in the configurable run-time, or a new body can be written that satisfies the specification. Rewriting the body may be useful either to simplify the implementation (possibly taking advantage of configuration pragmas provided in system. ads), or to meet coding requirements of some particular certification protocol. Alternatively, the source code can be modified to call an exponentiation routine that is defined within the application:

with Exp; function Calc(X: Integer) return Integer is begin return Exp(X,4)+ Exp(X, 52); end Calc;

6.6 Naming the Run-Time Library

To assist in keeping track of multiple run-time configurations, GNAT Pro provide a facility for naming the run-time library. To do this, include a line with the following format (starting in column 4) in system.ads:

Run_Time_Name: constant String := "Simple Run Time 1";

The name may contain letters, digits, spaces and underlines. If such a name is provided, then error messages pertaining to the subset include the name of the library:

1. function Calc (X : Integer) return Integer is 2. begin 3. return X ** 4+X ** 52; | >>> construct not allowed in this configuration (Simple Run Time1)

4. end Calc;

6.7 Creating a Configurable Run-Time Library

As described above, the run-time library may be tailored to suit a specific application. This process can be carried out either by augmenting an existing restricted run-time library implementation or by reducing an existing library. It is of course possible to add any units. However, the configuration of a complex run-time library may be quite difficult, and is best carried out in consultation with experts who are familiar with the structure of the GNAT run-time libraries. For details on how to customize the bareboard run-time libraries please refer to Customized Bareboard Run-Time Libraries.

Contents 45 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

46 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

CHAPTER SEVEN

SUPPORT FOR CERTIFIED SYSTEMS

7.1 The Certification Philosophy

GNAT is intended to reduce costs and risks in meeting software safety or security certification standards for applications written in Ada. One way this goal is met is through the use of language profiles: using one of the language profiles designed for certification, or an appropriately constrained Ada subset selected by the . The following GNAT defined- profiles have been designed with certification in mind and are know in this chapter as the Certifiable Profiles: • Light Profile • Light-Tasking Profile The Light Profile provides a flexible Ada subset that is supported by a certifiable Ada run-time. Depending on application requirements, this profile can be further restricted through the Restrictions pragma, with the application only including run-time code that is used by the application. The Light Profile run-times can also be customized directly to suit certification requirements: unneeded packages can be removed to allow for self-certification of the run-time while the -nostdlib linker switch can be used to prevent the use of the run-time. Do note that when the run-time library is suppressed some run-time sources are still required to provide compiler-time definitions. While this code produces no object code, be aware that the certification protocol may still require tests to ensure correct access to these definitions. The Light-Tasking Profile expands the Light Profile to include Ravenscar tasking support, allowing users to make use concurrency in their certification applications. Although limited in terms of dynamic Ada semantics, all Certifiable Profiles fully support static Ada constructs such as private types, generic templates, and child units. Some dynamic semantics are also supported. For example, these profiles allow the use of tagged types (at library level) and other Object-Oriented Programming features, including dynamic dispatching. Note that you can prohibit the general use of dynamic dispatching at the application level using pragma Restrictions. A traditional problem with predefined profiles is their inflexibility: if you need to use a feature that is outside a given profile, then it is your responsibility to address the certification issues deriving from its use. GNAT for cross platforms accommodate this need by allowing you to define a profile for the specific set of features you will use. Typically this will be for features with run-time libraries that require associated certification materials. Thus your program will have a tailored run-time library supporting only those features that you have specified.

GNAT User’s Guide Supplement for Cross Platforms 47 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

7.2 Using GNAT Pro Features Relevant to Certification

GNAT Pro contain a number of features especially useful for certified software:

• With the -gnatD or -gnatG options, the compiler generates a low-level version of the source program in an Ada-like format. This serves as an intermediate form between the original source program and the generated object code. This intermediate representation may be used to understand the assembly code and verify some of the origins of non- traceable code. This expanded low-level generated code can also be used as the reference point for run-time debugging. • With the -gnatR option, the compiler generates information about the choice of data representations. • The compiler produces an extensive set of warning messages to diagnose situations that are likely to be errors, even though they do not correspond to illegalities in Ada Reference Manual terms. • Two restriction identifiers for pragma Restrictions prohibit constructs that would generate implicit loops (No_Implicit_Loops) or implicit conditionals (No_Implicit_Conditionals). If these restrictions are specified, then either alternative code is generated without the implicit code, or the construct in question is rejected, forcing the programmer to make the loop or conditional explicit in the source. This is desirable in ensuring full testing of conditionals. See Controlling Implicit Conditionals and Loops. • A restriction identifier for pragma Restrictions can be used to restrict the form of explicit conditionals. Using the restriction identifier No_Direct_Boolean_Operators prohibits the use of and and or operators, forcing instead the use of and then and or else. This can be useful in some certification procedures in order to reduce the number of test cases needed to fully exercise compound conditions. • With the -gnatyx options, the compiler performs various style checks that can be used to enforce rigorous coding standards, easing the verification process by ensuring that the source is formatted in a uniform manner. • Annex H of the Ada Reference Manual is fully implemented, and all implementation-dependent characteristics of the GNAT Pro implementation are defined in the GNAT Reference Manual, further supporting the goal of reviewable object code.

7.2.1 Exceptions

The Certifiable Profiles provide limited local exception handling through the implicit application of pragma Restrictions (No_Exception_Propagation)`. This restriction allows exceptions to be raised and handled only if the handler is in the same subprogram (more generally in the same scope not counting packages and blocks). This limits the handling of exceptions to cases where raising the exception corresponds to a simple goto to the exception handler. This is especially useful for predefined exceptions. For example, the following is allowed with the Light and Light- Tasking:

begin X :=Y+Z; exception when Constraint_Error => ... result of addition outside range of X end;

With this restriction in place, handlers are allowed, but can only be entered if the raise is local to the scope with the handler. The handler may not have a choice parameter, use of GNAT.Current_Exception is not permitted, and use of reraise statements (raise with no operand) is not permitted.

48 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Warnings are given if an implicit or explicit exception raise is not covered by a local handler, or if an exception handler does not cover a case of a local raise. The following example shows these warnings in action:

1. pragma Restrictions (No_Exception_Propagation); 2. procedure p (C : in out Natural) is 3. begin 4. begin 5.C :=C-1; 6. exception 7. when Constraint_Error=> 8. null; 9. when Tasking_Error=> | >>> warning: pragma Restrictions (No_Exception_Propagation) in effect, this handler can never be entered, and has been removed

10. null; 11. end; 12. 13. begin 14.C :=C-1; | >>> warning: pragma Restrictions (No_Exception_Propagation) in effect, "Constraint_Error" may call Last_Chance_Handler

15. end; 16. 17. begin 18. raise Program_Error; | >>> warning: pragma Restrictions (No_Exception_Propagation) in effect, Last_Chance_Handler will be called on exception

19. end; 20. end p;

These warnings may be turned off globally using the switch -gnatw.X, or by using pragma Warnings (Off) locally. As shown by the warnings above, if any other exception is raised, it is treated as unhandled, and causes the ‘last chance handler’ to be invoked. This routine is described below. Exception handling can also be forbidden entirely while still allow the raising of exceptions by using: pragma Restrictions(No_Exception_Handlers);

No handlers are permitted in a program if this restriction is specified, so exceptions can never be handled in the usual Ada way. If run-time checking is enabled, then it is possible for the predefined exceptions Constraint_Error, Program_Error, or Storage_Error to be raised at run time. When such an exception is raised, a global ‘last chance handler’ routine is invoked automatically to deal with the fatal errors represented by these exception occurrences. The term ‘last chance’ is used because the handler routine is the last code executed. A default implementation is included with the profile implementation and does nothing other than terminate the application. This default version can be replaced by the user.

Contents 49 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

The replacement routine can be written in either Ada or C, and must have the link-time symbol __gnat_last_chance_handler. For example, a user-defined Ada procedure can be specified via pragma Export to have the required symbol name. Note that the parameters to the handler routine are profile-specific. Details are provided in the sections specific to the individual profiles. All last chance handler implementations must effectively terminate the application. For example, on a bareboard target, it could enter an infinite loop. Alternatively, it could restart the hardware, thereby invoking a new instance of the application. In no case, however, may the application instance experiencing the exception continue execution after the last chance handler routine executes. Exception declarations and raise statements are still permitted under this restriction. A raise statement is compiled into a call of __gnat_last_chance_handler. To suppress all run-time error checking and generation of implicit calls to the last chance handler, and to disallow all raise statements, you may use:

pragma Restrictions(No_Exceptions);

The following switch is not relevant if the program has pragma Restrictions (No_Exception_Handlers) or pragma Restrictions (No_Exception_Propagation):

• -E This switch causes traceback information to be stored with exception occurrences and is only applicable when there are exception handlers. The following switches are not relevant if the program has pragma Restrictions (No_Exceptions) or pragma Restrictions (No_Exception_Propagation): • -E See above. • -gnatE This switch enables run-time checks for ‘Access-Before-Elaboration’ errors.

7.2.2 Allocators

Allocators and unchecked deallocation are permitted in a certification context. Use of these features will generate calls on one of the following C convention functions:

void *__gnat_malloc( size_t size); void __gnat_free( void *ptr);

The corresponding Ada subprogram declarations are:

type Pointer is access Character; -- This is really a void pointer type, the result from -- Gnat_Malloc will always be maximally aligned.

function Gnat_Malloc(size: Interfaces.C.size_t) return Pointer; pragma Export(C, Gnat_Malloc, "__gnat_malloc"); procedure Gnat_Free(Ptr: Pointer); pragma Export(C, Gnat_Free, "__gnat_free");

These functions are part of the run-time library for some profiles, and must be provided by the user otherwise. If included in the run-time library, they appear in the file s-memory.adb. To know if a given profile provides this feature, see the relevant section in Predefined Profiles.

50 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

If these functions are not provided, then the user must define __gnat_malloc either in C or in Ada, using the above declarations; otherwise the program will fail to bind. Analogously, if the program uses Unchecked_Deallocation, then __gnat_free must be defined. For example, on VxWorks Cert, one approach (if no deallocation is to be allowed) is for the user to implement Gnat_Malloc through calls on memLib routines. The memNoMoreAllocations function can be invoked to prevent further allocations, for example at the end of package elaboration. To prohibit the use of allocators or unchecked deallocation, you can use pragma Restrictions with the following restriction identifiers (these are defined in the Ada Reference Manual):

Restriction Effect pragma Restrictions This prohibits the use of allocators except at the library level (thus allocations occur (No_Local_Allocators) only at elaboration time, and not after the invocation of the main subprogram) pragma Restrictions This prohibits all explicit use of allocators, thus preventing allocators both at the (No_Allocators) local and library level pragma Restrictions This prohibits implicit allocations (for example an array with nonstatic subscript (No_Implicit_Heap_Allocations)bounds declared at library level) pragma Restrictions This prohibits all use of the generic procedure (No_Unchecked_Deallocation)Ada.Unchecked_Deallocation

If any or all of these pragmas appear in the gnat.adc file, the corresponding construct(s) will be forbidden throughout the application. If all four of the above restrictions are in place, then no calls to either __gnat_malloc or __gnat_free will be generated.

7.2.3 Array and Record Assignments

The use of whole-object assignments of arrays and records is permitted. However, on some targets such constructs may generate calls on the C library functions memcpy, memmove, memset, or bcopy. There are two ways to deal with this issue. First, such assignments can be avoided at the source code level. You can replace an array assignment by an explicit loop, and a record assignment by a series of assignments to individual components. You can encapsulate such statements in a procedure if many such assignments occur. Second, you can reuse or define an appropriate replacement for one (or more) of the routines. For example, if certification protocols permit, you can reuse the memcpy, memset, memmove, and/or bcopy routine(s) from the C library. An an example of defining one’s own implementation, the following Ada procedure will supply the needed memcpy functionality: with System; use System; with Interfaces.C; use Interfaces.C; function memcpy(dest, src: Address; n: size_t) return Address; pragma Export(C, memcpy, "memcpy"); with Ada.Unchecked_Conversion; function memcpy(dest, src: Address; n: size_t) return Address is subtype mem is char_array(size_t); type memptr is access mem; function to_memptr is new Ada.Unchecked_Conversion(address, memptr); (continues on next page)

Contents 51 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) dest_p: constant memptr := to_memptr(dest); src_p: constant memptr := to_memptr(src); begin if n>0 then -- need to guard against n=0 since size_t is a modular type for J in 0..n-1 loop dest_p(J) := src_p(J); end loop; end if;

return dest; end memcpy;

The above memcpy routine provides the minimal required functionality. A more elaborate version that deals with alignments and moves by words rather than bytes where possible would improve performance. On some targets there may be hardware instructions (e.g. rep movsb on the x86 architecture) that can be used to provide the needed functionality. Note that memcpy is not required to handle the overlap case, and the GNAT Pro compiler ensures that any call to memcpy meets the requirement that the operands do not overlap. On the other hand, memmove and bcopy are required to handle overlaps. Note that the order of the arguments of bcopy differs from memcpy and memmove. A user-supplied version of bcopy should take into account these differences.

7.2.4 Object-Oriented Programming

Large part of Ada’s object-oriented programming facilities is supported on the Certifiable Profiles. Objects of tagged and class-wide types may be declared. Dispatching and class-wide subprograms are allowed. Restrictions are: • Tagged types must be declared at the library level. • No controlled types. • Ada.Tags.Internal_Tag and Ada.Tags.Tag_Error are not available in the default implementations of these profiles. The method invocation syntax of Object.Operation (...) is fully supported under the Light profile. Generic dispatching constructors are not supported under the Light profile. A subset of interface types is supported under the Light profile, with the following restrictions: • No task interfaces, protected interfaces or synchronized interfaces. • No dynamic membership test applied to interfaces (only those cases in which the evaluation can be performed at compile-time are supported). • No class-wide interface conversions. • No declaration of a tagged type covering interfaces in which its parent type has variable-size components. • The Address attribute is not supported on objects whose visible type is a class-wide interface. Note: Dispatch tables are used to implement dynamic dispatching. Each tagged type has an associated data structure including a table containing the address of each of its primitive operations. The format of dispatch tables is compatible with the format described in the C++ ABI. This means, in particular, that the dispatching mechanism is deterministic and bounded in time, with a performance similar to an indirect call. Furthermore, dispatch tables are

52 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

generated by the compiler as static data that is placed in a read-only data section of the object code; restriction Static_Dispatch_Tables can be used to identify tagged type declarations that cannot be placed in a read-only section. Appropriate linker scripts can be used to ensure that such sections are placed in ROM. Placing such tables in ROM is recommended because it offers some level of robustness to the dispatching mechanism: it prevents the possibility of unintended changes in such tables that could affect the control flow of the code. In addition, declarations of tagged types in this profile are statically elaborable and thus can be used in the presence of the restriction No_Elaboration_Code. In order for the debugger to be able to print the complete type description of a tagged type, the program must have Ada.Tags as part of its closure. Otherwise, the debugger will not be able to print the name of the type from which the tagged type has been derived. This limitation can easily be addressed by introducing an artificial dependency on the Ada.Tags unit. Another option is to compile one unit that declares a tagged type with -fno-eliminate-unused- debug-types. This does not affect the ability to print the value of tagged objects, which should work without problem regardless.

7.2.5 Functions Returning Unconstrained Objects

By default, the cross and bareboard run-times allow functions returning objects of unconstrained types, such as unconstrained array types or discriminated record types without default values for the discriminants. For such functions, the amount of storage required for the result is not known at the point of the call. To implement this capability, the compiler generates references to a secondary-stack mechanism that requires run-time support. If you need to use this capability, you should refer to the relevant section in Predefined Profiles, to see if it is already provided in the run-time library or if you are responsible for providing an appropriate implementation of this unit for a given profile. The specification of the secondary-stack mechanism is described in the Ada package System. Secondary_Stack, which is in the file s-secsta.ads. If you wish to disable this capability, you can use the pragma Restrictions (No_Secondary_Stack); this will generate an error at compile time for each call to a function returning an unconstrained object.

7.2.6 Controlling Implicit Conditionals and Loops

Certain complex constructs in Ada result in generated code that contains implicit conditionals, or implicit for loops. (‘Implicit’ means that the conditionals/loops are not present in the Ada source code.) For example, slice assignments result in both kinds of generated code. In some certification protocols, conditionals and loops require special treatment. For example, in the case of a conditional, it may be necessary to ensure that the test suite contains cases that branch in both directions for a given conditional. A question arises as to whether implicit conditionals and loops generated by the compiler are subject to the same verification requirements. To address this issue, GNAT define two restriction identifiers that control whether the compiler is permitted to generate implicit conditionals and loops :

pragma Restrictions(No_Implicit_Conditionals); pragma Restrictions(No_Implicit_Loops);

These are partition-wide restrictions that ensure that the generated code respectively contains no conditionals and no loops. This is achieved in one of two ways. Either the compiler generates alternative code to avoid the implicit construct (possibly with some loss of efficiency) or, if it cannot find an equivalent code sequence, it rejects the program and flags the offending construct. In the latter situation, the programmer will need to revise the source program to avoid the implicit conditional or loop. As an example, consider the slice assignment:

Contents 53 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Data(J..K) := Data(..S);

Ada language semantics requires that a slice assignment of this type be performed nondestructively, as though the right-hand side were computed first into a temporary, with the value then assigned to the left-hand side. In practice it is more efficient to use a single loop, but the direction of the loop needs to depend on the values of J and R. If J is less than R then the move can take place left to right; otherwise it needs to be done right to left. The normal code generated by GNAT Pro reflects this requirement: if J

This code clearly contains both implicit conditionals and implicit loops. If the restriction No_Implicit_Conditionals is active, then the effect is to generate code that uses a temporary: This code avoids an implicit conditional at the expense of doing twice as many moves. If the restriction No_Implicit_Loops is also specified, then the slice assignment above would not be permitted, and would be rejected as illegal. This means that the programmer would need to modify the source program to have an explicit loop (in the appropriate direction). This loop could then be treated in whatever manner is required by the certification protocols in use. The following constructs are not permitted in the presence of No_Implicit_Conditionals (note that some are in any event excluded from the Certifiable Profiles): • Comparison of record or array values • Array concatenation • Controlled types • Protected types • Asynchronous select • Conditional entry call • Delay statement • Selective accept • Timed entry call • Tagged types • Distributed System Annex features (shared passive partitions, etc.) • Width attribute applied to real type • Absolute value operator if checks are on • rem, mod, and division operators if checks are on • Is_Negative • Dynamic elaboration check The following constructs are not permitted in the presence of No_Implicit_Loops (note that entry families are in any event excluded from some or all Certifiable Profiles):

54 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• Array aggregate with others clause • Array types with implicit component initialization • Array equality test • Array concatenation • Logical operations on array types • Array assignments • Controlled array types • Entry families • Default array stream attributes

7.2.7 Controlling Use of Conditional Operators

Some testing procedures for certification can be more efficient if application programs avoid the explicit use of and / or and instead use and then / or else. This can facilitate meeting the requirement for MCDC (‘Modified Condition / Decision Coverage’) testing. The net effect of using the short-circuit versions is a significant reduction in the number of test cases needed to demonstrate code and condition coverage. GNAT provide an additional restriction identifier that addresses this issue by controlling the presence of direct boolean conditional operators:

pragma Restrictions(No_Direct_Boolean_Operators);

These are partition-wide restrictions that ensure that the source code does not contain any instances of the direct boolean operators and or or. This will alert the programmer to the requirement to use and then or or else as appropriate

7.2.8 Avoiding Elaboration Code

Ada allows constructs (e.g., variables with implicit initializations) for which so-called elaboration code must be generated. In a certification context the need to certify elaboration code will increase costs, as it will be necessary to address questions such as why the compiler implicitly generated the elaboration code, which Ada requirement it met, which test cases are needed. GNAT provides the pragma Restrictions (No_Elaboration_Code), which alerts you to constructs for which elaboration code would be generated by the compiler. When this pragma is specified for a compilation unit, the compiler outputs an error message whenever it needs to generate elaboration code. You must then revise the program so that no elaboration code is generated. As an example consider the following:

package List is type Elmt; type Temperature is range 0.. 1_000; type Elmt_Ptr is access all Elmt; type Elmt is record T: Temperature; Next: Elmt_Ptr; end record; X: Elmt; end List;

When compiling unit List, the compiler will generate the error message:

Contents 55 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

list.ads:11:04: violation of restriction"No_Elaboration_Code" at line1

In this example GNAT Pro needs to generate elaboration code for object X. To see the elaboration code that would be generated you can remove the No_Elaboration_Code restriction and use the -gnatG switch to view the low-level version of the Ada code generated by GNAT Pro. In this case we obtain: package list is type list__elmt; type list__temperature is range0.. 1000; type list__elmt_ptr is access all list__elmt; type list__elmt is record t : list__temperature; next : list__elmt_ptr; end record; [type list__TtemperatureB is new short_integer] freeze list__TtemperatureB [] freeze list__elmt [ procedure list__elmtIP (_init : out list__elmt) is begin _init.next := null; return; end list__elmtIP; ] list__x : list__elmt; list__elmtIP (list__x); end list;

Elaboration code is generated inside package List to null-initialize the access value inside X, by calling the initialization procedure for the type, namely list__elmtIP. To avoid generating elaboration code, you can add explicit initialization as follows: pragma Restrictions(No_Elaboration_Code); package List is type Elmt; type Temperature is range 0.. 1_000; type Elmt_Ptr is access all Elmt; type Elmt is record T: Temperature; Next: Elmt_Ptr; end record; X: Elmt :=(0, null); end List;

Since the initialization is now explicit, it becomes part of the requirements mapping and application design. In a certification context it is preferable to certify code that you write explicitly rather than code that gets generated implicitly.

56 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

7.2.9 Removal of Deactivated Code

Deactivated code in the executable requires specific treatment with standards such ED12/DO-178B (see 6.4.4.3d). This treatment can be simplified by diminishing the footprint of deactivated code in the final executable. This section summarizes the various features that can be used to minimize the footprint of deactivated code in the final executable program. • Automatic Removal The compiler automatically removes local nested subprograms that are never used at all levels of optimization. It also removes unused library-level subprograms declared within package bodies at optimization level -O1 or higher. • Static Boolean conditionals The compiler eliminates automatically all code protected by conditionals, if and case statements, that are statically detected to be false. For instance, with those declarations:

type Configs is (config1, config2, config3); ... C: constant Configs := config2;

the following code

if C= config1 then some_code0; end if; case C is when config1 => some_code1; when config2 => some_code2; when config3 => some_code3; end case;

is transformed into:

some_code2;

The elimination done by the compiler can be traced using an optional compiler warning enabled with -gnatwt. • Pragma Eliminate The user can prevent code generation for subprograms that are known to be deactivated by placing Eliminate pragmas in the configuration pragmas file:

pragma Eliminate(Unit, Unused_Subp, Source_Location => "unit.adb:19")

The compiler will issue an error if an attempt is made to call an eliminated subprogram. • Linker Level Removal Some configurations support linker level removal of unused subprograms and data. The source code needs to be compiled with the options -ffunction-sections and -fdata-sections and the linking must be performed with option -Wl,--gc-sections. Traceability of the code removal is provided through a chapter called “Discarded Input sections” in the map file that can be produced by the linker with option -Wl,-M. These methods can be used to reduce the amount of code in the final executable corresponding to deactivated source code. The last three offer means of tracing the removed code and thus can be used for traceability purposes or as documentation of the deactivation mechanism. The last method can also remove code added by the compiler such as the implicit initialization procedures associated with composite types when they are not used. It therefore simplifies the reverse traceability from object to source.

Contents 57 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

7.2.10 Traceability from Source Code to Object Code

During the build process, the GNAT Pro toolchain manipulates several program representations, in particular: • The initial source code; • The expanded code, which is low level Ada pseudo-code; • Assembler code; and • Object code. In order to help the traceability process, GNAT Pro gives access to the intermediate format, through the following options:

• -gnatD This switch causes a listing of a pseudo-Ada low-level version of the compilation unit to be directed to a file. • -gnatG This switch produces a listing of a pseudo-Ada low-level version of the compilation unit. • -gnatL This switch enhances traceability of the expanded code by adding the original source code as comments just before the corresponding expansion. It has to be used in conjunction with -gnatD or -gnatG. • -S This switch causes generation of an version of the compilation unit, instead of an object file. • -save-temps This switch causes the compiler to save temporary files (in particular, the .s file) while still generating .o and ALI files. • -fverbose-asm This switch causes the compiler to decorate the assembly output with comments containing the names of the entities (e.g. local variables) being manipulated by the current assembly instruction. • -mregnames This switch causes the compiler to emit symbolic names for register in the assembly output. This switch is specific to PowerPC and even though it is not directly related to traceability, it is worth mentioning because it greatly improves assembly code readability. • -Wa,-adhl This switch instructs the GNU assembler to produce a text listing of the generated code containing the high-level source and the assembly while excluding debugger directives (for readability reasons). The listing goes to standard output and can be redirected to a file using the syntax -Wa,-adhl=file.lst which save it in the file file.lst. • -gnatR This switch causes representation information to be generated for declared types and objects. These options can be combined in various ways. A fairly complete source to object traceability is provided by:

$ -gcc -c -gnatDL -Wa,-adhl -fverbose-asm -mregnames prg.adb

58 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

7.2.11 Optimization issues

The -On compiler switch sets the optimization level to n, where n is an integer between 0 and 3. If n is omitted, it is set to 1. Generally you should use the -On switch to enable optimization, because this is the level at which you can most easily track the correspondence between source code and object code. Although for safety-critical programs optimizations are often regarded with suspicion, the fundamental reason for this concern is traceability. At the -O0 level, traceability is in fact more difficult due to the large amount of naive code that is generated. The optimizations performed at level -O1 eliminate redundant code, but avoid the kind of code-shuffling transformations that can obscure the correspondence between source and object code. If you consider coverage, it can be useful to disable optimizations on conditional statements. The option -fno-short- circuit-optimize specifically disables boolean operator optimizations (those which transform or else into or or and then into and), and the options -fno-if-conversion and -fno-if-conversion2 disable optimization passes that try to remove conditional jumps for if statements and use conditional move instead. These switches help to preserve the original jump structure implied by the source, thus helping source-to-object traceability, and facilitating certification and coverage analysis at the object level.

7.2.12 Other useful features

The -gnaty compiler switches direct the compiler to enforce style consistency checks, which can be useful in ensuring a uniform lexical appearance (and easing program readability) across a project. Annex H in the Ada Reference Manual defines a set of restrictions identifiers, many of which are relevant for code that needs to be certified. If you provide a pragma Restrictions with any of these identifiers, the compiler will prohibit your program from using the corresponding construct.

7.2.13 Program Build Options

For the most part, you can build programs using the Certifiable Profiles in the same way, and with the same set of switches, as in a full Ada environment. However, certain switches are not relevant for the Certifiable Profiles. This section lists these switches; a complete description of the compiler switches appears in the GNAT User’s Guide for Native Platforms and, in the case of general gcc switches, the Using GNU GCC manual.

Compiler Switches

The following switches are not relevant in certain Certifiable Profiles, since they are associated with features that are outside these profiles:

• -fstack-check This switch enables stack overflow checking • -gnata This switch enables pragma Assert, subject to exception propagation and handling restrictions. • -gnato This switch enables run-time checks for integer overflow, subject to exception propagation and handling restrictions. • -gnatT This switch sets the timeslice in a tasking program.

Contents 59 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• -gnatz This switch is used for distributed Ada programs. gnatbind Switches

The following switches are not relevant in Light and Light-Tasking modes:

• -static This switch specifies linking with a static GNAT run-time library. • -shared This switch specifies linking with a shared GNAT run-time library. • -T This switch sets the timeslice for a tasking program. In addition, the -t switch overrides standard Ada unit consistency checks and would generally not be used for high- integrity applications. The -f switch for elaboration-order control should not be used; see the discussion of elaboration-order issues in GNAT User’s Guide for Native Platforms.

60 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX A

VXWORKS TOPICS

This appendix covers topics related to GNAT for various versions of the VxWorks RTOS.

A.1 Common VxWorks Topics

This section describes topics that are relevant to all GNAT for VxWorks configurations. Note that the GNAT tool prefix depends on the platform, as follow: • For Workbench / VxWorks 6.x / VxWorks 653 3.x, it is -wrs--; • for Workbench / VxWorks7 (up to SR0540), it is -wrs-vxworks7-; • for Workbench / VxWorks 7 (SR0600 or later), it is -wrs-vxworks7r2-; • for Workbench / VxWorks 653 2.x, it is -wrs-vxworksae-. In all cases above, is the CPU being targeted (Eg: arm, i586, etc). For VxWorks 7 platforms, instructions not providing a specifc release version (e.g. “SR0600 or later”) are applicable to all supported versions of VxWorks 7. Generally speaking, outside of the difference above in tool prefix, AdaCore tried to provide a consistent experience regardless of the VxWorks 7 version.

A.1.1 VxWorks Kernel Requirements

Tasking requires the following kernel components: • INCLUDE_TLS (included by default on VxWorks 7) • DKM_TLS_SIZE set to at least 100 on VxWorks 7 SRO610 or later GNAT.Sockets require the following kernel components: • INCLUDE_GETNAMEINFO • INCLUDE_GETADDRINFO

GNAT User’s Guide Supplement for Cross Platforms 61 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.1.2 Executing a Program on VxWorks

Executing an application involves loading it onto the target, running it, and then (if re-execution is needed) unloading it. This model and the instructions below apply to Workbench/ VxWorks 6.x and Workbench / VxWorks 7 when building an application for execution in the kernel space. RTP’s are treated somewhat differently, and VxWorks 653 provides several other mechanisms for loading and executing. These cases are described later in this Guide.

Loading and Running the Program

An Ada program is loaded and run in the same way as a C program. In order to load and run a program, we assume that the target has access to the disk of the host containing the required module and that the host shell’s working directory has been set to the directory containing it. The commands are typed into the Workbench host shell. The windsh prompt is the -> sequence. In this example, the module is named hello, and when executed it results in the display of the Hello World string. For VxWorks 6.x and VxWorks 7:

-> vf0=open("/vio/0",2,0) new symbol"vf0" added to symbol table. vf0= 0x2cab48: value= 12= 0xc -> ioGlobalStdSet(1,vf0) value=1= 0x1 -> ld< hello.out value= 665408= 0xa2740 -> hello Hello World value=0= 0x0 ->

The first two commands redirect output to the host shell window. They are only needed if the target server was started without the -C option. The third command loads the module, which is the file hello created previously by a gprbuild command. The Hello World program comprises a procedure named hello, and this is the name entered for the procedure in the target server’s symbol table when the module is loaded. To execute the procedure, type the symbol name hello into windsh as shown in the last command above. Depending on circumstances, sp or taskspawn should be used to spawn the module in a new task. These are generally used for finer control over execution options. Note that by default the entry point of an Ada program is the name of the main Ada subprogram in a VxWorks environment. It is possible to use an alternative name; see the description of switches for gpr package Binder for details.

Unloading the Program

It is important to remember that you must unload a program once you have run it. You cannot load it once and run it several times. If you don’t follow this rule, your program’s behavior can be unpredictable, and it will most likely crash. This effect is due to the implementation of Ada’s elaboration semantics. The compilation unit elaboration phase comprises a static elaboration and a dynamic elaboration. On a native platform they both take place when the program is run. Thus rerunning the program will repeat the complete elaboration phase, and the program will run correctly. On VxWorks, the process is a bit different. The static elaboration phase for a DKM is handled by the dynamic (typically when you type ld < program_name in windsh). The dynamic phase takes place when the program is run. If the program is run twice and has not been unloaded and then reloaded, the second time it is run, the static

62 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

elaboration phase is skipped. Variables initialized during the static elaboration phase may have been modified during the first execution of the program. Thus the second execution isn’t performed on a completely initialized environment. This is not an issue for SKMs and RTPs. Note that in C programs, elaboration isn’t systematic. Multiple runs without reload might work, but, even with C programs, if there is an elaboration phase, you will have to unload your program before re-running it.

A.1.3 Mixed-Language Programming on VxWorks using GNAT Exclusively

On VxWorks, the general requirements and recommendations provided in the section Mixed-Language Programming using GNAT Exclusively also apply here, and should therefore be observed. The GPRbuild knowledge base also contains the appropriate linker options for producing a module for the configuration that you select. In order to take advantage of that, for VxWorks 6, WIND_BASE must be defined before invoking these tools. For VxWorks 7 VSB_DIR must be defined.

A.1.4 Mixed-Language Programming using the VxWorks C/C++ Compilers

Use of the VxWorks C/C++ compilers for mixed Ada and C/C++ applications is supported, but only when built through GNATbench or when using the VxWorks 7 wrtool with an Ada Project generated by GNATbench. The use of GNATbench for mixed language applications is documented in the GNATbench help files available within Workbench. Please also review the Interoperability with VxWorks C/C++ Compilers section for issues to be aware of when using both the GNAT Pro Ada compiler and the VxWorks C/C++ compilers.

A.1.5 Interoperability with VxWorks C/C++ Compilers

VxWorks is packaged with one or more C/C++ compilers depending on the VxWorks version and target. GNAT Pro supports Ada-only and mixed-language applications using the VxWorks GNU, DIAB, and LLVM toolchains subject to the limitations described in this section. The ICC toolchain is not supported. The details of mixing GNAT Pro Ada with the VxWorks toolchains is generally taken care by GNATbench for pure Ada applications and mixed Ada and C/C++ applications. Similarly for Ada-only applications built outside of Workbench using GPRbuild. An exception to this is exception handling, where special care must be taken, and which is documented in the next section (Exception Handling).

A.1.6 Exception Handling

Exception handling for Ada-only applications works as expected on VxWorks without any special configuration for either the application or the kernel. However, this is not true for mixed Ada/C++ VxWorks applications where two different compilers are involved: the GNAT Pro Ada compiler and the VxWorks C++ compiler. Making two different compilers cooperate is always a challenge, but exception handling is particularly sensitive as both compilers provide their own exception runtime support. This section introduces the integration options available for Ada and Ada/C++ applications. It is followed by an advanced look at exception handling on VxWorks and the issues a mixed Ada/C++ application can encounter.

Contents 63 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Exception Integration Schemes

Three different integration schemes are provided by GNATbench: • EXCEPTIONS_GPRBUILD_ONLY: exception propagation only for pure Ada applications. • EXCEPTIONS_SEPARATE_DOMAINS: exception propagation is supported for mixed language applications but exceptions cannot propagate through the different languages. C++ exceptions only go through C++ frames, and if they hit an Ada frame then the application stops with an error. Same behavior for Ada exceptions. • EXCEPTIONS_FULL: exceptions raised in one language can be handled in either language: C++ exceptions can be handled in Ada, Ada exceptions can be caught in C++. The availability of the three integration options is dependent on the VxWorks C++ compiler:

DIAB

Exception handling is not supported when mixing GNAT Pro Ada and Diab C++. Due to this limitation GNATbench only supports EXCEPTIONS_GPRBUILD_ONLY. Mixed-language applications are still possible with the No_Exception_Propagation restriction.

GNU

GNAT and Wind River G++ are both GNU-based and consequently support: • EXCEPTIONS_SEPARATE_DOMAINS: provides the most robust solution by using GNAT libraries for Ada and VxWorks G++ libraries for C++. • EXCEPTIONS_FULL: being able to go through different languages requires using the same library for all languages, and in this case it must be Wind River’s G++’s libraries. In our experience this option works properly on VxWorks 7; however Wind River does not guarantee full compatibility of the VxWorks library with the exception information that GNAT generates. Even though both are GNU-based, they rely on different versions of GCC and it is still possible to get incompatibilities. When using EXCEPTION_FULL you will need to validate it in your own context. Note that -Os is not supported with EXCEPTIONS_FULL: gcc library routines to save floating-point registers (_savefpr_) have a different suffix on vxWorks (_savefpr__l). We suggest to use -O2 instead of -Os.

LLVM

LLVM support is similar to GNU: • EXCEPTIONS_SEPARATE_DOMAINS: provides the more robust solution. • EXCEPTIONS_FULL: a possible option at your own risk. Wind River provides a GNU-compatible layer with no guarantees: UnwindLevel1-gcc-ext.c. Contact Wind River support to learn more about this option.

64 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Exception Propagation Schemes

To understand the rationale and use of the three different exception integration schemes, a brief examination of how exception prorogation works is required. Generally, there are two schemes for exception propagation: • Setjump/Longjump (SJLJ): each task maintains a record of where it should jump if an exception is raised, updated each time the task enters a block that contains a handler. • Zero Cost Exceptions (ZCX): when an exception is raised, the runtime computes a backtrace from dwarf unwind information and determines where the proper handler is. No task-specific record is used. The design of the ZCX scheme results in low runtime overhead during normal program execution but suffers from costly overheads when an exception is raised and propagated, due to the complexity of unwinding mechanism. For most applications this is an acceptable trade-off, but would not be suitable for applications: • frequently raising exceptions; • being certified due to the complexity of the unwinding mechanism. Given the above trade-offs, the GNAT Pro Ada runtimes for VxWorks use the ZCX scheme, except for the cert and ravenscar-cert runtimes, where SJLJ is used due to the certification context. The remainder of this section will focus on ZCX and mixed Ada/C++ exceptions, due to the peculiarities of this exception scheme on VxWorks.

Zero Cost Exceptions

Underpinning ZCX are two tables located in dedicated ELF sections: • DWARF unwind info table (.eh_frames); • Exception handlers table (.gcc_except_table) Exception propagation is performed by the compiler runtime library, libgcc, using these tables. When an exception occurs, libgcc uses these tables to unwind the stack and jump to the corresponding exception handler when an exception is raised. The stack is unwound by generating a backtrace using the information from the unwind info table, while the exception handler table provides the address of the appropriate handler to jump to. The application unwind table is constructed by the linker concatenating the .eh_frame sections from the application’s individual object files. The start of the table is marked by the symbol EH_FRAME_BEGIN and a sentinel defined by libgcc marks the end. In practice, the first object file in the link order (typically crtbegin.o) defines the symbol, while the sentinel is defined in the last object file (typically crtend.o). For libgcc to propagate exceptions, the application unwind table has to be registered with libgcc. This is done by the application calling the register_frame_info function with the address of the unwind table. This registration must be done in the early stages of execution, before running any user or runtime code that may raise an exception. To achieve this, GNAT and the GCC C++ compilers leverages the C++ static constructor mechanism as the DKM loader and RTP startup code executes the application’s constructors prior to executing the application code (including the elaboration code of an Ada application).

Contents 65 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

ZCX on VxWorks

The challenge when using both the GNAT Pro Ada and VxWorks C++ compilers lies with building an unwind table that is understandable to both the Ada and C++ runtimes and then registering this table with the correct libgcc via a C++ static constructor. To understand the complexity involved and the issues that can be run into, this section details the workflow the VxWorks GNU and LLVM C++ compilers use to build and register the unwind table. GNAT Pro Ada closely follows these workflows to try to achieve compatibility with the C++ compilers. Note for ARM32 targets: both the VxWorks C++ and GNAT Pro Ada compilers follow the “Exception Handling ABI for the ARM architecture”, ensuring compatibility between the compilers through the ARM ABI. Note for Diab: due to the differences between the GCC and Diab workflows, exception handling is not supported when mixing GNAT Pro Ada and Diab C++. Consequently, the Diab workflow is not covered here.

GNU DKM Exception Workflow

When building a DKM with the VxWorks GNU toolchain in Workbench, the registration of C++ static constructors for the DKM is done through a TCL script called munch.tcl. This script generates the file ctdt.c containing: • a null-terminated list of C++ static constructors named _ctors; • a null-terminated list of C++ static destructors named _dtors; • an additional constructor to call register_frame_info. The DKM loader will then executed the constructors in the _ctors list upon load of the module.

LLVM DKM Exception Workflow

The VxWorks LLVM toolchain differs from the GNU toolchain with each object file recording its C++ static constructors in the corresponding .ctors. section (organized by priority). The final link merges these sections into a single .ctors section with corresponding symbols __CTOR_LIST__ and __CTOR_END__. While munch is no longer used, the _ctors list still exists with only one element: __exec_ctors, a routine that executes the constructors contained within the .ctors section.

RTP Exception Workflow

For RTPs, each object file records its C++ static constructors in the corresponding .ctors. section (organized by priority). The final link merges these sections into a single .ctors section with corresponding symbols __CTOR_LIST__ and __CTOR_END__. The RTP startup code executes the constructors contained within the .ctors section before executing the RTPs application code.

Mixing Ada and C++ in Workbench

The build workflow differs depending on the level of integration (EXCEPTIONS_SEPARATE_DOMAINS or EXCEPTIONS_FULL) and on the kind of VxWorks application (DKM, RTP, or SKM). In GNATbench, the complexity documented in this section is handled by gnat.makefile. In most cases, this support is transparent. However, many mixed-language applications have a complex architecture and not all cases can be supported out of the box. For these applications, gnat.makefile can be modified to suit the application as GNATbench will not overwrite this file.

66 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Selecting libgcc

Two libgcc’s are available in the context of VxWorks: the native libgcc provided with the operating system and the libgcc provided with GNAT. The choice of libgcc depends on the integration strategy chosen. Strategy EXCEPTION_FULL is only supported with the VxWorks libgcc. This is also the option that one would choose in a certification context, when using the libgcc provided with a certified version of VxWorks. Strategy EXCEPTION_SEPARATE_DOMAIN would use GNAT’s libgcc. This option has the advantage of avoiding interoperability issues between the two libgcc’s.

Mixing Ada and C++ Exceptions

Ada and C++ use the same ELF section to save the unwind information: .eh_frame. There are two options: merging them (EXCEPTION_FULL), or keep them separated (EXCEPTION_SEPARATE_DOMAINS). In case of EXCEPTION_FULL, it is important that GNAT’s crtend is not included in the link, otherwise it will introduce an additional sentinel frame into the unwind table that will hide part of the C++ unwind information. Suppressing crtend is performed through the linker -nostdlib switch, which GNATbench does automatically through gnat.makefile. For EXCEPTION_SEPARATE_DOMAINS, the two sections are kept separate by renaming GNAT’s .eh_frame section using objcopy --rename-section. Again, this is done automatically by GNATbench in most cases. For advanced usage, please see gnat.makefile. When both libgcc’s are included, we also need to handle symbol duplication. gnat.makefile does this by hiding every symbol except the module entry point and the routines to register frames. If you need to make other symbols visible, you may add other calls to objcopy -G or provide multiple -G argument in a call to objcopy.

Changes to the VxWorks DKM Exception Workflow

The constructor to call register_frame_info in ctdt.c is always resolved from the VxWorks libgcc, so cannot be used when also using the GNAT libgcc. In other words, the strategy EXCEPTION_SEPARATE_DOMAINS cannot use this constructor. When this additional constructor is not usable, GNAT provides an alternative static constructor that calls GNAT’s register_frame_info. GNATbench for Workbench makes use of this alternative constructor transparent: munch is called automatically when building the project from Workbench, and gnat.makefile passes the link option -noauto-register to avoid generating _ctors/_dtors, letting munch generate it. However, for troubleshooting exception issues it is useful to have a look at ctdt.c and see whether _ctors contains the list of C++ static constructors and whether the constructor for register_frame_info is in the list.

Changes to the VxWorks RTP Workflow

In Workbench, the Ada part of the application will be built during a first (partial) link phase, then Workbench will do the final link. libc/libc_internal must be linked only once. GNAT provides an option -nolibc to remove these libraries when linking the Ada part of the application. This option is added automatically by gnat.makefile.

Contents 67 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.1.7 Kernel Configuration for VxWorks

When configuring your VxWorks kernel we recommend including the target shell. If you omit it from the configuration, you may get undefined symbols at load time, e.g.

-> ld< hello.exe Loading hello.exe Undefined symbols: mkdir

Generally, such undefined symbols are harmless since these are used by optional parts of the GNAT run time. However if running your application generates a VxWorks exception or illegal instruction, you should reconfigure your kernel to resolve these symbols. On VxWorks 6 and VxWorks 7, ZCX (see below) is activated by default. In this mode, proper transformation of stack overflow signal deliveries into Ada exceptions requires increasing the kernel exception stack to at least 10*1024 bytes, which may be achieved by modifying the taskKerExcStackSize global variable before tasks are spawned. This variable is defined in $WIND_BASE/target/h/private/taskLibP.h. This affects all the tasks spawned after the change, and is typically needed for user stack-checking purposes. On PowerPC 64-bit this global variable needs to be 32*1024 bytes for proper stack overflow handling.

A.1.8 Main Task Attributes and the Application Stub

Several characteristics of the application main can only be controlled from the VxWorks environment: main stack size, main priority, and main task attributes. Often the default values are fine. In other cases one must explicitly set the desired values outside of the application source code. The taskSpawn() can be used to provide explicit values for the task name string, its VxWorks priority, stack size and other options (such as the floating point type). For applications requiring modification of these attributes that are invoked from the host or target shell, the system call can be used directly to spawn the application main task. For applications started using a Workbench launcher, these attributes can be set in the launcher. For applications being linked into a kernel image, one should use an application stub for this purpose. Although it can have any name, the default is usrAppInit() and is placed in a file in the project called usrAppInit.c. By defining the build macro USER_APPL_INIT one can use a routine with a different stub or go directly to the Ada main if no attribute modifications are needed. Here is a sample usrAppInit.c suitable for starting an Ada application linked into a VxWorks kernel image:

#include #include

/* Ada binder-generated main - ADA_MAIN is passed as a macro from the makefile */ extern void ADA_MAIN(void); void usrAppInit()

{ int stackSize= 0x80000;

/* For e500v2 processors, use VX_SPE_TASK instead */ int spawnFlags= VX_FP_TASK; (continues on next page)

68 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

/* MAIN_TASK_NAME is passed as a macro from the makefile */ char * mainTaskName=( char *) MAIN_TASK_NAME;

/* VxWorks priority = 255 - Ada priority */ int priority= 100;

/* Spawn Ada environment task */

taskSpawn(mainTaskName, priority, spawnFlags, stackSize, (FUNCPTR) ADA_MAIN,1,2,3,4,5,6,7,8,9, 10); }

ADA_MAIN is the name of the Ada main subprogram in lower case (i.e. the symbol for the entry point of the Ada application). MAIN_TASK_NAME is the name you would like associated with the Ada environment task for the application. These are typically passed using a -D= switch to the compiler in the makefile for the application component. The stack size can be varied to suit the needs of the environment task. It must be spawned with at least option VX_FP_TASK or one of the other floating point type options, depending on your board.

A.1.9 Stack Overflow Checking on VxWorks

GNAT does not perform stack overflow checking by default. This means that if the main environment task or some other task exceeds the available stack space, then unpredictable behavior will occur. To activate stack checking, compile all units with the gcc option -fstack-check. For example:

$ -gcc -c -fstack-check package1.adb

Units compiled with this option will generate extra instructions to check that any use of the stack (for subprogram calls or for declaring local variables) does not exceed the available stack space. If the space is exceeded, then a Storage_Error exception is raised. For declared tasks, the stack size is always controlled by the size given in an applicable Storage_Size pragma (or is set to the default size if no pragma is used). For the environment task, the stack size is defined by the stackSize argument when spawning the Ada program via the taskSpawn() routine. If no stack size is specified, the stack size is set to the VxWorks default value. Use of stack overflow checking requires that a buffer be added to the application stack requirement for each task, including the environment task, in order to handle stack overflows gracefully. The size of this buffer varies between 12KB and 16KB depending on architecture, e.g. a 64-bit architecture requires a larger buffer. For VxWorks 6 Cert and VxWorks 653 3.x, the restricted GNAT run-time libraries for kernel applications retrieve stack boundary information from the VxWorks kernel using the taskInfoGet() routine provided by the taskShow library. Therefore, in order to have stack overflow checking in this environment, the taskShow library must be linked into the VxWorks kernel. This can be done using one of the following methods: • Defining INCLUDE_SHOW_ROUTINES in config.h when using configuration header files • Selecting INCLUDE_TASK_SHOW when using the Workbench kernel configuration dialog. For VxWorks 6 full runtimes, VxWorks 7, and the VxWorks 653 2.x vThreads partition operating system (POS), -fstack-check is implemented using stack probing (more efficient). For VxWorks 6 and VxWorks 7 kernel applications, the kernel must be built with INCLUDE_PROTECT_TASK_STACK enabled. For VxWorks 653 2.x vThreads, one or more guard pages must be specified in the POS configuration file.

Contents 69 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.1.10 Interrupt Handling for VxWorks

GNAT offers a range of options for hardware interrupt handling on VxWorks 6 and for VxWorks 7 kernel modules (SKM / DKM). Interrupt handling is not supported for VxWorks 653 nor for VxWorks 6 and VxWorks 7 real-time processes. These are operating system restrictions (prior to recent versions of VxWorks 653). In rough order of latency and lack of restrictions: • Directly vectored interrupt procedure handlers • Directly vectored interrupt procedures that signal a task using a suspension object • Ada 95 / Ada 2005 / Ada 2012 protected procedure handlers for interrupts • Ada 83 style interrupt entry handlers for interrupts In general, the range of possible solutions trades off latency versus restrictions in the handler code. Restrictions in direct vectored interrupt handlers are documented in the VxWorks Programmer’s Guide. Protected procedure handlers have only the restriction that no potentially blocking operations are performed within the handler. Interrupt entries have no restrictions. We recommend the use of the protected procedure mechanism as providing the best balance of these considerations for most applications. All handler types must explicitly perform any required hardware cleanups, such as issuing an end-of-interrupt if necessary. Note that in the examples below certain routines are specific to VME bus interrupt handling. These are only examples, and the appropriate routines for your processor and board should be used instead. • Direct Vectored Interrupt Routines This approach provides the lowest interrupt latency, but has the most restrictions on what VxWorks and Ada run-time calls can be made, as well as on what Ada entities are accessible to the handler code. Such handlers are most useful when there are stringent latency requirements, and very little processing is to be performed in the handler. Access to the necessary VxWorks routines for setting up such handlers is provided in the package Interfaces.VxWorks. VxWorks restrictions are described in the VxWorks Programmer’s Manual. Note in particular that floating point context is not automatically saved and restored when interrupts are vectored to the handler. If the handler is to execute floating point instructions, the statements involved must be bracketed by a pair of calls to fppSave and fppRestore defined in Interfaces.VxWorks. As the compiler may use floating point registers for non-floating-point operations (such as memory block copy) it is highly recommended to either save and restore floating point registers or to inspect code generated for the interrupt handler. As stack checking doesn’t work within an interrupt handler, be sure that units containing interrupt handlers are not compiled with -fstack-check. As there is no task identity when executing an interrupt handler, any Ada run time library code that depends on knowing the current task’s identity must not be used. This includes tasking constructs (except for most subprograms of Ada.Synchronous_Task_Control), concatenation and other functions with unconstrained results, and exception propagation. In general, it is a good idea to save and restore the handler that was installed prior to application startup. Please refer to VxWorks manuals. The Ada handler code is installed into the vector table using routine intConnect, which generates wrapper code to save and restore registers. Example:

with Interfaces.VxWorks; use Interfaces.VxWorks; with System; (continues on next page)

70 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

package P is

Count: Natural :=0; pragma Atomic(Count);

-- Interrupt level used by this example Level: constant :=1;

-- Be sure to use a reasonable interrupt number for the target -- board! Refer to the BSP for details. Interrupt: constant := 16#14#;

procedure Handler(Parameter: System.Address);

end P;

package body P is

procedure Handler(parameter: System.Address) is S: Status; begin Count := Count+1; -- Acknowledge interrupt. Not necessary for all interrupts. S := sysBusIntAck(intLevel => Level); end Handler; end P;

with Interfaces.VxWorks; use Interfaces.VxWorks; with Ada.Text_IO; use Ada.Text_IO;

withP; use P; procedure Useint is task T;

S: Status;

task body T is begin for I in 1.. 10 loop Put_Line("Generating an interrupt..."); delay 1.0;

-- Generate interrupt, using interrupt number S := sysBusIntGen(Level, Interrupt); end loop; end T;

-- Save old handler Old_Handler: VOIDFUNCPTR := intVecGet(INUM_TO_IVEC(Interrupt)); begin S := intConnect(INUM_TO_IVEC(Interrupt), Handler'Access); S := sysIntEnable(intLevel => Level);

for I in 1.. 10 loop delay 2.0; Put_Line("value of count:"& P.Count'Img); (continues on next page)

Contents 71 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) end loop;

-- Restore previous handler S := sysIntDisable(intLevel => Level); intVecSet(INUM_TO_IVEC(Interrupt), Old_Handler); end Useint;

• Direct Vectored Interrupt Routines that Signal a Pending Task A variation on the direct vectored routine that allows for less restrictive handler code is to separate the interrupt processing into two levels. The first level is the same as in the previous section. Here we perform simple hardware actions and signal a task pending on a Suspension_Object (defined in Ada.Synchronous_Task_Control) to perform the more complex and time-consuming operations. The routine Set_True signals a task whose body loops and pends on the suspension object using Suspend_Until_True. The suspension object is declared in a scope global to both the handler and the task. This approach can be thought of as a slightly higher-level application of the C example using a binary semaphore given in the VxWorks Programmer’s Manual. In fact, the implementation of Ada.Synchronous_Task_Control is a very thin wrapper around a VxWorks binary semaphore. This approach has a latency between the direct vectored approach and the protected procedure approach. There are no restrictions in the Ada task code, while the handler code has the same restrictions as any other direct interrupt handler. Example:

with System; package Sem_Handler is

Count: Natural :=0; pragma Atomic(Count);

-- Interrupt level used by this example Level: constant :=1; Interrupt: constant := 16#14#;

-- Interrupt handler providing "immediate" handling procedure Handler(Param: System.Address);

-- Task whose body provides "deferred" handling task Receiver is pragma Interrupt_Priority (System.Interrupt_Priority'First+ Level+1); end Receiver;

end Sem_Handler;

with Ada.Synchronous_Task_Control; use Ada.Synchronous_Task_Control; with Interfaces.VxWorks; use Interfaces.VxWorks; package body Sem_Handler is

SO: Suspension_Object;

task body Receiver is begin loop -- Wait for notification from immediate handler (continues on next page)

72 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) Suspend_Until_True(SO);

-- Interrupt processing Count := Count+1; end loop; end Receiver;

procedure Handler(Param: System.Address) is S: STATUS; begin -- Hardware cleanup, if necessary S := sysBusIntAck(Level);

-- Signal the task Set_True(SO); end Handler;

end Sem_Handler;

with Interfaces.VxWorks; use Interfaces.VxWorks; with Ada.Text_IO; use Ada.Text_IO; with Sem_Handler; use Sem_Handler; procedure Useint is

S: STATUS;

task T;

task body T is begin for I in 1.. 10 loop Put_Line("Generating an interrupt..."); delay 1.0;

-- Generate interrupt, using interrupt number S := sysBusIntGen(Level, Interrupt); end loop; end T;

-- Save old handler Old_Handler: VOIDFUNCPTR := intVecGet(INUM_TO_IVEC(Interrupt)); begin S := intConnect(INUM_TO_IVEC(Interrupt), Handler'Access); S := sysIntEnable(intLevel => Level);

for I in 1.. 10 loop delay 2.0; Put_Line("value of Count:"& Sem_Handler.Count'Img); end loop;

-- Restore handler S := sysIntDisable(intLevel => Level); intVecSet(INUM_TO_IVEC(Interrupt), Old_Handler); abort Receiver; end Useint;

• Protected Procedure Handlers for Interrupts

Contents 73 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

This is the recommended default mechanism for interrupt handling. It essentially wraps the hybrid handler / task mechanism in a higher-level abstraction, and provides a good balance between latency and capability. Vectored interrupts are designated by their interrupt number, starting from 0 and ranging to the number of entries in the interrupt vector table - 1. In the GNAT VxWorks implementation, the following priority mappings are used: – Normal task priorities are in the range 0 .. 245. – Interrupt priority 246 is used by the GNAT Interrupt_Manager task. – Interrupt priority 247 is used for vectored interrupts that do not correspond to those generated via an interrupt controller. – Interrupt priorities 248 .. 255 correspond to PIC interrupt levels 0 .. 7. – Priority 256 is reserved to the VxWorks kernel. Except for reserved priorities, the above are recommendations for setting the ceiling priority of a protected object that handles interrupts, or the priority of a task with interrupt entries. It’s a very good idea to follow these recommendations for vectored interrupts that come in through the PIC as it will determine the priority of execution of the code in the protected procedure or interrupt entry. No vectored interrupt numbers are reserved in this implementation, because dedicated interrupts are determined by the board support package. Obviously, careful consideration of the hardware is necessary when handling interrupts. The VxWorks BSP for the board is the definitive reference for interrupt assignments. Example:

package PO_Handler is

-- Interrupt level used by this example Level: constant :=1;

Interrupt: constant := 16#14#;

protected Protected_Handler is procedure Handler; pragma Attach_Handler(Handler, Interrupt);

function Count return Natural;

pragma Interrupt_Priority(248); private The_Count: Natural :=0; end Protected_Handler;

end PO_Handler;

with Interfaces.VxWorks; use Interfaces.VxWorks; package body PO_Handler is

protected body Protected_Handler is

procedure Handler is S: Status; begin -- Hardware cleanup if necessary S := sysBusIntAck(Level);

(continues on next page)

74 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- Interrupt processing The_Count := The_Count+1; end Handler;

function Count return Natural is begin return The_Count; end Count; end Protected_Handler;

end PO_Handler;

with Interfaces.VxWorks; use Interfaces.VxWorks; with Ada.Text_IO; use Ada.Text_IO;

with PO_Handler; use PO_Handler; procedure Useint is

task T;

S: STATUS;

task body T is begin for I in 1.. 10 loop Put_Line("Generating an interrupt..."); delay 1.0;

-- Generate interrupt, using interrupt number S := sysBusIntGen(Level, Interrupt); end loop; end T;

begin S := sysIntEnable(intLevel => Level);

for I in 1.. 10 loop delay 2.0; Put_Line("value of count:"& Protected_Handler.Count'Img); end loop;

S := sysIntDisable(intLevel => Level); end Useint;

This is obviously significantly higher-level and easier to write than the previous examples. • Use of Alternate Interrupt Connection Routines The default connection routine for handlers in VxWorks is intConnect(), defined in intArchLib. Some boards require special routines (e.g. for PCI). GNAT provides package Interfaces.VxWorks. Int_Connection to allow a user to dynamically substitute alternate connection routines prior to calling Ada.Interrupts.Attach_Handler. This facility is only available for unrestricted Ada runtime libraries, when using the protected procedure mechanism for interrupt handling. Use of pragma Attach_Handler is incompatible with the use of an alternate connection routine. Connection routines should have the same profile as intConnect():

Contents 75 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

type Interrupt_Connector is access function (Vector: Interrupt_Vector; Handler: VOIDFUNCPTR; Parameter: System.Address := System.Null_Address) return STATUS; pragma Convention(C, Interrupt_Connector);

They are registered for subsequent calls to Ada.Interrupts.Attach_Handler by passing an access to them into Interfaces.VxWorks.Int_Connection.Connect. The connection routine can be changed multiple times in an application. • Ada 83 Style Interrupt Entries GNAT provides a full implementation of the Ada 83 interrupt entry mechanism for vectored interrupts. However, due to latency issues, we only recommend using these for backward compatibility. The comments in the previous section regarding interrupt priorities and reserved interrupts apply here. In order to associate an interrupt with an entry, GNAT provides the standard Ada convenience routine Ada. Interrupts.Reference. It is used as follows:

Interrupt_Address: constant System.Address := Ada.Interrupts.Reference(Int_Num);

task Handler_Task is pragma Interrupt_Priority(248); -- For instance entry Handler; for Handler'Address use Interrupt_Address; end Handler_Task;

Since there is no restriction within an interrupt entry on blocking operations, be sure to perform any hardware interrupt controller related operations before executing a call that could block within the entry’s accept statements. It is assumed that interrupt entries are always open alternatives when they appear within a selective wait statement. The presence of a guard gives undefined behavior. Example:

with Ada.Interrupts; with System; package Task_Handler is

-- Interrupt level used by this example Level: constant :=1;

Interrupt: constant := 16#14#;

Interrupt_Address: constant System.Address := Ada.Interrupts.Reference(Interrupt);

task Handler_Task is pragma Interrupt_Priority(248); -- For instance entry Handler; for Handler'Address use Interrupt_Address;

entry Count(Value: out Natural); end Handler_Task; end Task_Handler;

with Interfaces.VxWorks; use Interfaces.VxWorks; (continues on next page)

76 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) package body Task_Handler is

task body Handler_Task is The_Count: Natural :=0; S: STATUS; begin loop select accept Handler do -- Hardware cleanup if necessary S := sysBusIntAck(Level);

-- Interrupt processing The_Count := The_Count+1; end Handler; or accept Count(Value: out Natural) do Value := The_Count; end Count; end select; end loop; end Handler_Task;

end Task_Handler;

with Interfaces.VxWorks; use Interfaces.VxWorks; with Ada.Text_IO; use Ada.Text_IO;

with Task_Handler; use Task_Handler; procedure Useint is

task T;

S: STATUS; Current_Count: Natural :=0;

task body T is begin for I in 1.. 10 loop Put_Line("Generating an interrupt..."); delay 1.0;

-- Generate interrupt, using interrupt number S := sysBusIntGen(Level, Interrupt); end loop; end T;

begin S := sysIntEnable(intLevel => Level);

for I in 1.. 10 loop delay 2.0; Handler_Task.Count(Current_Count); Put_Line("value of count:"& Current_Count'Img); end loop;

S := sysIntDisable(intLevel => Level); (continues on next page)

Contents 77 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) abort Handler_Task; end Useint;

A.1.11 Handling Relocation Issues for PowerPC Targets

This section summarizes the issue of greater than 24bit relocations (which can occur in very large applications), how it is solved by default, and the drawbacks of the solution. The issues and solutions are different for kernel mode apps vs RTPs.

Kernel Mode

Summary

The -mlongcall option is on by default for all compilations, including the compilation of binder-generated files. This switch morphs a 24bit relocation into a 32bit absolute reference, resulting in a per-call performance penalty and bloat in the object code. A user requiring the relative addressing mode (for example for performance or code size tuning) will need to explicitly specify the -mno-longcall switch.

Technical Details

VxWorks on the PowerPC follows the variation of the SVR4 ABI known as the Embedded ABI (EABI). In order to save space and time in embedded applications, the EABI specifies that the default for subprogram calls should be the branch instruction with relative addressing using an immediate operand. The immediate operand to this instruction (relative address) is 24 bits wide. It is sign extended and 2#00# is appended for the last 2 bits (all instructions must be on a 4 boundary). The resulting 26 bit offset means that the target of the branch must be within +/- 32 Mbytes of the PC-relative branch instruction. When loading a program, VxWorks completes the linking phase by resolving all of the unresolved references in the object being loaded. When one of those references is a relative address in a branch instruction, and the linker determines that the target is more than 32 Mbytes away from the branch, the error occurs. This only happens when the BSP is configured to use more than 32 MBytes of memory. The VxWorks kernel is loaded into low memory addresses, and the error usually occurs when the target loader is used (because it loads objects into high memory, and thus calls from the program to the VxWorks kernel can be too far). One way to solve this problem is to use the Workbench host loader; this will place programs in low memory, close to the kernel. The default use of the -mlongcall option for gcc causes the compiler to construct the absolute address of a subprogram in a register and use a branch instruction with absolute addressing mode. To see the effect of -mlongcall, consider the following small example:

procedure Proc is procedure Imported_Proc; pragma Import(Ada, Imported_Proc); begin Imported_Proc; end;

If you compile Proc with the option -mno-longcall, the following code is generated:

78 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

_ada_proc: ... bl imported_proc ...

In contrast, here is the result with the default -mlongcall:

_ada_proc: ... addis9,0,imported_proc @ha addi0,9,imported_proc @l mtlr0 blrl ...

For additional information on this issue, please refer to WRS’ SPRs 6040, 20257, and 22767.

RTPs

The -mlongcall option is off by default for all compilations. Instead the linker switch --relax is on by default. During linking, an out of range call is detected and space is allocated at the end if each input object for only those “long calls” that are necessary, so the computational and code bloat is minimized. No user intervention is required.

A.1.12 Calling exported Ada procedures from the VxWorks shell

If you need to call Ada subprograms from outside your Ada application (for example, from the host or target shell, from a driver or a C or C++ application), you will in general need to make the executing task known to the Ada run-time library. A typical situation is the need to enable or disable traces in your Ada application from the shell by calling an Ada procedure that sets the value of a Boolean controlling the traces. The problem is the following: when you call the Ada subprogram, it may raise an exception on the target. This could be through normal execution, or it could be caused solely by the fact that the thread executing the subprogram has not been made known to the Ada run-time library. There are a number of situations in Ada applications where the run-time library must be able to determine what task is running, and must be able to access some Ada-specific data structures in order to do its job. If a VxWorks task has not been registered, the ‘id’ that is accessed by the run-time library will be invalid, and will reference invalid data (or invalid memory). The solution is to use the GNAT.Threads.Register_Thread and GNAT.Threads.Unregister_Thread routines, so that the task which called the subprogram is known to the Ada run-time. This way, when the Ada task id is requested at some point in the procedure’s execution, a valid value will be fetched, and the necessary data structures will have been allocated and properly initialized. The following small example shows how to use this feature:

package Traces is

procedure Put_Trace(Info: String); -- Print Info on the standard output if the traces are on

procedure Trace_On; pragma Export(C, Trace_On, "trace_on"); -- Activate the traces

(continues on next page)

Contents 79 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) procedure Trace_Off; pragma Export(C, Trace_Off, "trace_off"); -- Deactivate the traces end Traces; with System; use System; with Ada.Text_IO; use Ada.Text_IO; with GNAT.Threads; use GNAT.Threads; package body Traces is Trace: Boolean := False;

------Put_Trace ------

procedure Put_Trace(Info: String) is begin if Trace then Put_Line(Info); end if; end Put_Trace;

------Trace_On ------

procedure Trace_On is Id: System.Address; begin Id := Register_Thread; Trace := True; Unregister_Thread; end Trace_On;

------Trace_Off ------

procedure Trace_Off is Id: System.Address; begin Id := Register_Thread; Trace := False; Unregister_Thread; end Trace_Off; end Traces; with Traces; use Traces; procedure Increment is Value: Integer :=1; begin for J in 1.. 60 loop Value := Value+1; Put_Trace(Integer'Image(Value)); delay 1.0; end loop; (continues on next page)

80 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) end Increment;

After having compiled and loaded the application on your target, spawn it and control the traces by calling trace_on and trace_off from the shell. You should see numbers displayed in the VxWorks console when the traces are on.

-> sp increment task spawned: id=3b0dcd0, name= s1u0 value= 61922512= 0x3b0dcd0 -> trace_on value=0= 0x0 -> trace_off value=0= 0x0

A.1.13 Simulating Command Line Arguments for VxWorks

The GNAT implementation of Ada.Command_Line relies on the standard C symbols argv and argc. The model for invoking kernel ‘programs’ under VxWorks does not provide these symbols. For kernel programs the typical method for invoking a program under VxWorks is to call the sp function in order to spawn a thread in which to execute a designated routine (in GNAT, this is the implicit main generated by gnatbind). sp provides the capability of pushing a variable number of arguments onto the stack when the function is invoked. But this does not work for the implicit Ada main, because it has no way of knowing how many arguments might be required. This eliminates the possibility of using Ada.Command_Line for kernel applications. However there is no such restriction for either command line arguments nor for environment variables for RTP mode ‘programs’. For more information see the VxWorks documentation for rtpLib/rtpSpawn(). One way to solve this problem is to define symbols in the VxWorks environment, then import them into the Ada application. For example, we could define the following package that imports two symbols, one an int and the other a string:

with Interfaces.C.Strings; use Interfaces.C.Strings; package Args is -- Define and import a variable for each argument Int_Arg: Interfaces.C.Int; String_Arg: Chars_Ptr; private pragma Import(C, Int_Arg, "intarg"); pragma Import(C, String_Arg, "stringarg"); end Args;

An Ada unit could then use the two imported variables Int_Arg and String_Arg as follows:

with Args; use Args; with Interfaces.C.Strings; use Interfaces.C, Interfaces.C.Strings; with Ada.Text_IO; use Ada.Text_IO; procedure Argtest is begin Put_Line(Int'Image(Int_Arg)); Put_Line(Value(String_Arg)); end Argtest;

When invoking the application from the shell, one will then set the values to be imported, and spawn the application, as follows:

Contents 81 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

-> intarg=10 -> stringarg="Hello" -> sp (argtest)

A.1.14 Traceback Support on VxWorks

Call stack traceback computation is supported on VxWorks. Such computation is sometimes triggered implicitly, for instance when a program which was compiled with binder switch -E reports an unhandled exception. In addition, traceback computation can also occur through the use of dedicated units provided by your runtime, such as Ada.Exceptions.Traceback or, for runtimes that support it, GNAT.Traceback.

Traceback Computation When Using Restricted Runtimes

If your application meets all of the following criteria, then you need to compile your application with -fno-omit-frame- pointer: • Your application depends on System.Traceback, indicating that it may have to compute some tracebacks; • Your application is built using a restricted runtime (e.g. cert or ravenscar-cert); • Your application is targetting one of the following architectures: – AArch64 This requirement allows a significant reduction in complexity of the traceback computation algorithm, thus making it more practical to provide this capability to projects where certification is a factor.

A.1.15 Using addr2line on VxWorks

For general information about addr2line, see “Getting Internal Debugging Information” in the GNAT User’s Guide for Native Platforms.

Differences between VxWorks and native platforms

Using addr2line on VxWorks, where modules are often dynamically loaded, is a bit different than on native platforms. When dealing with dynamically loaded modules, one needs to determine the offset at which the module has been loaded. This allows addr2line to correlate the target addresses of the stack trace with the addresses in the load module. On VxWorks, there are three ways a module can be located into target memory: • it is dynamically linked and loaded (DKM) • it is statically linked with the kernel (SKM) • it is linked into its own virtual address space (RTP) In all cases, the addresses used in the module are different from the ones used within the target memory address space under VxWorks. In contrast, on a native system, the executable has the same addresses in the object file and in memory, as virtual addresses are used. There is no need to collate the addresses on target with those in the object module. While RTPs do execute in their own virtual address spaces, the adainit address still needs to be determined as described below. As addr2line uses the addresses in the module, we need to adjust the addresses returned as a traceback at run-time so that they can be correctly interpreted by addr2line. To do this manually, we would follow a procedure like this:

82 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A symbol that is always present in the module is determined in order to compute the offset between the addresses at run-time and the addresses in the module. Its address in the module is subtracted from its address in memory, and the computed delta is added to each address in the traceback.

Using -vxaddr2line

Manually performing the computation just described is tedious, so a tool has been introduced to automate the process: -vxaddr2line, where is the name of target (e.g. powerpc-wrs-vxworks for VxWorks 6.x and VxWorks 7. powerpc-wrs-vxworksae for VxWorks 653 2.x). All that needs to be done is to give the name of the module, the address of the symbol adainit in memory and the traceback values as parameters. The computation is then done automatically, and the result is transmitted to addr2line, which returns the symbolic traceback in the usual manner.

An example

The example session of this section is for powerpc-wrs-vxworks. Replace this target name by the target you are using. Consider the following simple source code :

1 2 procedure CE is 3 4 procedure Raise_Constraint_Error is 5 begin 6 raise Constraint_Error; 7 end; 8 9 procedure Sub_2 (Should_Raise_CE : Boolean) is 10 begin 11 if Should_Raise_CE then 12 Raise_Constraint_Error; 13 end if; 14 end; 15 16 procedure Sub_1 is 17 begin 18 Sub_2 (Should_Raise_CE=> True); 19 end; 20 begin 21 Sub_1; 22 end;

• Build the example with gprbuild, providing the -E binder argument in this case so that a raw backtrace is returned for the unhandled exception. -g is required in any case because addr2line uses debug information to perform the symbolic transcription.

$ gprbuild --target=powerpc-wrs-vxworks -g ce -bargs -E

Compile [Ada] ce.adb Bind [gprbind] ce.bexch [Ada] ce.ali Link [link] ce.adb

• Load and run the resulting module on the target board. It raises the expected unhandled exception and generates the associated raw backtrace:

Contents 83 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

-> ld< ce.out Loading/ce.out| value= 591824= 0x907d0 -> sp ce task spawned: id=1b8aae0, name= s2u0 value= 28879584= 0x1b8aae0 -> Execution terminated by unhandled exception Exception name: CONSTRAINT_ERROR Message: ce.adb:6 traceback locations: 0x3b8394 0x3b83e0 0x3b8420 0x3b8458 0x3b82f0 0x19a184

Now convert the backtrace into symbolic references. . . • Determine the address of a reference symbol of the module (we use the address of adainit), which we obtain by calling the VxWorks lkup function for SKMs and DKMs:

-> lkup"adainit" adainit 0x003b81d0 text (ce.out) value=0= 0x0

• For RTPs, adainit can be found using in a command shell:

powerpc-wrs-vxworks-nm foo.rtp| grep adainit-

• We now have the information needed to run vxaddr2line:

powerpc-wrs-vxworks-vxaddr2line ce.out 0x003b81d0 0x3b8394... 0x19a184 ------exec file Ref.addr. Run-Time backtrace

This gives the following:

000001C0 at.../ce.adb:6 0000020C at.../ce.adb:12 0000024C at.../ce.adb:18 00000284 at.../ce.adb:21 0000011C at.../b~ce.adb:88

[meaningless output for the last address] The last line is not shown here because it designates stub code within VxWorks and is not part of the user’s application. Note that on VxWorks 653 2.x, the program name argument to vxaddr2line is the .sm file for the partition in which the application is executing.

84 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.1.16 Removal of Unused Code and Data

GNAT for VxWorks supports unused code and data elimination. For a complete description of this functionality, please refer to the GNAT User’s Guide. The use of this functionality requires some extra care for VxWorks. GNAT for VxWorks performs partial linking by default on all VxWorks versions, except VxWorks 6 and 7 in RTP mode. Because of this partial linking, the unused code and data elimination requires the use of -e / --entry ld option to work correctly. The use of these options is described in the GNAT User’s Guide. For example, in order to compile my_program.adb, you can use the following command line:

$ gprbuild --target=powerpc-wrs-vxworks my_program -cargs -ffunction-sections \ > -fdata-sections -largs -Wl,--gc-sections -Wl,--entry=my_program

Compile [Ada] my_program.adb Bind [gprbind] my_program.bexch [Ada] my_program.ali Link [link] my_program.adb

f To debug a program built with these options on gdb, the option -gdwarf-3 should be used.

A.1.17 Debugging

In general, two are available for GNAT applications targeting VxWorks: the Workbench debugger and gdb (via GNAT Studio). The Workbench debugger can be used for all targets supported by Workbench 3.3.x or Workbench 4. gdb can be only used on these versions of VxWorks: • VxWorks 6 and VxWorks 6 Cert (under WB 3.3.x). SMP configurations are not supported. Debugging RTPs is not supported. • VxWorks 653 1.8.9.2 and 2.x (under WB 3.3.x). In order to display the value of an Ada object in Workbench, right-click on one of its occurrences in the source editor and select Add Watch Expression.... The encoded name of the entity will be displayed in a dialog window: for example, a variable named Alpha declared in package Ownship will be shown as ownship__alpha. After clicking on OK, you will see that the corresponding expression has been added to the Expression view. From there, you will be able to browse the content of your object. Workbench also displays the value of local variables in Ada subprograms; these are shown by the view Variables. For more information about the Workbench debugger, see Wind River WorkBench User’s Guide.

Contents 85 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.1.18 Frequently Asked Questions for VxWorks

• When I run my program twice on the board, it does not work. Why not? Ada programs generally require elaboration and finalization, so the compiler creates a wrapper procedure whose name is the same as the Ada name of the main subprogram, which invokes the elaboration and finalization routines before and after your program executes. But the static part of the elaboration is handled while loading the program itself, so if you launch it twice this part of the elaboration will not be performed the second time. This affects the proper elaboration of the GNAT run-time, and thus it is mandatory to reload your program before relaunching it. • Can I load a collection of subprograms rather than a standalone program? It is possible to write Ada programs with multiple entry points that can be called from the VxWorks shell (or from a C or C++ application). To do this, generate an externally-callable Ada subsystem (see “Binding with Non-Ada Main Programs” in the GNAT User’s Guide for Native Platforms. If you use this method, you need to call adainit before calling any Ada entry point. • When I use the break exception command, I get the message "exception" is not a function, why? If you are using gdb from GNAT: you are not in the proper language mode. Issue the command:

(gdb) set language ada

If you are using the gdb interface of Workbench: this debugger does not provide such a feature. You may emulate it by set breakpoints on the following functions: __gnat_debug_raise_exception for catching any exception, __gnat_unhandled_exception for catching only unhandled exceptions and __gnat_debug_raise_assert_failure to catch assert failures. • When I load a large application from the VxWorks shell using the ld command, the load hangs and never finishes. How can I load large ? This is a classic VxWorks problem when using the default rsh communication method. Using NFS instead should work. Use the nfsShowMount command to verify that your program is in a NFS mounted directory. • When I load a large application from the debugger using the wtx target connection, the load never finishes, why? Make sure that the memory cache size parameter of the target server is large enough. (target -m big_enough_size, or Memory cache size box in GUI.) • When I spawn my program under the VxWorks kernel shell, interactive input does not work, why? When a task is spawned from a kernel shell with the sp() or taskSpawn() command, it shares the same standard I/O file descriptors as the shell. Since the shell has a higher priority than the task, the shell receives the interactive input. The recommended method to pass input to such a task is via file redirection:

-> # here you can have interactive input -> main -> # here you cannot -> sp main -> # neither here -> taskSpawn("ess",100,0,8000000,main) -> # but you can input from a file: -> taskSpawn("Bae",100,0,8000000,main)< input_file

This approach is preferred because it removes the contention between the task and the shell over the interactive input.

86 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

VxWorks 6.9 and later include the ability for the standard input of the shell to be redirected to allow a task to access the interactive input unimpeded, an approach that may be suitable for some applications. See Redirecting Shell IO in the VxWorks Kernel Shell Users Guide for more information. • The errno of the task(s) of my Ada application is not null even though my application is running correctly. Is that normal? Yes. As explained in the VxWorks OS Libraries API Reference in the errnoLib section: “most VxWorks functions return ERROR when they detect an error, or NULL in the case of functions returning pointers. In general, they set an error status that describes the nature of the error”. There are a large number of calls to VxWorks functions in the Ada run-time. Whenever a system call returns a value indicating an error, the error status is set to a non-zero value. So despite the checking of the return value is to determine an appropriate action, errno can still be non-null. Resetting the error status in the Ada run-time each time a VxWorks function is called would add unnecessary system call overhead and would not avoid masking error status information that may appear in user code. So this approach would not help. It is a good practice not to rely on the error status value to detect errors. It should be only used to get more information on errors that have already been detected by checking the code returned by the VxWorks function. To be sure to get the error status corresponding to the error detected in the code, the use of the debugger is recommended. • I cannot display Ada objects in the debugger, why? On Workbench 3.3.x, Ada debugging is not enabled in the WB debugger. To enable it, you must set the environment variable DFW_ENABLE_ADA_SYMBOL_SEARCH to 1. You need only set this environment variable once, as long as it does not become undefined later.

A.2 Workbench / VxWorks 6.x Topics

This section describes topics that are specific to VxWorks 6. It introduces the basic features provided by the GNAT toolchain for this target, and shows how to use them. It also describes which functionalities are implemented, and describes some commonly encountered known issues. Full lists of known issues by version and platform are available in GNATtracker on the Documentation panel.

A.2.1 Installing GNAT for VxWorks 6

The installation of GNAT for PowerPC VxWorks 6.9 hosted on GNU/Linux requires the VxWorks environment to be set, allowing it to locate some files provided by VxWorks.

A.2.2 Using GNAT for VxWorks 6

GNAT for VxWorks 6 comes with two development environments: • GNAT Studio, which is the standard GNAT IDE. • GNATbench, the GNAT plug-in for Workbench (Wind River’s IDE based on Eclipse). Both environments share a common core technology, the GNAT Studio engine, so the choice of environment is mostly a matter of taste. GNAT Studio is more GNAT-centric and Workbench with the GNATbench plug-in is more VxWorks- centric. The debugger technology depends on the environment. The underlying debugger is gdb in GNAT Studio, and DFW in Workbench. Both debuggers are well integrated into their respective development environments. The debugging

Contents 87 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w interface in Workbench has a more VxWorks-centric view, and has practical displays to interact with the target. GNAT Studio has, via gdb, additional knowledge about Ada-specific data structures and provides additional facilities to display Ada variables. The choice between the GNAT Studio and the Workbench development environment will be determined by your development habits and your personal preferences. Note that when using Workbench, you can easily switch to GNAT Studio to use some GNAT Studio-specific features such as the entity viewer or the dependency graph, and then switch back to Workbench. GNAT Studio is opened with the same files as Workbench, and file synchronization is assured between GNAT Studio and Workbench.

A.2.3 Building a VxWorks 6 Application

GNAT for VxWorks 6 supports two build interfaces: • Workbench • GNAT Studio for three types of modules: • downloadable kernel modules (DKM) • real time process (RTP) modules • statically linked kernel modules (SKM) for VxWorks Cert

Building from Workbench

The GNATbench Ada Development User Guide describes how to use GNATbench within Workbench. This document, like all Workbench user guides, is accessible via the “Help Contents” sub-menu entry under the top-level Workbench “Help” menu. See the “Building” chapter for all the topics related to building Ada projects within Workbench. This chapter includes general material, such as an overview of the predefined and GNATbench-defined build commands, as well as specific information that is essential to building with GNATbench. When building a downloadable kernel module (DKM) using GNATbench, make sure that the Linker.Switches () attribute includes "-noauto-register". This switch prevents conflicts with the OS-provided static constructors and destructors that are added into DKM projects by Workbench when it builds an application module. The GNATbench documentation provides a number of tutorials with detailed, step-by-step instructions and screen- shots showing how to create and build VxWorks projects. These tutorials are located under the top-level node of the GNATbench Ada Development User Guide.

Building from GNAT Studio

Chapter “Working in a Cross Environment” in the GNAT Studio User’s Guide explains how to adapt a project and configure GNAT Studio to work in a cross environment.

88 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

RTPs and kernel modules

To support both RTPs and kernel modules, two different run-time libraries are provided. For example, you can build an Ada kernel module (DKM) from the demo1 example using the following command:

$ gprbuild --target=powerpc-wrs-vxworks -g --RTS=kernel demo1

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

This will build a relocatable object that you can download in the kernel context. The -g switch adds debugging information to the module. If you are building the same DKM within GNATbench, add the following into the Linker package in your root GPR file: package Linker is for Switches("Ada") use (..., "-noauto-register", "-r",...); end Linker;

The linker switch prevents conflicts with the munching step performed by Workbench on relocatable DKMS. For SKMs (to be statically linked into the VxWorks image), use:

$ gprbuild --target=powerpc-wrs-vxworks -g --RTS=kernel demo1 -largs -nostdlib -r

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

In this case, the -nostdlib switch prevents conflicts between the GNAT Pro version of libgcc.a and that provided by VxWorks, by suppressing the inclusion of the former. The -r switch allows a partial link that will be resolved when linked into the image. To build an Ada RTP module, you use the RTP run-time library. The compiler will automatically find the VxWorks 6 RTP libraries using the WIND_BASE environment variable. Note that if you want to build an application for ’ VxSim simulator you will need to pass the -vxsim switch to the linker. Otherwise the application will be built for a real x86 target. The previous example may be built as follows:

$ gprbuild --target=powerpc-wrs-vxworks -g --RTS=rtp demo1

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb (continues on next page)

Contents 89 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

To do so in GNAT Studio, you need to update your project properties and add the switches to the corresponding project attributes (e.g., –RTS=rtp, -mrtp for Ada build options). Note that use of gprconfig/gprbuild will insert the necessary includes, library references and -mrtp switches for compilation and linking automatically. If you are storing a RTP in a ROM filesystem (for example when using RTPs with the VxWorks Cert 6.x certified kernel), you must specify the base address for the RTP using a linker switch. This one generally works due to default memory layout:

package Linker is for Switches("Ada") use (..., "-Wl,--defsym,__wrs_rtp_base=0x40000000",...); end Linker;

None of the above special switches need to be provided when using Workbench with the GNATbench plugin to perform VxWorks 6 builds. VxWorks 7 builds for VxSim do require definition of __wrs_rtp_base, and the value is platform-dependent.

A.2.4 SMP Support

Starting with VxWorks 6.6, the OS supports symmetric multi-processing (SMP) for specific target boards. GNAT includes run-time libraries supporting DKM, SKM and RTP applications running on a SMP kernel. To use these libraries, use –RTS=kernel-smp or –RTS=rtp-smp, depending on the application type. When using these libraries, the VxWorks kernel must be configured with __thread support. These libraries are also compatible for use on uniprocessor kernels. Processor affinity is controlled using pragma Task_Info, by declaring a discriminant of . Task_Info.Task_Info_Type for a task type and giving it a value on task creation, or by using Ada 2012 pragma CPU. For the first two options, allowable values range from 0 to n-1, where n is the number of processors available. A value of zero sets the processor affinity to VxWorks logical processor 0, and so on. For pragma CPU, allowable values range from 1 to n, and the affinity in VxWorks terms is set to the logical processor with an ID one less than the specified value. Out of range values, or an attempt to use this mechanism on VxWorks versions prior to 6.6, will cause creation of the task to fail. By default, when the above mechanisms are not used, tasks inherit the processor affinity of the task that creates them (but see the notes on RTPs in the VxWorks user manuals). The Workbench debugger should be used to debug SMP applications, as multiprocessor synchronization is not provided in gdb.

90 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.2.5 Using the VxWorks 6 Simulator

If you have access to the build toolchain for the VxWorks simulator vxsim, it should be invoked using the i586-wrs-vxworks prefix. This toolchain also supports both RTP and kernel modules. The toolchain for the simulator is used in the same way as toolchains for real targets. Please see Building a VxWorks 6 Application. Note: RTPs to be run in vxsim need to be linked against vxsim-specific libraries. This can be done in GNAT Pro for Ada applications by specifying the linker switch -vxsim. The linker switch can be specified in the application’s project file:

Wind_Base := external ("WIND_BASE"); type Target_Machine_Type is ("vxsim", "real_target"); Target_Machine: Target_Machine_Type := external ("TARGET_MACHINE", "real_target"); package Linker is case Target_Machine is when "vxsim" => for Switches("Ada") use ("-vxsim"); when "real_target" => null; end case; end Linker;

For C-only RTPs built using gprbuild, the path to libraries should be passed explicitly:

Wind_Base := external ("WIND_BASE"); type Target_Machine_Type is ("vxsim", "real_target"); Target_Machine: Target_Machine_Type := external ("TARGET_MACHINE", "real_target"); package Linker is case Target_Machine is when "vxsim" => for Switches("C") use ("-L"& Wind_Base & "/target/usr/lib/simpentium/SIMPENTIUM/common", "-L"& Wind_Base & "/target/lib/usr/lib/simpentium/SIMPENTIUM/common"); when "real_target" => for Switches("C") use ("-L"& Wind_Base & "/target/usr/lib//PENTIUM/common", "-L"& Wind_Base & "/target/lib/usr/lib/pentium/PENTIUM/common"); end case; end Linker;

Contents 91 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.2.6 Debugging an Application on VxWorks 6

In VxWorks 6, the debugging interface used by the debuggers is a GDB/MI-based protocol named DFW. The component that offers debug services is called the DFW server. Therefore, to be able to connect to the target board, you need first to have a DFW server running and your target board registered with this server. You can do this in Workbench using the panels Remotes Systems or Target Manager. To run or debug an RTP, you need access to the file system where the RTP module is located. This can be done in several ways, for example via FTP or NFS. If the kernel has been loaded on the target board using an FTP server, the target board has access to the file system of this server. Therefore, if your RTP module is accessible in the FTP server’s file system, the target board will be able to load it. If not, you will have to use one of the other file system clients that VxWorks provides. Here is an example for NFS. Assuming that you want to execute /home/workspace/demo1.exe, located on a machine named rtphost whose IP address is 192.168.0.1 and which has a mountable NFS file system, you can execute it from the target shell with the following commands: hostAdd ("rtphost","192.168.0.1") nfsMount ("rtphost","/home/workspace","/mnt")

In the target server properties it is important to set the Pathname Prefix Mapping (corresponding to the previous settings) when creating the target server (section 19.1.3 of the Wind River WorkBench User’s Guide):

Target Path Host Path rtphost:/mnt/home/workspace /mnt/home/workspace

After this preliminary setup, you are ready to debug. A debugging session on VxWorks 6 comprises the following steps: • connect to the target board; • load the module into target memory; • execute and debug the application. The following sections explain how these steps map to the two debugging solutions: Workbench and GNAT Studio.

Using Workbench DFW

GNATbench is integrated into Workbench’s debugging solution. It provides Ada support similar to the what is available for C (breakpoints, control of the debugger execution, etc.). See Debugging for more information.

Using GNAT Studio and GDB

As already mentioned, the Ada debugger in GNAT Studio uses the DFW interface to control the execution of the program on the target. To debug an Ada program, the DFW server is launched from Workbench and then connected to the target. Note that gdb can only debug uniprocessor kernel applications; the Workbench debugger should be used for RTPs and SMP applications. gdb is not supported with Workbench 4, so cannot be used to debug when VxWorks 6 Cert is run as a guest OS over VxWorks 653 3.x.

92 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Several DFW servers may have been launched on your host; if so, you will need to tell the debugger which one to use. To do so: • In Workbench, open Windows => Preferences, then expand Wind River => Debug Server Setting. There, you should find the session name of the DFW server; e.g. dfw-wb3111-${user}. • Set the environment variable DFW_SERVER_NAME to this name; e.g., on Unix: DFW_SERVER_NAME=dfw-wb3111-me; export DFW_SERVER_NAME A kernel module generated by the GNAT toolchain can be loaded and run in the usual manner (for Ada or C DKMs). An example can be found in Common VxWorks Topics. Before starting a debugging session in GNAT Studio, you should ensure that several fields in your GNAT Project are filled in: • Program host: • Protocol: dfw to debug a kernel task • Debugger: powerpc-wrs-vxworks6-gdb The name of your connection to the board is displayed in Workbench, in the panel Remotes Systems or Target Manager, at the root of your target’s connection tree. As mentioned, the three steps to debug on VxWorks 6 are connecting, loading, and executing. To connect to your target and debug a kernel module, the debugger uses a target interface named dfw. To do so in GNAT Studio, you can specify the target protocol in your project properties, and use the menu Debug => Initialize => . Alternatively, if you want to use the command line debugger, you should use the target command:

(gdb) target dfw Connecting to DFW server:1603...Connecting to@... done.

where is the name of the target board you are attaching to. You can load your module either during initialization in GNAT Studio, with one of the choices given by the menu (e.g., Debug => Initialize => demo1), or from the console:

(gdb) load demo1

You can then start execution, using the menu Debug => Run or the Start/Continue button. As always, there is a corresponding call in the command line debugger, which is named start and takes the name of the main procedure as its argument:

(gdb) start demo1 Breakpoint1 at 0xad5768: file demo1.adb, line 4. Starting program: demo1 demo1 () at demo1.adb:4 4 procedure Demo1 is

If your module has already been loaded and executed from another tool (e.g. Workbench or the host shell) you can attach to the running process in the debugger. To do so, get the list of kernel tasks and RTPs with the command info wtx threads:

(gdb) info wtx threads 0 task 0x604df868 (tShell0) 1 task 0x6037bc70 (tWdbTask) 2 task 0x6036f6d8 (ipnetd) 3 task 0x604159e0 (ipcom_syslogd) (continues on next page)

Contents 93 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) 4 task 0x60427af0 (tNet0) 5 task 0x60403a38 (tAioIoTask0) 6 task 0x60403740 (tAioIoTask1) 7 task 0x603e59a8 (tAioWait) 8 task 0x6037e290 (tNbioLog) 9 task 0x60387c38 (tLogTask) 10 task 0x60170774 (tExcTask) 11 task 0x6037a480 (tJobTask) 12 task 0x73acc0 (tMy_p)

This gives you the id’s of the various tasks. To debug a task, use the attach command. For example, to attach tMy_p:

(gdb) attach 0x73acc0

You can then set breakpoints, start and stop the execution, and display the values of variables. . . For more detail, please refer to the GDB User’s Manual.

A.2.7 Known GNAT C++ Limitations on PowerPC VxWorks 6

• The most recent version of C++ being supported on this platform is C++-14. This is because support for more recent versions of C++ requires the target system to support C11. • The use of C99 complex numbers is not supported; use std::complex instead. • The std::thread::hardware_concurrency function is not supported; use the vxCpuEnabledGet function from vxCpuLib.h instead. • Due to system limitations, some C++ functions are not available in kernel mode. Here is a non-exhaustive list of those functions, as it can change depending on the VxWorks version : – asinh – acosl – asinl – atan2l – ceill – expl – fabsl – floorl – fmodl – frexpl – modfl – powl – sqrtl – tanl – tanhl – hypotl

94 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

– ldexpf – modff – hypotf – frexpf – std::isnan – std::vscanf

A.3 Workbench / VxWorks 7 Topics

This section describes topics that are specific to VxWorks 7. It introduces the basic features provided by the GNAT toolchain for this target, and shows how to use them. It also describes which functionalities are implemented, and summarizes commonly encountered known issues. Full lists of known issues by platform and version are available in GNATtracker in the Documentation panel.

A.3.1 Using GNAT for VxWorks 7

GNAT for VxWorks 7 here designates both: • GNAT Pro Ada • GNAT Pro C. Note that GNAT Pro Ada comes with a C compiler that is supported only for the following uses: • generating Ada bindings from C headers using -fdump-ada-spec; • rebuilding the Ada run-time library. GNAT for VxWorks 7 comes with a choice of two development environments: • GNAT Studio, which is the standard GNAT IDE. • GNATbench, the GNAT plug-in for Workbench (Wind River’s IDE based on Eclipse). Both environments share a common core technology, the GNAT Studio engine, so the choice of environment is mostly a matter of taste. GNAT Studio is more GNAT-centric and Workbench with the GNATbench plug-in is more VxWorks- centric. Note that interfacing GNAT with Wind River C++ compilers is only supported when building from GNATbench. See section Interoperability with VxWorks C/C++ Compilers for more details.

A.3.2 Building a VxWorks 7 Application

GNAT for VxWorks 7 supports two build interfaces: • Workbench • GNAT Studio for three types of modules: • downloadable kernel modules (DKM) • statically linked kernel modules (SKM) • real time process modules (RTP)

Contents 95 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Building a VxWorks 7 Application from Workbench

The GNATbench Ada Development User Guide describes how to use GNATbench within Workbench. This document, like all Workbench user guides, is accessible via the “Help Contents” sub-menu entry under the top-level Workbench “Help” menu. See the “Building” chapter for all the topics related to building Ada projects within Workbench. This chapter includes general material, such as an overview of the predefined and GNATbench-defined build commands, as well as specific information that is essential to building with GNATbench. When building a downloadable kernel module (DKM) using GNATbench, make sure that the Linker.Switches () attribute includes "-noauto-register". This switch prevents conflicts with the OS-provided static constructors and destructors that are added into DKM projects by Workbench when it builds an application image. You should also note that the GNATbench documentation includes a number of tutorials that provide detailed, step- by-step instructions and screen-shots showing how to create and build VxWorks projects. All of these tutorials are located under the top-level node of the GNATbench Ada Development User Guide.

Building a VxWorks 7 Application from GNAT Studio

Chapter “Working in a Cross Environment” in the GNAT Studio User’s Guide explains how to adapt a project and configure GNAT Studio to work in a cross environment.

VxWorks 7 RTPs and kernel modules

To support both RTPs and kernel modules, two different run-time libraries are provided. For example, you can build an Ada kernel module (DKM) from the demo1 example using the following command:

$ gprbuild --target=powerpc-wrs-vxworks7 -g --RTS=kernel demo1

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

This will build a relocatable object that you can download into the kernel context. The -g switch adds debugging information to the module. If you are building the same DKM within GNATbench, add the following into the Linker package in your root GPR file: package Linker is for Switches("Ada") use (..., "-noauto-register", "-r",...); end Linker;

The linker switch prevents conflicts with the munching step performed by Workbench on relocatable DKMs. For SKMs (which will be statically linked into the VxWorks image), use:

96 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

$ gprbuild --target=powerpc-wrs-vxworks7 -g --RTS=kernel demo1 -largs -nostdlib -r

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

In this case, the -nostdlib switch prevents conflicts between the GNAT Pro version of libgcc.a and that provided by VxWorks, by suppressing the inclusion of the former. The -r switch allows a partial link that will be resolved when linked into the image. To build an Ada RTP module, you will use the RTP run-time library. The compiler will automatically find the VxWorks 7 RTP libraries using the VSB_DIR environment variable. This variable should point to the root of the VxWorks Source Build for your target. The previous example may be built as follows:

$ gprbuild --target=powerpc-wrs-vxworks7 -g --RTS=rtp demo1 -largs -nostdlib -r

Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

To do so in GNAT Studio, you need to update your project properties and add the options to the corresponding project attributes (e.g., –RTS=rtp, -mrtp for Ada make options). Note that use of gprconfig/gprbuild will insert the necessary includes, library references and -mrtp switches for compilation and linking automatically. None of the above special switches need to be provided when using Workbench with the GNATbench plugin to perform builds. By default, an RTP is built statically, hence including all the necessary parts in the generated RTP file. It is also possible to build dynamically linked RTPs. To do that, you first need to specify the library as dynamic. This is done by adding the following in the library project file: for Library_Kind use"dynamic";

Then you have to specify that the RTP will use dynamic libraries. This is done by adding the following to the RTP project file: package Compiler is for Default_Switches ("ada") use ("-non-static"); end Compiler; package Linker is (continues on next page)

Contents 97 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) for Default_Switches ("ada") use ("-non-static"); end Linker;

A.3.3 VxWorks 7 SMP Support

VxWorks 7 supports symmetric multi-processing (SMP) and all GNAT runtimes are built with SMP support. But these runtimes can also be used with uniprocessor kernels. When using these libraries, the VxWorks kernel must be configured with __thread support. Processor affinity is controlled by using pragma Task_Info, by declaring a discriminant of type System. Task_Info.Task_Info_Type for a task type and giving it a value on task creation, or by using Ada 2012 pragma CPU. For the first two options, allowable values range from 0 to n-1, where n is the number of processors available. A value of zero sets the processor affinity to VxWorks logical processor 0, and so on. For pragma CPU, allowable values range from 1 to n, and the affinity in VxWorks terms is set to the logical processor with an ID one less than the specified value. Out of range values will cause creation of the task to fail. By default, when the above mechanisms are not used, tasks inherit the processor affinity of the task that creates them (but see the notes on RTPs in the VxWorks user manuals).

A.3.4 Debugging an Application on VxWorks 7

GNAT for VxWorks 7 generates debug information following the dwarf standard; this can be interpreted by the Workbench debugger. To use this debug technology, please consult the Workbench manual.

A.3.5 Using VxSim on VxWorks 7

For RTPs on VxWorks 7, an additional specification of __wrs_rtp_base must be provided for VxSim, the value of which depends on the architecture and Host OS. Refer to the BSP documentation for . This can be accomplished either explicitly as shown below, or by the setting of the WRS_RTP_BASE environment variable to .

package Linker is for Leading_Switches("Ada"|"C++"|"C") use (..., "-Wl,__rtp_base=",...); end Linker;

On VxWorks 7 (SR0600 and above) for x86_64, the kernel-large or rtp-large runtimes must be used when targetting VxSim-64. These runtimes have been built with -mcmodel=large, and their use with gprbuild also triggers the compilation of your code with that switch as well, ensuring that your entire application is built with the required -mcmodel.

98 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.3.6 Known GNAT C++ Limitations on VxWorks 7

• GNAT C++ is not supported with kernels built using the Safety Subset. • On 64-bit PowerPC, variadic virtual methods are only supported in RTP mode.

A.4 VxWorks 653 Topics

This section provides information specific to the GNAT cross-development system for the VxWorks 653 target. Supported versions are selected VxWorks 653 2.3.x, 2.4.x and 2.5.x editions. For VxWorks 653mc 3.1.x, VxWorks 6 Cert is supported as a guest OS. See the release notes for details.

A.4.1 Introduction

VxWorks 653 is a time- and space-partitioned real-time operating system that conforms to the ARINC-653 standard. Its purpose is to support the implementation of Integrated Modular Avionics (IMA) system architectures and similar architectures in other industries. Because an application running in one partition cannot be affected by those in different partitions, applications can be developed independently, and their safety certification can be unlinked from the safety certification of other subsystems. The VxWorks 653 architecture and programming model is described in the Wind River VxWorks 653 Programmer’s Guide. For programming purposes the operating system (OS) is divided into two parts:

• The Module OS, which contains drivers and other privileged software. This part of the system presents an API that is described in the VxWorks 653 Module OS API Reference, VxWorks 653 Module OS Errno Code List and the VxWorks 653 Programmer’s Guide. GNAT Pro does not directly support building applications for the Module OS. • The Partition OS, which is used within application partitions. This part of the system presents an API similar to that of VxWorks 5.x, or the VxWorks 6.x kernel, called vThreads for VxWorks 653 2.x. For VxWorks 3.x, VxWorks 6 Cert replaces vThreads. Each is enhanced with POSIX and APEX (ARINC-653) components. They are primarily described in the VxWorks 653 Partition OS API Reference, VxWorks 653 Partition OS Errno Code List and the VxWorks 653 Programmer’s Guide. GNAT for VxWorks 653 lets you develop applications for the various VxWorks 653 partition types and operating modes:

• Partition OS applications can be built with the full Ada run-time library (rts-full), a restricted Ravenscar run-time library (rts-light-tasking), or a restricted certifiable run-time library (rts-light). Appli- cation partitions may include either the full or partial APEX components, or just the vThreads components. It is expected that applications developed with GNAT will execute in application partitions under the Partition OS. This section describes the mechanics of building and debugging Ada applications for VxWorks 653, and also treats other issues relevant to application development in the various contexts listed above.

Contents 99 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A.4.2 Configuring a VxWorks 653 System

Typically, the platform will be jointly defined by specialists such as the platform developer and systems integrator. Application developers will then be provided with the platform and a description in XML configuration files of the resources available to them in the partitions their applications will execute. Definition of the platform is outside the scope of this manual, and is described in the VxWorks 653 Configuration and Build Guide. In this section, we will focus on integration of applications into the platform. We suggest you first familiarize yourself with the overall process as described in the above reference. This section applies to VxWorks 653 2.x. For VxWorks 653mc 3.x, the configuration schema is described in the corresponding configuration manual for that version. In the latter case, there is a small configuration file for the POS, and none for applications. They are simply built as SKMs and linked into the VxWorks 6 Cert POS kernel.

Application Configuration Files

For each application, there are two sections of XML configuration info to be provided. The first is in the partition description, which will be in either the module XML file, or in a partition-specific XML file. Refer to the VxWorks 653 Configuration and Build Guide for specific contents. An example fragment for a two partition system would be:

...

(continues on next page)

100 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

The application part references external XML files used to define the application characteristics, and the applications defined in that fragment are then referred to in the partition fragments. A typical application XML file will look like this:

Contents 101 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) Direction="SOURCE" MessageSize="4" QueueLength="100" Protocol="SENDER_BLOCK"/>

Its parts include a standard header that points to the corresponding schema, definition of the application entry point, the location of the generated object module and its name, memory area sizes, and an additional section to support C++ exception handling (if used). Finally, a section is provided that defines the APEX ports used by the applications. These are connected among partitions in the module XML file. A final configuration file that you may need to create (it will usually be provided as part of the platform) defines the interface to the system shared library that contains the partition operating system. An example for the certified vThreads POS would contain something like the following, and would be used as part of the application partition build as described in the next section:

Here we again see a standard header, followed by references to the interface description XML files for the components we need in the partition operating system. If, as recommended, you compose your systems directly with Workbench 3.3+ using GNATbench for VxWorks 653 2.4+, you will need to provide full XML files rather than the fragments described here.

102 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Partition Makefiles

This section applies to VxWorks 653 2.x. Full instructions for building with VxWorks 653mc 3.x appear in the GNATbench help files. Typical partition makefiles for C and C++ are described in the @cite{VxWorks 653 Configuration and Build Guide}. For Ada and mixed applications, we use the GPRbuild tool, rather than using .o files as targets as is shown in the guide. Here is an example makefile for a partition containing an Ada or mixed-language application. It is invoked from Makefile.wr in the usual way for building partitions, from within the VxWorks 653 development shell or Workbench. Note that if you are using GNATbench with VxWorks 653 2.4.x or more recent, GNATbench will automatically generate the partition Makefile, so this section can be skipped.

# Makefile.part1 - makefile for partition 1

######################## # # Parameters #

# INSTALL_DIR: root of build location # FIRST_APP_DIR, FIRST_APP_PROJ, FIRST_APP_MAIN: location, GPR file, module name # SYS_CFG_DIR: directory containing ssl interface file ssl.xml # XML_FILE: module XML file # POS: cert, full # RTS: full, light-tasking, light # BINDING: APEX binding to use - apex, apex_95, apex_minimal, apex_light, apex_light_

,→95 # CPU_TYPE: PPC, SIMNT

######################## # # Variables # include $(WIND_BASE)/target/vThreads/config/make/Makefile.vars

USER_OBJ = $(INSTALL_DIR)/part1/$(FIRST_APP_MAIN).o USER_MODULE = $(INSTALL_DIR)/first_app/$(FIRST_APP_MAIN).out

CFLAGS_EXTRA = "-DUSER_APPL_INIT=$(FIRST_APP_MAIN)()" ifeq ($(POS), cert) CFLAGS_EXTRA += -DCERT endif ifeq ($(POS),full) PART_OBJS = vThreadsCplusComponent.o \ vThreadsCplusLibraryComponent.o \ __ctype_tab.o else PART_OBJS = vThreadsCplusComponent.o endif ifeq ($(CPU_TYPE), PPC) BUILD_SPEC = powerpc-wrs-vxworksae else (continues on next page)

Contents 103 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) BUILD_SPEC = i586-wrs-vxworksae endif

######################## # # Rules # ######################## include $(WIND_BASE)/target/vThreads/config/make/Makefile.rules vpath %.gpr $(FIRST_APP_DIR) vpath %.c $(WIND_BASE)/target/vThreads/config/comps/src vpath %.c $(WIND_BASE)/target/vThreads/config/comps/src/templates default: part1.sm part1.rpt

# ssl.xml is the interface definition, not the ssl definition: ssl-stubs.c: $(SYS_CFG_DIR)/ssl.xml

FORCE_EXTERNAL_MAKE:

$(USER_MODULE): FORCE_EXTERNAL_MAKE gprconfig --batch --target=$(BUILD_SPEC) \ --config=ada,,$(RTS) --config=c --config=c++ gprbuild -P \ $(INSTALL_DIR)/first_app/$(FIRST_APP_PROJ) \ -gargs -XRuntime=$(RTS) -XCPU=$(CPU_TYPE) -XBinding=$(BINDING)

$(USER_OBJ): $(USER_MODULE) $(CP) $(USER_MODULE) $(USER_OBJ)

LDSFLAGS_EXTRA = -j $* part1.lds: $(XML_FILE)

LDFLAGS_EXTRA = -T $*.lds part1.sm: vxMain.o ssl-stubs.o $(USER_OBJ) $(PART_OBJS) part1.lds clean: $(RM) *-stubs.c *.o *.lds *.sm *.rpt powerpc-wrs-vxworksae-gnatclean -P \ $(INSTALL_DIR)/first_app/$(FIRST_APP_PROJ) \ -XRuntime=$(RTS) -XCPU=$(CPU_TYPE) -XBinding=$(BINDING)

A.4.3 Running and Debugging Applications

VxWorks 653 2.x and 3.x provide a sophisticated debugger that can handle C, C++ and Ada. The “GNATbench for WRS Workbench User’s Guide” describes how to prepare for debugging VxWorks 653 systems using Ada in the Workbench IDE and debugger. Specifically, see the “Preparing To Debug VxWorks 653 Integration Projects” section under the more general “Debugging” chapter of the guide. That chapter also discusses general use of the Workbench debugger for Ada. On 2.x, GNAT provides a VxWorks 653-targeted version of gdb that has been enhanced to provide Ada-knowledgeable debugging (as well as supporting C and C++). This version of gdb is normally invoked from within GNAT Studio

104 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w development environment. For 3.x, use the Workbench debugger. This section describes the use of the GNAT Studio debugger on VxWorks 653 2.x.

VxWorks 653 System Setup

In order to debug on VxWorks 653 you need to attach a debugger at the correct time during OS initialization. The suggested approach is to define two schedules for the system in the module XML file. The first (default) schedule does not allocate any time to application partitions; the second gives the application partitions their expected allotments. For example:

This approach will ensure that none of the application partitions will start execution after the system boots. We can then attach a debugger to a partition before it starts, so we can debug it from its beginning.

Contents 105 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Environment Setup

For VxWorks 653 2.x it is necessary to set up the Workbench environment variables for the debugger before launching GNAT Studio. These variables are set by the wrenv or wrenvw scripts, or by starting a Development Shell in Workbench (menu Project->Open Development Shell). The first sets up the environment in an existing shell; the second opens a new shell; the third opens a window within Workbench as a shell. On UNIX machines, source the script that corresponds to the shell you are using – wrenvsh. On a Windows machine, either make the system call the wrenv.bat or wrenvw.bat script on startup, or open a Development Shell in Workbench.

GNAT Studio Setup

In GNAT Studio, on the general properties page, designate the name of your target server in the Program Host field and select wtx as the protocol. Leave the Tools host field blank.

Debugging a Partition

The procedure to debug partition 1 is as follows: • Boot the target. It will eventually boot the partition OS and stop at a target shell prompt (assuming you’ve included a target shell). At this time, the Module OS has performed most of its initializations, and the partitions have been created, but not yet started. • Start your target server. This can be done from within Workbench, or from a command line (preferably using a shell script). It is recommended that you close the Workbench debugger if you start the target server from the Workbench GUI. • Within GNAT Studio, select Debug => Initialize => • Within GNAT Studio, select Debug``=>`Attach`. A dialog will pop up with a list of all Module OS tasks. Select ``tPartition1 from the list. The name given is constructed from the name of the partition as given in configRecord.c, prefixed by t. • At this point, you should be able to set breakpoints within the application partition, including the one to receive control whenever an exception occurs. You might also wish to display the call stack at this time by selecting Debug => Data => Call Stack. • Once you have set any desired breakpoints, hit the Continue button in GNAT Studio. The system is running, but since the first schedule is still being used by the core OS, the application partitions are not being scheduled. • Change to the schedule that allocates time to the application partitions by typing the following in the target shell:

arincSchedSet (1,0)

You can now debug the partition as you would any other program. When your debugging session is finished we recommend you detach from your target (Debug => Detach) before closing the debugger.

106 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Debugging Multiple Partitions

There are two methods that can be used to debug a multi-partition VxWorks 653 2.x system. In both methods the Workbench debugger should not be running. The first method is to use one GNAT Studio instance per partition. Each GNAT Studio instance should be attached to a partition, and no two instances should be attached to the same partition. Also, when debugging a multi-partition system you should not do system mode debugging with any of the instances of GNAT Studio. The second method is to use system-mode debugging. In this mode, the debugger takes control of the entire system, and allows you to debug all partitions at the same time. To use that method, you need to type “system” as the name of the task to attach to. Only one debugger can be attached to the system.

System Mode Debugging

Note that gdb supports ‘system mode’ debugging (see the Workbench documentation). To debug in system mode follow the steps provided above to start the debugger. Then open the task list dialog selecting Debug => Attach, type system in the text entry at the bottom of the dialog, and click OK. This will bring the target to system mode and attach the debugger to it. Breakpoints are preserved when switching between task mode and system mode. Alternatively, you can start system mode debugging by typing the following in the gdb prompt:

(gdb) attach system

Note then that instead of using the Continue button to start your application, you will have to type the following in the gdb prompt:

(gdb) continue

To exit system mode you can use the Debug => Detach menu entry. This will detach the debugger from the target and resume the execution of your VxWorks 653 system.

Debugger Commands Specific to VxWorks 653

The debugger provides the following two commands related to the handling of partitions. These features are also available graphically in GNAT Studio, through the Debug => Data => Protection Domain menu entry. • info pds This command prints the list of partitions available on the target. For each partition, the debugger prints its ID and name. An asterisk at the beginning of a partition entry identifies it as the current partition.

(gdb) info pds PD-ID Name * 0x15f78c vxKernel 0x8007a8 vxSysLib 0x800890 pdsAppDomain

• pd This command switches the debugger to the new partition. The partition ID or the partition name can be used to identify the target partition. Using the list of partitions from the example above, the two commands in the following example demonstrate how to switch to the vxSysLib partition using its partition ID (0x8007a8), and then how to switch to the pdsAppDomain using its name.

Contents 107 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(gdb) pd 0x8007a8 [Switching to PD 0x8007a8 (vxSysLib)] (gdb) pd pdsAppDomain [Switching to PD 0x800890 (pdsAppDomain)]

A.4.4 Application Design Considerations

As a general comment, one should never mix APEX processes, POSIX threads or Ada tasks in a single application partition. Each of these entities is part of a distinct high-level model for developing concurrent applications; mixing them will lead to confusion and unpredictable application behavior. Before starting, one should know what ‘foreign threads’ are. ‘Foreign threads’ refer to threads that are not created by the Ada run-time environment, and therefore are not known to it without taking additional bookkeeping steps. In order to facilitate seamless operation of such ‘foreign threads’ when they execute Ada code, they need to be registered with the Ada run-time. On some native platforms, GNAT accomplishes this automatically; another alternative is to use GNAT.Threads (which can be used for raw vThreads on VxWorks 653 2.x, or for kernel tasks on the VxWorks 653mc 3.x POS). Since VxWorks 653 applications are expected to comprise mainly APEX processes, the standard way to perform registration on VxWorks 653 is through the Apex_Processes.Create_Process routine in the Ada APEX binding provided with GNAT. By using this version of the binding, one can ensure that exception handling and other operations such as functions with unconstrained results and the process-level health-monitoring handler are executed correctly.

General Application Structure on VxWorks 653

For applications that are to execute in application partitions, there is a typical structure. There is usually one ‘main’ application that will perform initializations: allocating data, creating and starting various APEX processes, and finally setting the partition into ‘normal’ mode. Once the partition has entered normal mode, the vThread or kernel task executing the main is suspended, no more dynamic allocation is allowed, and the APEX processes defined within the partition are scheduled according to the characteristics defined for them within the main application. For an Ada application, this means that the main subprogram is expected to perform initializations as de- scribed, and then to suspend until the partition is restarted. This suspension occurs when Apex_Processes. Set_Partition_Mode (Normal); is called. All of the work of the application is performed by the subsidiary processes. These processes communicate with each other and with processes in other partitions using the APEX interface. C, C++ and Ada code can be mixed within an application, and there are various approaches available to manage the code. GNAT project files are the best method for combining mixed-language code within a partition. Note that more complex organization of applications within a partition (e.g. multiple initialization threads) are possible, but require more complex setup and coordination. Refer to VxWorks 653 Programmer’s Guide.

The ARINC-653 APEX Binding

The Ada binding to the ARINC-653 APEX (APplication EXecutive) comes with the compiler and is available for all run-time libraries. The bindings are precompiled for each valid combination of run-time library and binding variant. Sources are found under /include/apex/apex[_variant]/src/. Static libraries that can be linked to are in /lib/apex/--/ libapex.a. For example, for VxWorks 653 for the PowerPC architecture, and the use of the cert run-time and Ada 83 version of the APEX binding, the location of the library to link is /lib/apex/powerpc-wrs-vxworkae-cert-apex/libapex.a.

108 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

A GNAT project file to include in a project needing the APEX bindings is located at /lib/gnat/ apex.gpr. gprbuild and gnatmake know about this location, so to access this project file, add

with "apex";

to the top of your project file. This project file eliminates the need to explicitly include the desired APEX library into the gnatlink switches. Note that if you previously used environment.gpr in your project files for earlier versions of GNAT, it can still be used. This project file takes three scenario variables: • PLATFORM - the target triplet for your platform, e.g. powerpc-wrs-vxworksae. The default value is ‘powerpc- wrs-vxworksae’. • RUNTIME - the run-time library to use: light, light-tasking or full. The default value is ‘full’. • BINDING - the APEX binding to use: apex, apex_95, apex_light apex_light_95 or apex_minimal. The default value is ‘apex’. The bindings and valid combinations of RUNTIME and BINDING are described next. Several bindings are provided: • The standard Ada 83 APEX binding, designated by BINDING=apex. This binding is compatible with the full and cert run-time libraries. Applications using this binding must not use the Ada tasking facilities. • The standard Ada 83 APEX binding, designated by BINDING=apex_light. This binding is compatible with the light, full and ravenscar-cert run-time libraries. In this case, applications using the full or ravenscar-cert libraries must not use any APEX processes. • The standard Ada 95 APEX binding, designated by BINDING=apex_95. This binding makes use of the hierarchical library facility of Ada 95 and later versions. It also changes some definitions so that fewer explicit type conversions are needed in application code that uses the APEX binding. Wrapper packages are provided for backward compatibility with the Ada 83 binding. This binding is compatible with the cert and full run-time libraries. Applications must not use Ada tasking facilities. • The standard Ada 95 APEX binding, designated by BINDING=apex_light_95. This binding is compatible with the light, full and ravenscar-cert run-time libraries. In this case, applications using the full or ravenscar-cert libraries must not use any APEX processes. Additionally there are couple of suffixes needed to the apex part of the binding name, depending on the version of VxWorks 653 being used. These are to accommodate FACE conformance, or in one case, a bug in the VxWorks library: • For versions 2.4.x, no suffix is used • For 2.5.0.2, the suffix _1.3 is used for FACE conformance • For 2.5, 2.5.0.1, 3.0 and 3.1, _VXW653-11162 for FACE conformance and to address a library bug. The substring following the hyphen is the number of the Wind River Software Problem Report, which can be referenced on the Wind River Support site. For example, the value of BINDING for Ada 95 style APEX for the cert runtime and VxWorks 653 2.5.0.1 would be apex_VXW653-11162_95 . The easiest way to set the binding is to add the project file /lib/gnat/apex.gpr into the user project files via a context clause. GNAT will search and locate the path to this file if the environment variable GPR_PROJECT_PATH is defined to include /lib/gnat/ (this should be the case by default). It is strongly recommended that you use the bindings provided with the product rather than alternatives, as the provided bindings have been extensively tested for correctness. To access and use the apex project in a user project file:

Contents 109 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

with 'apex'; project My_Project is ... for Source_Dirs use (); -- To discriminate on eg variable Runtime: case apex.Runtime is when "cert" => ... end case; end My_Project;

Using the APEX Binding

The full bindings can be used if no Ada tasking constructs are used (note: ravenscar-cert applications should use apex_light or apex_light_95). Alternatively, the light bindings can be used with the full and ravenscar-cert run-time libraries as long as no APEX processes are used.

Using Ada Processes

The standard way to define an APEX process in C is to create an attributes structure containing the process information (i.e. its name, entry point, priority, etc.). This record is then passed to the APEX CREATE_PROCESS routine. It works the same way in Ada. One defines a record of type Apex_Processes.Process_Attribute_Type describing the process. This record is then given as a parameter to Apex_Processes.Create_Process. The APEX / Ada binding provided with GNAT for VxWorks 653 adds the defaulted parameter Secondary_Stack_Size to the procedure Apex_Processes.Create_Process. In order to support the use of unconstrained function results, a data structure called the secondary stack is allocated to each APEX process that executes Ada code. (The secondary stack is actually a mark/release heap). This parameter allows the user to specify the size of this data structure (in bytes). If the parameter is defaulted, the APEX binding will allocate a secondary stack with a size equal to one-fourth of the requested stack size for the process. This data structure is allocated out of the primary stack, which will have had its allocation increased by one-fourth, so that the original requested stack allocation is honored. Calls to Apex_Processes.Get_Process_Status will return the size of the primary stack minus the size of the secondary stack (i.e. the size originally requested by the application developer). Note that an APEX process created via the APEX Ada binding can query its secondary stack ‘high-water mark’ using GNAT.Secondary_Stack_Info.SS_Get_Max. This package is described in the GNAT Reference Manual. All APEX processes that execute Ada code, regardless of whether their bodies are largely in C or C++, must use the Ada binding routines to create the process or query its process status, or to create a process-level health monitoring handler. These routines and their parameters (for C) are described in apex_processes.ads and apex_health_monitoring.ads.

110 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Selection of a Run-Time Profile

As mentioned GNAT for VxWorks 653 provides several versions of the Ada Run-Time library suitable for differing certification and application needs. These include: • A full Ada run-time for application partitions, designated by the keyword ‘full’. This is useful for applications to GNAT and VxWorks 653. • A restricted Ada run-time for application partitions, certified to DO-178B, Level A, designated by the keyword ‘cert’. • A minimal Ada run-time that generates no object code (‘Zero FootPrint’), for use in either the Module OS or in application partitions, designated by the keyword ‘light’. • An implementation of the Ravenscar profile based on the cert profile for use in application partitions, designated by the keyword ‘ravenscar-cert’. The desired run-time library is selected at build time by setting the gprbuild flag –RTS=, using one of the keywords given above. One can also import apex.gpr, as described in the section on the APEX bindings, and define project variable RUNTIME using the -X switch. The VxWorks 653 certified partition operating system supports the use of the restricted, Ravenscar and zero footprint profiles. For more information about profiles, see the introductory chapters of this manual.

Replacement of the Default Last Chance Handler

All Ada run-time libraries provided with the GNAT for VxWorks 653 include the concept of a last chance handler. This routine is called when an application terminates due to the occurrence of an unhandled Ada exception. All of the provided run-time libraries, except Light, provide a default implementation of the last chance handler. Light requires one to be written by the application developer. The default handler can be overridden by the application developer in all cases, in order to provide such capabilities as raising an error to the health monitor. The following treatments apply: • For the cert, ravenscar-cert and full run-time libraries, the default handler prints a stack dump and exception message, calls APEX RAISE_APPLICATION_ERROR, and then terminates the process in which the exception occurred. The binder -E switch enables production of the stack dump. • For the light run-time library, there is no default handler. The profile of the last chance handler for all run-times except Light is: procedure Ada.Exceptions.Last_Chance_Handler (Except: Exception_Occurrence); pragma Export(C, Last_Chance_Handler, "__gnat_last_chance_handler"); pragma No_Return(Last_Chance_Handler);

This handler may be replaced by any Ada or C routine that exports the symbol __gnat_last_chance_handler and that matches the given parameter profile. The profile of the Light last chance handler is: procedure Last_Chance_Handler (Source_Location: System.Address; Line: Integer); pragma Export(C, Last_Chance_Handler, "__gnat_last_chance_handler");

Contents 111 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

The Source_Location parameter is a C null-terminated string representing the source location of the raise statement, as generated by the compiler, or a zero-length string if pragma Discard_Names is used. The Line parameter (when nonzero) represents the line number in the source. When Line is zero, the line number information is provided in Source_Location itself. Again, any Ada or C routine that exports __gnat_last_chance_handler and matches the designated profile may be used here. The recommended mechanism for replacing the last chance handler is to execute gprbuild, -wrs-vxworksae-gnatmake or the corresponding C compiler on the file providing __gnat_last_chance_handler. The resulting .o file should then be included in the linker directives for the Ada main application. Note that the cert, full and ravenscar-cert run-times support stack overflow checking using the gcc switch -fstack-check. It is expected that a user-written last chance handler will be compiled without this switch (or that it will be overridden with -fno-stack-check). Additionally, user-written last chance handlers must not require more than 4KB of stack space so that they can handle a stack overflow Storage_Error.

Process-Level Health Monitoring Handler

The APEX routine Apex_Health_Monitoring.Create_Handler allows an application developer to provide a process-level handler for health monitoring events. The task that executes this routine will receive the requested stack size, plus 1/4 of the requested size for a secondary stack. This allows such routines to be written in Ada, though they need not be. In addition to the standard HM events defined in APEX (Apex_Health_Monitoring), VxWorks 653 defines a number of extended HM codes. These are defined in $WIND_BASE/target/vThreads/h/hmTypes.h.

112 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX B

LYNXOS-178 TOPICS

This appendix presents information specific to GNAT for LynxOS-178 2.2.4.

B.1 Getting Started

This section is a starting point for using GNAT to develop and execute Ada programs for Lynx Software Technologies’ LynxOS-178 target environment. We assume that you know how to use GNAT in a native environment and how to start a telnet or other login session to connect to your board running LynxOS-178. To compile code for a LynxOS-178 system running on a X86 board, the basic compiler command is i586-elf- lynxos178e-gcc. In order to find the target libraries, GNAT requires the ENV_PREFIX variable to be defined. Please consult the LynxOS-178 documentation for more information about this environment variable. With GNAT, the easiest way to build the basic Hello World program is with gprbuild. For the LynxOS-178 2.2.4 X86 target this would look like:

$ gprbuild --target=i586-elf-lynxos178e hello using project file .../_default.gpr Compile [Ada] hello.adb Bind [gprbind] hello.bexch [Ada] hello.ali Link [link] hello.adb

(The first line is the command entered by the user – the subsequent three are the programs run by gprbuild.) This creates the executable hello, which you then need to load on the board (using ftp or an NFS directory for example) to run it. You can also include the binary in your KDI.

GNAT User’s Guide Supplement for Cross Platforms 113 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

B.2 Kernel Configuration

The appropriate configuration for your LynxOS-178 kernel depends on the target system and the requirements of your application. GNAT itself adds no additional demands; however in some situations it may be appropriate to increase the conservative resource assumptions made by the default configuration. Resource limits may be set as needed. See the documentation provided by LynuxWorks for more information.

B.3 Debugging

GNAT’s debugger is based on the same GNU gdb technology as the debugger provided by LynxOS-178, though with a great number of extensions and enhancements to support the Ada language and GNAT. The LynxOS-178 documentation is relevant to understanding how to get the debugger started if you run into difficulties. The procedure for cross debugging on LynxOS-178 requires that the executable is first launched on the target under the utility gdbserver, and then the cross debugger is started on the host and attached to it. It is recommended that you include the i586-elf-lynxos178e-gdbserver binary in your KDI so it’s always available for debugging. To demonstrate a debugging session, we will use a slightly more complex program called demo1.adb, which can be found in the examples directory of the GNAT distribution. This program is compiled with debugging information as follows:

$ gprbuild --target=x86-lynx178elf -g demo1 using project file .../_default.gpr Compile [Ada] demo1.adb [Ada] gen_list.adb [Ada] instr.adb Bind [gprbind] demo1.bexch [Ada] demo1.ali Link [link] demo1.adb

Once the executable is created, copy it to your working directory on the board. In this directory, you will have to launch the gdb server and choose a free port number on your TCP/IP socket. Presuming the Internet hostname of the board is myboard and the port chosen is 2345, issue the following command: myboard> i586-elf-lynxos178e-gdbserver :2345 demo1

Then return to your host environment and run the debugger. To run the cross debugger from the command line without the visual interface use the command i586-elf-lynxos178e-gdb. The first thing to do at the (gdb) prompt from within gdb is to load the symbol table from the executable:

(gdb) file demo1 Reading symbols from demo1...done. (gdb)

You then have to attach to the server running on the board. Issue the command:

(gdb) target remote myboard:2345

After the server has been started and attached from the host, the program is running on the target but has halted execution at the very beginning. The following commands set a breakpoint and continue execution:

114 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(gdb) break demo1.adb:37 Breakpoint1 at 0x100064d0: file demo1.adb, line 37. (gdb) cont Continuing.

Breakpoint1, demo1 () at demo1.adb:37 37 Set_Name (Fuel,"Fuel"); (gdb)

Here the execution has stopped at the breakpoint set above. Now you can use the standard gdb commands to examine the stack and program variables. Note that once execution has completed, the server on the board must be restarted before a new debugging session may begin.

B.3.1 Debugging Example

Carrying on a little further with the debugging session, the following example illustrates some of the usual debugging commands for moving around and seeing where you are:

(gdb) next 38 Set_Name (Water,"Water"); (gdb) bt #0 demo1 () at demo1.adb:38 #1 0x10001218 in main (argc=1, argv=2147483640, envp=2147483520) at b~demo1.adb:118 #2 0x10017538 in runmainthread () #3 0x10001048 in __start () (gdb) up #1 0x10001218 in main (argc=1, argv=2147483640, envp=2147483520) at b~demo1.adb:118 118 Ada_Main_Program; (gdb) down #0 demo1 () at demo1.adb:38 38 Set_Name (Water,"Water"); (gdb)

To examine and modify variables (of a tagged type here):

(gdb) print speed $1 = (name => "Speed ", value => -286331154) (gdb) ptype speed type = new instr.instrument with record value: instr.speed; end record (gdb) speed.value := 3 $2 = 3 (gdb) print speed $3 = (name => "Speed ", value => 3) (gdb) info local speed = (name => "Speed ", value => 3) fuel = (name => "Fuel ", value => -286331154) oil = (name => ' ' , value => -286331154, size => 20, fill => 42 '*', empty => 46 '.') water = (name => ' ' , value => -286331154, size => 20, fill => 42 '*', empty => 46 '.') (continues on next page)

Contents 115 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) time = (name => ' ' , seconds => 0, minutes => 0, hours => 0) chrono = (name => ' ' , seconds => 0, minutes => 0, hours => 0) db = (access demo1.dash_board.internal) 0x0 (gdb)

And finally letting the program it run to completion:

(gdb) c Continuing.

Program exited normally. (gdb)

116 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX C

BAREBOARD TOPICS

This appendix describes how to use the GNAT cross tools to build programs that do not require support from an embedded real-time operating system running on the target hardware.

C.1 Introduction

The bareboard run-times are provided as customized run-times that are configured to target a specific microcontroller or processor as documented in the respective target appendix. This simplifies the build of an embedded application as explained in this appendix. For different and processors, the run-time libraries need to be ported to your target. Note that any such changes must be revisited (and likely re-ported) if you update the compiler. See Customized Bareboard Run-Time Libraries for adapting a run-time to your board.

C.2 Bareboard Run-Time Libraries

For supported boards, AdaCore strives to make available the Light, Light-Tasking and Embedded run-times. However, Embedded and Light-Tasking may not be available for some supported boards that do not have the memory or hardware resources required to support these run-time libraries. Prebuilt run-time libraries are named after the run-time and the board that they support. For example, the name ‘embedded-tms570’ denotes an Embedded run-time library targeted to the Texas Instruments TM570 board. This library can be specified as follows: project Demo is ... for Runtime("Ada") use "embedded-tms570"; ... end Demo;

See Specifying the Run-Time Library for further details on how to specify your selection of a run-time library.

GNAT User’s Guide Supplement for Cross Platforms 117 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

C.2.1 Generic bareboard Light run-times

In addition to pre-built run-times targeting specific microcontrollers and processors, GNAT for bareboard ARM and GNAT for bareboard RISC-V include pre-built generic Light run-time libraries that target specific Cortex-M and RISC- V cores. These generic run-times lack microcontroller specific startup code and linker scripts, enabling them to be provided separately without creating and building a new run-time. See their respective target appendix for a list of supported Cortex-M and RISC-V cores. To help create the microcontroller specific startup code and linker scripts, GNAT Pro includes Startup-gen that will generate these files based on the properties of the board and microcontroller. See the Startup-gen User’s Guide for more details on how to use the tool with generic Light run-times.

C.3 Getting Started with the Bareboard Toolchain

To get started on GNAT Pro for a bareboard target, let’s imagine we would like to build a program whose purpose is to print “Hello World” on standard output. For this, you’ll need to update your path so as to add both GNAT Pro and GNAT Studio Pro. Once this is done, let’s start GNAT Studio. At startup, GNAT Studio opens a window allowing you to choose between using an existing project file, or creating a new one. Let’s select “Start with default project”, which will create one for us with the default settings. Next, we need to tell GNAT Studio which platform we want to target. Select Menu “Edit->Project Properties. . . ”. Click on the “Build->Toolchain” tab and select the GNAT Pro toolchain corresponding to your target. The second element that needs to be provided is the run-time you want to use. In the “Build->Toolchain” tab we just opened, just click on the down arrow to the right of the “Ada Runtime” field to list all the run-times which were automatically detected, and select the one you’d like to use. Our Hello World program is simple enough that any run-time, including the smaller (Light) run-time, is sufficient. Click on “Save” to exit the project editor. Now that this is done, we can write our program. We want that program to be part of our project, so let’s use the project view to create the file. The project view is a tab showing a blue folder named “Default” (the name of our project), and you should see two yellow folders underneath. Right-click on the first one, which should not have a small ‘o’ inside, and select menu “New->Ada Main Unit”. Let’s name our program “hello”, so enter “Hello” in the window that GNAT Studio then pops up. GNAT Studio has opened an editor for file “hello.adb”, and provided an implementation skeleton. We can complete that skeleton to contain the following program: with GNAT.IO; use GNAT.IO; procedure Hello is begin Put_Line("Hello World"); end Hello;

Once done, we also need to tell GNAT Studio to include this unit as one of the executables we want to build when building the project. Select menu “Edit->Project Properties” again, the select the “Sources->Main” tab, click on the “+” sign in the “Main files” sections and select “hello.adb”. Click on “Save” to exit the project editor. We’re now ready to build our program! The fastest way to trigger the build is to press the F4 key. A window allowing some customization of the build pops up, but the default settings should be good enough, so either click on “Execute” or just press Enter. You should see the output of the build in the “Messages” window, confirming that “hello” was successfully built.

118 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

GNAT Pro for bareboard comes with GNATemulator, AdaCore’s simulator. To run our program under that simulator, just select menu “Build->Emulator->Run with Emulator->hello.adb”. A new output window labeled “[. . . ]-gnatemu” should be opened, and should show the output of our program. It is also possible to debug the program while being run under GNATemulator, simply by selecting menu “Build- >Emulator->Debug with Emulator->hello.adb”. This starts the debugging session after which it is possible to debug the program as usual. It should also be possible to run your program on the real hardware, rather than GNATemulator. However, given the many variations on the host and target environment that you may be using, it is not possible to formulate a universally applicable sequence of commands for building, loading, and running a program.

C.4 Minimizing Object Code and Data Sizes

Bareboard targets typically have stringent constraints on available storage, both for data as well as object code. In addition to careful coding practices, such as sharing generic package instantiations as much as possible, you can request the removal of unused code and data at build time. The technique uses standard GCC switches. To achieve this reduction, you must specify switches for both the compiler and the linker. In the compiler switches, request removal of unused code by applying the "-ffunction-sections" switch. In the same way, request removal of unused data by applying the "-fdata-sections" switch. Specifying both switches is allowed. In the linker switches, specify "-Wl,--gc-sections" to have the linker remove (“garbage collect”) unused code and/or data. Both this linker switch and the compiler switch(s) are essential for any reduction to take effect. You can get a list of what is removed by including the "-Wl,--print-gc-sections" linker switch. For example:

package Compiler is for Default_Switches("Ada") use ("-O2", "-ffunction-sections", "-fdata-sections"); end Compiler;

... package Linker is for Default_Switches("Ada") use ( "-Wl,--gc-sections", "-Wl,--print-gc-sections"); end Linker;

C.5 Viewing Object Code and Data Sizes

You can have the linker display the amounts of storage used for both code and data, as well as the total amounts available and the resulting usage percentages. To get this information specify the "-Wl,--print-memory-usage" linker switch. For example:

package Linker is for Default_Switches("Ada") use ("-Wl,--print-memory-usage"); end Linker;

Contents 119 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Of course, you can combine this switch with the switch requesting removal of unused sections. The Linker package in the project file would then appear as follows: package Linker is for Default_Switches("Ada") use ( "-Wl,--gc-sections", "-Wl,--print-memory-usage"); end Linker;

With this switch applied the linker will print the information to standard output. The results will thus appear in the GNAT Studio Messages window. For example:

Memory region Used Size Region Size%age Used flash: 44268B2MB 2.11% sram: 48784B 256KB 18.61%

C.6 Stacks

Refer to The Primary and Secondary Stacks for information on setting task stack sizes. GNAT does not perform stack overflow checking by default. This means that if the main environment task or some other task exceeds the available stack space, then unpredictable behavior will occur. Support for stack overflow checking is provided in the Embedded run-times. To use, compile all units with the gcc option -fstack-check. Units compiled with this option will generate extra instructions to check that any use of the stack (for procedure calls or for declaring local variables in declare blocks) do not exceed the available stack space. If the space is exceeded, then a Storage_Error exception is raised.

C.7 Character Input/Output

The bareboard run-time libraries provide a customized version of package Ada.Text_IO that exports a minimal set of facilities. The package declaration of this customized version is as follows, for all the bareboard run-time libraries: package Ada.Text_IO is

procedure Get(C: out Character); -- Read from console

procedure Put(Item: Character); -- Output character to the console

procedure Put(Item: String); -- Output string to the console

procedure Put_Line(Item: String); -- Output string followed by new line to the console

procedure New_Line; -- Output new line character to the console end Ada.Text_IO;

120 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

The cut-down package is provided for the sake of initial board check-out and development and is not intended to be a production I/O capability. The implementations of the package body are target dependent. For example, on some targets the implementation drives a USART for this purpose. You can use a USB-to-Serial conversion cable to connect those pins (and a ground pin) to a USB port on the host computer, and run an application on the host to monitor that port in order to interact with the board. In contrast, on the ARM STM32F4x Discovery boards the implementation uses “semihosting”, in which the output goes to the screen showing the st-util outputs. No USB-to-Serial conversion cable is required in that case. The package GNAT.IO is also provided by the bareboard run-time libraries. The interface is slightly different, as shown below:

package GNAT.IO is pragma Preelaborate;

procedure Put(X: Integer); -- Output integer to specified file, or to current output file, same -- output as if Ada.Text_IO.Integer_IO had been instantiated for Integer.

procedure Put(C: Character); -- Output character to specified file, or to current output file

procedure Put(S: String); -- Output string to specified file, or to current output file

procedure Put_Line(S: String); -- Output string followed by new line to specified file, or to -- current output file.

procedure New_Line(Spacing: Positive :=1); -- Output new line character to specified file, or to current output file

end GNAT.IO;

Note, in particular, the ability to output an integer value, and the absence of any input routine. In both the GNAT.IO and Ada.Text_IO cases, the underlying board-specific implementation part is in an internal System.Text_IO package provided by the run-time library. See s-textio.adb in particular. You can change that package to reflect your target’s hardware I/O capabilities. However, since the exported interfaces are minimal, you may want to consider using a more target-specific facility as an alternative to GNAT.IO and Ada.Text_IO.

C.8 Floating-Point Support

The bareboard run-times support floating-point arithmetic on processors that have a floating-point unit (FPU) and provides emulated support in software for targets that lack an FPU. By default, the provided run-time libraries are configured to use the hardware FPU if one is present on the target. As documented in the GNAT Reference Manual, where possible GNAT is configured to follow the IEEE Standard for Floating-Point Arithmetic (IEEE 754). This holds true for the bareboard run-time libraries where the run-time libraries and FPU are configured to follow this standard where the target FPU supports this standard. When a target does not follow IEEE 754, the FPU and run-time configuration is documented explicitly in the target’s section. Be aware that to conform with IEEE 754, exceptions will not be raised in cases where a floating-point operation overflows. Instead, infinities will generated instead.

Contents 121 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Note: the configuration of the FPU is coupled to the configuration of the bareboard run-time library and should not be modified by the user.

C.9 Dynamic Memory Allocation

All bare-board run-times support dynamic memory allocation using standard Ada syntax for allocating and deallo- cating to and from the default storage pool (more commonly known as the “heap”). The package System.Memory implements this feature, in concert with the compiler. Note that the compiler creates calls to procedures declared within System.Memory and that the package defines a number of global symbols. ** Do not change the package spec.** The implementation in the package body is run- time dependent and can be modified if desired. For the Embedded run-times, package System.Memory implements dynamic memory allocation using calls to the included . This implementation is generally sufficient for most users, with the memory allocated from the start of the _end symbol defined in a linker script. Note: Newlib does not bound the amount of memory that can be allocated by malloc. For the Light and Light-Tasking run-times, dynamic memory allocation is implemented directly within the package body. (The package exports the procedures for use by C code.) The location and size of the heap is defined by the __heap_start and __heap_end symbols in the linker script. The implementation in the package uses these bounds to ensure the RAM is not over-allocated. All RAM not allocated to static objects and stacks is allocated to the heap. As a result, manual sizing of the heap is generally not required when using these run-times.

C.10 Bareboard Debugging

Debugging applications on bareboard targets involves connecting GDB to the board or an emulator via a gdb-server. You can then either use GDB on the command line, or use GNAT Studio or GNATbench to drive it. When connecting to a board, a debugging probe is used, typically over JTAG or a device specific connection. For compatibility with GDB, choose debugging hardware that provides a gdb-server, which may be either built into the debugging hardware or provided as a separate software program. The specific mechanisms for connecting, and whether an emulator and/or simulator is available, are target-specific and are discussed in the corresponding sections within this document.

C.11 Non-Symbolic Traceback

A non-symbolic traceback is a list of addresses of call instructions and the support to provide the generation of this information at run-time is provided in the Embedded run-time library. To enable this feature you must use the -E* gnatbind’s option. With this option a stack traceback is stored as part of the exception occurrence. Here is a simple example: with GNAT.IO; with Ada.Exceptions.Traceback; with GNAT.Debug_Utilities; procedure STB is

procedure P1 is K: Positive :=1; begin K :=K-1; (continues on next page)

122 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) exception when E: others => declare Buffer: constant Ada.Exceptions.Traceback.Tracebacks_Array := Ada.Exceptions.Traceback.Tracebacks(E); begin GNAT.IO.Put_Line("Call stack traceback locations:");

for J in Buffer'Range loop GNAT.IO.Put(GNAT.Debug_Utilities.Image_C(Buffer(J))); GNAT.IO.Put(""); end loop; end; end P1;

procedure P2 is begin P1; end P2; begin P2; end STB;

$ gprbuild -g --target=leon3-elf --RTS=embedded-leon3 stb -bargs -E $ leon3-elf-gnatemu stb Call stack traceback locations: 0x4000194C 0x40001518 0x400014F4 0x400014C0 0x4000116C

The location of these call instructions can be inspected with standard binary oriented tools, such as nm or objdump, or with the addr2line tool, that converts addresses into file names and line numbers. It is also possible to use GDB with these traceback addresses to debug the program. For example, we can break at a given code location, as reported in the stack traceback.

$ leon3-elf-addr2line -e stb 0x4000194C 0x40001518 0x400014F4 \ 0x400014C0 0x4000116C stb.adb:10 stb.adb:28 stb.adb:32 b~stb.adb:106 ??:0

$ leon3-elf-gdb stb (gdb) break *0x4000194c Breakpoint 1 at 0x4000194c: file stb.adb, line 10.

It is important to note that the stack traceback addresses do not change when debug information is included. This is particularly useful because it makes it possible to release software without debug information (to minimize object size), get a field report that includes a stack traceback whenever an internal bug occurs, and then be able to retrieve the sequence of calls with the same program compiled with debug information. By default, unhandled exceptions display the stack traceback information stored within the exception occurrence.

Contents 123 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

124 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX D

CUSTOMIZED BAREBOARD RUN-TIME LIBRARIES

This appendix describes how to customize, build, and install run-time libraries for use on bareboard targets. GNAT Pro includes one or more preinstalled run-time libraries for a specific board of the ISA and ABI targeted by the compiler and ancillary tools. In some cases, multiple boards with multiple run-time libraries may be supported. The files required for building these run-times are included with the installation and may be modified by developers. The files may be used to create a customized run-time, either as a relatively minor modification to an existing library, or as a distinct new run-time library for a new board. Note: When making permanent changes to a run-time library, ensure that you can repeat the process because you may need to do it more than once. In particular, you may need to do it again when you upgrade to a newer version of the compiler because the compiler and the run-time library are tightly coupled. Consequently, the run-time may have changed. If so, you will need to reapply your changes to this new run-time library instance. Therefore, we suggest you manage the differences, in addition to the resulting files, under configuration control. For example, you could generate and keep “patch” files that can be reapplied to the files of the run-time library. The run-time library consists of files that are dependent on the target board, as well as files that are target-independent. The latter implement language-defined functionality whereas the former are responsible for configuring and interacting with the hardware. The target-specific files are known as a Board Support Package (BSP). As such, they may require modifications when adapting a run-time library for an existing target or when porting the run-time library to a new target. In contrast, the files implementing language-defined functionality will almost certainly not be changed. The BSP files are located in the source directories of each run-time library. Modifications to the files of any one run-time library do not affect any other library. To adapt or port a run-time library: 1) Copy an existing run-time library directory tree 2) Modify or augment the files within the new run-time library 3) Build the run-time library. The sections below will provide the details and an example of performing these steps.

GNAT User’s Guide Supplement for Cross Platforms 125 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

D.1 Rationale for A New Run-Time Library

The following subsections discuss the various considerations that would lead one to create a new run-time library.

D.1.1 Hardware Considerations

The run-time libraries tested and shipped with GNAT are targeted to specific boards and setup configurations. Because microcontrollers have a range of on-chip configuration options, for example memory and clock configurations, a supplied run-time library supporting your microcontroller may not be configured optimally for your specific board. For instance, the STM32F4 run-times shipped with GNAT are configured to support the STM32F4 Discovery kit and its STM32F407 microcontroller. Even if you use the STM32F407 in your own project you may need to customize the STM32F4 run-time to support your particular setup. For example, the STM32F4 run-times are configured to use the 8MHz external clock provided by the STM32F4 Discovery kit whereas your setup may use a different clock source, such as the internal RC oscillator. However, not all provided run-times are necessarily tied to a particular microcontroller. Continuing the STM32F4 example, the STM32F4 run-times support both the STM32F4 Discovery and STM32F429 Discovery kits, which share similar hardware setups. But without tailoring the STM32F4 run-time you cannot take advantage of the higher clock frequencies and larger memory available on the STM32F429 microcontroller. One could alter the run-time library for the F4 to support the F429 but then it would no longer work for an actual F4 target. In that case it makes sense to create a new run-time library and tailor it specifically to the distinctive hardware, with a name indicating the new target. Other hardware differences also justify a new run-time. For example, the number and priority of interrupts may differ, or the startup-code may be required to set up additional devices or configure them in a different manner. In general, changes that would not work on a supplied run-time’s target justify a new run-time library.

D.1.2 Software Considerations

Application dependence on language-defined functionality is also a reason to create a new run-time library. This dependence is a potential problem because all the bareboard run-times supply subsets of the language-defined features. Different run-times provide different subsets. For example, some run-times do not include the Ada standard math packages. You may decide to augment a supplied run-time’s subset accordingly, in which case a new run-time library is arguably appropriate. Specifically, you can add language facilities that are implemented by stand-alone program units that do not require integration with the rest of the run-time library. Such units are not implemented directly by the compiler and are part of the run-time library only as a means of making them available to the builder. The language-defined math packages are good examples, as are some of the various container packages. You cannot add language-defined features that are not supported by the Embedded runtimes. Another reason for a new run-time library concerns dynamic memory allocation. The various run-times implement it differently, and you may want to change how that is done. A new run-time library is justified in that case too, even if nothing else is changed.

126 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

D.2 The Run-Time Library Structure

The run-time implementations are partitioned into two major parts. The “GNAT” part implements the sequential portion of the language not otherwise implemented directly by the compiler. The “GNARL” part implements the tasking portion of the language. Because the Light run-times do not include tasking there is no GNARL part to those run-time libraries. The run-time library directory tree structure reflects these logical partitions. For the Ravenscar-based run-times that include one or both of the tasking profiles (Ravenscar and/or Jorvik), there is both a gnat subdirectory and a gnarl subdirectory, each containing corresponding source files. For the Light run-times, which contain no tasking, there is only the gnat subdirectory. These subdirectories are located in the root of the run-time directory tree. Additionally, the supplied linker scripts are located in the ld subdirectory, also off the run-time root. The files that constitute the BSP are located in these directories. For each run-time, there are further subdirectories intended to hold files modified by you, if any. (Initially these subdirectories are empty.) The directory names have a “_user” suffix to reflect the intent. There will always be gnat_user and ld_user subdirectories. For the Ravenscar run-times there will also be a gnarl_user subdirectory. Any files found in these “user” directories automatically take precedence over those in the other directories when the run-time library is built. As a result, we recommend you copy the files you intend to modify into those subdirectories, rather than modify them in place. The latter approach will work but separating them will facilitate keeping track of the changes.

D.3 Building A Run-Time Library

Ultimately, a modified run-time library must be built and installed before the tool-chain (compiler etc.) can use it to create an executable image. Predefined builder options defining various switch settings are declared as scenario variables in the GNAT project files (“gpr” files) used to build the run-time library. Loader options are controlled by a scenario variable defined in an XML file. These options are discussed in dedicated sections below. Users can modify these definitions as needed. Important: you must use the for the target specified by the run-time project file. If you have multiple GNAT compilers installed, ensure that your environment path is set so that the cross compiler for your target takes precedence over other compilers. If building a run-time library fails, this is likely the problem.

D.3.1 Building

Run-time libraries are built using the gprbuild tool, with a primary GNAT project file specified as the principle parameter. These primary builder project files are named as follows: • For the Embedded and Light-Tasking run-times, the name is ravenscar_build.gpr for both run-times. • For the Light run-times, the name is runtime_build.gpr instead. These project files reference one or more other project files but users can ignore the others unless their content requires modification. All the project files are located in the roots of the individual subdirectory trees containing the run-time sources and other files for each individual run-time library. For example, to build the Light-Tasking run-time for the stm32f4 target (STM32F4 Discovery kit), we would go to the subdirectory for that specific run-time library and then issue the following command:

Contents 127 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

$ gprbuild -P ravenscar_build.gpr

The built run-time library is located in the subdirectory tree containing the GNAT project file. You may apply additional gprbuild command-line switches if needed. For example, to have gprbuild utilize all processors on your computer to build the run-time you would also specify the -j0 switch:

$ gprbuild -j0 -P runtime_build.gpr

Refer to the gprbuild documentation for all the switches available. As mentioned, various project build options are defined within the project files. These options are specified via the BUILD project scenario variable and are useful when debugging or profiling run-times: • Production: (default) no debug information, optimized, no assertions • Debug: debug information, no optimization, no assertions • Assert: assertions within the run-time library code are enabled • Gnatcov: sets the proper flags for use with the gnatcov tool To specify the scenario variable include -XBUILD= on the command line when invoking gprbuild. For example, to build the run-time with debugging information use:

$ gprbuild -j0 -P ravenscar_build.gpr -XBUILD=Debug

Be advised that enabling assertions within the run-time will significantly increase the execution and memory overhead. We recommend you only enable run-time assertions when requested by AdaCore support. If you want to remove the build artifacts use the gprclean tool, again specifying the primary GNAT project file. In addition, though, apply the “-r” switch to clean “recursively” because the primary project references other projects. For example:

$ gprclean -r -P ravenscar_build.gpr

D.3.2 Choosing the Location

Building a run-time library also effectively installs it because all you must do to employ it is pass its location to the builder and other tools. No particular location is required. The builder will be able to use it via the standard approaches documented in Specifying the Run-Time Library, including the :switch:--RTS switch on the command line and the Runtime attribute in GNAT project files. However, as that section indicates, some locations are more convenient than others. In particular, if a run-time library is placed in the same location as the run-times provided with the GNAT compiler, the run-time can be specified to the GNAT tools by the name alone (e.g., “embedded-stm32f4”). If installed outside this folder, the tools require the full path for the run-time. The run-times provided with the GNAT bareboard compilers are located in a subdirectory under the GNAT installation root, structured like so:

: \--> |--> lib |--> gnat |--> |-->... \-->

128 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

In the above, “” is the name of the ISA supported by the compiler, and is the same string used to specify the Target attribute in the GNAT project file. For the ARM EABI targets, for example, the target is “arm-eabi” so the tree is as follows:

: \--> arm-eabi |--> lib |--> gnat |--> embedded-stm32f4 |--> embedded-tms570 |-->... |--> light-tasking-stm32f4 |--> light-tasking-tms570 |-->... |--> light-stm32f4 |--> light-tms570 \-->...

The PowerPC ELF compiler would have “powerpc-elf” for the folder name, with run-time library names such as “embedded-mpc8641” and “light-mpc8641” to indicate the run-time and board supported. If you are rebuilding a run-time to simply apply different switches, invoke the builder as described above and specify the existing GNAT project file and the intended scenario variables and values. If you want a new set of switches – in effect a new scenario – we suggest you augment the existing project files to define that scenario and its switches, then build. Doing so will support repeatability when building in the future.

D.4 Example: Creating An STM32F429 Run-Time

To illustrate the process of modifying a run-time to a specific board this section will illustrate tailoring the run-time library for the STM32F4 Discovery kit into a new run-time supporting the STM32F429 Discovery kit. The STM32F429 Discovery kit is similar to the STM32F4 Discovery kit but contains more memory and supports a faster clock. Therefore, the new run-time will be created from the existing STM32F4 run-time library. We will also base our run-time off the Ravenscar-SFP run-time, so the new run-time library will be called light-tasking-stm32f429 to reflect the different target.

D.4.1 Initial Library Creation

Any bareboard run-time library supplied with GNAT can be used as the basis for a new, customized run-time library. You must choose a run-time that has the same ISA and ABI, obviously (e.g., powerpc-elf), but the closer the existing run-time library’s configuration is to your platform, the better. We suggest creating your new run-time library as a copy of an existing library if there is one sufficiently close to your platform. To do so, copy the entire run-time subdirectory tree and make modifications in that copy. Starting from a copy enables you to use or refer to the original run-time without having to reinstall GNAT. We also suggest the copy be located in the file system along with the run-times supplied with the compiler, for the reference convenience described above. Contact AdaCore if there is no shipped GNAT run-time that is close enough to be a good starting point. Using a for example, we first go to the GNAT subdirectory containing the supplied run-times:

$ cd /arm-eabi/gnat/lib

Be sure to use the path indicated, under your GNAT installation root directory. There are other folders with the same names, including some that have the names of the run-times, so some care is required.

Contents 129 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Next, copy the entire directory tree representing the existing run-time library:

$ cp -r light-tasking-stm32f4 light-tasking-stm32f429

And then go into that new directory tree:

$ cd light-tasking-stm32f429

We will first clean the library and then build it, as described in the Building A Run-Time Library section. This is a Ravenscar run-time so the name of the primary project file is ravenscar_build.gpr as shown below:

$ gprclean -r -P ravenscar_build.gpr

Note the -r switch to recursively clean. And now the build, just to verify that we’re starting with something that builds successfully:

$ gprbuild -P ravenscar_build.gpr

Although you could start using this run-time immediately, it is functionally equivalent to the original STM32F4 run- time at this point.

D.4.2 Tailoring the Library

Having verified that we are starting with a run-time that can be built successfully, we can now begin making hardware- oriented changes to the BSP files located within our copy. We recommend modifying copies of the BSP files so we will be copying from one part of our run-time to another, instead of from some other run-time library.

Changing Clock Frequency

The BSP package System.BB.Parameters (located in gnat/s-bbpara.ads) declares numerous parameters used by the run-time library to set up the microcontroller and describe the features of the microcontroller available to the run-time. This includes the clock source and frequency. When a run-time supports multiple boards under one processor family, many of these parameters will come from board-specific parameters declared in the System.BB.Board_Parameters package (in file gnat/s-bbbopa.ads). The STM32F4 run-times illustrate this structure. The processor clock frequency is defined via the Main_Clock_Frequency named number in the System.BB.Board_Parameters package:

1 package System.BB.Parameters is

2

3 Clock_Frequency: constant := Board_Parameters.Main_Clock_Frequency;

The System.BB.Board_Parameters package for the STM32F4 microcontroller is located within the run-time in the gnat/s-bbbopa.ads file. Because this file was copied from the STM32F4 run-time, the current value of the Main_Clock_Frequency is that of the maximum frequency of the STM32F4 Discovery kit:

1 package System.BB.Board_Parameters is

2

3 Main_Clock_Frequency: constant := 168_000_000;

However, we would like our STM32F429 run-time to run applications at the maximum speed of the STM32F429 Discovery boards: 180MHz. Therefore, we copy the spec file gnat/s-bbbopa.ads to the gnat_user subdirectory and make the modification there:

130 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

1 package System.BB.Board_Parameters is

2

3 Main_Clock_Frequency: constant := 180_000_000;

Once rebuilt, the new run-time will run applications on STM32F429 Discovery boards at the higher clock frequency.

Tailoring the Memory Layout

Changing the physical memory configuration for a board requires modification to linker scripts located in the ld directory. The names of the scripts reflect their purpose. For example, the PowerPC targets include the following: • ram.ld • qemu-ROM.ld When target families are supported, such as the STM32F4 family, common scripts are defined, with additional scripts tailoring them to specific boards. For example, the STM32 target scripts include the following: • common-RAM.ld • common-ROM.ld These common scripts are tailored by additional linker scripts that define the actual sizes and locations of the memory regions defined in the common scripts. For instance, the STM32F4 target contains ld/memory-map.ld that describes the memory sizes and locations of the RAM and Flash on the STM32F407. For our new STM32F429 Discovery target, the common linker scripts will work because their memory layout is suitable for the STM32F429. However, the STM32F429 has more Flash and RAM than the STM32F407. Therefore we will need to update the board-specific linker script to take advantage of the larger memory. To do so, we copy the linker script ld/memory-map.ld to ld_user and modify it to reflect the amount of memory available on the STM32F429. The change is from the original:

MEMORY { flash (rx) : ORIGIN= 0x08000000, LENGTH= 1024K sram (rwx) : ORIGIN= 0x20000000, LENGTH= 128K ... }

to:

MEMORY { flash (rx) : ORIGIN= 0x08000000, LENGTH= 2048K sram (rwx) : ORIGIN= 0x20000000, LENGTH= 192K ... }

With this change in place, our applications will be able to take advantage of the increased memory available on the STM32F429. Note that we do not need to modify the origin of each memory region as they are common between the STM32F407 and STM32F429.

Contents 131 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Selecting Linker Scripts

Multiple linker scripts may be included with a run-time to support different memory layout and loading scenarios. For example, scripts for the ARM Cortex-M support for loading a program to Flash (common-ROM.ld) or to RAM (common-RAM.ld). The LOADER scenario variable selects which linker script is used when building an application project with gprbuild. The variable is defined within an XML file named run-time.xml: a file that provides target-specific project settings to gprbuild and can be found at the root of every run-time directory tree. As can be seen in the abridged version of this XML file, the scenario variable LOADER controls the choice of linker script:

1 type Loaders is ("ROM", "RAM", "USER");

2 Loader: Loaders := external("LOADER", "ROM");

3

4 ...

5

6 package Linker is

7 for Required_Switches use Linker'Required_Switches&

8 ("-Wl,-L${RUNTIME_DIR(Ada)}/adalib",

9 "-nostartfiles", "-lc", "-lgnat",

10 "-L${RUNTIME_DIR(ada)}/ld_user",

11 "-L${RUNTIME_DIR(ada)}/ld")&

12 Compiler.Common_Required_Switches;

13

14 case Loader is

15 when "ROM" =>

16 for Required_Switches use Linker'Required_Switches&

17 ("-T", "common-ROM.ld");

18 when "RAM" =>

19 for Required_Switches use Linker'Required_Switches&

20 ("-T", "common-RAM.ld");

21 when "USER" =>

22 end case;

23 end Linker;

You can specify the value of this scenario variable on the command line when invoking gprbuild, thereby controlling which script is applied. The default value (ROM) is used if no explicit argument is specified, while the value USER allows a project specific linker script to be specified in the gpr file of the project. For example, given a project file app.gpr describing the application, we can invoke gprbuild and supply one or more scenario variable values:

$ gprbuild -P app.gpr -XLOADER=RAM

Or to take the default:

$ gprbuild -P app.gpr

132 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Increased Heap Size

Our target STM32F429 has more memory than the STM32F4 but we need not change the run-time to make it available for dynamic memory allocation. The “heap” will automatically get the additional memory because this is a Ravenscar- SFP run-time. See Dynamic Memory Allocation for the details of how the run-times implement dynamic memory allocation and deallocation.

Configuring Interrupts

When tailoring a run-time to a new processor the interrupt configuration will require review because the type and number of interrupts may have changed. This is important even when porting a run-time within the same microcontroller family because the number of interrupts will vary based on the peripherals offered by an individual family member. The files to review are located in the gnarl folder in the run-time root directory. At a minimum the interrupt trap vectors and interrupt names will require review. Typically interrupt trap vectors are defined in an interrupt vector table located in an assembly file: gnarl/handler.s. When porting within a microcontroller family you will only need to ensure the correct number of trap vectors are defined. When porting to a different processor family you will need to refer to that family’s reference manual to determine how to define the interrupt vector table. Interrupt names and their corresponding Interrupt_ID values are declared in the package Ada.Interrupts.Names (in file gnarl/a-intnam.ads). This file will require changes if the interrupt names or the number of interrupts differ on the new target. See package System.BB.MCU_Parameters (in file gnat/s-bbmcpa.ads) for the number of interrupts defined. That number must reflect the contents of the package Ada.Interrupts.Names. The STM32F429 Discovery kit used in this example has more interrupts than the STM32F4 Discovery kit, due to additional devices, so our new run-time requires modification. We copy gnat/s-bbmcpa.ads to gnat_user folder and change the value of Number_of_Interrupts from 81 to 92:

Number_Of_Interrupts: constant := 92;

We next copy gnarl/a-intnam.ads to gnarl_user and add the following:

-- Flash global interrupt FLASH_Interrupt: constant Interrupt_ID :=4;

Note that the F4 version of this file skips interrupt number 4. We then add the additional interrupts:

-- UART 7 global interrupt UART7_Interrupt: constant Interrupt_ID := 82;

-- UART 8 global interrupt UART8_Interrupt: constant Interrupt_ID := 83;

-- SPI 4 global interrupt SPI4_Interrupt: constant Interrupt_ID := 84;

-- SPI 5 global interrupt SPI5_Interrupt: constant Interrupt_ID := 85;

(continues on next page)

Contents 133 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) -- SPI 6 global interrupt SPI6_Interrupt: constant Interrupt_ID := 86;

-- SAI1 global interrupt SAI1_Interrupt: constant Interrupt_ID := 87;

-- LTDC global interrupt LTDC_Interrupt: constant Interrupt_ID := 88;

-- LTDC global error interrupt LTDC_ER_Interrupt: constant Interrupt_ID := 89;

-- DMA2D global interrupt DMA2D_Interrupt: constant Interrupt_ID := 90;

Likewise, in handler.S we add the additional trap vector table entries:

.word __gnat_irq_trap /* 98 UART7_IRQ */ .word __gnat_irq_trap /* 99 UART8_IRQ */ .word __gnat_irq_trap /* 100 SPI4_IRQ */ .word __gnat_irq_trap /* 101 SPI5_IRQ */ .word __gnat_irq_trap /* 102 SPI6_IRQ */ .word __gnat_irq_trap /* 103 SAI1 */ .word __gnat_irq_trap /* 104 LTDC */ .word __gnat_irq_trap /* 105 LTDC_ER */ .word __gnat_irq_trap /* 106 DMA2D */

We then rebuild the library to get these updates in place.

Interrupt Priorities

The new target hardware may support a different number of hardware interrupt priorities than the processor in the original run-time. In this case the Interrupt_Priority subtype defined in the System package must be changed. (Take note of the guidelines for modifying priority ranges and their language-defined requirements as documented in this section.) The file for package System is located in gnat/system.ads. The content is highly dependent on the run-time profile (each run-time profile requires its own version). Within the System package are declarations of priority subtypes and constants defined in accordance with the Ada Reference Manual. The STM32F4 Light-Tasking run-time, for example, contains the following definitions:

1 Max_Interrupt_Priority: constant Positive := 255;

2 Max_Priority: constant Positive := 240;

3

4 subtype Any_Priority is Integer range 0.. 255;

5 subtype Priority is Any_Priority range 0.. 240;

6 subtype Interrupt_Priority is Any_Priority range 241.. 255;

7

8 Default_Priority: constant Priority := 120;

Note: you should not modify anything else in the package. The Ada Reference Manual defines the subtype Any_Priority to represent all priority values, with higher numbers indicating higher priorities. This subtype is divided into to two subranges: Priority and Interrupt_Priority. Interrupt_Priority corresponds to the priorities used by interrupt handlers, while tasks, including the environment task,

134 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

typically use the priorities from the Priority subtype. This assignment of priorities ensures interrupts can interrupt the normal execution of tasks. Although Ada permits assigning tasks priorities from the Interrupt_Priority range this is not common and may be prevented on some targets, such as ARM. (Tasks are no longer intended to be interrupt handlers, after the initial update to the Ada language standard.) The range 0 .. 255 is recommended for the Any_Priority subtype because, in practice, 256 levels of priority are sufficient for any application and a smaller range does not reduce the memory requirements of the run-time library. However, you may use whatever bounds correspond to the hardware. Although the Ada standard requires that System.Priority include at least 30 values, that is subject to hardware realities, like all such requirements. The range of System.Interrupt_Priority should map to the range of interrupt hardware priority levels so that there is one-to-one correspondence between them. Thus, if your new target supports a different number of hardware interrupt priority levels, update Interrupt_Priority to reflect this number and adjust the range of Priority accordingly. For example, if your new target only supports a single hardware interrupt priority, update System to the following:

1 Max_Interrupt_Priority: constant Positive := 255;

2 Max_Priority: constant Positive := 254;

3

4 subtype Any_Priority is Integer range 0.. 255;

5 subtype Priority is Any_Priority range 0.. 254;

6 subtype Interrupt_Priority is Any_Priority range 255.. 255;

7

8 Default_Priority: constant Priority := 127;

Our STM32F429 target has the same interrupt priorities as the STM32F4 so we need not make any changes in this example.

Startup Code

The STM32F4 startup code is in multiple assembly language files located in the gnat subdirectory of the run-time library. There are two assembly language files for the startup code, one each for executing from RAM or ROM, plus a common file shared by both (that starts the FPU, for example). These files are named start-ram.S, start-rom.S, and start-common.S. The specific startup code is selected by the linker scripts’ references to the unique symbols defined in the assembly files, via the entry point definitions. For the Tasking and Embedded run-times, the vector table is initialized by assembly code in gnarl/handler.S. The Ada code in package System.BB.CPU_Primitives (gnat/s-bbcppr.adb) installs GNAT-specific handlers that raise exceptions for the traps. (In the Light run-time the startup code initializes the vector table.) Our STM32F429 target has the same startup requirements as the STM32F4 so we need not make any changes in this example.

Contents 135 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Floating-Point Co-processor

Package System.BB.Parameters (in file :file`gnat/s-bbpara.ads`) specifies whether a floating-point unit (FPU) is present, but this is used in conditional code in the context switch routine, not to decide whether to enable the FPU. The supported STM32 targets all have an FPU so the unit is enabled in the common startup code (start-common.S). Therefore we need not change the startup code for our F429 target.

D.4.3 Augmenting the Library

As described in the Software Considerations section you may want to create a new run-time for the sake of software changes. This section is focused on the specific case of adding software functionality by augmenting the run-time library. You can augment either the Light or Light-Tasking runtimes with functionality from an Embedded runtime by copying individual packages from the Embedded runtime. Any packages that you copy must adhere to the limitations described in the Software Considerations section. We recommend you create a new run-time library for this purpose. If you have already done so for the sake of hardware changes then you will continue to work with that new run-time in this section. Otherwise, first see Initial Library Creation for how to create a new run-time. The candidate source files, and their dependencies, are located in the gnat directory. They should be copied into the gnat_user directory in your run-time. See the The Run-Time Library Structure section if you are not familiar with these directories. You must ensure that the dependencies, if any, are also copied into the new run-time. As you will see below, these additional units can be numerous. Because this is run-time source code, it is possible that the copied code has specific hardware requirements. This is especially true for the lower-level units depended upon by language-defined library implementation code. These requirements must be met by the actual hardware used by your applications. For example, the run-time units implementing floating-point functionality may be implemented with the expectation of hardware support (e.g., a co- processor). You must ensure that the expected floating-point support is available. Otherwise, choose a different set of implementation files to copy. Once the additional sources are copied over, you simply build the run-time to include the new functionality. The language-defined units can then be used by the application. The lower-level dependencies should not be referenced by the application, typically, for the sake of portability. Note: If building an application fails with an error message indicating that the GNAT builder has no knowledge of a language-defined unit you think you’ve added to the run-time, either you didn’t copy the correct source files or you did not rebuild the run-time library after copying the files. As an example of augmenting the run-time, let’s say that the application requires the use of complex arrays, a feature that is not offered with the Light and Light-Tasking run-times but is with the Embedded run-times. Therefore, we will copy the files for packed arrays of size 5 that the application requires from an Embedded run-time to the gnat_user subdirectory of our run-time. Locating the source files corresponding to a unit name can be somewhat difficult at first because the source files in the run-times are named in the “8.3” encoded format. The file names do not use the full unit names, unlike the default naming scheme used for application sources, as you will see when we start copying all the files required. We will first copy the spec and body for the Ada.Numerics.Generic_Complex_Arrays generic package, located in the a-ngcoar.ads and a-ngcoar.adb files, where the ‘a’ stands for “Ada” and “ngcoar” is an encoding for “Numerics.Generic_Complex_Arrays.” These two files will be copied to the new run-time’s gnat_user subdirectory. Next, we must traverse the transitive closure of the dependencies and copy their sources as well. If we look at the generic package spec and body we see the following:

136 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

with Ada.Numerics.Generic_Real_Arrays, Ada.Numerics.Generic_Complex_Types; generic with package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays(<>); use Real_Arrays; with package Complex_Types is new Ada.Numerics.Generic_Complex_Types(Real); use Complex_Types; package Ada.Numerics.Generic_Complex_Arrays is

... with System.Generic_Array_Operations; use System.Generic_Array_Operations; package body Ada.Numerics.Generic_Complex_Arrays is

Therefore, we also need the sources for Ada.Numerics.Generic_Complex_Types, Ada.Numerics.Generic_Real_Arrays and System.Generic_Array_Operations: • a-ngcoty.adb (Ada.Numerics.Generic_Complex_Types) • a-ngcoty.ads • a-ngrear.adb (Ada.Numerics.Generic_Real_Arrays) • a-ngrear.ads • s-gearop.adb (System.Generic_Array_Operations) • s-gearop.ads In turn, these new packages also depend on a number of container packages: • a-contai.adb (Ada.Containers) • a-cgaaso.adb (Ada.Containers.Generic_Anonymous_Array_Sort) • a-cgaaso.ads • a-cogeso.adb (Ada.Containers.Generic_Sort) • a-cogeso.ads All these additional units are also language-defined so they can be referenced by the application, if needed.

Contents 137 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

138 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX E

ARM-ELF TOPICS AND TUTORIAL

This appendix describes topics relevant to GNAT for bareboard ARM and also presents a tutorial on building, running, and debugging an Ada application on an embedded ARM board.

E.1 Supported Processors and Run-Time Libraries

GNAT for bareboard ARM supports processors from the ARMv7 architecture family and provides both pre-built generic and microcontroller/processor specific runtimes.

E.1.1 Generic core runtimes

Generic Light run-times are provided for the following ARM Cortex cores: • Cortex M0: light-cortex-m0 • Cortex M0+: light-cortex-m0p • Cortex M3: light-cortex-m3 • Cortex M4: light-cortex-m4 • Cortex M4 with single precision floating point: light-cortex-m4f • Cortex M7 with single precision floating point: light-cortex-m7f • Cortex M7 with double precision floating point: light-cortex-m7d To use these generic runtimes you are required to provide your own microcontroller specific startup code and linker scripts. To help create these files you can use the Startup-gen tool as documented in Startup-gen User’s Guide These generic Light run-times provide a minimal Ada.Text_IO implementation using ARM semihosting. See to your debug probe documentation on enabling semihosting output.

E.1.2 Microcontroller runtimes

Run-time support is provided for the following processor families: • ST Microelectronics STM32F4 • Texas Instruments TMS570LC • Texas Instruments TMS570LS • Xilinx Zynq-7000

GNAT User’s Guide Supplement for Cross Platforms 139 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

For these processor families, pre-built run-time libraries are provided that represent subsets of the Ada language appropriate for the intended application domain and capabilities of the processors. Due to the range of individual processors within these families and the different configurations options available for a particular processor, these pre-built libraries target a specific processor or developer board. For the ST Microelectronics STM32F4, the run-time libraries are targeted at the STM32F4-Discovery and STM32F429I-Discovery kits. The following pre-built run-time libraries are available: • light-stm32f4 • light-tasking-stm32f4 • embedded-stm32f4 For the Texas Instruments TMS570LS, the following pre-built run-time libraries are available: • light-tms570 • light-tasking-tms570 • embedded-tms570 For the Texas Instruments TMS570LC, the following pre-built run-time libraries are available: • light-tms570lc • light-tasking-tms570lc • embedded-tms570lc For the Xilinx Zynq-7000, the following pre-built run-time libraries are available: • light-zynq7000 • light-tasking-zynq7000 • embedded-zynq7000 All pre-built run-time libraries include the necessary low-level hardware startup and initialization functionality required to run applications on the developer board. In many cases, the pre-built run-time libraries will run on other developer boards and processors if they share a similar configuration to these pre-built run-times. If your processor or board uses a different configuration you can modify and rebuild the pre-built run-time to meet your needs, or you wish to target a different processor within the supported Cortex families you can re-target the run-time. The run-time libraries are largely independent of the underlying hardware, simplifying this process.

E.2 Getting Started

Developing with GNAT for bareboard ARM 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 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 all supported ARM boards, the target ‘arm-eabi’ 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 an ARM target and the ‘Zero Foot Print’ STM32F4 run-time library is specified: project Demo is ... for Runtime("Ada") use "light-stm32f4"; for Target use "arm-eabi"; (continues on next page)

140 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) ... end Demo;

The second difference is how programs are run and debugged. This is dependent on your setup and the tools you use. For example, a debug probe can be used to download programs to an ARM microcontroller’s embedded flash or RAM. In this instance refer to the documentation accompanying the probe. In many cases, GNAT Studio can be used to debug your program if your debug probe provides a GDB server. See Debugging for details. If you are using the ST-LINK debug probe (embedded in the STM32F4x Discovery Kits), GNAT Studio integrates support that allows you to download programs to STM32 microcontrollers and debug them direct from GNAT Studio. The following guide Getting Started with the STM32F429-Discovery provides an introduction to setting up the required software to interact with the ST-LINK debug probe and how to download and debug programs on STM32F microcontrollers. While the guide uses the STM32F429 Discovery Kit, this introduction is applicable for other STM Discovery Kits or other boards utilising STM32F microcontrollers.

E.2.1 Getting Started with the STM32F429-Discovery

This guide describes how to setup, build, run, and debug an Ada application on the STM32F4x Discovery kits. Setup for Windows and Linux hosts are covered. While this section focuses on the STM32F429-Discovery Kit, much of the steps contained within this section are independent of the application and the target hardware itself. The example used by this guide, led_flasher-stm32f4, can be found in the directory: /share/examples/gnat-cross/led_flasher-stm32f4 This simple example flashes the two LEDs on the developer board, toggling between a standard flashing rate and a quicker flashing rate at the press of the blue User button on the board. The example provides a demonstration of the Ravenscar Run-Time, protected procedures as interrupt handlers and how to access the registers of a microcontroller. While the example targets the STM32F429-Discovery Kit, the embedded-stm32f4 run-time the example uses supports other STM32F4 Discovery Kits. Thus, this example can easily be run on other Discovery Kits by modifying the example to reflect the LED pin assignments for your Discovery Kit. See the lights.ads file on how to perform this modification. To begin this guide, it is assumed GNAT for bareboard ARM has been installed and the install bin directory is on the PATH environment variable. To complete the setup of the developer tools, the drivers and tools needed to interact with the debug probe included in the Discovery Kits need to be install as described in the following sections.

Contents 141 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

E.2.2 Host Setup

To program and debug the STM32F429-Discovery Kit you will need to install the open-source stlink project and add it to your PATH. You can obtain the latest version of stlink from its project page at https://github.com/stlink-org/ stlink. On Windows, you will also need to install the ST-LINK debug probe USB driver from https://www.st.com/en/ development-tools/stsw-link009.html.

E.2.3 Opening the Led_Flasher Project

The led_flasher-stm32f4 example can be found in the directory: /share/examples/gnat-cross/led_flasher-stm32f4 and has the following layout:

led_flasher-stm32f4: |--> README.txt |--> flasher.gpr |--> gnat.adc |--> obj: \--> src: |--> button.adb |--> button.ads |--> led_flasher.adb |--> lights.adb |--> lights.ads |--> st.ads |--> st-stm32f4.ads |--> st-stm32f4-exti.ads |--> st-stm32f4-gpio.ads \--> st-stm32f4-rcc.ads

If you have installed GNAT in a shared location you may first need to copy the example to a directory that you have write access to (e.g. in you home directory). The example has a typical project layout, capturing the sources for the project within the src directory while the object and other generated files are stored in the obj directory. The gnat.adc file contains the configuration pragmas for the project, while the README.txt provides an introduction to the example. flasher.gpr is the GPR project file for the example that captures the project settings, including the target and run-time used by the project. On Windows you can open the project in GNAT Studio by double clicking on the project file in Windows Explorer. Otherwise you can launch GNAT Studio from the Start Menu and open the project from within GNAT Studio. On Linux you can open the project with the following shell command from the led_flasher-stm32f4.adc directory:

$ gnatstudio -P flasher.gpr

Note if this is your first time running GNAT Studio, GNAT Studio will create a configuration directory and will alert you via a pop-up dialog box. Press ‘OK’ to close that box and continue. A ‘Tip of the Day’ dialog will appear. Press Close to dismiss it. A Welcome to GNAT Studio page will appear in the center of the GNAT Studio work area. Use the ‘x’ that will appear to the right of the title in the tab to close that page. You can now explore the project in the Project View on the left side of GNAT Studio.

142 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

E.2.4 Building

Within GNAT Studio, build the project using either the Build Main button on the toolbar or the Build/ Project->led_flasher.adb menu entry. In the latter case, if a pop-up window appears, press the Execute button in order to build with the default settings. As GNAT Studio builds the project it will display the Messages view at the bottom of the GNAT Studio window to show information about the build. On a successful build, the Memory Usage view will graphically display the memory usage of the led_flasher program, unless the preference is disabled. (See the preference Build Targets/Project/Build Main page, among others, containing the Display memory usage check-box.)

E.2.5 Running the Program

To run the compiled program, connect the STM Discovery Kit to the computer with a USB cable. Then click on the Flash to Board button on the toolbar. This will download the program to the STM Discovery Kit. Once the program has been downloaded the Message view will report:

Flashing image to board. Flashing complete. You may need to reset (or cycle power).

Press the black Reset button on the Discovery Kit to reset the board and run the program. The two user LEDs should now flash at different rates. Pressing the blue User button will cause the LEDs to flash at twice their rate. Pressing the User button again will cause the LEDs to flash at their normal rate.

E.2.6 Debugging the Program

With the board connected, click on the Debug on Board button on the toolbar. This will start a GNAT Studio debug session and launch the necessary tools required to debug the program on the board from GNAT Studio. The program will also be automatically loaded onto the microcontroller. Debugging a program on a board through GNAT Studio is similar to debugging a native program: • The program can continue to the next break point by pressing the Continue button on the toolbar or by using the Debug/Continue menu item. • The program can be stepped through statements using the corresponding menu items in Debug menu and buttons on the toolbar. • The program can be interrupted by pressing -\ or though the Debug/Interrupt menu. • Breakpoints can be set via the Breakpoints view, by clicking on the line numbers in the source editor while the program is interrupted or by right-clicking on the desired line and selecting Set breakpoint on line ... from the Debug menu. • Variables can be queried from the Variables view or by hovering the mouse over a variable with the program interrupted. GNAT Studio also provides a Debugger Console view that allows shell access to the underlying GDB client that is debugging the program. The GDB commands that correspond to the above debugging tasks can be entered into the console directly if desired. The program can be restarted by either using the black reset button on the board or via the Debugger Console with the command:

monitor reset

The debugging session can be exited via the Debug/Terminate menu or issuing the quit command in the Debugger Console.

Contents 143 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Debugging Walkthrough

If you do not have an active GNAT Studio debug session, click on the Debug on Board button on the toolbar. (Remember that you can hover the mouse cursor over the buttons to see their names, and that there is a preference in General/Custom Styles to have the button names displayed along with the button icons on the toolbar.) When the GNAT Studio session loads, the editor will switch to the main procedure in led_flasher.adb and the Debugger Console will report the initial output of gdb:

file/GNAT/share/examples/gnat-cross/led_flasher-stm32f4/obj/led_flasher Reading symbols from GNAT/share/examples/gnat-cross/led_flasher-stm32f4/obj/led_

,→flasher...done. remote debugging using localhost:4242 (gdb) load Loading section.text, size 0xafa4 lma 0x8000000 Loading section.ARM.extab, size 0x8c0 lma 0x800afa4 Loading section.ARM.exidx, size 0xf28 lma 0x800b864 Loading section.rodata, size 0x1ff4 lma 0x800c790 Loading section.data, size 0xe3c lma 0x800e784 Start address 0x80036fc, load size 62908 Transfer rate: 14KB/sec, 8986 bytes/write. (gdb) monitor reset halt

Here GDB has loaded the example program led_flasher and connected to the remote GDB server (the program relaying the debugging commands from GDB to the board). Once GDB is connected with the board, GNAT Studio issues the load command to load the program onto the board and follows with the monitor reset halt command to reset the microcontroller to a debuggable state. If the Debugging Console does not display the above, there is a communication problem with the board. If this occurs, quit GNAT Studio and reconnect the Developer Kit to your computer. Staying within the Debugger View, at the GDB command prompt (gdb) type

c

to run the program. The LEDs on the Developer Kit will flash at different speeds. Press the blue User button to change the speed of the LEDs. Now press -\ to interrupt the program. When you do this the program on the microcontroller stops running and the Debugger Console will report the instruction address and subprogram the microcontroller has stopped on:

Program received signal SIGTRAP, Trace/breakpoint trap. 0x080035ec in __gnat_sys_tick_trap ()

GNAT Studio will switch the Editor view to the line of code where the program stopped if it can locate the source files. Since led_flasher program is compiled with the debug flag this will occur when the debugger stops inside the program code. However, in the above case the program has stopped in the run-time code that has not been compiled with the debug flag and thus GNAT Studio will not switch to the run-time source code. We will now stop the debugger in a line in the example’s source code. With the Project view visible expand the src directory and open lights.adb. Scroll to line 47 and click on the line number. A mark will appear over the line number to indicate that the breakpoint has been set. You can also confirm the breakpoint in the Breakpoints View on the lower left of the GNAT Studio window. You can also add breakpoints from the Breakpoints view. In the view, click on the plus icon. In the Breakpoint editor windows that appears, enter button.adb into the file field and change the line field to 29. Click the OK button to close the window and to add the breakpoint. Double-clicking on the new breakpoint in the Breakpoints view will open the Button package and highlight the line the breakpoint is set on. For now in the Breakpoints view deselect the Enable checkbox next to the newly created breakpoint 2.

144 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

In the Debugger Console enter the command c to run the program to the next break point or press the continue button on the toolbar. The program will run to the selected breakpoint and GNAT Studio will switch the editor to the file location the program has stopped on (lights.adb:47 in this case). With the program stopped, you can query parts of the program state. For example, you can query the value of the local Divider object on line 51 by placing the cursor over the variable name. The value of the object will appear in a tooltip next to the variable (in this case it will show 1). You can also query the state of the protected object Speed_Button on line 47 by the same method, where it will show the Speed_State component as normal. Now press the blue User button on the board and continue the program. When the program stops, look at the state of the protected object: it should now be double. You can step through the statements of the program by pressing the step or next statement buttons on the GNAT Studio toolbar or by entering the s n commands into Debugger Console. Step (s) cause the debugger to stop at a new line of source code, while Next (n) will cause the debugger to step over subprogram calls. Try using these commands now and notice how the editor highlights the current position of the program. We will now change how long one of the LEDs on the board stay on for. First delete the breakpoints we created by selecting the breakpoints in the Breakpoints view and pressing the minus button on the view’s toolbar. Next, open lights.ads and go to line 45. This task object declaration creates a task that flashes the user LED PG13. Change the On_Time discriminate of the task to 75. Build the application again using the build button on the toolbar. Once the program has been built, we now need to load the updated program onto the microcontroller. Go back to the Debugger Console view and enter at the GDB prompt:

load

If the program has been successfully downloaded the console will print

`/GNAT/share/examples/gnat-cross/led_flasher-stm32f4/obj/led_flasher' has changed; re- ,→reading symbols. Loading section .text, size 0xafa4 lma 0x8000000 Loading section .ARM.extab, size 0x8c0 lma 0x800afa4 Loading section .ARM.exidx, size 0xf28 lma 0x800b864 Loading section .rodata, size 0x1ff4 lma 0x800c790 Loading section .data, size 0xe3c lma 0x800e784 Start address 0x80036fc, load size 62908 Transfer rate: 14 KB/sec, 8986 bytes/write.

Now you can reset the microcontroller and run the program by entering the following:

monitor reset c

Notice now that LED PG13 stay on for longer. To conclude the walkthrough, exit GNAT Studio’s debugging session by either typing quit in the Debugger Console or by using the Debug/Terminate menu item.

E.3 Changing Time Resolution

On the ARM Cortex-M boards, the Ravenscar run-time libraries use the ARM SysTick interrupt to implement Ada semantics for time, e.g., delay statements and package Ada.Real_Time. These clock tick interrupts occur at a given, regular rate determined by the run-time. As a result, the maximum resolution for time (e.g., in delay statements) is set by this interval because that is how often the run-time is invoked to examine the time and react as necessary. The interval is set in the System.BB.Board_Support package body, located within the run-time in the gnarl/ s-bbbosu.adb file:

Contents 145 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

1 with ...

2

3 package body System.BB.Board_Support is

4

5 ...

6

7 ------

8 -- Sys_Tick Handling --

9 ------

10

11 -- We use the Sys_Tick timer as a periodic timer with 1 kHz rate. This

12 -- is a trade-off between accurate delays, limited overhead and maximum

13 -- time that interrupts may be disabled.

14

15 Tick_Period: constant Time.Timer_Interval := Clock_Frequency/ 1000;

As you can see on line 15, the resolution for delays etc. is one millisecond. Applications can request smaller values but won’t actually get them because the hardware is not configured to do so. That one millisecond resolution is a good default, representing the trade-off described in the comments, but it may not be good enough for your application. The System.BB.Board_Support package files are located in the gnarl subdirectory. Therefore, we copy the body (not the spec) for the package to the gnarl_user subdirectory and make the modification there. We can change the divisor to whatever is required, keeping in mind that shorter intervals entail more frequent interrupt handling overhead. Then we rebuild the run-time. See the Customized Bareboard Run-Time Libraries annex for how to modify and build run-time libraries.

E.4 Target Restrictions

E.4.1 Task Priority Restriction

Due to a restriction stemming from the hardware model of interrupt handling and context switching in the ARMv7-M architecture, Ada tasks cannot have a base priority specified that is an interrupt priority value. This restriction applies only to ARMv7-M processors. It does not apply to the ARMv7-A or ARMv7-R architectures.

E.5 Debugging

The means for debugging applications on bareboard targets vary with the target board and debugging probe used. This section addresses both general GNAT Studio debugging topics and the use of the debugging probe embedded on the ST Microelectronics Discovery Kits.

E.5.1 Debugging with GNAT Studio

GNAT Studio offers a similar debugging experience when targeting an embedded ARM board as a native target, with GNAT Studio using the GDB client included with GNAT. The difference between native and remote debugging is remote debugging requires a GDB server to pass commands and data between the debug probe and GDB. An example of a GDB server is the st-util utility that communicates with the ST-LINK debug probe found on the STM Discovery Kits and used by GNAT Studio in the Getting Started tutorial. GNAT Studio can be set to automatically connect to your probe’s GDB server when you launch a debugging session in GNAT Studio on a per-project basis. To do this open the properties for your project in GNAT Studio by clicking on the pencil icon in the Project view and navigate to the Embedded properties sheet. Under Communication

146 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Settings enter the host address and port of your GDB server in the Program Host field as detailed by your probe’s documentation. For example, if you are using st-util as your GDB server and running it on your computer you would enter: localhost:4242

In the Protocol field choose remote from the drop down menu. If you are using the st-util GDB server, GNAT Studio provides built-in support for launching st-util when the user initializes a debug session. You can tell GNAT Studio that you are using this tool by selecting it from the Connection Tool drop down menu. Otherwise, you will need to ensure that you have your GDB server running before starting a debugging session in GNAT Studio.

E.5.2 ST Microelectronics Discovery Kits

This section provides details on using the ST-Link debugging probe embedded in ST Microelectronics Discovery Kits that enables symbolic debugging with GDB (on the command line or within GNAT Studio) over USB. Normally, GNAT Studio will handle the details of launching and connecting to the GDB server and thus this section is useful if you are not using GNAT Studio or run into problems while using GNAT Studio. Interaction with the on-board JTAG converter is accomplished by a stand-alone command-line executable named st-util that runs on the host. This executable is a third-party utility that provides a number of capabilities, including that of a GDB server. It is pre-built on the Windows hosted ARM-ELF toolchain but you must build it on Linux hosts. See Host Setup in the Getting Started section on installing and setting up st-util. Using st-util involves manually invoking it on the command line, without parameters, in a command shell. You must invoke it before GDB connects to the board, each time a connection is to be made. This includes the case in which a previous invocation and connection has terminated, because terminating the debugger session disconnects the gdb-server that ‘st-util’ provides. Note that if you just want to download your application to the board and let it run immediately, without debugging it, you can do so with another utility named st-flash that writes binary files to the on the board. As for st-util there is a version of st-flash pre-built in the Windows hosted toolchain. Note that st-flash requires that the executable produced by the toolchain be converted to a ‘binary’ format, which can be accomplished via the arm-eabi-objcopy command. For example, assuming we have a project that creates an executable named led_flasher in an obj subdirectory, we could build the project and then invoke the arm-eabi- objcopy command, as shown in the following:

$ gprbuild -P flasher.gpr $ arm-eabi-objcopy -O binary obj\led_flasher obj\led_flasher.bin

The result is the file led_flasher.bin that can be specified to st-flash on the command line. If you just enter the name st-flash on the command line it will print usage information. Usage information is also widely available on the Internet.

Contents 147 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Automatic Board Reset For Debugging

When debugging a bare ARM board, you may need to reset the board after initially connecting the debugger. A reset is suggested because the previously running application may have put the processor and peripherals in an inconvenient state for debugging. If, when running an application under the debugger, initial execution seems to have no effect, a reset is likely in order. This frequently can be the case with the ST Microelectronics Discovery boards. You can use the dedicated on-board button to reset the board after GDB connects to the board. Alternatively, you can automate the reset action using a GDB command file script. The command file below will cause a Cortex-M3 or -M4 board to automatically reset immediately after a GDB load command executes. Note that GNAT Studio issues that command as part of the Debug/Initialize menu invocation. Manual GDB load command invocations will also trigger the action.

define hookpost-load echo Resetting the processor and peripherals...\n set *0xE000ED0C := 0x05FA0004 echo Reset complete\n end

To use the script, copy the contents below into a file named .gdbinit (note the leading period in the name). Create the file if you do not already have one defined. You can put the file in the same directory as the project gpr file, but note that other locations are possible. In particular, other locations can be convenient, for example if you want to use the same initialization for every project, globally. See the GDB documentation for the possible locations and their effects. If you do place the .gdbinit file in the same directory as the project file, you will also need to enable local instances of the file so that GDB will not ignore it. To do so, create another .gdbinit file in your HOME directory (either on Linux or on Windows) and place the following inside it:

set auto-load safe-path/

Of course, if you already had a .gdbinit in your HOME directory, just add that line to it. That line will enable local instances of .gdbinit and so GDB will execute their content. The board reset is achieved by writing to the ‘Application Interrupt and Reset Control’ register located at address 0xE000ED0C. Both the processor and the peripherals can be reset by writing a value of 0x05FA0004. That value will write to the SYSRESETREQ bit. If you want to avoid resetting the peripherals, change the value to 0x05FA0001. That value will write to the VECTRESET bit. Do not use a value that sets both bits. For further details see the book by Joseph Yiu: The Definitive Guide to the ARM Cortex-M3 and Cortex-M4 Processors, 3rd edition, pp. 262-263. In both cases, any on-board debug hardware is not reset. For boards with a JTAG interface, you can use the GDB command:

monitor jtag_reset

to reset it. This command can be issued interactively at the GDB prompt, or could be part of another GDB macro.

148 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Troubleshooting

Here are some recommendations when you encounter unexpected behavior: • Sometimes, when first starting a debugging session, invoking the debugger’s Run or stepping commands may not have any effect. This can happen when prior execution leaves the board in an uncommunicative state. (Remember the board starts executing a valid loaded application whenever power is applied.) In such cases the board probably just needs to be reset. You can push the black button on the board to do so, and then try to load the executable (‘Debug’ => ‘Initialize demo’) again. If that doesn’t suffice, try disconnecting the board from the USB cable in order to cycle power, reconnect, and then try the full debugging steps again. • If st-util can communicate with the board but does not properly interact with it as described above, it may be that the firmware on the board has been updated. If you cannot reinstate the prior version of the firmware, you will need to invoke an additional utility each time you power-up the board. Download the STM32 ST-Link utility from the same ST Micro web page above by selecting the ‘STSW-LINK004’ part number. Selecting ‘STSW-LINK004’ will present a file named stsw-link004.zip for download. Unzip and install it. Put the binaries on the host system path. Then, before calling st-util, each time after first applying power to the board, invoke the following on the command line: st-link_cli -c If the firmware is the problem this can allow the board and st-util to work together properly.

Contents 149 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

150 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX F

ARM AARCH64-ELF TOPICS

This appendix describes topics relevant to GNAT for bareboard AArch64 and also presents a tutorial on building, running, and debugging an Ada application on an embedded AArch64 board.

F.1 Supported Processors and Run-Time Libraries

GNAT for bareboard ARM supports processors from the ARMv8 architecture family. Run-time support is provided for the following processor families: • Xilinx Zynq UltraScale+ MPSoC For these processor families, pre-built run-time libraries are provided that represent subsets of the Ada language appropriate for the intended application domain and capabilities of the processors. Due to the range of individual processors within these families and the different configurations options available for a particular processor, these pre-built libraries target a specific processor or developer board. For the Xilinx Zynq UltraScale+ MPSoC, the run-time libraries are targeted at the Avnet UltraZed board. The following pre-built run-time libraries are available: • light-zynqmp • light-tasking-zynqmp • embedded-zynqmp These runtime supports the running on the quad cortex-A53 SMP APU block of the UltraScale+ MPSoC: • boot from Exception Level 3-1: the boot process is configuring the various EL down to 1 in 64-bit mode. The runtime mode used is EL1 non-secure. • MMU: the mmu configuration is expecting 2GB of DDRAM and configures the memory access in 32-bit mode. • SMP: the four cores are supported by the runtime in SMP mode. • Interrupts: 16 level of interrupt priority are supported, and thus nested interruptions are supported as well. Finally, the use of the FPU is always supported, in tasks and in interrupt handlers.

GNAT User’s Guide Supplement for Cross Platforms 151 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

F.2 Getting Started with the UltraZed and GNAT

This guide will demonstrate how to run an Ada application on the Avnet UltraZed. The process for other UltraScale+ boards is largely similar, except you will have to provide a Hardware Platform Specification and a BSP tailored for your board. To begin, you will need to obtain and install from Xilinx: • Xilinx Software Developent Kit (XSDK) 2017.4 or later and from GNAT Tracker: • Gnatbench plugin for Eclipse CDT • GNAT for aarch64-elf

F.2.1 Preparation

GNAT installation

Before running XSDK, make sure that GNAT is installed and accessible from your environment (PATH). To test, type from your command line:

$ gprconfig --show-targets

The list should include aarch64-elf.

Hardware Platform Specification

As the UltraScale+ MPSoC is a configurable MPSoC, it requires a Hardware Platform Specification. For the Avnet UltraZed, visit their website and obtain the Board Definition Files for Vivado 2017.2 and later and follow the included tutorial. For this guide, the Hardware Platform Specification is called design_1_wrapper_hw_platform_0 specification. Open XSDK and create a standalone BSP from the File -> New -> Board Support Package. While this BSP is not strictly needed to build the application, it provides XSDK the information how to run or debug the application. Use “standalone bsp” as the project name and do not include any extra libraries.

F.2.2 Gnatbench Installation

With XSDK open: • Click on the menu item Help->Install New Software • Click on “Add”, select “Archive”, select the gnatbench zip file • Click on “OK” • Select AdaCore Plugins for Eclipse/CDT • Click on Next and finish the installation Restart XSDK before proceeding to the next step.

152 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

F.2.3 Create an Ada Project

Click on the menu File -> Other, and select Ada -> Ada Project In the dialog: Project name: hello, use default location (click Next) Project unit name: Hello, Single Project Main Program Settings: Hello, Generate the file as a Hello World application Directories settings: leave default Ada Builder settings: click on Scan, select aarch64-elf, make sure no other toolchain is selected. Click on Finish. Right click on the project, select “Properties”. In the “Project References” section, add a dependency over “standalone_bsp”. Close the dialog. Right-click on the project hello, choose “Build main” -> “hello.adb”.

F.2.4 Run/Debug the Application

Emulator-based Debugging

Click on the Menu “Debug” > “Debug Configurations” Select Xilinx C/C++ application (System Debugger on QEMU), and press the “New” button. • Target setup: – Debug Type: “Standalone Application Debug” – Connection: “QEMU” – Hardware Platform: “design_1_wrapper_hw_platform_0” • Application: – Project Name: click on Browse, select hello – Application: click on Search, select hello – Download checked for psu_cortexa53_0 – (optional): check Stop at program entry Click Apply, then Debug. This should launch QEMU and switch to the Debug perspective, and stop at the entry point (or at main). Clicking on the ‘Resume’ button will display “Hello World!” from the Emulator Console, and reset the simulator.

Contents 153 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

On-board Debugging

To begin: • set the board to start in JTAG mode • connect the JTAG module to your host • connect the UART to your host and open a terminal (115200 bauds) Now click on the Menu “Debug” -> “Debug Configurations” Select Xilinx C/C++ application (System Debugger), and press the “New” button. • Target setup: – Debug Type: “Standalone Application Debug” – Connection: “Local” – Hardware Platform: “design_1_wrapper_hw_platform_0” – Initialization File: “psu_init.tcl” – Run psu_init is checked • Application: – Project Name: hello – Application: select hello – Download checked for “psu_cortexa53_0” – Check “Reset processor” – (optional) check Stop at program entry if you need to debug the Click Apply, then Debug. The debug view should open automatically and the Cortex-A53 #0 should stop at main. The main entry point of the hello world example will be displayed. Press the continue button and the output “Hello World!” should print on your serial console.

F.3 Resources used by the runtime

• The GIC is configured to redirect the exceptions to the Ada runtime. • The Software generated interrupt 0 is reserved by the runtime and should not be used by user code. • The UART0 is used as standard input/output by the runtime.

F.4 Memory mapping

(continues on next page)

154 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

F.5 Boot

Only from RAM is currently supported, with the entry point set to 0x00000.

F.6 Debugging

F.6.1 Halting time when debugging

There may be scenarios when debugging where you need to halt Ada.Real_Time.Clock and the runtime timer services when the debugger halts a processor. To achieve this, the underlying system counter needs to be halted in response to a debug event. As the system counter is implementation defined in the ARMv8-A architecture, please refer to your processor’s documentation for further information on the system counter provided and whether it supports halt-on- debug. Do note that typical ARMv8-A processor implementations use the Generic Timer defined by the architecture to provide the system counter. This timer provides support for halt-on-debugging via an HDBG flag, however once again, it is up to the implementation whether this flag is supported or not. Furthermore, how debug events are routed to the Generic Timer is also left to the processor’s implementation. Refer to the ARMv8-A Architecture Reference Manual and your processor’s documentation for details.

Xilinx Zynq Ultrascale+

The Xilinx Zynq Ultrascale+ uses the ARMv8-A Generic Timer as the basis of its system counter (alternatively referred to as IOU_SCNTRS Module or System Timestamp Generator in the Xilinx documentation, referred to here as the system timer). The system timer supports halt-on-debug (HDBG). To enable this feature, the HDBG flag needs to be set and the CoreSight embedded cross trigger (ECT) configured to route the debug trigger from the desired core to the system timer.

Xilinx SDK

To enable the HDBG system timer flag while debugging from the Xilinx SDK, open the generated psu_unit.tcl file found within ZCU102_hw_platform project. This file initializes the Xilinx Processor System and can be used to enable the HDBG flag without changing your Ada application. Modifying psu_unit.tcl also ensures your application does not ship with the HDBG enabled. To enable the HDBG flag, find the following line in psu_unit.tcl`: mask_write 0XFF260000 0x00000001 0x00000001 and replace it with:

Contents 155 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

mask_write 0XFF260000 0x00000003 0x00000003

To configure the ECT: 1. Open the Debug Configurations dialog (Run->Debug Configurations. . . ). 2. From the left side of the dialog, select your debug configuration. 3. Under the Target Setup tab, enable the option Enable Cross-Triggering and click on the ellipsis button that is on the right of it. 4. Click the Create. . . button on the Cross Trigger Breakpoints window. 5. Under Cross Trigger Signals (Input), locate the processor core that your application is running on (typically A53-0) and click the checkbox next to DBGTRIGGER. 6. Under Cross Trigger Signals (Output), scroll down until you find FTM-STM. Select the checkbox next to HALT SYSTEM TIMER. 7. Click OK to close the Cross Trigger Breakpoints dialog boxes. You can now click Debug to debug your application with system counter halt-on-debug enabled. If you wish to disable this feature, open the debug configuration and deselect Enable Cross-Triggering.

Lauterbach

If you are using a Lauterbach probe, add to your TRACE32 script the following lines to enable the HDBG flag and configure the ECT: :: SYStem.Option CTITimerStop ZYNQULTRASCALE Data.Set 0xFF260000 0x00000003 For more information about this solution, please contact Lauterbach.

156 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX G

AVR-ELF TOPICS

This Appendix describes topics relevant to GNAT Pro for AVR-ELF and also presents a tutorial on building, running, and debugging a C application on an embedded AVR board.

G.1 Introduction to GNAT Pro for AVR-ELF

The AVR-ELF toolset targets AVR 8-Bit RISC microcontrollers from . AVR microcontrollers have limited resources: 32 8-bit wide registers, separate instructions and data memory, at most 256KB of flash for the instructions, and at most 64KB of internal SRAM for the data. There is a large number of microcontrollers, and although they have the same instructions set core, they vary in capabilities. Some low-end models can be programmed only in assembly, while at the higher end one finds dedicated instructions to handle a larger amount of memory. GNAT Pro has been tested only with the atmega128x, with less support for the other microcontrollers.

G.2 Compiler and Linker Flags for AVR-ELF

The compiler must know which microcontroller is targeted, because code generation is affected. Use option -mmcu=ARCH where ARCH is the AVR architecture defined as follow: • For atmega2560 and atmega2561 use -mmcu=avr6. • For enhanced cores with 128KB of flash atmega128x and at90usb128x use -mmcu=avr51. • For enhanced cores whose flash size is between 8KB and 64KB use -mmcu=avr5. • For enhanced cores with less than 8KB of flash use -mmcu=avr4. Do not try to link object files compiled for different targets, since the code generated is not compatible. The program should be compiled and linked with option -nostdlib to prevent linking with standard libraries (such as the C library) which are not provided by GNAT Pro. However, option -lgcc should be passed to the linker to link with the compiler support library.

GNAT User’s Guide Supplement for Cross Platforms 157 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

G.3 Getting Started

Developing with GNAT for bareboard AVR 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 all supported AVR boards, the target ‘avr-elf’ needs to be specified. For example, the following project file fragment shows the target specified via their respective attributes. In this example, an AVR target is specified: project Demo is ... for Target use "avr-elf"; ... end Demo;

The second difference is how programs are run and debugged. This is dependent on your setup and the tools you use. For example, a debug probe can be used to download programs to an AVR microcontroller’s embedded flash or RAM. In this instance refer to the documentation accompanying the probe. In many cases, GNAT Studio can be used to debug your program if your debug probe provides a GDB server. See Debugging for details.

G.3.1 Getting started with GNATemu

This guide describes how to setup, build, run, and debug a C application on GNATemu. The example used by this guide, atmega can be found in the directory: /share/examples/atmega> This simple example displays the “Hello World!!!” string. If you have installed GNAT in a shared location you may first need to copy the example to a directory that you have write access to (e.g. in your home directory). The example has a typical project layout, capturing the sources for the project within the src directory while the object and other generated files are stored in the obj directory. example.gpr is the GPR project file for the example that captures the project settings, including the target used by the project.

G.3.2 Building

The project can easily be built with the following shell command from the / share/examples/atmega> directory:

$ [BUILD=Debug] gprbuild -P example.gpr

Setting the BUILD environment variable to Debug will build the program with debug options. Set this variable if you intend to debug the program.

158 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

G.3.3 Running the Example

The program can be run with the following shell command from the /share/ examples/atmega> directory:

$ avr-gnatemu [-g] obj/main

The -g option opens the default and freezes the emulation on startup. This option should only be used if you intend to connect a debugger to the emulator as described in Debugging the Example.

G.3.4 Debugging the Example

After the emulator has been launched with the -g option, it is possible to launch the debugger with the following shell command from the /share/examples/atmega> directory:

$ avr-gdb obj/main (gdb) target remote localhost:1234 ... (gdb) break main (gdb) continue ... (gdb) detach

Contents 159 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

160 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX H

LEON3 TOPICS

This appendix describes topics relevant to GNAT for bareboard LEON3.

H.1 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.

H.2 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.

GNAT User’s Guide Supplement for Cross Platforms 161 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

H.3 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

H.4 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:

162 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

$ leon-elf-gdb main (gdb) target remote monnitor_address:2222 (gdb)

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.

H.5 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 pro- cessor 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.

H.6 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//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 }

Contents 163 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• 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);

H.7 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.

H.8 Console Output

UART 1 is used as the target console.

164 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX I

RISC-V 32-BIT TOPICS AND TUTORIAL

This appendix describes topics relevant to GNAT for bareboard 32-bit RISC-V and also presents a tutorial on building, running, and debugging an Ada application on an embedded 32-bit RISC-V board.

I.1 Supported Processors and Run-Time Libraries

GNAT for bareboard 32-bit RISC-V supports processors conforming to the RISC V 32-bit instruction set and provides both pre-built generic and microcontroller/processor specific runtimes.

I.1.1 Generic core runtimes

Generic Light run-times are provided for the following RISC-V ISA and extensions: • RV32I: light-rv32i • RV32IM: light-rv32im • RV32IAC: light-rv32iac • RV32IMAC: light-rv32imac • RV32IMAFC: light-rv32imafc • RV32IMAFDC: light-rv32imafdc To use these generic runtimes you are required to provide your own microcontroller specific startup code and linker scripts. To help create these files you can use the Startup-gen tool as documented in Startup-gen User’s Guide These generic Light run-times do not provide Ada.Text_IO functionality. For compatibility with existing code, the Ada.Text_IO package provided has its subprograms stubbed out.

I.1.2 Microcontroller runtimes

Run-time support is provided for HiFive1 developer board from SiFive. The following run-time library is pre-built: • light-hifive1 All pre-built run-time libraries include the necessary low-level hardware startup and initialization functionality required to run applications on the developer board. In many cases, the pre-built run-time libraries will run on other developer boards and processors if they share a similar configuration to these pre-built run-times. If your processor or board uses a different configuration, you can modify and rebuild the pre-built run-time to meet your needs, or if you wish to target a different processor within the supported families, you can retarget the run-time. The run-time libraries are largely independent of the underlying hardware, simplifying this process.

GNAT User’s Guide Supplement for Cross Platforms 165 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

I.2 Getting Started

Developing with GNAT for bareboard 32-bit RISC-V 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 all supported 32-bit RISC-V boards, the target ‘riscv32-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, a 32-bit RISC-V target and the ‘Zero Foot Print’ HiFive1 run-time library is specified:

project Demo is ... for Runtime("Ada") use "light-hifive1"; for Target use "riscv32-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.

I.2.1 Getting Started with GNATemulator

This guide describes how to set up, build, run, and debug an Ada application using GNATemulator with the light- hifive1 run-time. Setup for both Windows and Linux hosts is covered. While this section focuses on GNATemulator, most of the steps contained within this section are independent of the application and the target hardware itself. To begin this setup, it is assumed that GNAT for bareboard 32-bit RISC-V has been installed and that the install bin directory is in the PATH environment variable. Once installed, ensure that the installation bin directory (by default bin/usr/local/bin) included in your PATH.

I.2.2 Creating a new Project

Launch GNAT Studio:

$ gnatstudio

If this is your first time running GNAT Studio, note that GNAT Studio will create a configuration directory and will alert you via a pop-up dialog box. Press ‘OK’ to close that box and continue. A ‘Tip of the Day’ dialog will appear. Press Close to dismiss it. When on the Welcome page, click on Create new project and select Simple Ada project, and then click on Next. Change Location and Settings appropriately and press Apply. The project view is now displayed; it is then possible to edit project properties by right-clicking on the project name in the Project tab, and selecting Project->Properties. The project properties are now displayed. Open the Toolchains tab, and make sure that the riscv32-elf toolchain is selected and that the Ada run-time is light-hifive1. Then click on Save. You can now navigate the project tree and add your source code.

166 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

I.2.3 Building

Within GNAT Studio, build the project using either the Build Main button on the toolbar, or the Build/ Project->Build All menu entry. In the latter case, if a pop-up window appears, press the Execute button in order to build with the default settings. As GNAT Studio builds the project, it will display the Messages view at the bottom of the GNAT Studio window to show information about the build. On a successful build, the Memory Usage view will graphically display the memory usage of the program, unless the preference is disabled. (See the preference Build Targets/Project/Build Main page, among others, containing the Display memory usage check-box.)

I.2.4 Running the Program

Within GNAT Studio, run your program 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 riscv32-elf-gnatemu view.

I.2.5 Debugging the Program

In GNAT Studio, click on the Debug with Emulator button on the toolbar. This will start a GNAT Studio debug session and launch the necessary tools required to debug the program on the board from GNAT Studio. The emulator will be automatically launched. Debugging a program on the emulator through GNAT Studio is similar to debugging a native program: • The program can continue to the next breakpoint by pressing the Continue button on the toolbar or by using the Debug/Continue menu item. • The program can be stepped through statements using the corresponding menu items in Debug menu and buttons on the toolbar. • The program can be interrupted by pressing -\, or through the Debug/Interrupt menu. • Breakpoints can be set via the Breakpoints view, by clicking on the line numbers in the source editor while the program is interrupted or by right-clicking on the desired line and selecting Set breakpoint on line ... from the Debug menu. • Variables can be queried from the Variables view or by hovering the mouse over a variable with the program interrupted. GNAT Studio also provides a Debugger Console view that allows shell access to the underlying GDB client that is debugging the program. The GDB commands that correspond to the above debugging tasks can be entered directly into the console if desired. The debugging session can be exited via the Debug/Terminate menu or by issuing the quit command in the Debugger Console.

Contents 167 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

168 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX J

RISC-V 64-BIT TOPICS AND TUTORIAL

This appendix describes topics relevant to GNAT for bareboard 64-bit RISC-V and also presents a tutorial on building, running, and debugging an Ada application on an embedded 64-bit RISC-V board.

J.1 Supported Processors and Run-Time Libraries

GNAT for bareboard 64-bit RISC-V supports processors conforming to the RISC V 64-bit instruction set and provides both pre-built generic and processor specific runtimes.

J.1.1 Generic core runtimes

Generic Light run-times are provided for the following RISC-V ISA and extensions: • RV64IMAC: light-rv64imac • RV64IMAFC: light-rv64imafc • RV64IMAFDC: light-rv64imafdc To use these generic runtimes you are required to provide your own microcontroller specific startup code and linker scripts. To help create these files you can use the Startup-gen tool as documented in Startup-gen User’s Guide These generic Light run-times do not provide Ada.Text_IO functionality. For compatibility with existing code, the Ada.Text_IO package provided has its subprograms stubbed out.

J.1.2 Processor runtimes

Run-time support is provided for Spike, the RISC-V ISA Simulator, and the Microsemi PolarFire SoC Icicle Kit For the Spike simulator, the following run-time library is pre-built: • light-spike For the Microsemi PolarFire SoC, the following run-time libraries are pre-built: • light-polarfiresoc • light-tasking-polarfiresoc • embedded-polarfiresoc All pre-built run-time libraries include the necessary low-level hardware startup and initialization functionality required to run applications on the developer board. In many cases, the pre-built run-time libraries will run on other developer boards and processors if they share a similar configuration to these pre-built run-times. If your processor or board uses a different configuration, you can modify and rebuild the pre-built run-time to meet your needs, or if you

GNAT User’s Guide Supplement for Cross Platforms 169 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

wish to target a different processor within the supported families, you can retarget the run-time. The run-time libraries are largely independent of the underlying hardware, simplifying this process.

J.2 Getting Started

Developing with GNAT for bareboard 64-bit RISC-V 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 all supported 64-bit RISC-V boards, the target ‘riscv64-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, a 64-bit RISC-V target and the ‘Zero Foot Print’ Spike run-time library is specified:

project Demo is ... for Runtime("Ada") use "light-spike"; for Target use "riscv64-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.

J.2.1 Getting Started with GNATemulator

This guide describes how to set up, build, run, and debug an Ada application using GNATemulator with the light-spike run-time. Setup for both Windows and Linux hosts is covered. While this section focuses on GNATemulator, most of the steps contained within this section are independent of the application and the target hardware itself. To begin this setup, it is assumed that GNAT for bareboard 64-bit RISC-V has been installed and that the install bin directory is in the PATH environment variable. Once installed, ensure that the installation bin directory (by default bin/usr/local/bin) included in your PATH.

J.2.2 Creating a new Project

Launch GNAT Studio:

$ gnatstudio

If this is your first time running GNAT Studio, note that GNAT Studio will create a configuration directory and will alert you via a pop-up dialog box. Press ‘OK’ to close that box and continue. A ‘Tip of the Day’ dialog will appear. Press Close to dismiss it. When on the Welcome page, click on Create new project and select Simple Ada project, and then click on Next. Change Location and Settings appropriately and press Apply. The project view is now displayed; it is then possible to edit project properties by right-clicking on project name in the Project tab, and selecting Project->Properties. The project properties are now displayed. Open the Toolchains tab, and make sure that the riscv64-elf toolchain is selected and that the Ada run-time is light-spike. Then click on Save.

170 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

You can now navigate the project tree and add your source code.

J.2.3 Building

Within GNAT Studio, build the project using either the Build Main button on the toolbar, or the Build/ Project->Build All menu entry. In the latter case, if a pop-up window appears, press the Execute button in order to build with the default settings. As GNAT Studio builds the project, it will display the Messages view at the bottom of the GNAT Studio window to show information about the build. On a successful build, the Memory Usage view will graphically display the memory usage of the program, unless the preference is disabled. (See the preference Build Targets/Project/Build Main page, among others, containing the Display memory usage check-box.)

J.2.4 Running the Program

Within GNAT Studio, run your program 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 riscv64-elf-gnatemu view.

J.2.5 Debugging the Program

In GNAT Studio, click on the Debug with Emulator button on the toolbar. This will start a GNAT Studio debug session and launch the necessary tools required to debug the program on the board from GNAT Studio. The emulator will be automatically launched. Debugging a program on the emulator through GNAT Studio is similar to debugging a native program: • The program can continue to the next breakpoint by pressing the Continue button on the toolbar or by using the Debug/Continue menu item. • The program can be stepped through statements using the corresponding menu items in Debug menu and buttons on the toolbar. • The program can be interrupted by pressing -\, or through the Debug/Interrupt menu. • Breakpoints can be set via the Breakpoints view, by clicking on the line numbers in the source editor while the program is interrupted or by right-clicking on the desired line and selecting Set breakpoint on line ... from the Debug menu. • Variables can be queried from the Variables view or by hovering the mouse over a variable with the program interrupted. GNAT Studio also provides a Debugger Console view that allows shell access to the underlying GDB client that is debugging the program. The GDB commands that correspond to the above debugging tasks can be entered directly into the console if desired. The debugging session can be exited via the Debug/Terminate menu or by issuing the quit command in the Debugger Console.

Contents 171 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

172 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX K

X86_64 ELF TOPICS

This appendix describes topics relevant to GNAT for bareboard x86-64 ELF and also presents a tutorial on building, running, and debugging an Ada application in GNATemulator.

K.1 Supported Processors and Run-Time Libraries

GNAT for bareboard x86-64 ELF targets the Intel 64 architecture (also known as AMD64 or x86-64). Out of the box GNAT provides run-time support for the following Intel processor families: • Core and families: processors based on the and newer. • families: processors based on the microarchitecture and newer. For these processors the following generic run-times are provided: • light-x86_64 • light-tasking-x86_64 • embedded-x86_64 All run-time libraries include the necessary low-level hardware startup and initialization functionality required to run applications on systems containing the supported processor families. The run-times only support running on a single core.

K.1.1 Required CPU Features

While the Light run-time has the ability to run on any x86-64 processor, the Light-Tasking and Embedded run-times require the following CPU features that are only present in the supported processor families: • Invariant Time-Stamp Counter • XSAVEOPT instruction The run-time will check for these features on boot and will raise a run-time error if the processor does not support them.

GNAT User’s Guide Supplement for Cross Platforms 173 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

K.1.2 Running a x86_64-elf Application

The x86_64-elf run-times are designed to be booted from a variety of different via -specific linker scripts. Shipped with GNAT Pro is support for: • GNATemulator • Multiboot 1 and Multiboot 2 complaint bootloaders (like GRUB) • LynxSecure (as a LynxSecure Application) By default, applications are built for GNATemulator. To build your application for one of the other supported bootloaders, set the LOADER project variable to MULTIBOOT, MULTIBOOT2 or LSA. The LOADER variable can be specified as a switch to GPRBuild: gprbuild-P proj.gpr-XLOADER=MULTIBOOT or in GNAT Studio by adding the following to your project file: type LOADER_Type is ("MULTIBOOT"); LOADER: LOADER_Type := external ("LOADER", "MULTIBOOT");

GNATemulator

By default, applications are built to run in GNATemulator. To run your program you can either press the Run with Emulator toolbar button in GNAT Studio or run directly from the command line with: x86_64-elf-gnatemu my_program

Multiboot

The MULTIBOOT and MULTIBOOT2 loaders allow the resulting ELF binary to be booted directy using a multiboot complaint bootloader like GRUB.

LynxSecure

The LSA loader produces an application that can be loaded as a LynxSecure Application (LSA). To add the application to a LynxSecure SRP, you first need to convert the ELF binary to a raw binary image: x86_64-elf-objcopy-O binary.bin

Once converted, the application can be included in an SRP with the following switch:

--subject-fvbmada=ram=128m,cpus=1,realtime=true,SERIAL0,lsapath=.bin

174 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

K.1.3 Serial I/O

The run-times are configured to use serial port COM1 with the system default serial configuration.

K.1.4 Clock Speed

The Ravenscar run-times use the invariant Time-Stamp Counter (TSC) and Local APIC Timer as their clock sources and will attempt to determine the frequencies of these clock sources on boot, based on the information provided to it by the processor. On some processors this information may be unavailable, and the run-time will raise a program error indicating this problem. If this occurs, the TCS and Local APIC Timer frequency will need to be manually set in System.BB.Parameters. You may also need to manually set this frequency if the run-time determines the wrong TCS or Local APIC Timer frequencies.

K.1.5 Interrupts

x86-64 uses a split interrupt controller design. Each CPU has its own Local Advanced Programmable Interrupt Controller (APIC) that can receive external interrupts from PCI devices via the Message Signaled Interrupts (MSI) feature or from I/O APICs. The Ravenscar run-times only support attaching protected procedure handlers to Local APIC interrupt vectors via the Attach_Handler aspect. Interrupt vectors 33 to 254 are available for user applications, with Interrupt 32 reserved for the Spurious Interrupt Vector and Interrupt 255 reserved for the APIC Timer as used by the run-time. See Ada.Interrupts.Names for the list of vectors. Note that interrupt priorities are handled differently by the Intel Local APIC compared to interrupt controllers used by other processors. The Local APIC encodes the interrupt priority of a vector in the top 4 bits of the 8-bit vector number. Consequently, when attaching a protected procedure to an interrupt vector you need to ensure that the Interrupt Priority of the protected object corresponds to the priority class of the interrupt vector. Please refer to Ada.Interrupts.Names for a mapping of vector numbers to Interrupt Priorities, as the run-time will enforce these mappings. To attach a handler to an I/O APIC IRQ, route the IRQ to a Local APIC Vector using the Route procedure provided in Interfaces.X86_64.IO_APIC and attach the protected handler to the Vector. Then unmask the IRQ using the Mask procedure. For example, in the following code we connect a protected handler called Signal to IRQ4 by routing it to Local APIC Vector 33 and attaching the handler to that vector:

1 with Ada.Interrupts.Names; use Ada.Interrupts.Names;

2 with Interfaces.X86_64.IOAPIC; use Interfaces.X86_64.IOAPIC;

3

4 package My_Pack is

5 protected Handler_Object

6 with Interrupt_Priority => Vector_32_47_Interrupt_Priority

7 is

8 procedure Initialize;

9 procedure Signal with Attach_Handler => Vector_33;

10 end Handler_Object;

11 end My_Pack;

12

13 package body My_Pack is

14

15 protected body Handler_Object is

16 procedure Initialize is

17 begin

18 Route(Interrupt => IRQ4,

19 To_Vector => Vector_33);

20 Unmask(IRQ4); (continues on next page)

Contents 175 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page)

21 end Enable_External_Interrupt;

22

23 procedure Signal is

24 begin

25 Ada.Text_IO.Put_Line("Interrupt handled");

26 end Signal;

27

28 end Handler_Object;

29 end My_Pack;

K.1.6 Memory Layout

The GNAT for bareboard x86-64 run-times are designed to be loaded by a bootloader into RAM. By default the run-times are configured to use 128MB. If your system has more or less memory, modify memory-map.ld to suite your requirements or provide your own linker script by setting the environment variable LOADER to ‘USER’ and specifying the linker script via the ‘-T’ linker switch. The run-times will not automatically detect the amount of RAM in the system.

K.2 Getting Started

Developing with GNAT for bareboard 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. These 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 the x86-64 the target x86_64-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:

project Demo is ... for Runtime("Ada") use "light-x86_64"; for Target use "x86_64-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.

K.2.1 Getting Started with GNATemulator

This guide describes how to set up, build, run, and debug an Ada application on GNATemulator. Setup for both Windows and Linux hosts is covered. While this section focuses on GNATemulator, most of the steps contained within this section are independent of the application and the target hardware itself. To begin this setup, it is assumed that GNAT for bareboard x86-64 has been installed and that the install bin directory is in the PATH environment variable.

176 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

K.2.2 Creating a new Project

Launch GNAT Studio:

$ gnatstudio

If this is your first time running GNAT Studio, note that GNAT Studio will create a configuration directory and will alert you via a pop-up dialog box. Press ‘OK’ to close that box and continue. A ‘Tip of the Day’ dialog will appear. Press Close to dismiss it. When on the Welcome page, click on Create new project and select Simple Ada project, and then click on Next. Change Location and Settings appropriately and press Apply. The project view is now displayed. Next, open the project properties by right-clicking on the project name in Project tab, and selecting Project->Properties. With the project properties displayed open the Toolchains tab, and make sure that the x86_64-elf toolchain is selected and the Ada run-time is light-x86_64. Then click on Save. You can now add your source code.

K.2.3 Building

Within GNAT Studio, build the project using either the Build Main button on the toolbar, or the Build/ Project->Build All menu entry. In the latter case, if a pop-up window appears, press the Execute button in order to build with the default settings. As GNAT Studio builds the project, it will display the Messages view at the bottom of the GNAT Studio window to show information about the build. On a successful build, the Memory Usage view will graphically display the memory usage of the program, unless the preference is disabled. (See the preference Build Targets/Project/Build Main page, among others, containing the Display memory usage check-box.)

K.2.4 Running the Program

Within GNAT Studio, run your program 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 x86_64-elf-gnatemu view.

K.2.5 Debugging the Program

In GNAT Studio, click on the Debug with Emulator button on the toolbar. This will start a GNAT Studio debug session and launch the necessary tools required to debug the program on the emulator from GNAT Studio. The emulator will be automatically launched. Debugging a program on the emulator through GNAT Studio is similar to debugging a native program: • The program can continue to the next breakpoint by pressing the Continue button on the toolbar or by using the Debug/Continue menu item. • The program can be stepped through statements using the corresponding menu items in Debug menu and buttons on the toolbar. • The program can be interrupted by pressing -\, or through the Debug/Interrupt menu. • Breakpoints can be set via the Breakpoints view, by clicking on the line numbers in the source editor while the program is interrupted, or by right-clicking on the desired line and selecting Set breakpoint on line ... from the Debug menu.

Contents 177 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

• Variables can be queried from the Variables view or by hovering the mouse over a variable with the program interrupted. GNAT Studio also provides a Debugger Console view that allows shell access to the underlying GDB client that is debugging the program. Arbitrary GDB commands, including the commands corresponding to the above, can be entered into the console if desired. The debugging session can be exited via the Debug/Terminate menu or by issuing the quit command in the Debugger Console.

178 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX L

CROSS LINUX TOPICS

This appendix describes topics that are specific to the GNAT for Cross Linux.

L.1 Building a Cross Linux Application

To use GNAT Pro for Cross Linux the environment variable ENV_PREFIX needs to be set to the path containing the sysroot of your target. As background, the sysroot is the root directory for the folders containing the system headers and libraries provided by the target system. A typical sysroot would contain the following directories: mysysroot: |--> lib: |--> lib64: (on 64-bit Linux) \--> usr: |--> include: |--> lib: \--> lib64: (on 64-bit Linux))

At a minimum the sysroot should contain glibc 2.5 or greater. Please refer to your Embedded on how to obtain a sysroot corresponding to your target. GNAT Pro supports both single architecture sysroots and -style multiarch sysroots. Please note the Ubuntu cross compiler toolchain provided by the crossbuild-essential-* packages do not provide a sysroot useable by GNAT Pro. If you have trouble obtaining a sysroot, it is possible to build one by copying the target libraries from the target to your host. For instance, if you are developing with a ppc64-linux target, you could do the following to build a sysroot directory on your host:

$ mkdir ./sysroot $ mkdir ./sysroot/usr $ scp -rp my-ppc64-linux-target:/usr/include ./sysroot/usr/ $ scp -rp my-ppc64-linux-target:/usr/lib ./sysroot/usr/ $ scp -rp my-ppc64-linux-target:/usr/lib64 ./sysroot/usr/ $ scp -rp my-ppc64-linux-target:/lib ./sysroot/ $ scp -rp my-ppc64-linux-target:/lib64 ./sysroot/

To use that sysroot, you can then export ENV_PREFIX as follow.

$ export ENV_PREFIX=`pwd`/sysroot

To build the basic Hello world example on ppc64-linux, you can then invoke gprbuild with the following options:

$ gprbuild --target=powerpc64-generic-linux-gnu hello.adb

GNAT User’s Guide Supplement for Cross Platforms 179 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

WARNING: Some Linux systems provide linker scripts, e.g. libc.so, that may point to other shared libraries using a full path that starts with a double-slash ‘//’. While this does not cause any problem on GNU/Linux hosts, on Windows hosts, such paths are interpreted as UNC path. This should not prevent sysroot to be expanded, however Windows users creating sysroots from a live target system may want to fix them to avoid the latency of a network search.

L.2 Debugging an Application on Cross Linux

This section describes the steps needed to run the Cross Linux debugger. The debugging solution that GNAT provides on this target consists of three tools: • gdbserver: A debugging server on target, which provides a low-level interface to control the debugged program. • gdb: The debugger itself, run on the host; it connects to GDBserver and allows the user to control the debugged program through a command-line interface. • gnatstudio: GNAT Studio, which provides a graphical front-end for gdb. To start a debugging session, you first need to start the program under control of GDBserver. For example, if the board has an internet connection to the development host, and assuming the Internet hostname of the board is myboard, your application is named myapp, and the port on which GDBserver will wait for requests is port 2345, the command would be: myboard> gdbserver myboard:2345 myapp

This starts the execution of your program on the target, and then suspends it at the very beginning. Once this is done, GDBserver then waits for the debugger to connect. You can now start the debugger. In GNAT Studio, in the Languages tab of the project properties page, you would specify the name of the debugger (e.g. powerpc64-generic-linux-gnu-gdb). You would then be able to start this debugger with the command: Debug => Initialize => . Alternatively, you can run the debugger gdb from the command line. You are now ready to connect the debugger to the GDB server:

(gdb) target remote myboard:2345

Once the debugger is connected to the GDBserver, you can debug your program as usual (insert breakpoints, inspect variables and memory, etc); remember that the program’s execution has already been started by GDBserver, and thus use “continue” to resume the program’s execution, rather than “run”. Below is an example of a debugging session where the user is interested in debugging a function called some_function, and therefore, after connecting to the target, inserts a breakpoint and then resumes his program until reaching that breakpoint:

(gdb) target remote myboard:2345 ... (gdb) break some_function ... (gdb) continue ...

Note that the debugger needs access to the exact shared libraries being used by your program. By default, what the debugger does is automatically download from the target a copy of each shared library the program uses. It is recommended to keep the default, as this ensures that the debugger’s knowledge of the shared libraries matches exactly the libraries actually installed on the target, which is crucial. However, if you are debugging on a target with a slow connection, the download may be taking long enough that you would prefer to maintain on the host a copy of the target system’s shared library (the sysroot described above), and then tell the debugger to use your sysroot instead.

180 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

For this, before connecting to GDBserver, use the following debugger command (where SYSROOT_PATH should be replaced by the path where the sysroot is located on the host):

(gdb) set sysroot SYSROOT_PATH ...

For further information about the debugger or the GDB server, please refer to the GDB User’s Manual.

Contents 181 of 204 GNAT User’s Guide Supplement for Cross Platforms 23.0w

This page is intentionally left blank.

182 of 204 GNAT User’s Guide Supplement for Cross Platforms GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX M

PIKEOS TOPICS

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

M.1 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.

M.1.1 Creating a PikeOS kernel integration project

To setup your PikeOS kernel project, please consult the PikeOS User Manual section 8 : Basic Steps of the PikeOS Build Process. Be sure to pick the template devel-pikeos-native as it contains a project pre- configured with the major development features.

M.1.2 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.

GNAT User’s Guide Supplement for Cross Platforms 183 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

M.1.3 PikeOS interrupts

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

M.1.4 PikeOS muxa configuration

As explained earlier, console and debugging functionalities 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.

M.2 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;

184 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

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

$ gprbuild --target=arm-sysgo-pikeos --RTS=embedded -g hello.adb

A similar command would be used on other CPUs; only the target and the prefix of tools would change (e.g. powerpc- sysgo-pikeos-gcc). In the rest of this tutorial, we will use arm-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 **/target/pikeos $ cd ** $ source ./PikeOS.sh $ make boot

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

M.3 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.

M.4 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 p4ext-cert-app.c in the GNAT run-time library; the path to the GNAT run-time library is given by arm-sysgo-pikeos-gnatls -v. After copying it in your source directory, you can recompile it with the following command:

$ arm-sysgo-pikeos-gcc -c -DDEBUG p4ext-cert-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:

$ gprbuild --target=arm-sysgo-pikeos --RTS=embedded -f -g hello.adb \ -largs p4ext-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 /target/pikeos $ cd $ source ./PikeOS.sh $ make boot

Contents 185 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

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, the proper set of options would be: :: -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 by the actual name of your host machine):

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

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

$ telnet 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.52 21 102 COLD_START (continues on next page)

186 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

(continued from previous page) 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 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 :1551 using GDB’s remote protocol, either from GNAT Studio or from the command line:

(gdb) file hello (gdb) target remote:1551 Remote debugging using: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) b5 Breakpoint1 at 0x80101da: file hello.adb, line 5. (gdb) c Continuing.

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

Contents 187 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

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

188 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX N

IOS TOPICS

This section describes how to set a project up for deployment on iOS devices, and how to use GNAT Pro for iOS to include Ada code in your App. It also describes how to build and deploy this App on the iOS simulator.

N.1 Prerequisites

In order to use GNAT Pro for iOS, you need to have Xcode and the Xcode Command Line Tools installed on your machine. Please refer to the Xcode documentation on how to install these components.

N.2 Preparing Your Ada Project for Xcode Integration

The recommended approach for including Ada in your iOS App is to bundle your Ada code into a library, using a GPRbuild Standalone Library Project file. For instance, here is a simple Standalone Library Project file which creates an archive called libiplanet.a in the lib directory. project IPlanet is for Languages use ("Ada", "C"); for Source_Dirs use ("src"); for Object_Dir use "obj"; for Library_Dir use "lib"; for Library_Kind use "static"; for Library_Name use "iplanet"; for Library_Interface use ("main"); end IPlanet;

With a Standalone Library Project file, the resulting library provides two functions to perform the library’s elaboration and finalization. The names of these functions depend on the name of the library (specified using the Library_Name attribute in your project file). For instance, with the IPlanet project file above, the name of the elaboration function is iplanetinit. This will be important later on, when integrating your Ada project into your App. To build your Ada project, simply use gprbuild as usual. For instance:

$ gprbuild --target=aarch64-ios-darwin -P iplanet

Please refer to the GPRbuild documentation for more detailed information regarding project files. Your iOS App needs to know the identities of all the Ada functions that it is going to call. This is achieved by creating a header file containing all the function prototypes. This file will be integrated later into the iOS App project. Here we will assume that the project provides one header file called iplanet.h.

GNAT User’s Guide Supplement for Cross Platforms 189 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

N.3 Integrating Your Ada Project into Your App

Developing an App for iOS requires that an Xcode Project be created for that App first. Please refer to the Xcode documentation for instructions on how to create such a project. To integrate your Ada project: • Add a call to the elaboration function of your Ada library (see above) inside your App’s code such that this function gets called before your App starts calling the rest of your Ada library. For instance, if your App uses Swift, and assuming you are using the project file above, this can be done by adding a call to iplanetinit at the start of the “application” function in file AppDelegate.swift. • Integrate the Ada code into your project. For this, use the Add files to ... menu item in the Project Navigator’s contextual menu. • Add the various C header files provided by your Ada project (iplanet.h in the example project above). • Add your Ada library’s archive file (libiplanet.a in our example above). • Add the Ada runtime libraries libgnat.a and libgnarl.a. The location of those files is usually in /lib/gcc/aarch64-apple-darwin/ /rts-native/adalib, where is the location where you installed GNAT Pro, and is the version printed by the command aarch64-apple-darwin-gcc -dumpversion, for example 6.4.1. • Tell Xcode where to find the various C header files you just added, by adding the path where those files are located to the Objective-C Header field in the project Build Settings tab. • Tell Xcode where to find the Ada libraries you just added. For this, update the Library Search Path in the Build Settings tab. – Add the directory where your Ada library is located. – Add the directory where libgnat.a and libgnarl.a are located (see location above). • Additional libraries may be required by your project. In that case, just follow the same process described above. • Because Ada runtime libraries are not built with bitcode enabled, you have to disable bitcode in the Build Settings tab of your App’s project. Once you have performed the above steps, you should be able to add calls from your App to your Ada project and then build your project as usual (menu Product → Build For → Running).

N.4 Running Your App on Your iOS Device

Once the iOS App has been built, you can deploy it and run it on your device through Xcode using the standard method recommended by the Xcode documentation. Note that the first time you run the App you will have to trust your developer app certificate on your device. To do so: • Open the settings app on your iOS device • Navigate to General → Device Management • Select your Developer App certificate to trust it.

190 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

N.5 Using the iOS Simulator

Using an iOS simulator to run the App is roughly the same process as for the real iOS device, except for the following changes: • Your Ada project needs to be built with the ios-simulator runtime, using the native GNAT Pro compiler. For this, we no longer use --target=aarch64-ios-darwin in our gprbuild command, and add --RTS=ios-simulator instead. For instance:

$ gprbuild -P iplanet --RTS=ios-simulator

• In the Xcode project, the location for libgnat.a and libgnarl.a runtime libraries is in /lib/gcc///rts-ios-simulator/adalib where is the output of gcc -dumpmachine (eg: x86_64-apple-darwin14.5.0) Once you have completed these steps, just rebuild and run your App using Xcode targeting the iOS simulator. Please refer to the Xcode documentation for more information.

N.6 Debugging Your App on Your iOS Device

Once the iOS App has been deployed on your device, you can debug it using Xcode. As with any debugger, you can suspend/resume the App, add/remove breakpoints, both in Swift or in Ada code. However, beyond this, the Xcode debugger only has limited support for Ada. Because of App high-security rules, the AdaCore debugger cannot be used to debug your App directly on the iOS device. Our recommendation is to validate all your Ada code on the iOS simulator, where the AdaCore debugger can be used for debugging Ada. The rest of your App can be validated on the iOS device, using the Xcode debugger.

N.7 Debugging Ada on the iOS Simulator

The recommended way to debug the Ada code in your App using the iOS simulator is to start your App Xcode, then start GNAT Studio and attach the AdaCore debugger to your running App. To do so: • In Xcode’s top navigation icons, choose a simulator. • Start the simulation. – Find the process ID of your App. For instance, in a terminal, type:

$ ps aux | grep Devices | grep Application

• Start GNAT Studio. • In GNAT Studio, start the debugger using the Initialize → no main file menu. • Then attach the debugger to the App using its Process ID (menu Debug → Debug → Attach). Alternatively, type attach PID in the debugger console, where PID is the process ID of your App. • The App should suspend and you can now use GNAT Studio to debug your App.

Contents 191 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Known Limitations

Once you have connected the AdaCore debugger to your App, you now have two debuggers connected to the same App at the same time. Since neither knows about the other, it is important to not use the Xcode debugger while the AdaCore debugger remains connected to your App. This will avoid one debugger interfering with the other. After the initial attachment and the first “continue” command, the AdaCore debugger is not able to suspend your App. The only way for the debugger to stop the App again is through breakpoints or catchpoints, so be sure to insert any of them before you resume your App’s execution.

192 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX O

QNX TOPICS

This appendix presents information specific to GNAT for QNX 7 cross configurations.

O.1 Getting Started

This section is a starting point for using GNAT to develop and execute Ada programs for Blackberry’s QNX 7 target environment. We assume that you know how to use GNAT in a native environment and how to start an ssh or other login session to connect to your board running QNX. We also assume that you have installed the QNX Software Development platform. To compile code for a QNX target using GNAT Pro, you will need to first set up your environment from the QNX Software Development platform. For example:

$ source ~/qnx700/qnxsdp-env.sh

With GNAT, the easiest way to build the basic Hello World program is with gprbuild. For the aarch64 QNX target this would look like:

$ gprbuild --target=aarch64-nto-qnx hello using project file .../_default.gpr Compile [Ada] hello.adb Bind [gprbind] hello.bexch [Ada] hello.ali Link [link] hello.adb

(The first line is the command entered by the user – the subsequent three are the programs run by gprbuild.) This creates the executable hello, which you then need to load on the board to run it.

GNAT User’s Guide Supplement for Cross Platforms 193 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

O.2 Integration with Momentics

The GNAT Pro toolchain can be integrated with the Momentics development environment by installing the GNATbench plugin. Once installed, comprehensive documentation on how to use GNATbench with QNX is available in the help menu.

194 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

APPENDIX P

GNU FREE DOCUMENTATION LICENSE

Version 1.3, 3 November 2008 Copyright 2000, 2001, 2002, 2007, 2008 , Inc http://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The purpose of this License is to make a manual, textbook, or other functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The Document, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A“Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A“Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

GNAT User’s Guide Supplement for Cross Platforms 195 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A“Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called Opaque. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. The “publisher” means any person or entity that distributes copies of the Document to the public. A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

196 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer- network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers.

Contents 197 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements”. 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION

198 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site. “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. “Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.

Contents 199 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright © YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”. If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with . . . Texts.” line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free , such as the GNU General Public License, to permit their use in free software.

200 of 204 Contents GNAT User’s Guide Supplement for Cross Platforms 23.0w

INDEX

Symbols A __gnat_free, 29, 50 AArch64-ELF Topics, 149 __gnat_last_chance_handler, 31 Ada.Exceptions.Traceback, 82 __gnat_malloc, 29, 50 Ada.Unchecked_Deallocation generic, 50 -E (gnatbind), 50 addr2line, 82 -M (gnatlink), 57 Allocator, 50 -O (gcc), 59 Always_Compatible_Rep (configuration -S (gcc), 58 parameter), 38 -T (gnatbind), 60 and/or usage control, 55 -Wa (gcc), 58 Annex H (Ada Reference Manual), 48 -Wl (gnatlink), 57 Annex H restrictions, 59 --RTS=, 18 APEX (for VxWorks 653), 99 --RTS= switch, 32 ARINC-653, 99 --gc-sections (gnatlink), 57 ARINC-653 Binding (for VxWorks 653), 108 -adhl (gcc), 58 ARM tutorial, 149 -f (gnatbind), 60 ARM-ELF Topics, 137 -fdata-sections (gcc), 57 Array and record assignments and the -ffunction-sections (gcc), 57 Certifiable Profiles, 51 -fno-if-conversion (gcc), 59 Avoiding elaboration code, 55 -fno-if-conversion2 (gcc), 59 AVR-ELF Topics, 156 -fno-short-circuit-optimize (gcc), 59 -fstack-check (gcc), 59 B -fverbose-asm (gcc), 58 Back-End zero cost exceptions, 38 -gnatD (gcc), 36, 48, 58 Backend_Divide_Checks (configuration -gnatE (gcc), 50 parameter), 38 -gnatG (gcc), 36, 48, 56, 58 Backend_Overflow_Checks (configuration param- -gnatL (gcc), 58 eter), 38 -gnatR (gcc), 48, 58 Bareboard debugging, 122 -gnatT (gcc), 59 Bareboard Topics, 116 -gnata (gcc), 59 bcopy, 51 -gnato (gcc), 59 Binder switches, 60 -gnatwt (gcc), 57 Building a VxWorks 7 Application from -gnaty (gcc), 48, 59 GNAT Studio, 96 -gnatz (gcc), 59 Building a VxWorks 7 Application from -mregnames (gcc), 58 Workbench, 95 -nodefaultlibs (gcc), 34 -nostdlib (gcc), 34 C -nostdlib switch, 29 Certifiable Profiles, 47 -save-temps (gcc), 58 Certified Systems, 45 -shared (gnatbind), 60 Character Input/Output (Bareboard), 120 -static (gnatbind), 60 Child units (permitted in Certifiable Profiles), 47 -t (gnatbind), 60 Command_Line_Args (configuration parameter), 38

GNAT User’s Guide Supplement for Cross Platforms 201 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

Compiler switches, 59 GNAT Studio (for VxWorks 653), 104 conditional operators, 55 gnat.adc file, 51 Configurable run-time, 33 gnatbind switches, 60 Configurable_Run_Time (configuration parameter), 38 I Configurable_Run_Time (in package System), 44 Implicit conditionals, 53 Configuration pragmas (for tailoring the run Implicit loops, 53 time), 37 Interrupt Handling (VxWorks), 69 Constraint_Error, 49 iOS Topics, 189 Cross Linux Topics, 178 Customized Bareboard Run-Time J Libraries, 123 Jorvik Profile, 23 D K Deactivated code, 56 Known GNAT C++ Limitations on PowerPC Debugging (Bareboard), 122 VxWorks 6, 94 Debugging (for VxWorks 653), 104 Known GNAT C++ Limitations on VxWorks Denorm (configuration parameter), 38 7, 98 DO-178B, 56 Duration_32_Bits (configuration parameter), 38 L Dynamic Memory Allocation (Bareboard), 122 Last_Chance_Handler, 31, 111 LEON3 Topics, 159 E Light mode, 59, 60 EABI (for VxWorks on PowerPC), 78 Light Profile, 47 Elaboration code, 55 Light Run_Time, 28 Embedded ABI (for VxWorks on PowerPC), 78 Light-Tasking mode, 59, 60 Embedded ARM tutorial, 149 Light-Tasking Profile, 47 Embedded Run_Time, 27 Light-Tasking Run-Time, 31 Example - memcpy function in Ada, 51 LynxOS-178 Topics, 112 Exception declaration (permitted under No_Exception_Handlers), 50 M Exceptions and the Certifiable Machine_Overflows (configuration parameter), 38 Profiles, 48 Machine_Rounds (configuration parameter), 38 Exceptions and the Last Chance MC/DC (in DO-178B and DO-178C), 55 Handler, 30 memcpy, 51 Exit_Status_Supported (configuration memLib, 51 parameter), 38 memmove, 51 Exponentiation (and configurable run-time), 44 memNoMoreAllocations, 51 memset, 51 F Minimizing Code and Data Sizes features excluded by, 54 (Bareboard), 119 Front-End longjmp/setjmp exceptions, 38 Mixed-language programming (for VxWorks), 63 Frontend_Exceptions (configuration parameter), Modes (of GNAT Pro Configuration), 32 38 Modified Condition/Decision Coverage, Full Ada Run-Time Library (for VxWorks 653), 55 99 Module OS (for VxWorks 653), 99 Functions returning unconstrained objects, 53 N Naming the run-time library, 45 G No_Allocators restriction, 51 gdb (for VxWorks 653), 104 No_Direct_Boolean_Operators restriction, Generic templates (permitted in Certifiable Pro- 55 files), 47 No_Implicit_Conditionals, 54 GNAT Pro Run-Time Library, 34

202 of 204 Index GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

No_Implicit_Conditionals restriction, Restricted Run-Time Library (for VxWorks 48, 53 653), 99 No_Implicit_Heap_Allocators restriction, returned by functions, 53 51 Reviewable object code, 48 No_Implicit_Loops, 54 RISCV32-ELF Topics, 164 No_Implicit_Loops restriction, 48, 53 RISCV64-ELF Topics, 167 No_Local_Allocators restriction, 51 RTPs and kernel modules, 89 No_Secondary_Stack restriction, 53 Run_Time_Name (for configurable run time), 45 No_Unchecked_Deallocation restriction, 51 S s-secsta.ads (package spec System.Secondary_Stack), O 53 Object-Oriented Programming (and the Certifi- Secondary Stack, 21, 110 able Profiles), 47 Secondary stack (for unconstrained objects Object-Oriented Programming and the returned by functions), 53 Certifiable Profiles, 52 Signed_Zeros (configuration parameter), 38 Optimization issues, 58 Slice assignment and implicit loops and conditionals, 53 P Specifying a Run-Time, 32 Partition OS (for VxWorks 653), 99 Specifying the Run-Time Library, 18 PikeOK Topics, 181 Stack_Check_Default (configuration parameter), POSIX (for VxWorks 653), 99 38 PowerPC VxWorks, 78 Stack_Check_Limits (configuration parameter), 38 pragma Detect_Blocking, 37 Stack_Check_Probes (configuration parameter), 38 pragma Discard_Names, 37, 112 Standard Run-Time, 27 pragma Locking_Policy, 37 Storage_Error, 49 pragma Normalize_Scalars, 37 Support_Aggregates (configuration parameter), 38 pragma Queuing_Policy, 37 Support_Atomic_Primitives (configuration pa- pragma Restrictions, 38, 47, 48 rameter), 38 pragma Restrictions (No_Secondary_Stack), 53 Support_Composite_Assign (configuration pragma Suppress_Exception_Locations, 31 parameter), 38 pragma Task_Dispatching_Policy, 37 Support_Composite_Compare (configuration pa- Preallocated_Stacks (configuration parameter), rameter), 38 38 Support_Long_Shifts (configuration parameter), Primary and Secondary Stacks, 18 38 Primary Stack, 19 Suppress_Standard_Library (configuration pa- Program_Error, 49 rameter), 38 System.Secondary_Stack, 53 Q System.Traceback, 82 QNX Topics, 193 T R Tagged types at library level (permitted in raise statement (permitted under Certifiable Profiles), 47 No_Exception_Handlers), 50 Traceability from Source Code to Ravenscar Profiles, 23 Object Code, 57 Record and array assignments and the Tutorial (Embedded ARM), 149 Certifiable Profiles, 51 Typographical conventions, 14 relocation issues, 78 Relocation issues for PowerPC VxWorks U targets, 78 Unchecked_Deallocation generic, 50 Removal of Deactivated Code, 56 Unconstrained objects, 53 Restricted Ravenscar Run-Time Library Use_Ada_Main_Program_Name (configuration pa- (for VxWorks 653), 99 rameter), 38

Index 203 of 204 GNAT User’s Guide Supplement for Cross Platforms, Release 23.0w

V Viewing Code and Data Size (Bareboard), 119 vThreads (for VxWorks 653), 99 vxaddr2line, 82 VxWorks 653 application structure, 108 VxWorks 653 Topics, 99 VxWorks 7 RTPs and kernel modules, 96 VxWorks PowerPC, 78 VxWorks Topics, 60 W Workbench / VxWorks 6 Topics, 87 Workbench / VxWorks 7 Topics, 95 wrenv* scripts (for VxWorks 653), 105 X x86_64-ELF Topics, 171 Xcode, 190 Z ZCX_By_Default (configuration parameter), 38 Zero Footprint (Light) Run-Time Library (for VxWorks 653), 99

204 of 204 Index