Timeout.attach_us() with very short time does not work fine

02 Aug 2011

When a handler is attached to Timeout with very short time, it seems that the handler is not called correctly under several conditions. The number of Timeout objects and interval time are related to the condition.

The following five codes demonstrate the behaviour of Timeout. I believe I can expect all defined LEDs blink syncronously, but some combination of numbers of Timeout and interval time shows different result.

  • code1 : One Timeout, 1us, no good.
  • code2 : One Timeout, 2us, no good.
  • code3 : One Timeout, 3us, works fine.
  • code4 : Two Timeout, 3us, no good.
  • code5 : Two Timeout, 4us, works fine.

// Code1 ---- BAD ----
// One Timeout, 1 micro-second delay.
// Timeout misfires at 1st and 3rd of every 4th.

#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led4(LED4);

Timeout timeout1;
void TimeoutHandler1( void ) { led1 = !led1; }

int main() {
    while (1) {
        timeout1.attach_us( &TimeoutHandler1, 1 ); // <---- 1 micro-second.
        led4 = !led4;
        wait_us( 1000000 ); // 1 second.
    }
}

// Code2 ---- BAD ----
// One Timeout, 2 micro-second delay.
// Timeout misfires only at 3rd and 6th timing and syncronize again.
#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led4(LED4);

Timeout timeout1;
void TimeoutHandler1( void ) { led1 = !led1; }

int main() {
    while (1) {
        timeout1.attach_us( &TimeoutHandler1, 2 ); // <---- 2 micro-seconds.
        led4 = !led4;
        wait_us( 1000000 ); // 1 second.
    }
}

// Code3 ---- GOOD ----
// One Timeout, 3 micro-second delay.
// LED1 and LED4 blink synchronously.
#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led4(LED4);

Timeout timeout1;
void TimeoutHandler1( void ) { led1 = !led1; }

int main() {
    while (1) {
        timeout1.attach_us( &TimeoutHandler1, 3 ); // <---- 3 micro-seconds.
        led4 = !led4;
        wait_us( 1000000 ); // 1 second.
    }
}

// Code4 ---- BAD ----
// Two Timeout, 3 micro-second delay.
// Timeouts misfire.
#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led4(LED4);

Timeout timeout1;
Timeout timeout2;
void TimeoutHandler1( void ) { led1 = !led1; }
void TimeoutHandler2( void ) { led2 = !led2; }

int main() {
    while (1) {
        timeout1.attach_us( &TimeoutHandler1, 3 );
        timeout2.attach_us( &TimeoutHandler2, 3 ); // <---- One more Timeout.
        led4 = !led4;
        wait_us( 1000000 ); // 1 second.
    }
}

// Code5 ---- GOOD ----
// Two Timeout, 4 micro-second delay.
// LED1, LED2, and LED4 blink synchronously.
#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led4(LED4);

Timeout timeout1;
Timeout timeout2;
void TimeoutHandler1( void ) { led1 = !led1; }
void TimeoutHandler2( void ) { led2 = !led2; }

int main() {
    while (1) {
        timeout1.attach_us( &TimeoutHandler1, 4 ); // <---- 4 micro-seconds.
        timeout2.attach_us( &TimeoutHandler2, 4 );
        led4 = !led4;
        wait_us( 1000000 ); // 1 second.
    }
}

Is it my usage error?

Thank you for reading ( and running ) many codes. Koichi Shibata

13 Sep 2011

This is just an educated guess, but I think you are running up against the limits of the CPU or of the library implementation. Just because the time value is set in microseconds this does not imply that it can accurately count One microsecond. If what you are doing requires interrupts with microsecond resolution, you probably need dedicated hardware (ie, a FPGA).