前回、Arm社Mbed Online Compilerから Keil Studio Cloud への移行を開始。Mbed Online Compiler上のプロジェクト複数の移行を行ってみましたが、成功も失敗もあり。今回は失敗原因を追究してビルド成功させたいです。またWeb環境からのデバッグについても試みてみます。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
前回、Mbed Online CompilerからKeil Studio Cloudを開くと表示される「Copy Programs from Mbed Online Compiler」ウインドウで3プロジェクトをコピーしてみました。しかし1プロジェクトのコピーに失敗したようでした。以下のプロジェクト名で作成した自前のRTOSの練習用プロジェクトです。ターゲットボードはST Microelectronics社製、Nucleo F401RE (STM32F401RE搭載)ボードです。
Nucleo_rtos_training00
今回は「Copyウインドウ」を使わず、
-
- Keil Studio Cloud上で新規 Mbed Project、Mbed OS6 の empty projectを作成
- empty projectのソースファイルとしてMbed Online Compilerから持ってきたソースを貼り付け
という手順で移行させてみたいと思います。
Keil Studio Cloud上での新規 Mbed Projectの作成
プロジェクトの新規作成は、以下のようにFileメニューから行えます。
上記を選択すると、Example projectの選択画面が現れます。今回は、既存のexampleを使わず empty Mbed OS project を選択しました。
さて、作成した空のプロジェクトのmain.cppとして以下のソースを貼り付けました。
// Nucleo RTOS Training0 #include "mbed.h" #define E_FLAG1 (1UL) DigitalOut led1(LED1); InterruptIn button(USER_BUTTON); EventFlags e_flag; Semaphore sem(1); Thread t1; Thread t2; Thread t3; Thread t4; void pressed() { e_flag.set(E_FLAG1); } void print_name(const char* name) { printf("%s\n\r", name); fflush(stdout); } void print_thread() { while (true) { wait(1); print_name("Fixed Interval Th1"); } } void sem_thread(void const *name) { while (true) { sem.wait(); printf("Sem, %s\n\r", (const char*)name); wait(1); sem.release(); } } void userButtonThread() { while (true) { e_flag.wait_any(E_FLAG1); printf("User Button Pressed. Th.4 \n\r"); } } int main() { printf("\n\r\n\r*** RTOS Training ***\n\r"); t1.start(print_thread); t2.start(callback(sem_thread, (void *)"Th2")); t3.start(callback(sem_thread, (void *)"Th3")); t4.start(callback(userButtonThread)); button.fall(&pressed); while (true) { led1 = !led1; wait(0.5); } }
あれれ、エラー出ているやんけ!
上記のソースを作成してから少し月日は経過しておるのですが、Mbed Online Compiler環境のプロジェクト内では、問題なくビルドして実行できています。しかし、Keil Studio Cloudのエディタをみると、多数のエラー(赤の波線)が表示されていました。なんで?
最初に報告されていた赤の波線は以下です。USER_BUTTON定義されていない?
USER_BUTTONは、Nucleo F401REボード上に2つあるプッシュスイッチのうち青色のUSERと書かれたスイッチに繋がるGPIOポートを指定するためのマクロです。Mbed Online Compiler環境では ターゲットボードをNucleo F401REと指定しておけば “mbed.h” をインクルードするだけで使えるようになってます。
しかし、Keil Studio Cloud上では未定義になっているみたいです。そこで以下のような#define文を追加してみました。
#define USER_BUTTON (PC_13)
するとOK。上記をみるとPC_13とか、STM32マイコンのポート名などは使用できるようです。また、LED1という実装依存なポート名のエイリアスも使えます。どういうわけかUSER_BUTTONが抜けておると。ま、いいか。コマケー話だし。
次は アチコチで使っていた wait() 関数が皆エラーになってました。こんな感じ。
なんで、wait()って使えていたよね~ということで Mbed OS の API ドキュメントを参照してみました。リンクが以下に。
上記より、1か所引用させていただきましょう。
Note: The function wait is deprecated in favor of explicit sleep functions. To sleep, replace wait with ThisThread::sleep_for (C++) or thread_sleep_for (C). To wait (without sleeping), call wait_us. wait_us is safe to call from ISR context.
wait()って非推奨になってしまっていたのね。ThisTread::sleep_for()を使うのがよろしいみたい。そこでそちらに変更しようと書き始めるとKeil Studio Cloudのエディタ上では補完候補としてsleep_for()が現れてくるではありませんか。「こっちを使え」ということですな。早く言ってよ~。
ただのwait()関数以外にも引っ掛かっていたwait()がありました。セマフォを獲得するまで「待つ」セマフォクラスのメンバ関数のwait()です。こんな感じ。
先ほどのwait()関数同様に、以下のドキュメントを参照してみると
上記セマフォクラスのドキュメントにwait()などありません。何と!Mbed Online Compiler環境ではコンパイル通っているのよ。。。だいたいサンプルプログラムでsem.wait()していたからその真似をしただけだったのに。。。
まあ泣く子と統合開発環境には勝てないので、wait()の代わりにacquire()としてみます。これまたタイプ始めると補完候補にacquire()が表示されます。Keil Studio Cloudのエディタが認識している「最新の」APIセットで書けと。古いAPIを使うためには古いヘッダとか古いライブラリをもってこないとならないみたいです。でもそういうことすると新しいのと衝突することもあるしな~。知らんけど。古いAPIに拘らず、指摘されたら更新しておくのがよろしかろうと。
さて以下にビルド結果のバイナリファイルを二つ並べておきます。小文字でrtosと書かれている40KBのファイルの方がMbed Online Compilerでのビルド結果。大文字でRTOSと書かれている34KBのファイルの方が、Keil Studio Cloudでのビルド結果です。
Keil Studio Cloudの方がコンパクトになりました。
実行確認
上記のオブジェクトのうち、Keil Studio Cloudの生成したオブジェクトを実機Nucleo F446REに書き込んで実行してみました。標準出力に接続したTeraTerm画面が以下に。
ちゃんとスレッドどもが走り回り、USER_BUTTONを押すとそれに対応するスレッドも実行されているようです。結局、移行できなかったプロジェクトには移行に障害になるような奴らが含まれていたってこと?
デバッガを起動
前回Keil Studio Cloudのブラウザ画面から、PCにUSB接続した実機へのバイナリの書き込みは行ってみましたが、デバッガについては行っていなかったです。
今回は上記プロジェクトでデバッガ起動してみました。デバッガ起動直後の様子が冒頭のアイキャッチ画像に。実際にブレークポイントをしかけ、そこで止めたところが以下です。
ブラウザ上の開発環境からのデバッグもOKっと。