Hardware Abstraction Layers (HALs)

There are several abstraction layers used to make some hardware feature(s) available to the generic firmware code. They allow us to implement certain functionality (eg. the protocol) without having to rewrite specific code for each platform.

HALs are implemented as C structs and contain functions pointers for the task implementation, some might also include data fields if supporting data is needed. All function pointers receive the HAL itself as the first argument, making all of the data and functionality provided by the HAL available to it.

All HALs have a void pointer drv_data field, which can be used by the implementer to store internal data, which may be needed to perform tasks.

BLOCKDEV

The BLOCKDEV HAL provides the functionality required to interact with storage devices with a block device topology.

struct blockdev_hal_t {
	/* read block from a block device */
	s8 (*read)(struct blockdev_hal_t mem_block, u16 block, u16 offset, void *buffer, u16 size);

	/* program block to a block device */
	s8 (*write)(struct blockdev_hal_t mem_block, u16 block, u16 offset, void *buffer, u16 size);

	/* erase block on a block device */
	s8 (*erase)(struct blockdev_hal_t mem_block, u16 block);

	/* ensure data on storage is in sync with the driver */
	s8 (*sync)(struct blockdev_hal_t mem_block);

	/* minimum size of a block read */
	u16 read_size;

	/* minimum size of a block write */
	u16 write_size;

	/* size of an erasable block */
	u16 block_size;

	/* total number of blocks */
	u16 block_count;

	void *drv_data;
};

HID

The HID HAL provides the functionality required to interact with the host as a HID device. See USB HID for information about the protocol.

struct hid_hal_t {
	/* send packet to the host */
	int (*send)(struct hid_hal_t interface, u8 *buffer, size_t buffer_size);
	/* arbitrary user data */
	void *drv_data;
};

Why is there no receive?

The HID HAL only provides a send command because the receive the functionality should be handled by the target in the main loop, who should call protocol_dispatch on received data.

SPI

The SPI HAL provides the functionality required to interact with SPI peripherals. See SPI introduction for information about the protocol.

struct spi_hal_t {
	/* bidirectional byte transfer */
	u8 (*transfer)(struct spi_hal_t interface, u8 data);
	/* select/unselect device */
	void (*select)(struct spi_hal_t interface, u8 state);
	/* arbitrary user data */
	void *drv_data;
};

Ticks

The ticks HAL provides the functionality to interact with the system clock.

struct ticks_hal_t {
	/* wait for x milisecs */
	void (*delay_ms)(u32 ticks);
	/* wait for x microsecs */
	void (*delay_us)(u32 ticks);
	/* arbitrary user data */
	void *drv_data;
};