Mistake on this page?
Report an issue in GitHub or email us

Callback

A callback is a user provided function that a user may pass to an API. The callback allows the API to execute the user’s code in its own context.

This is the technical reference for callbacks. You should read the Callbacks section of the Platform Overview first for deeper insight into their use.

Calling callbacks

Callbacks overload the function call operator, so you can call a Callback like you would a normal function:

void run_timer_event(Callback<void(float)> on_timer) {
    on_timer(1.0f);
}

The only thing to watch out for is that the Callback type has an empty Callback, just like a null function pointer. Default initialized callbacks are empty and assert if you call them. If a callback may be empty, you need to check if it is empty before calling it.

void run_timer_event(Callback<void(float)> on_timer) {
    if (on_timer) {
        on_timer(1.0f);
    }
}

You can reset Callbacks to empty by assigning nullptr.

The Callback class is what’s known in C++ as a “Concrete Type”. That is, the Callback class is lightweight enough to be passed around like an int, pointer or other primitive type.

Callback class reference

Serial passthrough example with callbacks

#include "mbed.h"

RawSerial  pc(USBTX, USBRX);
RawSerial  dev(D1, D0);
DigitalOut led1(LED1);
DigitalOut led4(LED4);

void dev_recv()
{
    led1 = !led1;
    while(dev.readable()) {
        pc.putc(dev.getc());
    }
}

void pc_recv()
{
    led4 = !led4;
    while(pc.readable()) {
        dev.putc(pc.getc());
    }
}

int main()
{
    pc.baud(9600);
    dev.baud(9600);

    pc.attach(&pc_recv, Serial::RxIrq);
    dev.attach(&dev_recv, Serial::RxIrq);

    while(1) {
        sleep();
    }
}

Thread example with callbacks

The Callback API provides a convenient way to pass arguments to spawned threads. This example uses a C function pointer in the Callback.

#include "mbed.h"

Thread thread;
DigitalOut led1(LED1);
volatile bool running = true;

// Blink function toggles the led in a long running loop
void blink(DigitalOut *led) {
    while (running) {
        *led = !*led;
        wait(1);
    }
}

// Spawns a thread to run blink for 5 seconds
int main() {
    thread.start(callback(blink, &led1));
    wait(5);
    running = false;
    thread.join();
}

Sonar example

Here is an example that uses everything discussed in the introduction to callbacks document in the form of a minimal Sonar class. This example uses a C++ class and method in the Callback.

#include "mbed.h"

/**
 *  Sonar class for the HC-SR04
 */
class Sonar {
    DigitalOut   trigger;
    InterruptIn  echo;     // calls a callback when a pin changes
    Timer        timer;
    Timeout      timeout;  // calls a callback once when a timeout expires
    Ticker       ticker;   // calls a callback repeatedly with a timeout
    int32_t      begin;
    int32_t      end;
    float        distance;

public:
    /**
     *  Sonar constructor
     *  Creates a sonar object on a set of provided pins
     *  @param trigger_pin  Pin used to trigger reads from the sonar device
     *  @param echo_pin     Pin used to receive the sonar's distance measurement
     */
    Sonar(PinName trigger_pin, PinName echo_pin) : trigger(trigger_pin), echo(echo_pin) {
        trigger = 0;
        distance = -1;

        echo.rise(callback(this, &Sonar::echo_in));    // Attach handler to the rising interruptIn edge
        echo.fall(callback(this, &Sonar::echo_fall));  // Attach handler to the falling interruptIn edge
    }

    /**
     *  Start the background task to trigger sonar reads every 100ms
     */
    void start(void) {
        ticker.attach(callback(this, &Sonar::background_read), 0.01f);
    }

    /**
     *  Stop the background task that triggers sonar reads
     */
    void stop(void) {
        ticker.detach();
    }

    /**
     *  Interrupt pin rising edge interrupt handler. Reset and start timer
     */
    void echo_in(void) {
        timer.reset();
        timer.start();
        begin = timer.read_us();
    }

    /**
     *  Interrupt pin falling edge interrupt handler. Read and disengage timer.
     *  Calculate raw echo pulse length
     */
    void echo_fall(void) {
        end = timer.read_us();
        timer.stop();
        distance = end - begin;
    }

    /**
     *  Wrapper function to set the trigger pin low. Callbacks cannot take in both object and argument pointers.
     *  See use of this function in background_read().
     */
    void trigger_toggle(void) {
        trigger = 0;
    }

    /**
     *  Background callback task attached to the periodic ticker that kicks off sonar reads
     */
    void background_read(void) {
        trigger = 1;
        timeout.attach(callback(this, &Sonar::trigger_toggle), 10.0e-6);
    }

    /**
     *  Public read function that returns the scaled distance result in cm
     */
    float read(void) {
        return distance / 58.0f;
    }
};


int main() {
    // Create sonar object on pins D5 and D6
    Sonar sonar(D5, D6);
    // Begin background thread sonar acquires
    sonar.start();

    while(1) {
        wait(0.1f);
        // Periodically print results from sonar object
        printf("%f\r\n", sonar.read());
    }
}
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.