Initialisation¶
Vortex::EnsureInitialized() brings every manager up, one at a time, in a fixed order. Call it once, early in
app_main(), before you touch any manager.
Figure description and sources
Left to right, then the second row. The facade initialises the managers one at a time, in the order of the calls in its init function. The first group is required: if any of them fails, EnsureInitialized() returns false and the application should not continue. The second group is best effort: a failure there is logged as a warning, the manager stays unavailable and the system reports itself as degraded, so a bench with only some chips fitted still comes up. The order and the required / best-effort split are read from the init function, which returns false only in the required branches.
Drawn from: lib/api/Vortex.cpp Vortex::InitializeAllComponents; figure module docs/diagrams/figures/init-order.py.
The order¶
From Vortex.cpp
(Vortex::InitializeAllComponents); do not edit.
| Step | Manager | Member | If it fails |
|---|---|---|---|
| 1 | NvsManager |
vortex.nvs |
initialisation fails (EnsureInitialized() returns false) |
| 2 | CommChannelsManager |
vortex.comms |
initialisation fails (EnsureInitialized() returns false) |
| 3 | GpioManager |
vortex.gpio |
initialisation fails (EnsureInitialized() returns false) |
| 4 | LedManager |
vortex.leds |
initialisation fails (EnsureInitialized() returns false) |
| 5 | MotorController |
vortex.motors |
warning; the system runs degraded |
| 6 | AdcManager |
vortex.adc |
warning; the system runs degraded |
| 7 | ImuManager |
vortex.imu |
warning; the system runs degraded |
| 8 | EncoderManager |
vortex.encoders |
warning; the system runs degraded |
| 9 | TemperatureManager |
vortex.temp |
warning; the system runs degraded |
The order follows the dependencies: storage first, so configuration and calibration can be read early; then the
buses; then the GPIO pins, which include the PCAL95555 expander lines the TMC9660 needs; then the status LED, early
so an LED-only bench works without the motor controller. After that come the managers that depend on the TMC9660:
AdcManager reads its channels through the TMC9660, and TemperatureManager reads the NTC through AdcManager and
the chip temperature from the TMC9660.
What happens when a step fails¶
- Required steps (NVS, comms, GPIO, LEDs). If one fails,
EnsureInitialized()fails closed: it shuts down, in reverse order, every manager that had come up, so no bus, pin or handler is left open behind a facade that says it is not initialised. It returnsfalse,GetLastError()says why (BusUnavailable,InitFailed, ...), and callingEnsureInitialized()again retries from the start. Each manager also fails closed on its own: a manager whoseInitialize()fails releases what it had opened before it returns. - Best-effort steps (motors, ADC, IMU, encoders, temperature). A failure is logged as a warning and the manager
stays unavailable; the remaining steps still run and
EnsureInitialized()returnstrue. The log then saysInitialized in degraded modeand lists which of Motors, ADC, IMU, Enc and Temp areOFF. Checkvortex.motors.IsInitialized()(or the diagnostics) before relying on a best-effort manager. - The motor controller is the exception to "just a warning". If
MotorControllerdoes not come up, the facade drives the TMC9660 driver-enable line (PCAL_TMC_DRV_EN) inactive, so a chip that half-booted cannot leave its gate drivers enabled.Shutdown()does the same before it releases the motor controller.
This lets a bench with only some chips fitted, or with the motor supply off, still come up and log.
The onboard TMC9660 and its transport¶
Step 5 creates the onboard TMC9660 before initialising MotorController. It takes the four TMC9660 control lines
(reset, driver enable, fault, wake) from GpioManager, which is why GPIO comes first, and registers the chip on one
of two host links:
| Transport | How to select it | What happens |
|---|---|---|
| UART (default) | nothing | TMCL over the UART at TMCL address 1; the SPI mux pin PCAL_TMC_SPI_COMM_EN stays released |
| SPI | Vortex::SetOnboardTmc9660Transport(VortexOnboardTmc9660Transport::Spi) before EnsureInitialized() |
TMCL over SPI2; MotorController asserts the SPI mux while it talks to the chip |
SetOnboardTmc9660Transport() is ignored (with a warning) once initialisation has completed.
Calling a manager directly¶
Every manager has its own EnsureInitialized(), which returns true at once if the manager is already up. Code that
uses one manager on its own can call it, but going through Vortex::EnsureInitialized() gives the right order, the
onboard TMC9660 registration and the system diagnostics. EncoderManager creates no device by itself; see
EncoderManager.
Shutting down¶
Vortex::Shutdown() de-initialises every initialised manager, in this order: temperature, LEDs, encoders, IMU, ADC,
motors, GPIO, comms, NVS. That is the start-up order reversed except for the LED manager, which is shut down second
although it starts fourth. It then clears the initialised flag, so a later EnsureInitialized() starts again from
the beginning. It returns false if the HAL was not initialised.