Skip to content

These module docs are in beta and may be incomplete.

modm:processing:protothread: Protothreads

Protothreads are extremely lightweight stackless threads designed for severely memory constrained systems, such as small embedded systems or wireless sensor network nodes. Protothreads provide linear code execution for event-driven systems implemented in C. Protothreads can be used with or without an underlying operating system to provide blocking event-handlers.

Protothreads provide sequential flow of control without complex state machines or full multi-threading.

Since they implement some kind of cooperative multi-threading, Protothreads are non-preemptable. Therefore, a context switch can only take place on blocking operations, which means you don't need complex synchronization.

Protothreads are also stackless, so local variables are not preserved across context switches, and must instead become member variables of the modm::Protothread subclass

A protothread runs within a single function (modm::Protothread::run()) and cannot span over other functions. A protothread may call normal functions, but cannot block inside a called function. Blocking inside nested function calls is instead made by spawning a separate protothread for each potentially blocking function.

The protothread concept was developed by Adam Dunkels and Oliver Schmidt: http://dunkels.com/adam/pt

Originally ported to C++ for use by Hamilton Jet (www.hamiltonjet.co.nz) by Ben Hoyt, but stripped down for public release.

Example

#include <modm/processing/protothread.hpp>

using Led = GpioB0;

class BlinkingLight : public modm::pt::Protothread
{
public:
    bool
    run()
    {
        PT_BEGIN();

        // set everything up
        Led::setOutput();
        Led::set();

        while (true)
        {
            timeout.restart(100);
            Led::set();
            PT_WAIT_UNTIL(timeout.isExpired());

            timeout.restart(200);
            Led::reset();
            PT_WAIT_UNTIL(timeout.isExpired());
        }

        PT_END();
    }

private:
    modm::ShortTimeout timeout;
};
// ...

BlinkingLight light;

while (1) {
    light.run();
}

Content

// Class
class modm::pt::Protothread;
class modm::pt::Semaphore;

// Define
#define PT_BEGIN
#define PT_CALL(resumable)
#define PT_END
#define PT_EXIT
#define PT_RESTART
#define PT_SPAWN(child)
#define PT_WAIT_THREAD(child)
#define PT_WAIT_UNTIL(condition)
#define PT_WAIT_WHILE(condition)
#define PT_YIELD

Dependencies

modm:processing:protothread modm_processing_protothread modm: processing: protothread modm_architecture modm: architecture modm_processing_protothread->modm_architecture modm_processing modm: processing modm_processing_protothread->modm_processing modm_driver_bme280 modm: driver: bme280 modm_driver_bme280->modm_processing_protothread modm_driver_bmp085 modm: driver: bmp085 modm_driver_bmp085->modm_processing_protothread modm_driver_ds1631 modm: driver: ds1631 modm_driver_ds1631->modm_processing_protothread modm_driver_hmc6343 modm: driver: hmc6343 modm_driver_hmc6343->modm_processing_protothread modm_driver_tmp102 modm: driver: tmp102 modm_driver_tmp102->modm_processing_protothread modm_driver_tmp175 modm: driver: tmp175 modm_driver_tmp175->modm_processing_protothread modm_driver_vl6180 modm: driver: vl6180 modm_driver_vl6180->modm_processing_protothread