モダンOSのお砂場(34) Mbed OS6、EventQueueを使ってみる

Joseph Halfmoon

前回のMbed OS6は bare metal profileでしたが、今回はRTOS部分を含むフルセットのAPIが使える状態でサンプル・プログラムをビルドしています。とはいえbare metalでも「行けそう」な小さなもの。使ってみるMbed OS機能は EventQueueです。Queueに溜まっているお仕事を取り出しては処理してくれる働き者。

前回同様、MbedですがArm社の幾つかある純正環境ではなく、PC上の以下のIDE環境でビルドを行っています。

VSCode + PlatformIO

プロジェクトそのものは、PlatformIO HOMEから、

  • ターゲットボード: Nucleo F401RE
  • プラットフォーム:Mbed

と指定して生成しています。PlatformIOが自動生成してくれた platformio.ini ファイルは以下のようなシンプルなものです。前回みたとおり、この状態でST Microelectronics製 Nucleo F401RE ボードをPCに接続すれば、勝手に接続先を見つけてUpload、Debugまで出来る状態にしてくれます。

[env:nucleo_f401re]
platform = ststm32
board = nucleo_f401re
framework = mbed

前回は、bare metal profile であったので、APIに「縛り」を加えるために

mbed_app.json

ファイルを追加していましたが今回は不要です。フルセットのAPIが使える状態。

EventQueue

Mbed OS6では、Queueの名のつく構造が2つあります。

  • Queue
  • EventQueue

前者の Queue の方は、Thread(Mbed OS6では「マルチ」で走るのはThreadです)間で通信するための構造です。FreeRTOSの回で何度か使ったものと同じようなものじゃないかと想像します。

今回使ってみるのは後者の EventQueue です。これは「やるべき仕事のキッカケ=イベント」をEventQueueに積んでおくと、Queueを管理している誰かさんが、条件整ったものからQueueよりイベントを取り出して起動してくれるというもの。ただし、Threadのように「プリエンプティブ」に制御権を移すような対象ではないようです。複数の仕事をちゃきちゃきと回すためには、素早く制御権を返納(関数から戻ればよい)する必要があるようです。

「イベント・ドリブン」なマルチタスクと言ってよいのかな?これでも幾つかの仕事を並行に行うことはできそうです。軽くて良い?ぶっちゃけ、あまりクリティカルなものがなければ、これと割り込みハンドラ(ISR)で足りるかも。

以下のサンプル・プログラムでは、それぞれ別な出力端子をトグルさせる関数2つをイベント・キューに積み、一方は6ms、他方は7msの周期で起動させています。それ以外に10秒に一回、プログラム名とOSバージョンを標準出力へ表示する仕事もイベント・キューに積んでいます。キューに積む仕事は単発でも行けますが、今回は全て周期的に起動です。

ソースコードはこんな感じ。

// Event Queue sample
#include <mbed.h>
#include "mbed_events.h"
#include <stdio.h>
using namespace std::chrono_literals;

DigitalOut pa_6(PA_6);
DigitalOut pa_7(PA_7);

void togglePA6() {
  pa_6 = !pa_6;
}

void togglePA7() {
  pa_7 = !pa_7;
}

int main() {
  EventQueue queue;
  queue.call_every(10s, printf, "Event QUEUE sample 000 OS: %d.%d\n",MBED_MAJOR_VERSION, MBED_MINOR_VERSION);
  queue.call_every(6ms, togglePA6);
  queue.call_every(7ms, togglePA7);
  queue.dispatch_forever();
}
ビルド

VSCodeの下のステータスバーにPlatformIOのビルドのボタンがあるので、それを押せば「ビルド一発」で出来ます。しかし、フルセットのMbed OS6なので、初回は相当時間がかかります。とても古くて遅いPCなのであまり参考にはなりませぬが、手元の環境では以下のように30分以上かかりました。勿論2回目以降は修正部分だけなので、ごく短い時間で済みます。なお、生成されたオブジェクトは、RAMもFlashもF401REのリソースの10分の1も使っておらず、コンパクトです。
1stTimeBuild

実行結果

出力端子 PA_6 にオシロのC1(黄色)、PA_7にオシロのC2(青色)を接続して波形を観察してみたものが以下です。

ResultWave
トグルの周期が6msと7msなので、波形としては周期12msと14msが観測できています。端子をトグルするだけの軽い仕事なので当然ですが、結構正確にトリガが、かかっていることが分かります。しかし、呆然と波形を眺めて続けていると、稀に波形が乱れる瞬間がある気がします。10秒に1回printfが走るときかもしれません。周期タスクに集中するためにはそういうモノにはお引き取りいただいた方が良いのかも。

いいんでないかい。何が?

モダンOSのお砂場(33) Mbed OS6、bare metal profile、Lチカ へ戻る

モダンOSのお砂場(35) Mbed OS6、Threadを使ってみる、STM32 へ進む