I2Cのクロックストレッチ

I2Cバスは、通常はマスターがSCLラインを制御することで通信を主導し、スレーブはマスターのタイミングに従います。しかし、スレーブ側の処理が間に合わないとき、スレーブはSCLラインをLowに保持することでマスターを待たせることができます。これを「クロックストレッチ」といいます。

例えばBOSCH社の9軸センサBNO055はしばしばクロックストレッチでACKビットを100μsec以上待たせます。

上: SCL, 下: SDA, 横軸: 50μsec/DIV
f:id:licheng:20220123102901p:plain:w480

ところが、Raspberry Pi PicoのArduino環境 (本家版ではなくEarle Philhower版のほう) では、I2Cのクロックストレッチ待ちは100μsecでタイムアウトしてしまいます。このため、AdafruitのBNO055ライブラリが正しく動作しなくなります。タイムアウト時間が100μsecというのはいささか短いように思われます。

f:id:licheng:20220123103125j:plain:w480

そこで、I2Cドライバのソース( Wire.cpp ) の_clockStretch関数を下記のように修正します。

static bool _clockStretch(pin_size_t pin) {
//  auto end = time_us_64() + 100;  // 100usecでタイムアウト
    auto end = time_us_64() + 1000; // 1000usecでタイムアウト
    while ((time_us_64() < end) && (!digitalRead(pin))) { /* noop */ }
    return digitalRead(pin);
}

Wire.cppは、Windowsインストーラ版であれば下記のディレクトリにあります。

%LOCALAPPDATA%\Arduino15\packages\rp2040\hardware\rp2040\x.x.x\libraries\Wire\
(x.x.x はバージョン番号)

メモ:ビザンツ史

ビザンツ帝国の領土の変遷


五大総主教座

主要な王朝と皇帝

■レオ朝 (457 - 518)
ゼノン:西方に介入。ゲルマン人オドアケルテオドリックにイタリア統治を委任(建前)。
ユスティニアヌス朝 (518 - 602)
ユスティニアヌス大帝(笑):イタリアと北アフリカを再征服。ササン朝のホスロー1世とも戦う。『ローマ法大全』を編纂。
ヘラクレイオス朝 (610 - 711)
ラクレイオス:ササン朝に勝利するもイスラムの侵攻を受けシリアを失う。公用語ラテン語からギリシャ語に。

イサウリア朝 (717 - 802)
レオーン3世:イスラムの侵攻を退ける。聖像禁止令を出す。
マケドニア朝 (867 - 1057)
バシレイオス1世:マケドニアアルメニア系農民から皇帝に成り上がる。
バシレイオス2世:第一次ブルガリア帝国を滅ぼし、バルカン半島全土の支配を回復。通称「ブルガリア人殺し」。

コムネノス朝 (1081 - 1185)
アレクシオス1世:ローマ教皇ウルバヌス2世に援軍を要請し、第1回十字軍を招いてしまう。
アンゲロス朝 (1185 - 1204)
全員無能。第4回十字軍に帝都を奪われ滅亡。
パレオロゴス朝 (1261 - 1453)
ミカエル8世:帝都を奪回して帝国を再興。
コンスタンティノス11世:オスマン朝のメフメト2世により帝都陥落。帝国滅亡。

M5StickCのSpeaker Hatの不具合対策

M5StickCのSpeaker HatはD級アンプIC PAM8303 (3W、モノラル)を内蔵しています。

安くて小さいので、分解してPAM8303モジュール基板として利用するのもアリかなと思います。
(右は比較のため、ユニバーサル基板に386で組んだアンプ)

f:id:licheng:20220109094603j:plain:w480

しかし! このSpeaker Hat、やたらノイズが大きく音質が悪い、ケーブルで延長したりすると音が鳴らない、異常発熱するなどの不具合がTwitter上で散見されます。私もM5Stamp Picoにつないでみて同様の不具合に悩まされました。

困っていたところ、Twitterで重大な情報を得ました。

驚いて調べてみたところ、たしかにベタGND(水色)に離れ小島(緑色)ができてつながっていません!

f:id:licheng:20220108233909j:plain:w480

そこで私もC3とC4をジャンパでGNDに接続する修正をほどこしたところ、見事に問題解決しました!

f:id:licheng:20220108233935j:plain:w480

しかし、なぜこのような不具合が生じたのか疑問です。人為的なミスでビアを打ち忘れたとしても、ふつうはCADのチェックでエラーになるはずです。また、このレベルの不具合が見過ごされて広く世に出ているというのが意外です。

GR-ROSE IoTシステム開発コンテスト総復習

この記事は がじぇるねGR Advent Calendar 2021 の22日目です。

先月参加したGR-ROSE IoTシステム開発コンテスト 作品LT大会、ユニークな発表が多数ありましたが発表時間内では私の理解が追い付かなかったので、YouTubeで復習します。こうやって後から見返せるのはありがたいですね。自分の発表は見たくありませんが (^^;)

※ この記事は私の個人的なまとめです。独断と偏見を含みます。また私の理解不足のせいで誤解や抜け落ちがあるかもしれませんがご容赦ください。

エントリー (発表順、敬称略)

開始時間をクリックすると動画が始まります。

No タイトル 発表者 開始時間
コロナ禍・リモートワークとIoT 豊田陽介 0:10:05
GR-ROSEとAzureでつっこみロボをつくる 金子啓太 0:17:50
GR-ROSEを使って、RFIDタグ情報をAzureと連携してみる 松田夕貴 0:26:20
えっ!GR-ROSEってA*mじゃないの?から始めた話 永久健三 0:33:25
3軸アーム GUI 石垣翔子 0:42:40
コネクテッドマウス 長島宏明 0:50:25
IoT渾天儀で太陽の運行を知る 西村備山 1:01:05
GR-ROSE de ロボットカー 林 宜憲 1:08:45
LIDAR JUMP!! TKTK360 1:17:50
いろいろお知らせしてくれるIoT鳩時計 しろいとり子 1:26:35
Azureロボットは二足歩行の夢を見るか? 中村恭一 1:33:50
GR-ROSEとIoTCでいろいろ見守り 大栄 豊 1:42:30
IoT Central をつかった雲台制御 すぎやま 1:56:05
GR-ROSE + Azureで、見守りや防犯の仕組み robojp 2:01:35
ドローンにおけるGR-ROSE & Azure IoT Centralの一使用例 chaos 2:11:00
ネット経由でサーボアームを制御してみようとした(仮) TakSan 2:24:00
GR-ROSE による温湿度制御 やま 2:33:45

接続方法についての所感

Azure IoT vs MQTT

今回、17名中12名はIoT Centralを利用しました。一方で4名がMQTTを使用しており、MQTTの根強さがうかがえます。

マイクロソフト太田さんの言う「デバイスの数が何十万、何百万になったときに、MQTTでやるよりもAzure IoTを使ったほうが簡単」というは理解できる一方で、「そんな数のデバイスを想定してないしシンプルにMQTTでやりたい」というのも理解できます。加えて、われわれ組込み系技術者はブラックボックスを嫌う傾向があり、「チンプンカンプンな概念を理解して使うよりも低レベルからフルスクラッチしたほうが早くて確実だ!」という習性があるように思います (^^;)

Azure IoT Hubへの道

今回、少なくとも3名がGR-ROSEからAzure IoT Hubへの接続を試みるもうまくいかず代替手段をとることになりました。Azure IoT Hubへ直接接続されたのは石垣さんお一人だけのようです。石垣さんいわく「サンプルプログラムをIoT Hub用に改良しただけ」とのことですが、私も林さんもそこでつまづきました (^^;) これについてはもう少し詳しい情報が欲しいところです。

【2021/12/24 追記】
石垣さんからを情報いただき、接続できるようになりました。ありがたや!

その他のAzure技術についての所感

私はApp Serviceで Node.js を使ってWebアプリをホストしましたが、静的なファイルのホスティングBlob Storageを使うという手もあるんですね。また、Functionsを使ってサーバーレスでコードを実行するという手法をはじめて知りました。

その他の技術についての所感

Unityあり、ROSあり、基板設計あり、CNC加工ありと、みなさん多彩な技術をお持ちで、これぞコミュニティーの醍醐味という感じがしました。

使用デバイスについての所感

GR-ROSEがロボット用ボードということもあって、PWMサーボやシリアルサーボを使った作例が目立ちました。3軸ロボットアーム持ってるかたが4名もいてビックリ。その他に面白そう・便利そうと思ったものをピックアップします。

使用技術一覧 (主なもの)

No IoT接続 その他のAzure技術 その他の技術 主なデバイス
IoT Hub
(テレメトリ)
(MQTT経由)
Stream Analystics
Functions (Node.js)
Power BI
LINE Notify
Node.js (MQTT.js)
Grove CO2センサ
M5Stack Core2
LEDテープ+光拡散チューブ
IoT Central
(コマンド/API使用)
Blob Storage
(ホスティング)
- PWMサーボ (べゼリー)
Grove MP3モジュール
IoT Central
(テレメトリ/ルール)
- - UHF RFIDタグ / リーダー
MQTT - IFTTT, Google Assistant
Beebotte(MQTTブローカー)
Google Home
赤外線リモコン
IoT Hub
(ダイレクトメソッド?)
(デバイスツイン?)
Functions (Python) PHP(フロントエンド) 3軸ロボットアーム
IoT Central
(テレメトリ)
- TynyUSB(USBスタック)
TOPPERS, 基板設計
マウスのセンサIC
(ADNS-5050)
IoT Central
(コマンド/API使用)
App Service
(Node.js)
- ステッピングモータ
IoT Central
(コマンド)
Blob Storage(ログ)
Machine Learning
- シリアルサーボ
(KRS-3301, 回転モード)
TOFセンサ(VL53L0X)
MQTT Virtual Machines
(MQTTブローカー)
Unity LiDARセンサ(Camsense X1)
micro:bit
IoT Central
(コマンド/ジョブ)
- 3Dプリンタ PWMサーボ
Grove MP3モジュール
Grove 4-Digit Display
IoT Central
(コマンド)
- 板金設計/CNC加工 PWMサーボ
(KRS-4024, PWMモード)
IoT Central
(テレメトリ)
- GDBデバッグ 温湿度センサ
(HS3001, AHT20)
IoT Central
(テレメトリ)
- Python, Node-RED(ローカル)
ARマーカー, 3Dプリンタ
3軸ロボットアーム
9軸センサ(MPU9250)
IoT Central
(テレメトリ)
- - 焦電型赤外線センサ(PaPIRs)
PWMサーボ, プチブロック
IoT Central
(テレメトリ)
- ROS2 / Micro-ROS, RViz
Node.js(ローカル)
ドローン(+姿勢センサ)
3軸ロボットアーム
MQTT - shiftr.io(MQTTブローカー) 3軸ロボットアーム
IoT Central
(テレメトリ/コマンド)
- - 温湿度センサ(HS3001)
PWMサーボ

中華なデジタル顕微鏡Andonstar ADSM301

中国製のデジタル顕微鏡を買いました。
AndonstarのADSM301という製品です。
アマゾンで15999円。アマゾン発送ですぐ届きました。

f:id:licheng:20210807181130j:plain:w640

良いところ

  • 5インチの本体画面 / HDMI出力(フルHD) / USB接続(720P) の3通りの使い方ができる。
  • マイクロSDカード対応でスタンドアローンでも撮影・録画できる。
  • これだけの機能でこの価格!

良くないところ

  • メーカーのサイトを見ても製品仕様が分かりにくい。
  • 本体の操作ボタンがペコペコで安っぽい。操作画面が古臭い。
  • 本体画面はチルトできない。 (もうちょい上向きであってほしかった)
  • 本体画面とHDMI出力、USB接続は排他利用。 (これはしかたないか)

Andonstarのラインナップ

昨今では中国製のデジタル顕微鏡がアマゾンでもいろいろ出回るようになりました。中でもAndonstarというメーカーの製品はユーザー数が多いようで、YouTubeでもレビュー動画がたくさん見つかります。アマゾンでもメーカーの公式ストアが販売しているので安心感があります。

Andonstarのデジタル顕微鏡は品種がたくさんあってラインナップがいまいち分かりにくいのですが、ポイントは、①イメージセンサの画素数 ②本体画面のサイズ ③HDMI出力の可否 ④USB接続の可否 ⑤価格 です。

AD206 AD208 ADSM301 ADSM302 AD407 AD409
イメージセンサ 2M 2M 3M 3M 4M 4M
画面サイズ 7" 8.5" 5" 5" 7" 10.1"
HDMI出力 × ×
USB接続 × × ×
価格 \13k \15k \16k \23k \25k \40k

まず、イメージセンサの画素数によってローエンドのAD20x、ミドルレンジのADSM30x、ハイエンドのAD40xに分かれます。AD20xは画面は大きいもののHDMI出力もUSB接続もできません。ADSM30xは画面は5インチと小さめですがHDMI出力、USB接続とも対応しています。AD40xは画面も大きくHDMI出力にも対応していますが、AD407はなぜかUSB接続には非対応。AD409は全部入りでWiFiにも対応したフラッグシップモデルといった感じです。

なのでそこそこの価格でUSB接続が欲しいならADSM30xになります。ADSM301とADSM302の差がいまいちよく分りませんが、ADSM302のほうがスタンドが大きく対物距離も大きくとれて倍率も高い(つまり作業スペースを広く取れる)っぽいです。またADSM302は本体画面をチルトできます。

私はコスパ重視でADSM301を選びました。

ADSM301の3通りの使い方

(1) 本体画面 (スタンドアローン)

モニタにもPCにも接続せず、本体単独で使うことができます。本体画面の解像度は854x480ですが、ハンダ付け作業にはじゅうぶんでしょう。
本体にはマイクロSDカードのスロットがあり、写真や動画を撮って保存できます。動画の解像度はフルHD(1920x1080)です。写真の解像度は設定で変更できます。

(2) HDMI出力

本体にミニHDMI出力端子があり、外部モニタに映像を出力できます。解像度はフルHD(1920x1080)です。モニタに接続すると自動でHDMI出力に切り替わり本体画面は消灯します。

(3) USB接続

本体にマイクロUSB端子がありPCに接続できます。専用ソフトもありますが、とくに何もインストールしなくてもWindows 10ではカメラとして認識しました。ふつうのWebカメラと同様にカメラアプリでの写真撮影や動画録画ができます。解像度はフルHDではなく、写真・動画とも1280x720になります。アプリの設定で録画の解像度をフルHDに設定することはできますが、カメラ入力の解像度じたいは720P固定です。
f:id:licheng:20210802215314j:plain:w600

専用アプリは寸法や角度などを計測するためのものです。Andonstarのサイトからダウンロードできますが、インストールしようとすると「WindowsによってPCが保護されました」というブルーの警告メッセージ。かまわず実行するとノートン先生が「疑わしい処理を遮断しました」のメッセージ。いちおうインストールされたアプリを実行してみると「MSVCR100.dllが見つからない」というエラー連発。無理してインストールする必要も無いかなと思います。

写せる範囲

写せる範囲は、スタンドを上げて対物距離を最大にしたときで25mm×14mm程度。
f:id:licheng:20210801213356j:plain:w300 f:id:licheng:20210801213412j:plain:w300

スタンドを下げて対物距離を最短にしたときで、8mm×5mm程度。
f:id:licheng:20210801213426j:plain:w300 f:id:licheng:20210801213439j:plain:w300

加えて最大4倍までのデジタルズームができます。(USB接続時は無効)

試しにハンダ付け作業に使ってみた

0.75mmピッチ端面スルーホール部品のハンダ付けを試してみました。じゅうぶん使えますね。本体画面を使うのが遅延なくかつ自然な視線の向きになって良いと思います。ただ、実体顕微鏡とちがって遠近感が無いため思いのほか糸ハンダが操りにくいです。これはちょっと慣れが必要かも。実体顕微鏡が双眼で立体視できるのはやはり重要なことでした。

所感

この性能のものがこの価格で買えるのが驚異的ですね。自分の使い方としては

の2つがメインになりそうです。

参考サイト

GR-ROSEのブートとプログラム書き込みの仕組み

この記事は がじぇるねGR Advent Calendar 2021 の18日目です。

GR-ROSEのブートとプログラム書き込みの仕組みは、公式の資料がやや分かりにくかったので調査しました。
(ふつうに使うぶんにはほぼ必要ない知識です。)

まず、起動時のシーケンスを概観すると下図のようになります。

f:id:licheng:20211211111043p:plain:w440

(1) ユーザーアプリの起動

通常は、スライドスイッチSW1は「R」にセットされており、電源ONするとユーザーアプリが実行されます。

f:id:licheng:20211211110451j:plain:w320

(2) USBファームウェアの起動

リセットボタンを押すと、USBファームウェアが起動し、PCにはUSBストレージとして認識されます。ここにユーザーアプリのbinファイルをコピーするとユーザーアプリがマイコンに書き込まれます。

電源ON(コールドスタート)かリセットボタン押下(ウォームスタート)かの区別は、USBファームウェアがRSTSR1レジスタの値を見て判定しています。ただし、ウォームスタートであってもソフトウェアリセットの場合はユーザーアプリが起動します。これはRSTSR2レジスタの値を見て判定しています。

(3) USBブートモード

スライドスイッチSW1が「P」にセットされている場合、電源ONまたはリセットするとUSBブートモードで起動します。このモードではPCからRenesas Flash Programmer (RFP) を使ってプログラム(motファイルなどの形式)を書き込むことができます。

スライドスイッチSW1はRXマイコンのMD端子とUB端子につながっています。RXマイコンはMDがHighのときシングルチップモード(通常起動)になり、MDがLowでUBがHighのときUSBブートモードになります。

(2)でのプログラム書き込みはGR-ROSEのUSBファームウェアが提供する機能であるのに対し、(3)はRXマイコンにもともと備わっているブートプログラムの機能です。なんらかの理由でGR-ROSEのUSBファームウェアが消えてしまった場合(例えばE2デバッガを接続してプログラムのデバッグをおこなった場合)には、(3)の方法でUSBファームウェアを書き直すことができます。USBファームウェアmotファイルはGR-ROSEの公式ページからダウンロードできます。

GR-ROSEのFlashメモリマップと起動手順

スライドスイッチSW1が「R」のとき、RXマイコンはシングルチップモードで起動し、リセットベクタ(FFFFFFFC番地)に格納されているアドレスにジャンプします。リセットベクタにはUSBファームウェアのリセットハンドラ(PowerOn_Reset_PC関数)のアドレスが格納されているので、まずUSBファームウェアが起動します。USBファームウェアは前述のようにリセット要因をチェックして、ユーザーアプリを起動するかまたはUSBファームウェアの実行を継続します。

f:id:licheng:20211210225837p:plain:w400

ユーザーアプリのリセットハンドラ(PowerOn_Reset_PC関数)はFFE00000番地になるようにビルドされます。USBファームウェアは、ユーザーアプリを起動する場合にはこのFFE00000番地にジャンプします。

USBファームウェアの実行が継続された場合、PCからコピーされたbinファイルはまずUSBストレージ領域に書き込まれ、それからユーザーアプリ領域に展開され、その後ユーザーアプリのリセットハンドラにジャンプします。

GR-ROSEで FreeRTOS vs Azure RTOS

この記事は がじぇるねGR Advent Calendar 2021 の14日目です。

GR-ROSEでは、FreeRTOSとAzure RTOSという2つのRTOSをお手軽に使うことができます。
この記事ではGR-ROSEでこの2つのRTOSを比較します。

FreeRTOSとAzure RTOSについて

FreeRTOSはオープンソースRTOSで、2017年にAmazonに買収され現在はMITライセンスで公開されています。(買収以前はGPLライセンスでした。)

いっぽう、Azure RTOSは元の名をThreadXといい、2019年にMicrosoftに買収されました。ソースコードGitHubで公開されてはいますが、プロプライエタリなライセンスになっています。Microsoftは特定のマイコンメーカーとOEMライセンス契約を結んでおり、ライセンスされたマイコンでは無償でAzure RTOSを利用できます。逆に言えば、ライセンスされていないマイコンにAzure RTOSを移植して勝手に再配布したり本番利用したりはできません。別途ライセンス料金を支払う必要があります。

f:id:licheng:20211204111701j:plain:w400

この2つのRTOSのどちらが良いかというのは一概に言えませんが、IoTに関して言えば答えは簡単です。クラウド側がAWSならFreeRTOS、AzureならAzure RTOSでしょう。そもそもAmazonMicrosoftも自社のIoTソリューションのためにこれらのRTOSを買収したわけですから、とうぜん自社のIoTクラウドサービスとの連携をサポートしています。

f:id:licheng:20211204102653j:plain:w500

ベンダ クラウド RTOS
Amazon AWS FreeRTOS
Microsoft Azure Azure RTOS

この記事ではIoTサポートの話は横に置いて、RTOSの基本的な部分について2つのRTOSを比較していきます。

GR-ROSEでFreeRTOSとAzure RTOS

GR-ROSEの開発環境はWebコンパイラ、e2studio、IDE for GRの3種があり、どれもFreeRTOSベースのArduino互換SDKが基本です。Arduino互換のAPIが使えるので、FreeRTOSをまったく意識しなくともプログラムできますが、FreeRTOSのAPIを使用すればマルチタスクなプログラミングも可能です。

#include <Arduino.h>
#include <FreeRTOS.h> // FreeRTOSのAPIを使う場合はインクルード
#include <task.h>     // タスク関係
#include <semphr.h>   // セマフォ、ミューテックス関係
#include <queue.h>    // キュー関係

いっぽう、Azure RTOSに関してはWebコンパイラとe2studioでAzure IoT Central用のサンプルプロジェクトが提供されています。こちらもArduino互換SDKですが、Azure RTOSAPIを使用すればマルチタスクなプログラミングも可能です。IDE for GRはサポートしてません。

#include <Arduino.h>
#include <tx_api.h> // Azure RTOSのAPIを使う場合はインクルード

マルチタスク

まずはRTOSの根幹であるマルチタスクから。(FreeRTOSではタスク、Azure RTOSではスレッドという用語を使いますが、方言の差くらいに捉えておきます。)

FreeRTOSでは次のように書きます。タスク関数へ渡す引数やハンドルの取得は不要ならNULLを渡します。

結果 = xTaskCreate(
    タスク関数, タスクの名前, スタックサイズ,
    タスク関数へ渡す引数のポインタ, 優先度, ハンドルを返すポインタ );

Azure RTOSでは次のように書きます。スタックに用いるメモリは予め確保した領域を渡します。プリエンプション閾値とタイムスライス値については後述します。自動スタートは、スレッドをすぐに開始するならTX_AUTO_STARTを、保留状態にするならTX_DONT_STARTを渡します。

結果 = tx_thread_create(
    ハンドルを返すポインタ, スレッドの名前, スレッド関数,
    スレッド関数へ渡す引数, スタック先頭へのポインタ, スタックサイズ,
    優先度, プリエンプション閾値, タイムスライス値, 自動スタート);

優先度の数字に注意してください。FreeRTOSでは数字の大きいほうが優先度が高くなるのに対し、Azure RTOSでは数字の小さいほうが優先度が高くなります。

GR-ROSEのメインタスク( setup()とloop() )は、FreeRTOS環境では優先度3、スタック512バイトに設定されています。(FreeRTOS/src/amazon_freertos_common/freertos_start.c)
いっぽう、Azure RTOS環境では優先度4、スタック4キロバイトに設定されています。(src/main.c)

排他制御

マルチタスクで並列処理をすれば、たいていの場合はミューテックスなどを使った排他制御が必要になります。

FreeRTOSでは次のように書きます。最大待ち時間はtick数で指定します。後述しますが、GR-ROSEでは tick = 1msec となっています。portMAX_DELAYを指定すると永久に待ちます。

SemaphoreHandle_t mutex;
mutex = xSemaphoreCreateMutex();
結果 = xSemaphoreTake(mutex, 最大待ち時間); // ミューテックスを獲得する (ロックする)
結果 = xSemaphoreGive(mutex); // ミューテックスを返却する (アンロックする)

Azure RTOSでは次のように書きます。優先度継承については後述しますが、 TX_INHERITを指定すると優先度継承が有効となり、TX_NO_INHERITを指定すると無効になります。待ちオプションは、TX_NO_WAITを指定すると待たずに即座に戻り、TX_WAIT_FOREVER を指定すると永久に待ち、それ以外の値の場合は指定したtick数まで待ちます。GR-ROSEでは tick = 10msec となっています。

TX_MUTEX mutex;
結果 = tx_mutex_create(&mutex, ミューテックスの名前, 優先度継承);
結果 = tx_mutex_get(&mutex, 待ちオプション); // ミューテックスを獲得する (ロックする)
結果 = tx_mutex_put(&mutex); // ミューテックスを返却する (アンロックする)

優先度継承(Priority Inheritance)とは、スレッド間で待ち合いをする場合にそれらのスレッドの中の最高の優先度でクリティカルセクションを実行するというものです。優先度の高いスレッドが優先度の低いスレッドに待たされて遅れるケース(優先度の逆転)を緩和する狙いがあります。

FreeRTOSではミューテックスは必ず優先度継承になります。タスク間の同期など優先度継承をすべきでない場合にはミューテックスではなくバイナリーセマフォを用います。

タスク間通信

マルチタスクでもう一つよく使うのが、キューを使ったタスク間のメッセージのやりとりです。

FreeRTOSでは次のように書きます。最大待ち時間は前述のミューテックスの場合と同様です。

QueueHandle_t queue;
queue= xQueueCreate(キューの長さ, 要素のサイズ);
結果= xQueueSend(queue, 要素へのポインタ, 最大待ち時間); // キューの末尾に要素を送る
結果 = xQueueReceive(queue,  要素を返すポインタ, 最大待ち時間); // キューから要素を受け取る

Azure RTOSでは次のように書きます。要素のサイズは32ビットワード単位であることに注意してください。指定できる値は1~16です。キューに用いるメモリは予め確保した領域を渡します。キューのサイズはトータルのバイト数を指定します。待ちオプションは前述のミューテックスの場合と同様です。

TX_QUEUE queue;
結果 = tx_queue_create(&queue, キューの名前, 要素のサイズ, キューの先頭へのポインタ, キューのサイズ);
結果 = tx_queue_send(&queue, 要素へのポインタ, 待ちオプション); // キューの末尾に要素を送る
結果 = tx_queue_receive(&queue, 要素を返すポインタ, 待ちオプション); // キューから要素を受け取る

プリエンプション

プリエンプションとは、現在実行中のタスクより優先度の高いタスクが実行可能である場合にOSが強制的にタスクスイッチすることです。プリエンプションが無いと、タスクが自発的に待ち状態に入らないかぎりタスクスイッチは起こりません。これを協調的マルチタスクと言います。

【FreeRTOSの場合】
FreeRTOSはプリエンプティブマルチタスクにも協調的マルチタスクにも設定できます。GR-ROSEのFreeRTOSはプリエンプティブマルチタスク、同一優先度タスクのタスクスイッチ(タイムスライス)あり、システム割り込み周期(tick)は1msecに設定されています。

#define configUSE_PREEMPTION       1      // プリエンプション有効
#define configUSE_TIME_SLICING     1      // 同一優先度タスクのタイムスライスあり
#define configTICK_RATE_HZ         (1000) // tick = 1msec
// configUSE_PREEMPTIONが0のときはconfigUSE_TIME_SLICINGは無視されます。

【Azure RTOSの場合】
Azure RTOSは基本的にプリエンプティブマルチタスクですが、スレッドごとに生成時にtx_thread_createの引数で優先度の他にプリエンプション閾値、タイムスライス値が設定できます。また TX_DISABLE_PREEMPTION_THRESHOLD を定義することでプリエンプションを無効にも設定できるようです。

プリエンプション閾値より優先度の高いスレッドのみがプリエンプションの対象になります。したがって、プリエンプション閾値は優先度以下の値を指定します。プリエンプション閾値に0を設定するとプリエンプションはおこなわれません。

タイムスライス値は、同じ優先度の実行可能状態のスレッドがあるときにタスクスイッチをおこなう時間をtick数で指定します。優先度とプリエンプション閾値に同じ値を設定したときのみ有効です。タイムスライス値にTX_NO_TIME_SLICE (=0)を設定するとタイムスライスが無効になります。つまり同じ優先度のスレッド間ではプリエンプションがおこなわれなくなります。

GR-ROSEのAzure RTOSでは、メインスレッドは優先度=プリエンプション閾値、タイムスライス値はTX_NO_TIME_SLICEに設定されています。

※ 現状、GR-ROSEのAzure RTOSではプリエンプションがうまく機能していないようです。この件はRulzにて問い合わせ中です。

APIリファレンス