Kbox-UniStack Docs
STM32 (HAL)

STM32 HAL Peripherals

The concrete STM32 HAL drivers that implement the core peripheral interfaces of kbox-stack — the driver catalog, transceivers, construction order, and interrupt callbacks.

Each hardware concern in kbox-stack is an I<X> interface defined in the portable core; see Peripheral Interfaces. This page lists the concrete STM32 (HAL) drivers that implement them and how you construct and feed them.

Driver catalog

Core interfaceSTM32 (HAL) driverConstructor arguments
IBusDriverHalKnxBusDriver(UART_HandleTypeDef& uart, DMA_HandleTypeDef& hdmaRx, DMA_HandleTypeDef& hdmaTx, void (*uartInitFunc)(void), IClock&, IWatchDog&)
IFlashHalFlash(uint16_t flashBaseAddress, uint16_t flashTailAddress)
ILedHalLed(GPIO_TypeDef* gpioPort, uint16_t gpioPin, IClock&)
IButtonBaseButton() (portable; no HAL handles)
IClockBaseClock() (portable; driven by a 1 ms timer tick)
IWatchDogHalIWDGWatchDog(IWDG_HandleTypeDef& watchDog)
ITransmitterNcn5130 / ElmosE98123see below

BaseClock and BaseButton carry no STM32 handles — they are portable helpers. BaseClock counts milliseconds/seconds from an external Tick() (the example calls it from the 1 ms TIM2 interrupt); BaseButton just forwards an interrupt to a registered callback. Everything else is a true HAL driver holding ST HAL handles.

Transmitters

The transmitter (an ITransmitter) drives the analog KNX front-end that couples the MCU UART to the TP1 bus. It sits on top of the bus driver.

#include <Stack/Peripheral/Transmitter/Ncn5130.h>

Ncn5130 transmitter(busDriver, clock, watchDog);

Ncn5130(IBusDriver& busDriver, IClock& clock, IWatchDog& watchDog) — it needs the clock and watchdog because bringing up the transceiver involves timed delays. It exposes Init() and SetIndividualAddress(KnxAddress&).

#include <Stack/Peripheral/Transmitter/ElmosE98123.h>

ElmosE98123 transmitter(busDriver);

ElmosE98123(IBusDriver& busDriver) — the Elmos front-end takes only the bus driver. Swap this in place of Ncn5130 if your board uses an Elmos transceiver; the rest of the construction is unchanged.

Constructing the peripherals

Build the peripherals at file scope in dependency order — a later object references earlier ones. This is the exact order from the example:

HalIWDGWatchDog watchDog(hiwdg);
BaseClock       clock;

// Bus driver first: it owns the UART + DMA and needs clock + watchdog.
HalKnxBusDriver busDriver(huart2, hdma_usart2_rx, hdma_usart2_tx,
                          MX_USART2_UART_Init, clock, watchDog);

// Transmitter sits on the bus driver.
Ncn5130 transmitter(busDriver, clock, watchDog);

// Persistent flash, LEDs, button.
HalFlash baseFlash(0x0801u, 0xF400u);
HalLed   indicatorLed(GPIOB, YELLOW_LED_Pin, clock);
HalLed   knxLed(GPIOB, RED_LED_Pin, clock);
BaseButton button;

These are then passed into MakeStack(...) — see Your First Application for the full stack assembly.

Interrupt callbacks

The Hal* drivers are event-driven: ST HAL interrupt callbacks must be routed to them. Wire these three (from the example's main.cpp):

// Data arrived on the KNX UART (USART2, DMA RX): feed the bus driver.
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size) {
  if (huart->Instance == USART2) {
    busDriver.OnInterupt(Size);
  }
}

// USART error: let the bus driver recover.
void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart) {
  if (huart->Instance == USART2) {
    busDriver.OnError();
  }
}

// GPIO (button) interrupt: the KNX programming button toggles address mode.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
  if (GPIO_Pin == KNX_BUTTON_Pin) {
    stack.OnButtonPress();
  }
}

Route the button through stack.OnButtonPress() (not directly to the BaseButton). The stack owns programming-mode entry/exit; the button object is what the stack registers its own handler on.

Per-driver reference