Return to Home Page

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();
    }
Return to Top