Ownership¶
Who creates what, who owns it, and how long it lives. In one sentence: every manager is a function-local static singleton that lives for the whole program, and each manager creates and owns the handlers and bus objects it needs during its own initialisation.
Figure description and sources
Managers on the left, hf-core handlers in the middle, chip drivers on the right. An arrow means "includes and uses": a manager owns the handler it points at, and each handler wraps exactly one driver. ValveManager owns both valve drivers (MAX22200 for the solenoid channels, TLE92466ED for the proportional channels), AdcManager owns the ADS7952 external ADC, and TemperatureManager owns the NTC and MCP9700 sensor handlers. Managers with no arrow (communication buses, GPIO, NVS, the status LED) get their objects from the platform binding and talk to them through the interface classes only.
Drawn from: lib/managers #includes; lib/core/handlers #includes; figure module docs/diagrams/figures/manager-dependencies.py.
Manager map¶
From the #include lines of
lib/managers and the hf-core handlers; do not edit.
| Manager | Uses managers | hf-core handlers (driver) | Drivers used directly | Interface classes |
|---|---|---|---|---|
AdcManager |
CommChannelsManager |
ads7952 (hf-ads7952) |
- | BaseAdc |
CommChannelsManager |
- | - | - | BaseCan, BaseSpi, BaseUart, BaseUsbSerialJtag |
GpioManager |
- | - | - | BaseGpio |
LedManager |
- | - | - | - |
NvsManager |
- | - | - | BaseNvs |
TemperatureManager |
AdcManager |
mcp9700 (hf-mcp9700), ntc (hf-ntc-thermistor) |
- | BaseTemperature |
ValveManager |
CommChannelsManager, GpioManager |
max22200 (hf-max22200), tle92466ed (hf-tle92466ed) |
- | - |
Singletons¶
Flux and every manager follow the same pattern:
GetInstance()returns a function-localstaticobject (constructed on first use; C++ guarantees that construction is thread-safe).- Copy and move are deleted, so there is exactly one of each.
Fluxholds references to the managers (flux.valvesisValveManager::GetInstance()), soflux.valvesandValveManager::GetInstance()are the same object. Use whichever reads better.
Who owns which object¶
| Object | Owner | Created | Notes |
|---|---|---|---|
| Valve SPI bus, ADC SPI bus, CAN controller | CommChannelsManager |
In its EnsureInitialized() |
Objects in the platform binding's static slots; other managers borrow raw BaseSpi* / BaseCan* pointers |
| UART ports | CommChannelsManager |
On the first AcquireUart() for a port |
Up to kMaxUartPorts (3), binding slots, cached for later calls |
| One GPIO object per GPIO-category pin | GpioManager |
In its EnsureInitialized() |
Binding slot per functional pin; fixed table sized from the pin map |
Max22200Handler, Tle92466edHandler |
ValveManager |
In its EnsureInitialized() |
Members (std::optional), constructed in place; each borrows an SPI device from comms and its control pins from GpioManager |
MCU ADC (ADC1), one Ads7952Handler per ADS7952 device |
AdcManager |
In its EnsureInitialized() |
ADC1 in a binding slot; ADS7952 handlers are members (std::array of std::optional, four slots); channels registered from the pin map |
MCU die sensor, NtcTemperatureHandler, Mcp9700TemperatureHandler |
TemperatureManager |
In its EnsureInitialized() |
Die sensor in a binding slot; the two thermistor handlers are members and borrow ADC channels from AdcManager |
| WS2812 strip | LedManager |
In its EnsureInitialized() |
The binding drives the WS2812 RMT driver (LedStrip*); the manager keeps the animation state |
Three NVS namespaces (flux, flux_cal, flux_cfg) |
NvsManager |
Binding slots, referenced at construction, opened in its EnsureInitialized() |
App(), Calibration(), Config() return them as BaseNvs& |
A borrowed pointer stays valid for as long as its owner is initialised, which in practice is the whole program.
Do not keep a pointer across a Shutdown() / Deinitialize().
Memory¶
The managers use fixed-size std::array tables, sized at compile time from the pin map, for everything that has a
known count (pins, ADC channels, valve channels, SPI devices). Pin, bus, port, NVS and LED objects live in the
platform binding's static slots (Platform bindings); the hf-core handlers are manager members,
constructed in place during initialisation. Nothing in the HAL library allocates from the heap, and
tools/lint/lint_hal_alloc.sh keeps it that way in CI (ADR 0005).