Drivers
=======

.. toctree::
   :hidden:

   flash <flash>
   mmc <mmc>
   Charge Control <chg_ctrl/chg_ctrl>


Description
~~~~~~~~~~~

Device drivers in the Mynewt context includes libraries that interface
with devices external to the CPU. These devices are connected to the CPU
via standard peripherals such as SPI, GPIO, I2C etc. Device drivers
leverage the base HAL services in Mynewt to provide friendly
abstractions to application developers.

.. code-block:: console


    +———————————————————————————+
    |            app            |
    +———————————————————————————+
    |          (n)drivers       |
    +———————————————————————————+
    |     HAL     |     BSP     |
    +—————————————+—————————————+

-  The Board Support Package (BSP) abstracts board specific
   configurations e.g. CPU frequency, input voltage, LED pins, on-chip
   flash map etc.

-  The Hardware Abstraction Layer (HAL) abstracts architecture-specific
   functionality. It initializes and enables components within a master
   processor. It is designed to be portable across all the various MCUs
   supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's
   MK64F12 etc.). It includes code that initializes and manages access
   to components of the board such as board buses (I2C, PCI, PCMCIA,
   etc.), off-chip memory (controllers, level 2+ cache, Flash, etc.),
   and off-chip I/O (Ethernet, RS-232, display, mouse, etc.)

-  The driver sits atop the BSP and HAL. It abstracts the common modes
   of operation for each peripheral device connected via the standard
   interfaces to the processor. There may be multiple driver
   implementations of differing complexities for a particular peripheral
   device. For example, for an Analog to Digital Converter (ADC)
   peripheral you might have a simple driver that does blocking ADC
   reads and uses the HAL only. You might have a more complex driver
   that can deal with both internal and external ADCs, and has chip
   specific support for doing things like DMA’ing ADC reads into a
   buffer and posting an event to a task every ’n’ samples. The drivers
   are the ones that register with the kernel’s power management APIs,
   and manage turning on and off peripherals and external chipsets, etc.
   The Mynewt core repository comes with a base set of drivers to help
   the user get started.

General design principles
~~~~~~~~~~~~~~~~~~~~~~~~~

-  Device drivers should have a consistent structure and unified
   interface whenever possible. For example, we have a top-level
   package, “adc”, which contains the interface for all ADC drivers, and
   then we have the individual implementation of the driver itself. The
   following source files point to this:

   -  high-level ADC API: ``hw/drivers/adc/include/adc/adc.h``
   -  implementation of ADC for STM32F4:
      ``hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c`` (As of the
      1.0.0-beta release, ADC for nRF51 and nRF52 are available at an
      external
      `repo <https://github.com/runtimeco/mynewt_nordic/tree/master/hw/drivers/adc>`__.
      They are expected to be pulled into the core repo on Apache Mynewt
      after the license terms are clarified.). The only exported call in
      this example is
      ``int stm32f4_adc_dev_init(struct os_dev *, void *)`` which is
      passed as a function pointer to ``os_dev_create()`` in
      ``hal_bsp.c``, when the adc device is created.

-  Device drivers should be easy to use. In Mynewt, creating a device
   initializes it as well, making it readily available for the user to
   open, use (e.g. read, configure etc.) and close. Creating a device is
   simple using
   ``os_dev_create(struct os_dev *dev, char *name, uint8_t stage, uint8_t priority, os_dev_init_func_t od_init, void *arg)``.
   The ``od_init`` function is defined within the appropriate driver
   directory e.g. ``stm32f4_adc_dev_init`` in
   ``hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c`` for the ADC device
   initialization function.

-  The implementation should allow for builds optimized for minimal
   memory usage. Additional functionality can be enabled by writing a
   more complex driver (usually based on the simple implementation
   included by default in the core repository) and optionally compiling
   the relevant packages in. Typically, only a basic driver that
   addresses a device’s core functionality (covering ~90% of use cases)
   is included in the Mynewt core repository, thus keeping the footprint
   small.

-  The implementation should allow a user to be able to instantiate
   multiple devices of a certain kind. In the Mynewt environment the
   user can, for example, maintain separate contexts for multiple ADCs
   over different peripheral connections such as SPI, I2C etc. It is
   also possible for a user to use a single peripheral interface (e.g.
   SPI) to drive multiple devices (e.g. ADC), and in that case the
   device driver has to handle the proper synchronization of the various
   tasks.

-  Device drivers should be MCU independent. In Mynewt, device creation
   and operation functions are independent of the underlying MCU.
-  Device drivers should be able to offer high-level interfaces for
   generic operations common to a particular device group. An example of
   such a class or group of devices is a group for sensors with generic
   operations such as channel discovery, configure, and read values. The
   organization of the driver directory is work in progress - so we
   encourage you to hop on the dev@ mailing list and offer your
   insights!

-  Device drivers should be searchable. The plan is to have the newt
   tool offer a ``newt pkg search`` capability. This is work in
   progress. You are welcome to join the conversation on the dev@
   mailing list!

Example
~~~~~~~

The Mynewt core repo includes an example of a driver using the HAL to
provide extra functionality - the UART driver. It uses HAL GPIO and UART
to provide multiple serial ports on the NRF52 (but allowed on other
platforms too.)

The gist of the driver design is that there is an API for the driver
(for use by applications), and then sub-packages to that driver that
implement that driver API using the HAL and BSP APIs.

Implemented drivers
~~~~~~~~~~~~~~~~~~~

Drivers live under ``hw/drivers``. The current list of supported drivers
includes:

+----------------------------------------+--------------------------+
| Driver                                 | Description              |
+========================================+==========================+
| ``adc``                                | TODO: ADC driver.        |
+----------------------------------------+--------------------------+
| ``flash``                              | SPI/I2C flash drivers.   |
+----------------------------------------+--------------------------+
| ``lwip``                               | TODO: LWIP.              |
+----------------------------------------+--------------------------+
| ``mmc``                                | MMC/SD card driver.      |
+----------------------------------------+--------------------------+
| ``sensors``                            | TODO: sensors.           |
+----------------------------------------+--------------------------+
| ``uart``                               | TODO: UART driver.       |
+----------------------------------------+--------------------------+
| ``chg_ctrl``                           | Charge control drivers.  |
+----------------------------------------+--------------------------+
