Embeddedsparkandada-Web.Pdf
Total Page:16
File Type:pdf, Size:1020Kb
Copyright © 2018 AdaCore All rights reserved. Introduction This booklet is a sampling of AdaCore blogs, including some of our engineers’ ARM project creations! They illustrate how embedded system developers can take advantage of Ada’s benefits in software reliability, early error detection, code readability, and maintainability while still satisfying performance requirements. The blogs were written by Raphaël Amiard, Jonas Attertun, Arnaud Charlet, Fabien Chouteau, Tristan Gingold, Anthony Leonardo Gracio, Johannes Kanig, Jérôme Lambourg, Yannick Moy, Jorge Real, J. German Rivera, Pat Rogers and Rob Tice. For more blogs, visit our AdaCore Blog Page http://blog.adacore.com . Tristan Gingold, Yannick Moy iv Table of Contents Tetris in SPARK on ARM Cortex M4 ................................................................. 7 How to Prevent Drone Crashes Using SPARK ................................................. 29 Make with Ada: All that is Useless is Essential............................................... 39 Make with Ada: "The Eagle has landed" ........................................................ 45 Make with Ada : From Bits to Music .............................................................. 49 Make with Ada: Formal Proof on My Wrist ................................................... 55 Porting the Ada Runtime to a New ARM Board ............................................. 59 Make with Ada: Candy DisPenser, with a Twist... .......................................... 77 Make with Ada: ARM Cortex-M CNC Controller ............................................ 83 Make with Ada: DIY Instant Camera .............................................................. 89 Driving a 3D Lunar Lander Model with ARM and Ada .................................... 93 New Year’s Resolution for 2017: Use SPARK, Say Goodbye to Bugs ............... 99 Getting Started with the Ada Driver’s Library Device Drivers ...................... 103 SPARK Tetris on the Arduboy ...................................................................... 111 Writing on Air .............................................................................................. 117 Ada on the First RISC-V Microcontroller ...................................................... 127 DIY Coffee Alarm Clock ................................................................................ 131 The Adaroombot Project ............................................................................. 135 Make with Ada: Brushless DC Motor Controller .......................................... 141 Make with Ada 2017- A "Swiss Army Knife" Watch ..................................... 159 There’s a Mini-RTOS in My Language .......................................................... 173 Bitcoin Blockchain in Ada: Lady Ada Meet Satoshi Nakamoto ..................... 181 Ada on the micro:bit ................................................................................... 193 SPARKZumo: Ada and SPARK on Any Platform ............................................ 199 5 Tetris in SPARK on ARM Cortex M4 6 Tetris in SPARK on ARM Cortex M4 By Tristan Gingold, Yannick Moy Jan 07, 2015 Tetris is a well-known game from the 80's, which has been ported in many versions to all game platforms since then. There are even versions of Tetris written in Ada. But there was no version of Tetris written in SPARK, so we've repaired that injustice. Also, there was no version of Tetris for the Atmel SAM4S ARM processor, another injustice we've repaired. The truth is that our colleague Quentin Ochem was looking for a flashy demo for GNAT using SPARK on ARM, to run on the SAM4S Xplained Pro Evaluation Kit of our partner Atmel. Luckily, this kit has an extension with a small rectangular display that made us think immediately of Tetris. Add to that the 5 buttons overall between the main card and the extension, and we had all the necessary hardware. 7 Tetris in SPARK on ARM Cortex M4 Now, how do you make a Tetris in SPARK for ARM? First, the ingredients: • a SAM4S Xplained Pro Evaluation Kit + OLED1 Xplained Pro extension + Atmel manuals • GNAT GPL 2014 for ARM • a recent wavefront of SPARK Pro 15.1 (*) • the WikiPedia page describing Tetris rules • a webpage describing the Super Rotation System (SRS) for Tetris • an engineer who knows SPARK • an engineer who knows ARM (*) If you don't have access to SPARK Pro 15.1, you can use SPARK GPL 2014, but expect some differences with the verification results presented here. Count 2 days for designing, coding and proving the logic of the game in SPARK, another 2 days for developing the BSP for the board, and 0.5 day for putting it all together. Now the detailed instructions. The whole sources can be downloaded in the tetris.tgz archive at http://blog.adacore.com/uploads/attachments/tetris.tgz. A Core Game Logic in SPARK SPARK is a subset of Ada that can be analyzed very precisely for checking global data usage, data initialization, program integrity and functional correctness. Mostly, it excludes pointers and tasking, which is not a problem for our Tetris game. We modeled the display (the board) as an array of Y_Size lines, where each line is an array of X_Size cells, and the origin is at the top left corner: 8 Tristan Gingold, Yannick Moy A cell is either empty, or occupied by a piece in I, O, J, L, S, T, Z (the name of the piece hints to what form it takes...), and the piece falling as a record with the following components: • a shape in I, O, J, L, S, T, Z • a direction (North, East, South or West) according to SRS rules • a pair of (X,Y) coordinates in the board, corresponding to the coordinate of the top-left cell of the square box enclosing the piece in SRS Two global variables Cur_Board and Cur_Piece store the current value of the board and falling piece. Finally, SRS rules are encoded in Boolean matrices defining the masks for oriented shapes (where True stands for an occupied cell, and False for an empty cell). All the above can be expressed straightforwardly in SPARK as follows: -- possible content of the board cells type Cell is (Empty, I, O, J, L, S, T, Z); -- subset of cells that correspond to a shape subtype Shape is Cell range I .. Z; -- subset of shapes that fits in a 3 x 3 box, that is, all expect I and O subtype Three_Shape is Cell range J .. Z; -- the board is a matrix of X_Size x Y_Size cells, where the origin (1,1) -- is at the top left corner X_Size : constant := 10; Y_Size : constant := 50; 9 Tetris in SPARK on ARM Cortex M4 subtype X_Coord is Integer range 1 .. X_Size; subtype Y_Coord is Integer range 1 .. Y_Size; type Line is array (X_Coord) of Cell; type Board is array (Y_Coord) of Line; Cur_Board : Board; -- the current piece has a shape, a direction, and a coordinate for the -- top left corner of the square box enclosing the piece: -- a 2 x 2 box for shape O -- a 3 x 3 box for all shapes except I and O -- a 4 x 4 box for shape I subtype PX_Coord is Integer range -1 .. X_Size - 1; subtype PY_Coord is Integer range -1 .. Y_Size - 1; type Direction is (North, East, South, West); type Piece is record S : Shape; D : Direction; X : PX_Coord; Y : PY_Coord; end record; Cur_Piece : Piece; -- orientations of shapes are taken from the Super Rotation System at -- http://tetris.wikia.com/wiki/SRS -- shape O has no orientation -- shape I has 4 orientations, which all fit in the 4 x 4 box -- shapes except I and O have 4 orientations, which all fit in the 3 x 3 box -- Note that Possible_I_Shapes and Possible_Three_Shapes should be accessed -- with Y component first, then X component, so that higher value for -- Direction correspond indeed to clockwise movement. subtype I_Delta is Integer range 0 .. 3; type Oriented_I_Shape is array (I_Delta, I_Delta) of Boolean; subtype Three_Delta is Integer range 0 .. 2; type Oriented_Three_Shape is array (Three_Delta, Three_Delta) of Boolean; -- orientations for I Possible_I_Shapes : constant array (Direction) of Oriented_I_Shape := (((False, False, False, False), (True, True, True, True), (False, False, False, False), (False, False, False, False)), ((False, False, True, False), (False, False, True, False), (False, False, True, False), (False, False, True, False)), ((False, False, False, False), (False, False, False, False), (True, True, True, True), (False, False, False, False)), ((False, True, False, False), (False, True, False, False), (False, True, False, False), (False, True, False, False))); Possible_Three_Shapes : constant array (Three_Shape, Direction) of Oriented_Three_Shape := (-- orientations for J (((True, False, False), (True, True, True), (False, False, False)), ((False, True, True), (False, True, False), (False, True, False)), ((False, False, False), (True, True, True), (False, False, True)), ((False, True, False), (False, True, False), (True, True, False))), -- orientations for L (((False, False, True), (True, True, True), (False, False, False)), ((False, True, False), (False, True, False), (False, True, True)), ((False, False, False), (True, True, True), (True, False, False)), ((True, True, False), (False, True, False), (False, True, False))), -- orientations for S 10 Tristan Gingold, Yannick Moy (((False, True, True), (True, True, False), (False, False, False)), ((False, True, False), (False, True, True), (False, False, True)), ((False, False, False), (False, True, True), (True, True, False)), ((True, False, False), (True, True, False), (False, True, False))), -- orientations for T (((False, True, False), (True, True, True), (False, False, False)), ((False, True, False), (False, True, True), (False, True, False)),