FreeRTOSにおけるタスクの遷移について

RX66N + FreeRTOSの環境で開発をしております。

FreeRTOSがらみの質問なので場違いかもしれませんが、アドバイスいただけたらお願いします。

まず、OSの設定としては

・プリエンプティブスケジュール(configUSE_PREEMPTION=1)

・タイムスライスOFF(configUSE_TIME_SLICING=0)

で使用しています。

同じ優先度のタスクAとタスクBがあり、タスクAがRunning、タスクBがBlocked状態とします。

この時タスクAがタスクBのBlocked状態を解除するシステムコールを呼んだとします。

タスクの状態としてはAがRunning、BがReadyになると思いますが、

タスクAがBlockedに入る前にタスクBに遷移するのは仕様ですか?

また、上記のように同じ優先度の2つのタスクがRunningとReadyステータスだった場合、

割込みやより優先度の高いタスクの実行により切り替わることはありますか?

同じ優先度でタイムスライスがオフであれば、実行中のタスクがBlockedに入るまでもう一方のタスクには

切り替わらないつもりでいたので戸惑っております。

(以前使用していたitron準拠のOSではそのような動きはしなかった認識です)

よろしくお願い致します。

■環境

・RX66N

・RX ファミリ Renesas FreeRTOS

・e2studio

・CC-RX v3

  • ふぐりんさん、こんにちは、Joです。

    またしてもいろいろと実験していただきありがとうございます。

    つまりタイムスライスがOFFの場合、単純に2つの同一優先度のタスクだけが動いている限りはBlockedになるまでもう一方のタスクに切り替わることはないが、他のいろいろが動いている中で「Yield」されるとそれをきっかけにタスクが遷移されることがある。

    というわけですね。

    確かにこれまでの結果を踏まえるとそういう仕様なら辻褄が合いそうな気がしますね。

  • Joさんこんにちは!

    参考にしていただけるとうれしいです。(今回の問題の原因かどうかは置いといてw)
    私も良い勉強になりました。


    ただですねえ・・オシロの画像よく見るとTaskGの処理が終わるまでの時間が全て160usecぐらいなのに気づきまして。
    「あれー?実験によってはTaskAやTaskXの実行時間(dummy(500)=20usec弱)は後ろにずれるはずなのに」
    て思って確認してました。(よっぽど暇なんだと思われたくないけど、気になったら仕方ないですよねw)

    で、わかりました。
    テストコマンドは実行直後にコンソールにプロンプト">"を出すんですが、その出力待ちでした。

    コンソール機能にはエミュレータ経由のデバッグコンソールを使っています。
    これは1文字づつ送受信するんですが、FINEボーレートが1500000bps(1.5Mbps)だと1文字送信するのに実測で158.8usecかかってます。(前出力文字の送信が終わるまで次の出力要求がダイナミックループで待たされる)

    この待ちはFINE通信にかかる時間なのでTaskAが動こうとTaskXが動こうと変わりません。

    (あーすっきりした)

  • ふぐりんさん、Joさん

    シェルティです、こんにちは。ルネサスの中の人です。今はセキュリティやRTOS開発、GitLabを用いた社内CI/CD環境整備などを担当しています。

    種々実験いただきありがとうございます。シェルティが実験しようとしていた内容と同じ(タスク遷移時にポートで動作を追う(さらにそのあとTracealyzerでも確認する))ですね。シェルティのほうでもふぐりんさんと同じく「再現しない」ところまでは確認しました。

    私もふぐりんさんやJoさんのように、なんでこうなるのか気になってしまい、ふぐりんさんと同じ実験を考えて詳細を追ってみようとしていたところ、実はゴールデンウィーク中に家族に不幸がありお葬式などを仕切っていて実験時間が消えてしまいました。

    ざっと見たところYieldでタスクが動き出すのは合っているように思いますね。タイマで起動するスケジューラのコードをステップ実行で追っていって、どの瞬間にタスクが動き出すか捕まえればカラクリが分かると思います。

    #すみませんシェルティも自分でFreeRTOSを設計したわけではないのでこのあたり暗記が出来てないですね。詳細などを知りたい場合はAWSの技術チームに質問して教えてもらってます。

    またこちらでも実験出来て何か追加で分かったことがあれば書き込みます。

    以上です

  • こんにちは。NoMaYです。

    まだ、APIの使い方との兼ね合い、とか、コンフィグレーションの他の設定との兼ね合い、とか、可能性があるかも知れませんけれども、今回の話題の捉え方の1つの考え方として、以下の事例との類似性みたいなのが頭に思い浮かびました。

    コンパイラのコード生成の話題:

    ・ 以前に使っていたマイコンのコンパイラでは以下のコードで正しく外部変数をリードするコードが生成されていた

    ・ ところが、今回使い始めたマイコンのコンパイラでは外部変数をリードするコードが生成されない

    extern int flag_set_reset_in_interrupt;

    void func(void)
    {
        。。。
        flag_set_reset_in_interrupt = 0;
        。。。
        while(flag_set_reset_in_interrupt == 0)
        {
            。。。
        }
        
        。。。
    }

     
    ・ 今は、変数宣言にvolatileを付けて下さい、というリプライに食い下がってくる人はいないでしょうけれども、、、

    ・ 組み込みソフトウェアならば、外部変数が割り込みで変更される可能性は当たり前なのだから、コンパイラのバグでしょ!、そんな最適化を導入したこと自体がバグでは?、というのも的外れで無いのかもと思いますけれども、、、

    ちょっと、そういうことが、頭に思い浮かびました。

    なので、この後のどこかの時点で、以下のような流れが要るのかなぁ?、と思いました。

    ・ 同一優先度の別タスクに意図せず(以前に使っていたμITRON系RTOSとは違うタイミングで)切り替わることで問題が発生したことは分かるのですが具体的な問題としてどんなものなのか?

    ・ 問題を一般化出来るのなら、ひょっとして、FreeRTOSでの何かのAPIの定番の使用例みたいなのがあったりするのかな?(上記の例で言えば、変数宣言にvolatileを付けて下さい、といったような感じのもの、みたいな、、、)

  • シェルティさんこんにちは!
    すいません。やりとりが数日あいてたみたいだったんでしゃしゃり出てしまいました。
    おかげで勉強になって楽しかったです。

    Tracealyzerというのを使われるんですね。今調べてました。
    似たようなので私もDT10(今はDT+)持ってるんですがそういえば最近使わないなあ・・
    Tracealyzerのレコーダ部分は公開されてるようですね。で、そういうツールと連携できる仕組みがFreeRTOS側にすでに用意されてるみたいで、ちょっと今興奮してますw

  • NoMaYさんこにちは。
    お久しぶりです!NORTiとFITの共存の件(GitHub更新しました)も何か問題ありましたらご連絡くださいw

    volatileのたぐい・・と思ったら、JoさんのはRX66Nでした。私はRX65Nでテストしましたが、FreeRTOSのポーティングが別みたいです。なにか微妙に違うかもしれないですね。

    readme.txt
    The following table shows which port is recommended to be used.
    
    
    RX MCU Group    CPU     FPU         FPU         Port Layer
                    Core    (Single     (Double     CC-RX                   GNURX               ICCRX (*6)
                    Type    Precision)  Precision)
    
    RX110           RXv1    No          ---         Renesas/RX100 (*1,*2)   GCC/RX100 (*1,*2)   IAR/RX100 (*1,*2)
    RX111           RXv1    No          ---         Renesas/RX100 (*1,*2)   GCC/RX100 (*1,*2)   IAR/RX100 (*1,*2)
    RX113           RXv1    No          ---         Renesas/RX100 (*1,*2)   GCC/RX100 (*1,*2)   IAR/RX100 (*1,*2)
    RX130           RXv1    No          ---         Renesas/RX100 (*1,*2)   GCC/RX100 (*1,*2)   IAR/RX100 (*1,*2)
    RX13T           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    
    RX210           RXv1    No          ---         Renesas/RX200 (*3)      N/A (*3)            N/A (*3)
    RX21A           RXv1    No          ---         Renesas/RX200 (*3)      N/A (*3)            N/A (*3)
    RX220           RXv1    No          ---         Renesas/RX200 (*3)      N/A (*3)            N/A (*3)
    RX230,RX231     RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX23E-A         RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX23W           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX23T           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX24T           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX24U           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    
    RX610           RXv1    Yes         ---         N/A (*4)                N/A (*4)            N/A (*4)
    RX62N,RX621     RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX630           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX634           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX63N,RX631     RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX64M           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX65N,RX651     RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX66N           RXv3    Yes         Yes         Renesas/RX700v3_DPFPU   GCC/RX700v3_DPFPU   IAR/RX700v3_DPFPU
    RX62T           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX62G           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX63T           RXv1    Yes         ---         Renesas/RX600           GCC/RX600           IAR/RX600
    RX66T           RXv3    Yes         No          Renesas/RX600v2 (*5)    GCC/RX600v2 (*5)    IAR/RXv2 (*5)
    
    RX71M           RXv2    Yes         ---         Renesas/RX600v2         GCC/RX600v2         IAR/RXv2
    RX72M           RXv3    Yes         Yes         Renesas/RX700v3_DPFPU   GCC/RX700v3_DPFPU   IAR/RX700v3_DPFPU
    RX72N           RXv3    Yes         Yes         Renesas/RX700v3_DPFPU   GCC/RX700v3_DPFPU   IAR/RX700v3_DPFPU
    RX72T           RXv3    Yes         No          Renesas/RX600v2 (*5)    GCC/RX600v2 (*5)    IAR/RXv2 (*5)
    
    Notes:
    
    *1: If the application writer wants to use their own tick interrupt configuration when tickless idle
    functionality is not used, please define configSETUP_TICK_INTERRUPT() (in FreeRTOSConfig.h) and provide
    the configuration function.  Please be aware that port.c is hard coded to use CMT0 though it seems to be
    configured to use any CMTn according to the definition of configTICK_VECTOR (in FreeRTOSConfig.h).
    
    *2: If the application writer wants to use their own tick interrupt configuration when tickless idle
    functionality is used, please modify port.c for the configuration.  Please be aware that port.c is
    hard coded to use CMT0 though it seems to be configured to use any CMTn according to the definition of
    configTICK_VECTOR (in FreeRTOSConfig.h).
    
    *3: RX100 ports are also available.
    
    *4: RX600 ports use MVTIPL instruction but RX610 MCUs don't support this instruction.
    
    *5: RX700v3_DPFPU ports are also available with the following definition in FreeRTOSConfig.h.
    
    #define configUSE_TASK_DPFPU_SUPPORT            0
    
    *6: PriorityDefinitions.h has to be provided for port_asm.s in case of other than RX700v3_DPFPU port.
    It contains two definitions of interrupt priority like the following.
    
    #define configKERNEL_INTERRUPT_PRIORITY         1
    #define configMAX_SYSCALL_INTERRUPT_PRIORITY    4
    
    
    For more information about Renesas RX MCUs, please visit the following URL:
    
    https://www.renesas.com/products/microcontrollers-microprocessors/rx.html
    

    ってFreeRTOSのログ見たら、この一覧表コミットしたのNoMaYさんですか?すごい。


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

    皆様お忙しい中いろいろとご検討いただきありがとうございます。
    私のほうから何も報告できず申し訳ないです。

    こちらの現在の開発環境がNORTi向けに作ったプロジェクトを流用してFreeRTOSで動かしているため、同一優先度のタスクが意図せず切り替わることが仕様としてあるのであれば、コードの作りに問題がないか確認が必要なのと、優先度など再調整が必要だなと思ったまでです。もしくは私の気づいていないOSの設定などがあれば助言いただければと考えておりました。

    なのでタスク切り替えの仕様がRTOSと違うことで絶対的な問題があるかというと、今のところそうは思っていません。

    NoMaYさんが書かれているように定番の実装例のようなものでコントロールできればありがたいですね。