GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
GR-ROSEのAzureRTOS環境について質問なのですが、OSのtickは何msecなのでしょうか?また、プリエンプションは機能しているのでしょうか?
AzureRTOSはプリエンプティブスケジューラだと認識しているのですが、スレッドが自発的に処理を手放さない限りCPUを占有し続けるように見えます。
下記のスケッチは、loop()より優先度の低いスレッド2つを1tickのタイムスライスで交互に動作させるつもりなのですが、まったくタスクスイッチが起こらず、優先度が高いはずのloop()すら回りません。(同様のことをFreeRTOSで書くと意図した動作になりました。)
環境:e2studio (rose_sketch_azure_20210911.zip ベース)
#include <Arduino.h> #include <tx_api.h> #define STACK_SIZE 512 static TX_THREAD thread1, thread2; static ULONG stack1[STACK_SIZE / sizeof(ULONG)]; static ULONG stack2[STACK_SIZE / sizeof(ULONG)]; void funcThread1(ULONG parameter){ while(1){ digitalWrite(PIN_LED2, 1); //delay(100); //tx_thread_relinquish(); } } void funcThread2(ULONG parameter){ while(1){ digitalWrite(PIN_LED2, 0); //delay(100); //tx_thread_relinquish(); } } void setup() { pinMode(PIN_LED1, OUTPUT); pinMode(PIN_LED2, OUTPUT); Serial.begin(115200); UINT status = 0; if ((status = tx_thread_create( &thread1, "Thread1", funcThread1, 0, stack1, STACK_SIZE, 16, 16, 1, TX_AUTO_START))) { Serial.println("Error1"); } if ((status = tx_thread_create( &thread2, "Thread2", funcThread2, 0, stack2, STACK_SIZE, 16, 16, 1, TX_AUTO_START))) { Serial.println("Error2"); } } void loop() { static int toggle = 0; toggle = 1 - toggle; digitalWrite(PIN_LED1, toggle); delay(100); }
西村備山さん
こんにちは、シェルティです。
見落としなさそうなので、こちらで再現実験してみたところ再現しました。どうもスケジューラ内部でディスパッチャーが起動してなくてタイムスライスが働いてないように見えてます。ソフトウェア割り込みが思った通り動いてないですね。
マイクロソフト社にポーティングいただいたのですが、このあたりピンポイントに指摘して見解を得ようと思います。続報ありましたらまた報告いたします…
こんなFAQがありましたが、参考になりますか?How do I change the default tick rate for ThreadX?https://en-support.renesas.com/knowledgeBase/16977349FAQの元ネタと思われるのがこれhttps://renesasrulz.com/synergy/f/synergy---forum/8091/threadx-tick
ほやさん, コメントありがとうございます。
質問の意図としましては、Azure RTOSの挙動を明らかにしたいのが目的です。tickが10msecに設定されているならひとまずそれで構わないのですが、タスクスイッチが発生するはず(つもり)のコードを書いてもタスクスイッチが発生しないので疑問に思っております。
FreeRTOSやAzure RTOSのRXマイコンへの移植を担当しています。
timetickは以下で決まってます。
https://github.com/azure-rtos/getting-started/blob/3a5855b8e82263738ad29f897d201bc0376ecc3d/Renesas/RSK_RX65N_2MB/app/board_init.c#L32
①GR-ROSEの環境だと違うかもしれませんが、board_init.cの中でR_CMT_CreatePeriodic()を呼び出しているところの第1引数でtimetickが決まってます。単位はHzです。100を入れると10msに1回タイマ割り込みが発生します。
②ThreadX自体のtimeticはTX_TIMER_TICKS_PER_SECONDにてデフォルト100Hzで決まってます。
https://github.com/azure-rtos/threadx/blob/b216ceb25e2b6ae1ea83c1ae91d114a6fc2fc4ec/common/inc/tx_user_sample.h#L119
①②を合わせることで任意のtimetickに変更できます。
2点目のプリエンプションについては機能していると思います。
第 3 章 - Azure RTOS ThreadX の機能コンポーネント | Microsoft Docs
以上です
チェックポイント1個だけですが持ってきました。TX_DISABLE_PREEMPTION_THRESHOLDが定義されているとプリエンプションしなくなりますね。この定義をgrepして確認してみてはいかがでしょうか。
シェルティさん情報ありがとうございます。
GR-ROSEの環境ですと、wiring.c でR_CMT_CreatePeriodic(100u, timer_callback, 0) が呼ばれ、timer_callback()で _tx_timer_interrupt() が呼ばれます。
また、tx_api.h で TX_TIMER_TICKS_PER_SECOND が 100 と定義されています。
以上から、tickは確かに10msecのようです。
そして TX_DISABLE_PREEMPTION_THRESHOLD は定義されてないようです。
しかし、上記のスケッチでスレッドの切り替わりが発生しません。(オシロで確認しました。)
スレッド内で delay(100); や tx_thread_relinquish(); を呼ぶとスレッドが切り替わるので、プリエンプトが機能していないように思われるのです。
何か見落としがありますでしょうか?
マイクロソフト社にポーティングいただいたのですが、このあたりピンポイントに指摘して見解を得ようと思います。続報ありましたらまた報告いたします。
本件、ご連絡いただき、誠にありがとうございます。
シェルティさん
ご対応ありがとうございます。よろしくお願いします。
ちなみにE1をつないで少し見てみましたが、最初は繰り返し呼ばれている timer_callback() がいつの間にか呼ばれなくなってました。
この辺でいったん切り上げます。続報お待ちしております。
シェルティです、こんにちは。
本件マイクロソフトのAzure RTOSチームと会話を始めました。まだ答えにたどり着いてないですが、引き続き会話を進めて答えを導きたいと思います。時間がかかっておりすみません。進捗ありましたらまた報告します。
タイムスライス、プリエンプション問題の改修版を添付のzipにてご用意しました。
RXv2コア用GCC版で、threadx/ports以下のファイルをzipしたものです。
差し替え可能であれば、お手持ちのthreadx/ports以下のファイルを添付の
ファイルに差し替えてお試しいただけると幸いです。
ports-20220128.zip