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()は何をトリガとして実行状態に移行するのか、逆に、どういう状態だと待機状態に移行するのか、また、そういったことをコンフィグレーションする関数があったりしないか、とか気になるのです。

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

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

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

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

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

Children
  • 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です。

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

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

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

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

    ①GUI_X_Ex.cの実装ですが、GUI_X_Unlock(), GUI_X_Lock()ともにシェルティさんが例示したgithubコードと同一で、RTOSの場合分けは行われているので問題ないと思われます。

    emWinのFITモジュールのバージョンは6.32.a.1.00で、最新のものを使用しています。

    ②ありがとうございます。URLの記事を参考に実装してみようと思います。

    RTOS自体初心者なのでたすかります。

  • NoMaYさん

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

    ご指摘通りと思います。すみません、emWinのマニュアルをちゃんと開いてもう一度読んでみるべきでした。今回マニュアルをうろ覚えの状態で書き込んだので「動いていたような気がします」という書き方で含みを持たせてしまったのですが、確信をもてないことをあまり書くものではないですね。ご指摘いただき感謝いたします。

    tanigawaさん

    すみません、上記の通りなので②は当たっていないかもしれません。もう少し他の要因も考えてみます。

    以上です

  • 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とっています

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