読者です 読者をやめる 読者になる 読者になる

mbed OS のスケジューラー MINAR で割り込み処理

電子工作 mbed

mbed Advent Calendar 2015の14日目の記事です。

注: この記事は technology preview 版のソフトウェアを利用したものになるので、今後変わる可能性があります。

前回の記事でMINARでの定期的な処理の実行ができるようになったので、この記事では割り込み処理を扱います。

スイッチを押すとLEDをON/OFF

公式ドキュメント(https://docs.mbed.com/docs/getting-started-mbed-os/en/latest/Full_Guide/MINAR/)の A single event from an interrupt handler に記載されているコードを試します。

スイッチを押すとLEDをON/OFFするコードは以下のようになります。

#include "mbed-drivers/mbed.h"

static DigitalOut led(LED1);

static void toggle_led(void) {
    // LEDの状態を反転する
    led = !led;
}

static void switch_pressed(void) {
    // toggle_ledの実行をキューへ積む
    minar::Scheduler::postCallback(toggle_led);
}

void app_start(int, char**) {
    // SW2の入力をトリガーにしてswitch_pressedを実行
    static InterruptIn user_sw(SW2);
    user_sw.rise(switch_pressed);
}

このコードを yotta build してコードを書き込むと、以下のように動きます。

f:id:mia_0032:20151213204824g:plain

動作を説明すると

  1. InterruptInとして指定されたSW2が押されるとswitch_pressedが呼び出される。
  2. switch_pressedの中でMINARスケジューラーにイベントのキューを積む。
  3. MINARスケジューラーによってtoggle_ledが実行されLEDのON/OFFが反転する。

といった流れになります。

スイッチを押すとLEDが一定時間だけ点灯する

前回の記事で使ったdelayメソッドと組み合わせることで、押したタイミングでLEDをONして、1秒経ったらOFFにするようなコードを書くこともできます。

先ほどのコードのswitch_pressedの中にdelayをつけたLEDを消すイベントを追加すればOKです。

#include "mbed-drivers/mbed.h"

using mbed::util::FunctionPointer1;
using mbed::util::FunctionPointerBind;
using mbed::util::Event;

static DigitalOut led(LED1, 1);

static void blinky(int i) {
    led = i; // 1 => off, 0 => on
}

static void switch_pressed(void) {
    FunctionPointer1<void, int> ptr_to_blinky(blinky); // 関数へのポインターの生成
    FunctionPointerBind<void> bind_of_blinky_on(ptr_to_blinky.bind(0)); // 引数(0)をbind
    FunctionPointerBind<void> bind_of_blinky_off(ptr_to_blinky.bind(1)); // 引数(1)をbind
    Event e_on(bind_of_blinky_on); // LEDを光らせるイベントを生成
    Event e_off(bind_of_blinky_off); // LEDを消すイベントを生成

    // LEDを光らせるイベントをキューへ積む
    minar::Scheduler::postCallback(e_on);
    // LEDを消すイベントを1秒後に実行するようにキューへ積む
    minar::Scheduler::postCallback(e_off).delay(minar::milliseconds(1000));
}

void app_start(int, char**) {
    // SW2の入力をトリガーにしてswitch_pressedを実行
    static InterruptIn user_sw(SW2);
    user_sw.rise(switch_pressed);
}

動作する様子は以下のようになります。

f:id:mia_0032:20151213204934g:plain

1のコードと違い、LEDをコントロールする関数(blinky)に引数が必要になるため、FunctionPointer1を使っています。このあたりは前回の記事をご参照ください。

動きとしては

  1. InterruptInとして指定されたSW2が押されるとswitch_pressedが呼び出される。
  2. switch_pressedの中でMINARスケジューラーにLEDを点けるイベントと消すイベントのキューを積む。
  3. delayを指定していないイベントが先に発火して、LEDが点く。
  4. delayをつけたイベントが発火して、LEDが消える。

といった感じになります。

終わりに

mbed OSの新しいスケジューラーMINARの使い方がだいぶわかってきました。

mbed OSはIoTを意識しているようなので、そのうちインターネット上のAPIを使って何かやってみたいところです。

明日はod_1969さんです。よろしくお願いします。

関連エントリ