Modules

Most of the flight code is organized in modules. This page describes the essential functions of a module and how these functions are called.

In this page

What exactly is a Module?

To get an idea of what a LibrePilot module looks like, you can take a look at the Example module (flight/modules/Example), specifically example.c:

example.c
#include "openpilot.h"
#include "examplemodevent.h"
#include "examplemodperiodic.h"
#include "examplemodthread.h"

void ExampleStart(void)
{
    ExampleModPeriodicInitialize();
    ExampleModThreadInitialize();
}

void ExampleInitialize(void)
{
    ExampleModEventInitialize();
}
MODULE_INITCALL(ExampleInitialize, ExampleStart);

As you can see, a module is just a bunch of code that must contain three essential things:

Initialize FunctionThis function is called by the System module on startup. It usually contains all the initialization code neccessary for the module to work, as the name suggests.
Start FunctionAnother function called by the System module on startup, just a few lines after all the module initialization functions are called. This function usually contains code to set up Tasks (aka Threads).
MODULE_INITCALLIn order for the above two functions to get called, a module must call the MODULE_INITCALL macro. This will be described further in the next section.

Module Code Execution

So, say you've created a new module. It has a start- and an initialize function. Where are these functions called from? How does LibrePilot know about these functions?

The answer is the MODULE_INITCALL macro, defined in flight/pios/inc/pios_initcall.h. In short, this macro creates a struct containing two function pointers, one for the start- and one for the initialize function. Using attributes, it instructs the compiler to place this struct in a specific section of memory where it can later be found again. Since all modules call this macro, this section contains pointers to all initialize- and start functions.

On startup, the System module calls another macro - MODULE_INITIALISE_ALL - which loops through all initialization function pointers and calls the functions they point to. Remember, this is possible because all initialize functions are put in one place (the .initcall section). As mentioned before, a few lines later, the System module calls the MODULE_TASKCREATE_ALL macro, which in turn loops through all the start function pointers and calls the corresponding functions.

Fun Fact

The Linux kernel makes use of pretty much the same initcall mechanism. You can find a more detailed description of how it works here.

Tip

Have a look at the LibrePilot System Architecture page in the Developer Manual section of the documentation for descriptions of a few important modules.