STM32 bindings for Ada language: register descriptions, startup routines etc.
Find a file
2024-07-05 02:35:36 +03:00
common/gpr (style) checks enabled 2024-07-05 02:35:36 +03:00
examples >refactor< GPIO Ports 2024-07-03 23:25:11 +03:00
gnat_runtime + one example for STM32F401 "black pill" added. 2024-03-20 17:22:53 +03:00
library (style) checks enabled 2024-07-05 02:35:36 +03:00
tools Merge branch 'master' of git.disroot.org:Vovanium/stm32-ada 2024-01-23 14:27:02 +03:00
.gitignore + Tools: derived units generation 2021-10-13 16:29:46 +03:00
LICENSE Initial commit 2019-01-15 21:23:45 +03:00
Makefile % building multiple runtimes in one file is causing total rebuilds 2024-03-23 19:14:09 +03:00
README.md % update blackpill doc 2024-03-20 21:53:03 +03:00
todo-modules-f4 * update on implemented modules 2024-07-04 13:27:48 +03:00

stm32-ada

Ada bindings for STM32 internals

Design directions

Main design goal is a type safety. Specific enumerations and records are used in hardware definitions. Common structure of a peripherial module is a record with all its registers and every register is a record with all its fields. That is every field is addressed using scheme Unit.Register.Field

While it is generally preferred to have entities same identifiers as in STM's user manuals, it is not always possible. So some of them have originel or a bit changed name.

  • The identifier clashes with Ada keyword. E. g. ABORT bit-field is renamed to ABRT.
  • Identifier is not given by UM. This is common case for bit-field values. They taken descriptive names based on original UM text.
  • Identifier decomposition and generalization. Bitfield identifiers are shortened if they have common part. Also if two or more registers have same or analogous fields they commonly share the same record type, thus having same field names. Thus RCC's xxxRST, xxxEN and xxxLPEN registers a defined the same with RST/EN/LPEN part removed from their bit fields.

Compiler implication

System.Address should be standard 32 bit byte address as in CPU registers and peripherals (DMA etc.).

Development boards supported

stm32f429disco (stm32f429disc1) -- board available from STM. 429disco in examples.

STM32F407Z-based board from PiSwords. Widely available from chinese suppliers. 407z_piswords in examples.

STM32F401/411-based "black pill" boards from WeAct. Also widely available from chinese suppliers. 401c_blackpill in examples (Note: currently there's no suitable runtime for STM32F401/STM32F411. See GNAT section of this README for details).

Default values

Default values are given to register and their field according to following rules:

  • cleared by writing '0' (rc_w0) fields set to logic '1', that is True;
  • clered by writing '1' (rc_w1) field set to logic '0', that is False;
  • for read-only registers default values are not set;
  • when reset state is specified default is set to it;
  • there may be convenient to set default to some specific value, those cases are documented.

Current inconsistencies and importabilities

GNAT's System'To_Address attribute is used in peripherials definitions (STM32.model-name.Units packages). I currently cannot decide if Preelaborate is really needed there.

Common implementation notes

Interrupts

Interrupt handling in multitasked (Ravenscar) profiles require support from OS / RTL. That is, no interrupt definitions done there. Use Ada.Interrupts.Names to define interrupt handlers. This obviously limit the set of supported devices to ones supplied with compiler.

Interrupts in minimal (ZFP) profiles though do not require any system support as they fully handled by user code. However interrupt vector table should be implementer by the user too. For this maybe some constants will be set.

Hardware quirks and workarounds

APB

APB does not support partial writes to 32-bit registers. The library provides access to register fields as records. This could lead compiler to emit byte and half-word writes to APB registers causing erroneous effects. As a workaround those registers should be read to local variable, this variable altered, and then written back to the hardware. GNAT users may not need the workaround, because of its pragma Volatile_Full_Access used in this library.

SVD conversion scripts

Put SVD data directory (e.g. STM32F4_svd_V1.2) under tools/imported_data directory. Scripts and makefile in tools/would convert it to .ads files (they obvously need editing, however compiled fine) and stripped text files needed primarily for comparisons.

Compiler specific notes

There are compiler-specific pragmas so your compiler may complain about them.

GNAT

Volatile_Full_Access pragma is used on (at least writable) APB registers as byte- and half-wide writes are not supported by APB. Read STM docs on what those accesses actually do.

Currently GPR cannot manage aggregate projects for different targets. GNU Make script is used to build whole set of libraries instead.

There are no GNAT runtime for some widely used boards. For STM32F401 "black bill" there's a patch that makes suitable runtime from STM32F4 one in directory gnat_runtime. To build and run "black pill" examples please add required runtime to GNAT by doing following steps:

  • Go to Gnat runtime directory {gnat's prefix}/arm-eabi/lib/gnat
  • Copy runtime: cp -r light-stm32f4 light-stm32f401
  • Apply patch: `patch -p1 -d light-stm32f401 < {patch dir}/light-stm32f401.patch
  • Go to runtime dir: cd light-stm32f401
  • Clean: gprclean -P runtime_build.gpr
  • Compile runtime: gprbuild -P runtime_build.gpr