Scope. This document describes the
boards/peripheral/registry — a convenience mechanism used inside this repository so that tests and examples can dynamically opt a peripheral (SPI-NOR flash, SD card, IMU, etc.) into any compatible board via a build flag. It exists to make cross-board testing of peripheral drivers cheap.In an actual application project, you would not use this registry. You would simply define the peripheral instances you need directly in your
board.c(the same way you defineg_whalUart,g_whalSpi, etc.) and call them directly from your application. The registry adds a layer of indirection that's only worth its cost when you're trying to mix-and-match peripherals across many boards from a single test binary.
This guide covers how to add an external peripheral device to the wolfHAL
peripheral registry. Peripherals are bus-attached devices (e.g., SPI-NOR
flash, SD cards) that live in boards/peripheral/ and are opt-in at build
time.
A peripheral consists of three parts:
- A device configuration file that instantiates the device with board-specific parameters (SPI bus, CS pin, clock speed, etc.)
- An entry in the peripheral registry (
peripheral.c) so that board init and tests can discover the device - A board.mk entry to conditionally compile the peripheral and its driver source
Peripherals are organized by device type under boards/peripheral/:
boards/peripheral/
peripheral.h # Registry structs and extern arrays
peripheral.c # Registry arrays (g_peripheralBlock[], g_peripheralFlash[], g_peripheralSensor[])
board.mk # Conditional build rules
block/
sdhc_spi_sdcard32gb.h
sdhc_spi_sdcard32gb.c
flash/
spi_nor_w25q64.h
spi_nor_w25q64.c
sensor/imu/
bmi270.h
bmi270.c
Create a header and source file for your device under the appropriate type directory.
Declare the global device instance:
#ifndef BOARD_SPI_NOR_W25Q64_H
#define BOARD_SPI_NOR_W25Q64_H
#include <wolfHAL/wolfHAL.h>
#include <wolfHAL/flash/flash.h>
#include <wolfHAL/flash/spi_nor_flash.h>
extern whal_Flash g_whalSpiNorW25q64;
#endifDefine the device instance with its configuration. The device references board
globals (g_whalSpi, g_whalGpio, SPI_CS_PIN, g_whalTimeout) from
board.h:
#include "spi_nor_w25q64.h"
#include <wolfHAL/flash/spi_nor_flash.h>
#include "board.h"
#define W25Q64_PAGE_SZ 256
#define W25Q64_CAPACITY (8 * 1024 * 1024)
static whal_Spi_ComCfg g_w25q64ComCfg = {
.freq = 25000000,
.mode = WHAL_SPI_MODE_0,
.wordSz = 8,
.dataLines = 1,
};
whal_Flash g_whalSpiNorW25q64 = {
.driver = &whal_SpiNor_Driver,
.cfg = &(whal_SpiNor_Cfg) {
.spiDev = &g_whalSpi,
.spiComCfg = &g_w25q64ComCfg,
.gpioDev = &g_whalGpio,
.csPin = SPI_CS_PIN,
.timeout = &g_whalTimeout,
.pageSz = W25Q64_PAGE_SZ,
.capacity = W25Q64_CAPACITY,
},
};Add a conditional include and an entry in the appropriate registry array.
In peripheral.c:
#ifdef PERIPHERAL_SPI_NOR_W25Q64
#include "flash/spi_nor_w25q64.h"
#endifAnd add an entry to the matching array (before the sentinel):
whal_PeripheralFlash_Cfg g_peripheralFlash[] = {
#ifdef PERIPHERAL_SPI_NOR_W25Q64
{
.name = "spi_nor_w25q64",
.dev = &g_whalSpiNorW25q64,
.sectorSz = 4096,
},
#endif
{0}, /* sentinel */
};The registry structs are defined in peripheral.h:
whal_PeripheralBlock_Cfgfor block devices (g_peripheralBlock[])whal_PeripheralFlash_Cfgfor flash devices (g_peripheralFlash[])whal_PeripheralSensor_Cfgfor sensor devices (g_peripheralSensor[])
Each array is terminated by a zero sentinel so that board init and test code can iterate without knowing the count.
In boards/peripheral/board.mk, add a conditional block for your
peripheral. The block checks whether the peripheral name appears in the
PERIPHERALS variable and adds the define, config source, and driver source:
ifneq ($(filter mydevice,$(PERIPHERALS)),)
CFLAGS += -DPERIPHERAL_MYDEVICE
BOARD_SOURCE += $(_PERIPHERAL_DIR)/type/mydevice.c
BOARD_SOURCE += $(WHAL_DIR)/src/type/mydevice_driver.c
endifThis compiles both the peripheral configuration and the underlying driver source when the peripheral is enabled.
Enable peripherals using the PERIPHERALS variable:
make BOARD=stm32wb55xx_nucleo PERIPHERALS="spi_nor_w25q64"
Multiple peripherals can be enabled simultaneously:
make BOARD=stm32wb55xx_nucleo PERIPHERALS="spi_nor_w25q64 bmi270"
Peripheral devices are automatically picked up by their matching test suite.
Flash peripherals are tested by the flash test, and block peripherals by the
block test. See Adding a Test for details on the test
framework.
Instance files are named <driver>_<instance>:
sdhc_spi_sdcard32gb— sdhc_spi driver, 32GB SD cardspi_nor_w25q64— spi_nor driver, W25Q64 chipbmi270— bmi270 driver (single instance, no qualifier needed)
Summary:
- Directory:
boards/peripheral/<type>/(e.g.,flash/,block/,sensor/imu/) - Files:
<driver>.hand<driver>.cfor single-instance peripherals; otherwise<driver>_<instance>.hand<driver>_<instance>.c - Flag:
PERIPHERAL_<NAME>(e.g.,PERIPHERAL_SPI_NOR_W25Q64) - PERIPHERALS variable: lowercase name (e.g.,
spi_nor_w25q64,bmi270) - Global instance:
g_whal<Name>(e.g.,g_whalSpiNorW25q64,g_whalBmi270)