2016年8月18日木曜日

mbed-rtosのThreadをdeprecated(非推奨)を避けて使ってみる。

Threadのコンストラクタは

Thread(mbed::Callback<void()> task,
  osPriority priority=osPriorityNormal,
  uint32_t stack_size=DEFAULT_STACK_SIZE,
  unsigned char *stack_pointer=NULL)

だとdeprecated(非推奨)のWarningが出るのでどうすればいいかやってみた。

ThreadのAPI DocumentやThread.hを見ると、

Thread(osPriority priority=osPriorityNormal,
  uint32_t stack_size=DEFAULT_STACK_SIZE,
  unsigned char *stack_pointer=NULL)

を使えばいいようだが、コンストラクタでThread本体の関数が指定できない。APIドキュメントを見ると、どうやら

template <typename T, typename M>
osStatus start(T *obj, M method)

で、本体の関数(task)を指定するらしい。Templateを使っていてちょっとわかりにくいが、objにClassから導出されたオブジェクトへのポインタ、methodにClassのメンバ関数へのポインタを指定すればいいらしい。Templateのこういう使い方は慣れていないので間違ってるかもしれない(@@;

APIドキュメントには載っていないが

osStatus start(mbed::Callback<void()> task);

という、Classのメンバ関数ではない素の関数もtaskに指定できるようだ。

テスト・プログラム

#include "mbed.h"

DigitalOut led1(LED1);

class Foo {
public:
    void print() {
        int cnt = 0;
        while (true) {
            printf("Foo::print(): %d\r\n", cnt);
            cnt++;
            Thread::wait(100);
        }
    }
};

void print()
{
    int cnt = 0;
    while (true) {
        printf("print(): %d\r\n", cnt);
        cnt++;
        Thread::wait(100);
    }
}

int main()
{
    printf("\r\n\n*** RTOS basic example ***\r\n");
    
    Foo foo;
    
    Thread thread1;
    Thread thread2;
    thread1.start(&print);
    thread2.start(&foo, &Foo::print);
    
    while (true) {
        led1 = !led1;
        Thread::wait(500);
    }
}

thread1が素のprint()、thread2がFooクラスのメンバ関数のprint()をThreadのtaskとして指定している。

実行結果

メモ:

プロジェクトに「mbed-rtos」をインポートしておけば、"rtos.h"をインクルードしないでもコンパイルできた。

mbed OS 5のExampleと思われる「mbed-os-example-blinky」というプロジェクトをオンライン・コンパイラでやってみたが、「mbed-os」というライブラリがインポートされていて、普通の「mbed」はインポートされていない。このライブラリでmbed OS 5とClassic mbedを分離しているのかな?

「mbed-os」はパブリッシュされていないようで、オンライン・コンパイラでは普通にインポートできないようだ。

RTOSはなんかややこしそうなで出来るだけ使わない方向でいきたいが、シーケンスのタイミング取りに使うTimer割り込みは、TickerだとISR内で重い処理ができないので(参考:「Nucleo F401RE(mbed)をMasterにしてPSoC4とSPI通信する。」)RtosTimerは使わざるを得ないかもしれない。大丈夫だろうか(@@;