Peripheral Driver - Architecture Overview

Peripheral driver structure

A driver is designed to support a use-case (of a peripheral). For example, instead of one timer-counter driver, the ASF4 has drivers for PWM, timer, and input-capture.

Use-case drivers can sometimes support various peripherals, for example, a timer could run on the TC, TCC, or RTC. These are all peripherals that provide the functionality of the use-case, in this case, a counter and a compare IRQ. For example: On Microchip's M0+ family, the USART, SPI, and I2C are use-cases of the SERCOM peripheral.

The ASF4 driver architecture is built up of three layers:

Users are intended to interact with the HAL layer, which is hardware agnostic and can be used on a wide range of devices and platforms. The three layers are largely transparent to the user, though all are available. Each layer is organized into folders in the project structure, each containing files with API associated with the respective layer.

HAL folder (Hardware Abstraction Layer)

This folder contains hardware independent/agnostic API, for hardware with the same kind of functionality. The interface, which most users will use, is in the HAL layer. 
Naming convention: HAL functions start with usecase_, for example, adc_dma_driver.

In the hal folder, there are four sub-folders. The include and the src folders contain the definition of the HAL interfaces and implementation of the hardware agnostic part of the driver. The documentation folder contains the documentation of each driver as displayed in the Atmel START help text. The utils folder contains API definitions and implementations of the utility function drivers.

HPL folder (Hardware Proxy Layer)

Hardware-aware functionality is needed by the HAL, is implemented in the hardware-aware HPL level, keeping the HAL level hardware agnostic. There will be a peripheral configuration file associated with the HPL layer. 
Naming convention: HPL functions start with _usecase_, for example: _usart_async_init()

The hpl folder has multiple subfolders - one folder per hardware module supported by ASF4. These folders contain .h and .c files implementing the HPL layer.

HRI folder (Hardware Register Interface)

HRI level functions are used to configure register bits or bitfields, for example bit_set(), bit_clr().

The hri folder has multiple .h-files - one file per hardware module supported by ASF4. These files define the register interface of hardware modules.

Layers

The drivers are implemented in layers in order to:

  1. 1.Provide software interfaces abstracted from the underlying implementation.
  2. 2.Make it easier to document the drivers and architecture making it easier for users and developers to create, use, modify, and debug the code.
  3. 3.Multiple layers make it possible to have both stable and unstable APIs. For instance, the top layer HAL API should be as stable as possible, and only modified when necessary, and these modifications must be documented. The HPL layer, however, is not meant to be used as standalone and cannot, in that context, be called a "public" API, which means that the threshold for modifying this interface shall be much lower. For example, support for a new feature in hardware can be performed in the HPL and the HAL is kept untouched.
  4. 4.Multiple layers make it easier to separate code making up the hardware support from reusable common code. In ASF4, all hardware support code is in the HPL. The HRI interface describes only the hardware register interface. The HAL usually needs to be written only once and then reused with different HPL layers.
Figure 1. The ASF4 Driver Architecture