Using a HAL is a great way to develop software that can be easily reused and ported from one application and platform to the next. Why would a developer want to do such a thing? For starters, reinventing the wheel over and over again gets pretty boring. I believe most developers want to be working on cutting edge development work instead of being stuck in a never-ending Groundhogs Day1 loop. Even for developers who prefer to do the same thing over and over and over again, development time lines are short, budgets are tight and there is just way too much work that needs to be done on any given project. The goal is therefore to write code that can be reused and in order to do that, developers need to create a hardware abstraction layer to allow their middleware and application code to access the microcontroller hardware generically.
Creating a rock-solid HAL does not happen overnight. The process to create the HAL is an iterative process and very well might take years. The good news is that developers can create a HAL very quickly and then with each project adjust and modify it until nearly every conceivable permutation has been encountered. We are going to walk through the HAL creation process but before we do, let’s take a look at the characteristics that every HAL needs to have. (Keep in mind that this book examines a HAL that jump starts a developers HAL needs. Rather than taking years to tweak, the readers of this book will be able to do so very quickly based on the processes and accompanying materials).
A Good HAL’s Characteristics
So far in this book, we’ve discussed several characteristics that portable and reusable software should exhibit. A well designed and thought out HAL will exhibit these properties but there are a few characteristics that should be highlighted at this point. We are about to design a hardware abstraction layer, not the code that runs behind the interface but the actual interface itself. A good HAL will contain the following characteristics:
- Human readable
- Abstracted complexities
- Well documented
- Generic control capability
- Extensible, specific control capability
- Encapsulates data
The hardware abstraction layer should contain a basic set of functions to control the underlying peripherals that are human readable and generic. The interface should be simple and contain less than a dozen functions. The more complex the interface becomes, the more difficult the interface will be to understand, port and just simply use. Developers should only expose the need-to-know information for the interface and allow all the details to be hidden behind the interface. Developers who use the HAL don’t need to be an expert in the underlying hardware and complexities, just an expert in how to use the interface!
The HAL Design Process
Designing a hardware abstraction layer is a relatively straight forward process that is repeated for each microcontroller peripheral potentially multiple times for different architectures. The general process contains seven steps:
- Review the microcontroller peripheral datasheet
- Identify peripheral features
- Design and create the interface
- Create stubs and documentation templates
- Implement for target processor(s)
- Repeat for each peripheral
The process, while apparently simple, can require a few executions before becoming completely clear. In this chapter, we will walk through this generic process for designing a hardware abstraction layer and then in subsequent chapters we will walk through the process again for specific peripherals and external components.
Jacob’s Expert Tip of the Week
To master your hardware abstraction layers and maximize code reuse, learn more about how to design HALs for real-time systems by reading my book “Reusable Firmware Development“. (I know a selfish plug but if I don’t do it who will?)