Instead of having one generic driver per peripheral, the ASF4 drivers provide interfaces to ways of using the peripheral. These ways are named "use-cases". A use-case typically implements a subset of the total functionality provided by the peripheral. This is useful as many of the peripherals on SAM devices, such as the SERCOM, provide a very broad functionality. This would cause a generic driver providing access to all the functionality of the module to be very large. Because the use-case limits the scope of functionality provided to the user, the driver is easier to implement and test and is more optimal than a generic driver would be. The figure below shows that a SERCOM hardware module can be used to implement various communication protocols, each protocol (or use-case) being implemented by a specific ASF4 driver. There is no generic "SERCOM" driver in the ASF4 HAL layer, but instead a specific "USART" driver, "I2C" driver, "LIN" driver, and so on.
The use-case approach together with the HAL and HPL layers allow the driver to be implemented in different ways, depending on the available hardware. As an example, a driver that issues a periodic interrupt can be implemented using for example:
Atmel START is used to select the hardware instance to be used to implement the driver. This is done during ASF4 configuration.
ASF4 has different types of drivers; Peripheral-, Utility-, and Middleware-drivers.
Uses DMA system to transfer data from ADC to a memory buffer in RAM. The user must configure the DMAC system driver accordingly. To set the memory buffer and its size the adc_dma_read function is used. This function programs DMA to transfer the results of input signal conversion to the given buffer. A callback is called when all data is transferred if it is registered via the adc_dma_register_callback function.
The driver is intended for using ADC functions in a real-time operating system, i.e. a thread-safe system.
A peripheral driver is a driver that is directly related to some functionality in some hardware peripherals. This is usually not the full functionality set available in the hardware peripheral, but a subset to make it portable between hardware platforms with different hardware peripheral implementations. A peripheral driver in the ASF4 consists of the HRI, HPL, and HAL layers. The user will normally interface only with the topmost HAL layer.
Utility drivers are hardware agnostic drivers that implement commonly used software concepts. The utility drivers are available for both the ASF4 drivers and the user application. Examples of utility drivers are a generic linked list or a ring buffer. Utility drivers can also be in form of C macro definitions.
Moving commonly used code into utility drivers makes it easier to maintain code and help the compiler to optimize the code because the same code is used by different drivers, but only one copy is needed. The utility drivers are fully abstracted and not bound to any particular hardware platform or type.
Middleware drivers are built on top of peripheral drivers and do not have any direct link to the underlying hardware. A middleware driver can depend on multiple peripheral drivers at the same time or support a range of different peripheral drivers. These drivers usually implement highly abstracted code that implements some kind of software concepts like graphics libraries, USB classes, or file systems.