The following diagrams shows the general architecture of a system using HAL and a generic RTOS.
Note that the RTOS is a not mandatory part of the architecture, an OSAL can be implemented also on a bare metal system, in this case the RTOS is not present but HAL still offers its full functionality.
The HAL is structured in several internal layers. Note that the HAL code is entirely compiler independent because details like critical zones, ISRs and other platform-specific details are abstracted by the OSAL.
In this layer there are the portable Device Drivers. Portable drivers take care of:
This is the layer that exports the API used by the main application. This layer is perfectly portable, there are no dependencies on any specific HW architecture.
In this layer there are the device driver implementations for a specific MCU. The application does not interact directly with this layer.
This layer encapsulate all the dependencies between the HAL and the physical board:
The board initializer is called internally by the HAL, the application does not interact directly with this layer.
Complex Drivers are higher level drivers that do not interact directly with the hardware but use other drivers in order to perform their I/O functions. For example an LCD driver could use the SPI driver for communication without interacting directly with the SPI hardware.
Is code portability really possible using HAL? What are the limitations?