Kbox-UniStack Docs

Constructing the Stack

How to build a kbox-stack instance — the MakeStack factory overloads, the caller-owned KnxStackStorage, StackParameters, and choosing between the Standard and Secure paths.

MakeStack

The stack is created by the MakeStack factory, not by a public constructor — the concrete Stack type is hidden inside the archive. MakeStack placement-new's the stack into your KnxStackStorage and returns an IKnxStack&. There are two overloads.

Standard (9 arguments) — plain telegrams, no KNX Data Secure:

IKnxStack& MakeStack(
    KnxStackStorage& storage,
    StackParameters& stackParameters,
    IBusDriver&      busDriver,
    IWatchDog&       watchDog,
    ILed&            knxLed,
    IClock&          clock,
    ITransmitter&    transmitter,
    IButton&         button,
    KnxFlashLayout&  layout);

Secure (10 arguments) — adds an ISecurity& as the last argument:

IKnxStack& MakeStack(
    KnxStackStorage& storage,
    StackParameters& stackParameters,
    IBusDriver&      busDriver,
    IWatchDog&       watchDog,
    ILed&            knxLed,
    IClock&          clock,
    ITransmitter&    transmitter,
    IButton&         button,
    KnxFlashLayout&  layout,
    ISecurity&       security);

Every reference you pass — stackParameters, all I<X> peripherals, the layout, and (for secure) the security object — must outlive the returned IKnxStack&. Passing a temporary or a stack-local produces a dangling reference. Give them static/file-scope lifetime. layout must already be built (via MakeFlashLayout(), see below) before either overload runs.

MakeFlashLayout

Both MakeStack overloads above take a KnxFlashLayout&, not a raw IFlash&. You build that layout first, from a single base flash region, with MakeFlashLayout():

static KnxFlashLayoutStorage layoutStorage;   // static/file-scope lifetime — REQUIRED

// Classic — regions: {stack-state, user-data}.
KnxFlashLayout& layout = MakeFlashLayout(
    layoutStorage, baseFlash, stackParameters, /*userDataPageCount=*/1u);

The Secure overload additionally takes the SioSizing (so it can size the counter/SIO-key regions):

// Secure — regions: {counter, sio-key, stack-state, user-data}.
KnxFlashLayout& layout = MakeFlashLayout(
    layoutStorage, baseFlash, stackParameters, sioSizing, /*userDataPageCount=*/1u);

layout.IsValid() is checked by Stack::Init() — an invalid layout reports StackErrorTypeEnum_FLASH_LAYOUT_INVALID through onStackError and stops before any flash-dependent step runs. See the Integration Contract for the full error contract.

Builder/KnxDeviceStorage.h bundles KnxFlashLayoutStorage + KnxStackStorage (+, for Secure, SecureStackStorage/SioStorage<S>) into one KnxDeviceStorage / KnxSecureDeviceStorage<S> object per device, with forwarding overloads of MakeFlashLayout/MakeStack/MakeSecure that take the bundle directly. This is the recommended way to wire a new device — see API Reference · Consumer storage bundles.

KnxStackStorage

MakeStack needs somewhere to place the stack object. That is KnxStackStorage — a plain, aligned byte buffer you declare with static lifetime:

static KnxStackStorage stackStorage;   // static/file-scope lifetime — REQUIRED

No heap. The buffer size is fixed at compile time and depends on KNX_APDU_MAX: the larger APDU configuration selects a larger buffer. Because the storage is yours, its lifetime is your responsibility — if it goes out of scope, the IKnxStack& returned by MakeStack dangles. Declare it static (or global).

StackParameters

StackParameters bundles the six event callbacks, the four table sizes, the device identity PID arrays, the manufacturer id, and a PropertyStore. You construct it once and pass it (by reference) to MakeStack.

The constructor signature (order matters):

StackParameters(
    onKnxTelegram, onDifference, onTelegram, onErrorKnxTelegram,
    onResetCommand, onStackError,
    addressTableSize, associationTableSize,
    groupObjectTableSize, applicationProgramSize,
    PID_PROGRAM_VERSION /* [5] */,
    PID_HARDWARE_TYPE   /* [6] */,
    PID_SERIAL_NUMBER   /* [6] */,
    propertyStore,
    manufacturerId    = 0x023Eu,
    maxApduLengthInit = 0x0037u);

Standard vs Secure

Build the flash layout, then call the 9-argument MakeStack directly. No ISecurity is involved; telegrams are plain.

static KnxFlashLayoutStorage layoutStorage;
KnxFlashLayout& layout = MakeFlashLayout(
    layoutStorage, baseFlash, stackParameters, /*userDataPageCount=*/1u);

static KnxStackStorage stackStorage;
StackParameters stackParameters(/* ... */);

IKnxStack& stack = MakeStack(
    stackStorage, stackParameters, busDriver, watchDog, knxLed,
    clock, transmitter, button, layout);

Build the flash layout, then the security object with MakeSecure (it reads the layout's CounterView()/SioKeyView()), then pass the returned ISecurity& as the 10th argument to MakeStack. The secure invariants (separate AES contexts, a single monotonic counter store) are wired inside MakeSecure — you do not wire them by hand.

static KnxFlashLayoutStorage layoutStorage;
KnxFlashLayout& layout = MakeFlashLayout(
    layoutStorage, baseFlash, stackParameters, sioSizing, /*userDataPageCount=*/1u);

static SecureStackStorage secureStorage;   // static lifetime — REQUIRED
ISecurity& secure = MakeSecure(
    secureStorage, layout, sioSizing, sioBuffers, deviceIA, clock);

static KnxStackStorage stackStorage;
IKnxStack& stack = MakeStack(
    stackStorage, stackParameters, busDriver, watchDog, knxLed,
    clock, transmitter, button, layout,
    secure);

See KNX Data Secure for the full secure setup.

Your application logic

Derive your logic from KnxLogicBase. Its constructor takes the IKnxStack& and auto-calls SetLogic(this) — registration cannot be forgotten:

class MyLogic : public KnxLogicBase {
 public:
  explicit MyLogic(IKnxStack& stack) : KnxLogicBase(stack) {}
  void Work() override { /* ... */ }
};

MyLogic logic(stack);   // registers itself with the stack in its ctor

The concrete peripheral objects you pass to MakeStack (the bus driver, transceiver, flash, LED, …) are platform-specific. On STM32 these are the Hal* classes wired to HAL handles. See the platform walkthrough: First Application.

Next steps