tech days 2015: arm programming with gnat and ada 2012
TRANSCRIPT
Goals
• Introduce the target hardware
• Introduce the development environment
– Tools, runtime libraries, etc.
• Show you some “tips and tricks” we use internally
– Switches we apply
– Debugging techniques
– et cetera
• Basically everything you need to get started
• Provide pointers for where to go next
– The AdaCore bare-board community GitHub project
2
Agenda
• The Target Hardware
• The Software Tools
• The Runtime Libraries
• “Hello World”
• Where To Go Next
3
“STM32F4 Discovery” Evaluation Board
• 32-bit ARM Cortex-M4F microcontroller at 168 MHz
• 1 MB of Flash memory
• 192 KB of RAM
• On-board USB-JTAG debugger interface
• Four user LEDs: orange, green, red, blue
• Two pushbuttons (user (blue) and system reset (black))
• 3-axis accelerometer
• Timers, DMA, USARTs, others…
5
“STM32F4 Discovery” On-Board Devices
“ST-LINK” USB
Debug Support
User LEDs
Port/Pin Header
Port/Pin Header
Audio Out
Jack
Audio DAC
6
“STM32F429 Discovery” On-Board Devices
“ST-LINK”
USB Debug
Support
User LEDs
2.24” QVGA LCD
with Touch Panel
3-Axis Gyro included
7
Required Software
• You should already have these installed
• The USB device driver
– Third-party software available publicly
– Install this before you ever connect the board to the host
computer
• The GNAT GPL 2015 release
– Compiler etc.
– GPS
• The “st-link” utilities (“st-util” and “st-flash”)
– Pre-installed with Windows installation of GNAT tools
– Must be built and installed by Linux users
9
Connecting the USB Cable
• Connects the on-board power/debug USB connector to the host
computer
• If it doesn’t fit, that’s the wrong end!
– The other one is Micro-USB and is much thinner
Power/Debug
Mini-USB
Connector
10
Using the “ST-LINK” Utilities
• “st-util” provides a GDB server that talks to the on-board support
• “st-flash” writes apps to memory
• Available on the command line
• Both available via GPS toolbar when the plug-in is active
• You may need to run st-util on the command line if the board is
unresponsive to GPS’ invocation of it
– st-util will “get the board’s attention” when seems hung up
• Sometimes you’ll need to cycle power to the board
11
Flashing & Debugging Within GPS
• Supports STM32F4 boards via st-link utils
• Invoked using toolbar icons
• Visible only if “stm32f4” is used in the gpr file to specify the runtime
library name
Flash to
Board
Load, then
start GDB
12
GNAT Project Files
• Text files with Ada-like syntax
• Also known as “gpr files” due to file extension
• Integrated into command-line tools
– Specified via the –P project-file-name switch
• Integrated into the IDEs
– The fundamental artifact
13
Configurable Properties
• Source directories and specific files’ names
• Output directory for object modules and .ali files
• Switch settings for tools
• Source files for main subprogram(s) to be built
• Source programming languages
– Ada / C / C++ are preconfigured
• Many others…
14
Sample Simple Project File
project Demo is
for Languages use ("Ada");
for Main use ("demo.adb");
for Source_Dirs use ("src");
for Object_Dir use "obj";
package Compiler is
for Switches ("Ada") use
("-g", -- enable debugging
"-gnatwa", -- enable all optional warnings
"-gnata", -- enable pre/postcondition checks
"-gnatQ", -- don’t quit
"-gnatw.X"); -- suppress warnings about exceptions
end Compiler;
package Builder is
for Switches ("Ada") use ("-g"); -- enable debugging
end Builder;
end Demo;
15
Specifying the Remote Connection
• Enables GDB to locate the GDB server
project Demo is…
package Ide is
for Program_Host use "localhost:4242";
for Communication_Protocol use "remote";
end Ide;
…
end Demo;
16
Removing Unused Data and Object Code
• Requires switches for compiler and linker
package Linker is
for Switches ("Ada") use ("-Wl,--gc-sections", "-Wl,--print-gc-sections");
end Linker;
Optional. Prints
those removed.
Required
package Compiler iscase Build_Mode is
when "debug" =>…
when "production" =>for Switches ("Ada") use (…, "-ffunction-sections", "-fdata-sections");
end case;end Compiler;
RequiredRequired
17
Displaying Percentages Used
• Implemented after GNAT GPL 2015 release
package Linker is
for Switches ("Ada") use ("-Wl,--gc-sections", "-Wl,--print-memory-usage");
end Linker;
18
The Bare-Board Runtime Libraries
• “SFP” (Small Foot Print”)
– Intended for certification
– A subset of the non-tasking part of the language
• “Full”
– A very large subset of the non-tasking part of the language
• Both provide the Ravenscar tasking subset
• Both are reconfigurable
– You can add or remove functionality and rebuild
• There is also a Zero Footprint “ZFP” runtime
– No tasking
– Almost no object code20
The Runtime Library Names
• Indicate whether Ravenscar is provided
• Indicate the degree of language subset supported
• Indicate the target platform
• Examples
– “zfp-stm32f4”
– “ravenscar-full-stm32f4”
– “ravenscar-sfp-stm32f4”
Ravenscar
tasking
subset
Small
Footprint
subset
Target
Hardware
21
Essential Project File Content
• Specify the runtime library directory path/name
• Specify the platform name
• Both can be specified on the command-line but easier in gpr file
for Runtime ("Ada") use "ravenscar-sfp-stm32f4";
for Target use "arm-eabi";
Basename sufficient
when in default
location
for Runtime ("Ada") use "/path/to/ravenscar-full-stm32f429";
22
The Last Chance Handler (“LCH”)
• Specifies response to unhandled exceptions
– Since exception propagation is not supported in some RTLs
– The last thing executed in that case
• A procedure
• Semantics
– Called automatically by compiled code
– Must never return to caller (loop forever, reset, etc.)
• Default version does nothing but loop
• A user-defined version can override default
23
“Hello World” of Embedded Systems
• Blinks LEDs, of course!
• Located in the compiler installation tree
– Directory name is “demo_leds-stm32f4”
• In Windows, with default installation choice:
• Contains a GNAT project file
• Located it and invoke GPS with it now
C:\GNAT\2015\share\examples\gnat-cross\demo_leds-stm32f4
demo_leds.gpr
25
Load Into Flash and Execute
• Load the program into FLASH using toolbar icon
• Program will start automatically after loading
– You may need to reset the board using the black button
– Sometimes you must cycle power to the board
29
Loaded and Running
Plugin loads
the image Push the blue User
button to change the
LED rotation directionUser LEDs
30
Troubleshooting Load/Debug In GPS
• If GPS toolbar icon cannot work for some reason…
• Terminate the debug session in GPS
• Open a command line and invoke st-util there
– It will connect to the board, emit some messages, and wait for
GDB server commands
Command Line st-util for Debugging
• In GPS, start the debugger via the menu
– Apply the “Debug -> Initialize -> demo” menu
32
Additional st-util Messages In Shell
• You will see messages from st-util in the command line console
33
And You’re Ready To Go…
• You can set breakpoints, etc. if desired
• Then press the debugger toolbar icon to “Continue” (or start) to run
35
Source Files Included
• gnat.adc
• button.adb
• button.ads
• demo.adb
• driver.adb
• driver.ads
• last_chance_handler.adb
• last_chance_handler.ads
• leds.adb
• leds.ads
• registers.ads
• stm32f4.ads
• stm32f4-gpio.ads
• stm32f4-reset_clock_control.ads
• stm32f4-sysconfig_control.ads
pragma Partition_Elaboration_Policy (Sequential);
36
Main Subprogram
with Driver; pragma Unreferenced (Driver);
-- The Driver package contains the task that actually controls the app so-- although it is not referenced directly in the main procedure, we need it-- in the closure of the context clauses so that it will be included in the-- executable.
with Last_Chance_Handler; pragma Unreferenced (Last_Chance_Handler);
-- The "last chance handler" is the user-defined routine that is called when-- an exception is propagated. We need it in the executable, therefore it-- must be somewhere in the closure of the context clauses.
with System;
procedure Demo ispragma Priority (System.Priority'First);
beginloop
null;end loop;
end Demo;
37
Setting Tasks’ Stacks and Priorities
• For any task created, set the stack to around 4K
– The default is far too large for these boards
– Can make it larger if necessary
• Can set the priority similarly, as needed
– Remember there is a default applied already
package Driver is
task Controller is
pragma Storage_Size (4 * 1024);
end Controller;
end Driver;
package Driver is
task Controller
with Storage_Size => (4 * 1024);
end Driver;
OR
38
with LEDs; use LEDs;
with Button; use Button;
with Ada.Real_Time; use Ada.Real_Time;
package body Driver is
type Index is mod 4;
Pattern : constant array (Index) of User_LED := (Orange, Red, Blue, Green);
task body Controller isPeriod : constant Time_Span := Milliseconds (75); -- arbitraryNext_Start : Time := Clock;Next_LED : Index := 0;
beginloop
Off (Pattern (Next_LED));
if Button.Current_Direction = Counterclockwise then
Next_LED := Next_LED - 1;
else
Next_LED := Next_LED + 1;
end if;
On (Pattern (Next_LED));
Next_Start := Next_Start + Period;
delay until Next_Start;
end loop;end Controller;
end Driver; 39
package Button ispragma Elaborate_Body;
type Directions is (Clockwise, Counterclockwise);
function Current_Direction return Directions;
end Button;
Button Interface
• Pressing the blue User button changes the value returned by the
“current direction” function
40
with Ada.Interrupts.Names;
with Ada.Real_Time; use Ada.Real_Time;
with Registers; use Registers;
with STM32F4; use STM32F4;
with STM32F4.GPIO; use STM32F4.GPIO;
package body Button is
protected Button is
function Current_Direction return Directions;…
end Button;
protected body Button is
function Current_Direction return Directions is …procedure Interrupt_Handler is …
end Button;
function Current_Direction return Directions isbegin
return User_Button.Current_Direction;end Current_Direction;
procedure Initialize is …
beginInitialize;
end Button;41
protected Button ispragma Interrupt_Priority;
function Current_Direction return Directions;
private
procedure Interrupt_Handler;
pragma Attach_Handler (Interrupt_Handler, Ada.Interrupts.Names.EXTI0_Interrupt);
Direction : Directions := Clockwise; -- arbitrary
Last_Time : Time := Clock;
end Button;
42
Debounce_Time : constant Time_Span := Milliseconds (500); -- semi-arbitrary
protected body Button is
function Current_Direction return Directions isbegin
return Button.Current_Direction;end Current_Direction;
procedure Interrupt_Handler isNow : constant Time := Clock;
begin
-- Clear interrupt
EXTI.PR (0) := 1;
-- Debouncing
if Now - Last_Time >= Debounce_Time then
if Direction = Counterclockwise thenDirection := Clockwise;
elseDirection := Counterclockwise;
end if;
Last_Time := Now;
end if;
end Interrupt_Handler;
end Button;43
…
with Registers; use Registers;with STM32F4; use STM32F4;with STM32F4.GPIO; use STM32F4.GPIO;
package body Button is …
procedure Initialize isRCC_AHB1ENR_GPIOA : constant Word := 16#01#;
begin-- Enable clock for GPIO-ARCC.AHB1ENR := RCC.AHB1ENR or RCC_AHB1ENR_GPIOA;
-- Configure PA0GPIOA.MODER (0) := Mode_IN;GPIOA.PUPDR (0) := No_Pull;
-- Select PA0 for EXTI0SYSCFG.EXTICR1 (0) := 0;
-- Interrupt on rising edgeEXTI.FTSR (0) := 0;EXTI.RTSR (0) := 1;EXTI.IMR (0) := 1;
end Initialize;
beginInitialize;
end Button; 44
Using the LCH with the Debugger
• Put a breakpoint on the first statement
• If breakpoint is hit, use GPS to examine the memory at Msg.all to
show the designated string
– Use the “Debug->Data->Examine Memory” menu
– Put “msg.all” into the Locations entry pane (no quotes)
…
package body Last_Chance_Handler is
procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is
begin
Off (Green);
…
end Last_Chance_Handler;
end Last_Chance_Handler;
45
STM32F4 Documentation
• For devices across the entire STM32F4 family
– GPIO, Timers, etc.
– “RM0090 Reference manual”
– Subtitled “STM32F405xx/07xx, STM32F415xx/17xx,
STM32F42xxx and STM32F43xxx advanced ARM-based 32-bit
MCUs”
– Also known as file “DM0003120”
• Specific to the STM32F4 Discovery board
– “UM1472 User manual”
– Subtitled “Discovery kit for STM32F407/417 lines”
– Also known as file “DM00039084”
47
GNAT and GPS Documentation
• The GNAT Cross User Guide
– “GNAT User's Guide Supplement for Cross Platforms”
– Especially see the tutorial: “ARM-ELF Topics and Tutorial”
• GPS Users Guide
48
The ARM GitHub Repository
• https://github.com/AdaCore/bareboard
• Makes everything much easier!
• Adds significant functionality
• Contents, currently for STM32F4 products:
– Device drivers
– Complete demonstration projects for drivers
– Components (using drivers) e.g., Gyro and Accelerometer
– Complete demonstration projects for components
– Larger applications
• Trains, and Game of Life, both on STM32F429
• Licensed for both proprietary and Free apps
49
STM32F4_Discovery Package…package STM32F4_Discovery is
subtype User_LED is GPIO_Pin;
Green : User_LED renames Pin_12;Orange : User_LED renames Pin_13;Red : User_LED renames Pin_14;Blue : User_LED renames Pin_15;
All_LEDs : constant GPIO_Pins := LED3 & LED4 & LED5 & LED6;…
procedure Initialize_LEDs;
procedure Turn_On (This : User_LED) with Inline;
procedure Turn_Off (This : User_LED) with Inline;
procedure Toggle (This : User_LED) with Inline;
…
Accelerometer : Three_Axis_Accelerometer;
GPIO_A : GPIO_Port renames STM32F40xxx.GPIO_A;
GPIO_B : GPIO_Port renames STM32F40xxx.GPIO_B;…
User_Button_Port : GPIO_Port renames GPIO_A; User_Button_Pin : constant GPIO_Pin := Pin_0; User_Button_Interrupt : constant Interrupt_Id := Names.EXTI0_Interrupt;…
Board Additions
Board Addition
Board Specific Number
Board Addition
50
51
STM32F429_Discovery Package…package STM32F429_Discovery is
subtype User_LED is GPIO_Pin;
Green : User_LED renames Pin_13;Red : User_LED renames Pin_14;
All_LEDs : constant GPIO_Pins := LED3 & LED4;
…
procedure Initialize_LEDs;
…
procedure Toggle (This : User_LED) with Inline;
…
Gyro : Three_Axis_Gyroscope;
GPIO_A : GPIO_Port renames STM32F42xxx.GPIO_A;
GPIO_B : GPIO_Port renames STM32F42xxx.GPIO_B;…
GPIO_K : GPIO_Port renames STM32F42xxx.GPIO_K;
…
Two Fewer User LEDs
Two More
GPIO Ports
Other device differences…
Gyro instead of
accelerometer
Example Driver Library Simplification
procedure Initialize isbegin
Configure_User_Button_GPIO;Connect_External_Interrupt (User_Button_Port, User_Button_Pin);Configure_Trigger (User_Button_Port, User_Button_Pin, Interrupt_Rising_Edge);
end Initialize;
procedure Initialize isRCC_AHB1ENR_GPIOA : constant Word := 16#01#;
begin-- Enable clock for GPIO-ARCC.AHB1ENR := RCC.AHB1ENR or RCC_AHB1ENR_GPIOA;-- Configure PA0GPIOA.MODER (0) := Mode_IN;GPIOA.PUPDR (0) := No_Pull;
-- Select PA0 for EXTI0SYSCFG.EXTICR1 (0) := 0;-- Interrupt on rising edgeEXTI.FTSR (0) := 0;EXTI.RTSR (0) := 1;EXTI.IMR (0) := 1;
end Initialize;
52