RTOSでのemWin(RX65N)

RTOSでのemWinについて

はじめまして。Tanigawaと申します。

RX65N envision kitを用いて、RenesasのGithubにある「GLCDC RW2D emWin(Segger GUIミドルウェア)」を参考に、RTOSでGUIアプリケーションを作成しようとしています。

emWinのイベント処理(スイッチのオンオフなど)からシリアルに送信キューを送りたいとき、どう書いてよいかわかりません。

以下のようにApplication.cに記述すると動作はするのですが、いかにもまずい書き方な気がして自信がありません。

emWinの処理ととRTOSのタスクの兼ね合いがわからないので、良い方法を教えていただきたいです。

#include "Application.h"

char string[32];

extern QueueHandle_t queue_handle_1;

void process_switch_on(WM_HWIN hDisplayedText)

{

TEXT_SetText(hDisplayedText, "ON");

TEXT_SetBkColor(hDisplayedText, GUI_WHITE);

TEXT_SetTextColor(hDisplayedText, GUI_BLUE);

led_on();

sprintf(string, "ON\r");

xQueueSend(queue_handle_1, string, portMAX_DELAY);

}

シリアル通信のほうは「queueの活用 printデバッグのシリアライズ」を参考に、キューによるシリアル送信タスクを実装しています。

よろしくお願いします。

Parents
  • tanigawaさん、こんにちは。NoMaYです。

    > 試しに一秒ごとに固定文字列をQUEUEに送信するタスクを加え、画面上のスイッチをトグルすると「ON」「OFF」とQUEUEに送信するプログラムをかいてみたところ、高確率でフリーズしてしまいます。やはりRTOSの処理はタスクの管理内で行わないと不具合が生じるようです。

    以下の記事自体はスーパーループ向けですけれども、tanigawaさんは既にFreeRTOSとくっつけられていますけれども、以下のMainTask()をどこに記載されましたか?

    1 GLCDC DRW2D emWin(Segger GUIミドルウェア)
    github.com/renesas/rx72n-envision-kit/wiki/1-GLCDC-DRW2D-emWin(Segger-GUIミドルウェア)

    ・rx72n_envision_kit.cのソースコード全体を以下に記載する(説明は後述)

    #include "GUI.h"

    void main(void);

    void main (void)
    {
        /* The follow function is generated by the AppWizard. */
        MainTask();
    }

     

  • NoMayさん、こんにちは。tanigawaです。

    プロジェクトのメインファイル(プロジェクト名.c)に記述していました。

    新たにタスクを作成して、そのタスク内に上記のMainTask()を記述すればよいということですね?

    たしかにそれで解決しそうです。

    ありがとうございます。

  • tanigawaさん、こんにちは。NoMaYです。

    > プロジェクトのメインファイル(プロジェクト名.c)に記述していました。

    後で自分でソースを確認してみようとは思いますけれども、これは、FreeRTOSプロジェクトでRXスマートコンフィグレータが生成したソースのmain_task()から呼び出されているmain()でしょうかね。(Amazon FreeRTOSプロジェクトの場合だったかも。)

    > 新たにタスクを作成して、そのタスク内に上記のMainTask()を記述すればよいということですね?

    いえ、上の場合だったりしますと、実質的に既にもうタスクのひとつであるmain_task()から呼ばれていることになるのです。そして、気になることは、RTOSですので、タスクの優先度はどうすれば良いのか、MainTask()は何をトリガとして実行状態に移行するのか、逆に、どういう状態だと待機状態に移行するのか、また、そういったことをコンフィグレーションする関数があったりしないか、とか気になるのです。

  • NoMayさん、こんにちは。tanigawaです。

    返信ありがとうございます。

    main_task()は画像の通り、FreeRTOSプロジェクトでスマートコンフィグレータが生成したソースで、その中にMainTask()を記述しています。

    また、画面のスイッチをトグルしたときの動作は以下の画像の通りapplication.cに記述しています。

    たしかに、新たにタスクを生成して(emWinの)MainTaskを記述するのは優先順位などがわからないですし、そもそもFreeRTOSプロジェクトで自動生成されたmain_task()で処理している分には問題なさそうですね。

    問題は、applicarion.cのイベント処理でQUEUE送信を行うと動作がフリーズすることなのですが、おそらくmain_task()内の処理で呼ばれている(つまり実質タスク関数内)ので、application.cに記述しても大丈夫な気もするのですが...

  • tanigawaさん、こんにちは。NoMaYです。

    実はきちんと分かっていないのですけれども、以下のオンラインドキュメントを見てみようと思います。(見ている最中です。)

    www.segger.com/doc/UM03001_emWin.html#Execution_Model_Single_Task_Multitask

    Execution Model: Single Task / Multitask

    emWin has been designed from the beginning to be compatible with different types of environments. It works in single task and in multitask applications, with a proprietary operating system or with any commercial RTOS such as embOS or uC/OS.


  • tanigawaさん、こんにちは。NoMaYです。

    ルネサスさんのGitHubのくだんの記事はAppWizardを使用する記事ですけれども、その場合のMainTask()は以下のスレッドで以前に調べたところでは以下の通りでした。APIの詳細は以下のオンラインドキュメントを見てみることになると思います。(ただし、なぜかAPPW_Exec()とか記載されていません。) そして、GUI_X_Delay()は記憶ではFITモジュールの中にソースがあったような気がしますので、これから探してみます。

    www.segger.com/doc/UM03003_AppWizard.html

    Config_ICUでのIRQの設定について
    community-ja.renesas.com/cafe_rene/forums-groups/beginners/f/002-2095199602/9604/config_icu-irq/47530#47530

    void MainTask(void) {
      //
      // Setup configuration dependent pointers
      //
      APPW_X_Setup();
      //
      // Initialize AppWizard
      //
      APPW_Init(APPW_PROJECT_PATH);
      //
      // Create all persistent screens except initial screen
      //
      APPW_CreatePersistentScreens();
      //
      // Create initial screen...
      //
      APPW_CreateRoot(APPW_INITIAL_SCREEN, WM_HBKWIN);
      //
      // ...and keep it alive
      //
      while (1) {
        while (GUI_Exec1()) {
          APPW_Exec();
        }
        APPW_Exec();
        GUI_X_Delay(5);
      }
    }



    [追記]

    GUI_X_Delay()は、この後のシェルティさんのリプライに書かれていたGUI_X_Ex.cの中にありましたね。

    void GUI_X_Delay(int ms)
    {
    #if (BSP_CFG_RTOS_USED == 0) /* Non-OS */
        int32_t t_end = g_time_ms + ms;

        /* WAIT_LOOP */
        while ((t_end - g_time_ms) > 0)
        {
            R_BSP_NOP();
        }
    #elif (BSP_CFG_RTOS_USED == 1) /* FreeRTOS */
        vTaskDelay(pdMS_TO_TICKS(ms));
    #else
        #warning "Warning!! It is necessary to implement to delay process."
    #endif
    }

     

  • tanigawaさん

    こんにちは、シェルティです。ルネサスの中の人です。

    RX72N Envision Kitの初期ファーム開発を担当しました。FreeRTOSベースでemWinのAPIをいろんなタスクから同時呼び出しに耐えられるように設計しています。

    https://github.com/renesas/rx72n-envision-kit

    NoMaYさんも参照されている「UM03001」というemWinのマニュアルを当時結構頑張って読みました。少し前にSegger本社(ドイツ)にも出張し、emWinの活用について議論もしました。emWinは良いソフトだと思います。

    書き込み内容を読んでみて気になるのは以下2点ですね。

    ①tanigawaさん環境では「GUI_X_Ex.c」の実装はどうなっていますか? emWinは複数タスクからの要求を想定し、要求の処理前後で利用資源のロック(GUI_X_Lock())・アンロック(GUI_X_Unlock())を実行します。FreeRTOSと組み合わせる場合、最新のemWinのFITモジュールでは「GUI_X_Ex.c」の中ではFreeRTOSのセマフォのtake/giveをロック・アンロック内に実装しています。

    https://github.com/renesas/rx-driver-package/blob/02a3aa774781c4b43e5220a65e3e7304c2c5961f/source/r_emwin_rx/r_emwin_rx_vx.xx_xxx/r_emwin_rx/lib/Config/GUI_X_Ex.c#L342

    使用しているemWinのFITモジュールのバージョンによってはGUI_X_Ex.c」の実装が不完全かもしれません。またコードが最新であってもBSP_CFG_RTOS_USED == 1が偽の場合、FreeRTOS関連のAPIが呼ばれずマルチタスク処理が適切に行えていないかもしれません。BSP_CFG_RTOS_USEDは r_bsp_config.h にあるので値がいくつかも合わせて確認してみてください。

    ②また、GUIボタンを押したらシリアルにキューを使って文字を送る(現状コードだと高頻度でフリーズする)、ですが、GUIボタンを押した後にemWin内で発生するイベントコールバックは、タッチ処理をするI2Cバスの割込みコンテキストで動いていたような気がします。この場合、”fromISR"付きのAPIを使う必要があります。

    https://qiita.com/azuki_bar/items/7f31eb80e8b6b2eff17f

    以上です

  • シェルティさん、こんにちは。NoMaYです。

    > GUIボタンを押した後にemWin内で発生するイベントコールバックは、タッチ処理をするI2Cバスの割込みコンテキストで動いていたような気がします。

    これホントなんでしょうか?咄嗟に、そうだとすると、そこからTEXT_○○○といったemWinのGUI APIを呼ぶこと自体の是非から私は疑心暗鬼になってしまう、のですけれども。

  • NoMaYさん、こんにちは。tanigawaです。

    わざわざ調べていただいてありがとうございます。

    自分も公式ドキュメントを読みこんでみようと思います。

Reply Children
  • tanigawaさん、こんにちは。NoMaYです。

    その後どうでしょうか?進展はありましたでしょうか?

  • NoMaYさん、こんにちは。tanigawaです。

    自分としてはやはり、RX72N Envision kit を用いた 音声認識・発話および LCD 表示ソリューション

    のソフトウェア構成図が気になっていて、lcd_task()というtaskを作成してemwinのメインルーチンを実行しているみたいなんですよね。

    そこで、自分でもそのようなtaskを作成して(とりあえずタスク優先度は最大で)試しているところです。

    ただ、このアプリケーションノートによるとlcd_taskのヒープサイズは102kBなのですが、そのように設定してビルドすると、

    E0562320:Section address overflowed out of range : "B_1"

    E0562320:Section address overflowed out of range : "B"

    E0562320:Section address overflowed out of range : "B_2"

    E0562320:Section address overflowed out of range : "R"

    E0562320:Section address overflowed out of range : "R_1"

    E0562320:Section address overflowed out of range : "R_2"

    とセクションアドレスエラーになってしまいます。

    現在のセクション構成は左図、RX65Nのアドレス空間は右図で、RXでemWinを使用するときのフレームバッファの計算方法を参考にフレームバッファ2つの構成にしています。

    アドレス空間の内蔵RAM領域をみるとセクションの切り方はこれ以外ないように思えるのですが...

    タスクの設定は下のようにしていて、lcd_taskのヒープサイズを約130kBとっています

    当然ながら参考アプリケーションノートとは大きく異なるので、ヒープサイズをちょうどよく設定すれば上手くいくんじゃないかと思っていろいろ試行錯誤しているところです...

  • tanigawaさん、こんにちは。NoMaYです。

    そうですか。まだ、FreeRTOS(Kernel only)+emWin AppWizardフレームワーク+仮想デバッグコンソール([訂正]←通常のUARTでしたね)デバッグメッセージシリアライズタスク、の組み合わせが動作していないのですね。


    ところで、

    > 試しに一秒ごとに固定文字列をQUEUEに送信するタスクを加え、画面上のスイッチをトグルすると「ON」「OFF」とQUEUEに送信するプログラムをかいてみたところ、高確率でフリーズしてしまいます。

    とのことですが、FreeRTOS自体は動作しているのでしょうか?これは、例えば、以下のような確認方法で別のLEDのトグルが動き続けるか、もしくはトグルが止まってしまうのか、ということで確認してみたらどうなりますでしょうか?

    (1) 自身のプログラムで最高優先度のタスクを作る
    (2) そのタスクの中で vTaskDelay で500ms毎にLEDをトグルさせる
    (3) 上記の文中で「フリーズ」となった状態では上記(2)のLEDのトグル動作はどうなっているのか?


    また、トグル動作が止まってしまう場合、デバッガで以下の操作をするとどこで止まりますか?

    (4) デバッガのストップボタンを押す


    なお、RXスマートコンフィグレータ上でタスクを定義しているので気付いていないのかな、と思ったのですけれども、実は、生成されたソースコード上では、最初から用意されているmain_task()もRXスマートコンフィグレータ上で定義したタスクも同じFreeRTOS APIで生成されているものですので、FreeRTOS APIに関して言うとlcd_task()というtaskを作成する必要は無いですよ。ただ、RXスマートコンフィグレータ上では別管理になってしまっていますので誤解されているのかなと思うのです。咄嗟に、私が過去に投稿したメモに辿りつけていないですが、main_task()もRXスマートコンフィグレータ上で管理出来ると良いなぁ、みないな投稿をした記憶があります。

    あと、以下のスレッドの以下の投稿で私も書いたことに関連しますけれども、私が思うところでは、RX65N Envistion KitでemWin使用時にLCDのフレームバッファを2面確保するのは、そもそも無理があるのではないかなぁ、と思うのです。

    RX65N/RX72N emWin+AppWizardでJapanese Language Displayが出来るか調べてみることにしました(Is it available?)
    community-ja.renesas.com/cafe_rene/forums-groups/tools/f/forum21/8320/rx65n-rx72n-emwin-appwizard-japanese-language-display-is-it-available/46443#46443

    [追記]

    > 咄嗟に、私が過去に投稿したメモに辿りつけていないですが、main_task()もRXスマートコンフィグレータ上で管理出来ると良いなぁ、みないな投稿をした記憶があります。

    とりあえず一つ出て来たのですけれども、これですとあまりはっきりとは言って無かったですね。(記憶違いだったかな。)

    e2 studio v7.5.0のFreeRTOS ProjectでVisual Expression+Renesas RX Simulator/TB-RX65Nで試せるSample Programを作ってみた
    community-ja.renesas.com/cafe_rene/forums-groups/tools/f/forum21/5970/e2-studio-v7-5-0-freertos-project-visual-expression-renesas-rx-simulator-tb-rx65n-sample-program/33117#33117

    但し、ちょっとmain_task()は例外的であり、もともと、FreeRTOSプロジェクト生成時にメインのソース内に出力されたmain_task()が存在しており、かつ、その時点で、main_task()の生成処理もfreertos_start.c内のProcessing_Before_Start_Kernel()内に記述されていて、RXスマートコンフィグレータのFreeRTOS Objectと別扱いになっています。(FreeRTOSオブジェクトの場合は、各タスクのソースはfrtos_skeletonフォルダ内のタスク名.cに出力されており、また、各タスクの生成処理はfrtos_startupフォルダ内のfreertos_object_init.c内に出力されています。) とはいえ、main_task()も他タスクと同様にRXスマートコンフィグレータにFreeRTOSObjectとして表示させたいので、今回は、以下のように対処することにしました。


  • NoMaYさん、こんにちは。tanigawaです。

    提案していただいた方法を試したところ、フリーズした際にLEDの点滅が止まり、デバッガでは

    以下の画像のようにvAssertCalled()で止まっていました。

    >実は、生成されたソースコード上では、最初から用意されているmain_task()もRXスマートコンフィグ レータ上で定義したタスクも同じFreeRTOS APIで生成されているものですので、FreeRTOS APIに関して言うとlcd_task()というtaskを作成する必要は無いですよ。

    そうだったのですね。すっかり勘違いしていました。

    ただ、main_task()の優先順位やヒープサイズなど、スマートコンフィグレータで設定するタスクとの違いが気になるところです。

    [追記]

    すいません、フリーズする原因がわかりました。

    写真のようにシリアル通信用の端子を刺してPCと通信を行っているのですが、

    端子が差し込みが深すぎると写真右のようにディスプレイに接触し、ノイズにより動作が停止してしまうのが原因だったみたいです。

    試しに差し込みを浅くして動作させたところ、フリーズしなくなりました(ディスプレイに接触するまで差し込んだ瞬間フリーズする)

    お騒がせしてすみませんでした。

  • main_task()、freertos_start.c内で同じように定義されていますね。失礼しました。

    ret = xTaskCreate(main_task, "MAIN_TASK", 512, NULL, 3, NULL);

    ということは、スマートコンフィグレータで作成するタスクと何の違いもないのですね。

    スタックサイズ512Bのmain_task()にemWinのメインルーチンを記述しても動作するということは、

    emWin用のヒープサイズ102KBは別(emWinのFITモジュール?)で確保されているため、

    タスクで確保する必要はないのですね。これも勘違いしていました。

    自分の一番最初の質問に戻ると、main_taskは通常のタスクと等しく、

    その中で実行されるemWinのapplication.cでRTOSのAPIを呼び出すことに

    何ら問題はないということなのですね。

    フリーズの原因はしょうもないものでしたが、質問する中で参考資料など提示していただき、

    理解が深まりました。ありがとうございました。