Application Framework
The “Application Framework” on the Pico is pretty minimal. It is heavily inspired
by the Arudino main() + loop()
design.
The best way to understand it is through a walkthrough of the boot process from main.cpp
.
int main() {
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
#ifdef CMAKE_HAS_VIDEO_SUPPORT
auto* factory = new pico::di::PimoroniFactory();
pico::ApplicationContainer* applicationContainer = factory->getApplicationContainer();
#else
auto* factory = new pico::di::NoVideoFactory();
pico::ApplicationContainerNoVideo* applicationContainer = factory->getApplicationContainer();
#endif
applicationContainer->onMain(); //Run main one-time setup code.
#ifdef CMAKE_HAS_VIDEO_SUPPORT
multicore_reset_core1();
multicore_launch_core1(core1_entry); //Launch the coprocessor and have it block.
// Push the pointer to the application container to the second core. This unblocks the co-processor.
multicore_fifo_push_blocking((uint32_t)applicationContainer);
//Wait for the CPU1 setup to complete.
sleep_ms(3000);
#endif
while (true) {
applicationContainer->onLoop();
}
}
This reveals the following “framework callbacks”
//Run once on main CPU main()
void onMain();
//Run once on the main CPU loop()
void onLoop();
//Run once on the co-processor
void onCpu1Main();
//Run once on co-processor loop
void onCpu1Loop();
The ApplicationContainer
is a dependency holder. Using a factory (NoVideoFactory
or PimoroniFactory
) in an abstract factory pattern
, the factory sets up the dependency tree. Each factory has an abstract method getApplicationContainer()
that fetches an ApplicationContainer
that is all set up.
In a way, this is a protoypical Hardware Abstraction Layer. Each “board” (whether the Mainboard I built, or a Pimoroni VGA test board) can substitute different peripherals (like an IPowerSwitch, or a mock video switch), and the same business logic can run.
The ApplicationContainer
also sets up the Observers.
Threading Model
Every dependency that needs to have recurring events on a cpu’s loop iteration registers a method in the ApplicationContainer. There is no multitasking on a particular CPU, anything can block anyone else.
void ApplicationContainerNoVideo::onLoop() {
watchdogManager->onCpu0Loop();
dmaManager->onCpu0Loop();
}