# Design

This document describes some of the design of the Ada_Drivers_Library. It might
not be 100% accurate or up-to-date, but it gives a good overview and hopefully
can help you understand the project.

The main design goal of the Ada_Drivers_Library is code reuse. Each part of the
project should be made - as much as possible/reasonable - so that others can
reuse it in a different context. For example, a driver for an external
temperature sensor can be used with an STM32F4 micro-controller, but also with
an nRF51 or even a Raspberry Pi running Linux.

## Overall architecture

There are four main logical parts in this project:


 - **`Driver`**, it is where the low-level drivers for micro-controller
    peripherals are implemented. The low-level drivers are based on an hardware
    mapping (generated by SVD2Ada) and provide a more easy to use and more safe
    interface to the peripherals of a device. Examples: Timers, GPIO, I2C
    controllers, DMA, etc.

 - **`Middleware`**, it is a machine agnostic part that provides a variety of
    service like bitmap drawing, communication stacks, file systems or
    component drivers (more on that later).

 - **`HAL`**, `Middleware` often needs to rely on `Driver` to provide its
    services. The HAL (Hardware Abstraction Layer) defines interfaces to allow
    communication between the two parts. The HAL is the heart of the project,
    seen and used by everything so it's important that it remains as light as
    possible and depends only on itself or on Ada features available on every
    configuration. For those reasons, the HAL provides only definitions of
    features - using Ada interfaces - and no implementation.

 - **`Board support`**, it is a collection of packages that provide an easy
    access to the features of a given board. For instance if a board has a
    screen, an audio DAC or an accelerometer sensor. To do so they will use
    both the `Driver` and `Middleware`.

Note that it is not a problem for the `Driver` code to use features of the
`Middleware` when necessary, however it's is crucial that `Middleware` never
directly depend on the `Driver` otherwise it's not machine agnostic anymore...

The drivers are divided by architectures, vendors and then devices. For the
moment we have:

 * arch
   * ARM
     * STM32
       * STM32F40x
       * STM32F7x9
       * ...
     * Nordic
       * nRF51
   * RISC-V
     * SiFive
       * FE310

Most of the `Middleware` part is located in the middleware/ directory at the
root of the project. It is subdivided in Protocols, Bitmap_Drawings, Audio,
Tools, etc.

There is also the `Components` library, it is a little bit special because it
implements drivers for external chips (IO expander, gyro, thermal printer,
etc). That doesn't sound very hardware agnostic, however the code can be used
on any micro-controller. From a logical standpoint, it belongs in the machine
agnostic part of the project. Because of this specificity and for historical
reason, The `Components` library has its own subdir in the root of the project.
It might move to the middleware/ directory at some point.
