Skip to content

Level 2 Hardware Abstraction Layer (HAL) Guidelines

Adding a device driver (HAL)

First, you will need to figure out which folder to put it in. Lets take the [Sharp GP2Y0A21YK0F Analog Distance Sensor] ( for example. For the sharp distance sensor it should be placed in the library/devices/sensors/distance/. If there doesn't seem to be a proper place for your sensor, make a new folder for it.

Second, you will need to figure out which peripheralss you will need. In the case of the Sharp distance sensor, you will need ADC.

Third, if the device has category interface file, make sure to inherit the interface so that the device driver can be used as the interface. For example, there may exist a Distance1D interface for 1-dimensional distance sensors, and if that is the case, SharpGP2Y0A21 should inherit it.

Finally, you can get started with creating your new device driver. L1 Peripherals must be taken as const Object references (const Adc & adc) as their parameters for their constructors. The HAL driver can take more parameters than then just the L1 drivers.

Adding a device category interface

If there is a device category that does not currently exist, it can be added, but must be added in the following way. Lets take temperature as an example:

Category interface: devices/sensors/temperature.hpp Implementation file: devices/sensors/temperature/si7060.hpp

If the category is temperature, then there should be a temperature folder. In this case, this is apart of the sensors category. The implementations of the category shall reside in that folder.

The interface file should be outside of the folder of implementations.

Testing L2

Generally, HAL drivers are tested by dependency injecting mock version of the L1 peripherals that the driver takes. With the sharp distance example, sharp a mock ADC would be created using the FakeIt mocking library.

Mock<sjsu::Adc> mock_adc;
// We only need to fake the methods that our class uses
Fake(Method(mock_adc, Initialize));
// Method mock.Read will return 512 once.
When(Method(mock_adc, Read)).Return(512);
// Pass mock ADC reference to sharp test object
const sjsu::Adc & mock_adc_reference = mock_adc.get();
SharpGP2Y0A21 test_subject(mock_adc_reference);

Then, for each test section, test that the appropriate methods were called with the appropriate inputs. In the Sharp case it would be helpful to change what the mock_adc::Read() returns in order to change the behavior of the Sharp distance method. You can then check that the returned distance values agree with the mocked return value of the ADC function.