@hotel if you’re looking into initialization code overhaul, I’d have a HUGE wish: Make main() the actual code entry point and let the user control the initialization. I’ll try to explain:
When working on MCUs, deep embedded or even reasonably embedded but high-reliability control systems, I as a rule avoid dynamic allocation (at least wherever possible). Think of a hard-to-service system that has to have uptime in years - what would happen to your heap fragmentation, for example.
For a typical system with many interdependent subsystems, I “allocate” all those subsystems on the stack of the main() function and enter whatever control loop (RTOS, some event queue or a simple round-robin scheduler) from there. That way, I always have all the systems properly allocated, cross referenced, possibly freed in the correct order (under testing or if that system has a concept of shutdown). Something like this (made up sample that would apply to robot use case):
int main(...) {
Motor left(...);
Motor right(...);
Gyro gyro(...);
Chassis chassis(left, right, gyro); // passing in references
Robot r(chassis, ....);
[...]
SystemStateDispatcher mainDispatch(teleop, autons, ....);
mainDispatch.runLoop();
}
I think that approach like this is doable in VexCode, since you own main() and it has the vex::competition class that allows you registering callbacks for auton and teleop (instead of providing fixed symbol callbacks, though I’d rather see a class with virtual members you’d subclass, allows you to keep any context you want to pass).
As for initializing whatever you need, you might request a PROS object to be declared first (and LVGL integration too), such as:
int main(...) {
PROS pros;
LVGL lvgl;
That way, you have full control over initialization order, no globals to worry about and so on.
Under current PROS setup, I’d have to allocate objects on the heap in initialize and keep a global pointer, or just go flat global with all the objects (and all the problems it brings).