Cortex-M マイコンにRTTを導入してみた
初めに
マイコンのデバッグの方法の1つに、プログラムの実行状態(変数の内容、分岐条件など)をターミナル(PCの画面上)に表示してバグを見つける方法があります。
そして、この表示データをターゲットからPCに送信する方法として、USBや、UART、ICE経由(セミホスティング)などがあります。
RTT(Real Time Transfer)は、SEGGER 社が提供するICE:J-LINKを使用して、データをPCに送信する方法の1つです。
今回は、Cortex-MマイコンにRTTを用いたターミナル出力に関して記載します。
目的
従来プログラム評価の際に、USB経由で実行状態をPCに送信して表示していましたが、この方式だと、不具合を評価時に見逃してしまう可能性が有りました。
この方式は、表示データを送信する処理をマイコンのプログラムが担う事になり、評価時(表示データ送信有)と製品版(表示データ送信無)で動作が異なってしまい、この差異で発生したり、しなかったりする不具合があるためです。今回RTTを導入する事にした目的は、上記の不具合の見逃しを防止することにあります。
RTTを選定した理由
前述の目的を達成するため下記の特徴があるRTTを選定しました。
マイコンの負荷が少ない
送信バッファにデータを書込んで置くだけで、J-LINKが自動でPCにデータを送信します。
他の方式では、マイコンのプログラムを動かしてデータを送信するためマイコンの負荷が発生します。
通信速度が速い
RTT 1に対して、SWO(Serial Wire Output) 120 / セミホスティング 10,700 の時間を要します。
デバッグ時と製品版で同じコードを使用できる
前述しましたが、RTTは送信バッファにデータを書込んでおけば、マイコンのプログラムの動作無しで、J-LINKが自動でPCにデータ送信します。J-LINKが接続されていなければ、送信バッファにデータを書くだけとなるので、デバッグ版のコードを製品版として使用する事が可能となります。
サンプルプログラムでの確認
IAR社のEWARMでRTTを試してみました。
ダウンロード&インストール
下記からSEGGER のJ-Linkツールをダウンロードしてインストールを行います。
https://www.segger.com/downloads/jlink/JLink_Windows.exe
ソース追加
インストールしたフォルダ(SEGGER\JLink\Samples\RTT)下のzipファイルを解凍すると下記4つのフォルダにソースファイルがあります。
RTTフォルダ下のソースをEWARM のプロジェクトに追加します。
exsamples/MainRTT_PrintfTest.c をリンクするとSEGGER_RTT_printf関数によりターミナル出力ができます。
Syscalls/SEGGER_RTT_Syscalls_IAR.c をリンクすると、IDE(IARのEWARM)が提供しているprintf の出力先がRTTに変更されます。
IDE提供の weak __write() をオーバーライドしています。
SEGGER_RTT_Syscalls_IAR.c をリンクしない事で、printfを従来のターミナルIO 出力とし、SEGGER_RTT_printf をRTT出力とする事もできます。
出力結果
ターミナル出力した結果は、RTT Viewer等のSEGGER が提供しているツールや、TeraTerm等のターミナルソフト、ブラウザで表示する事が可能です。
下記出力結果となります。
製品版への組み込み
製品版に組み込む時は、exsamples/MainRTT_PrintfTest.c をプロジェクトから除外して、SEGGER_RTT.c の下記を修正します。
_SEGGER_RTT 構造体を固定アドレス(0x2000 0000)に配置します。
0x2000 0000 は、今回使用したマイコンのRAMの先頭アドレスです。
RTT Control Block(_SEGGER_RTT)を Auto Detect するため、RAMの先頭に配置します。
RAMの先頭に配置されていないとViewer がRTT Control Blockを自動検索できませんでした。
RAMの先頭に配置できない場合は、RTT Viewerの設定を変更する事で対応できます。
アドレス指定:「Address」(RTT Control BlockのアドレスをMAPから検索してアドレスを入れます。)
検索範囲指定:「Search Range」(RAMの先頭アドレスとサイズを入れます。)
RAMの先頭に配置するのが、RTT Viewerのデフォルト設定値「Auto Detection」が使用できるので分かりやすいと思います。
【_SEGGER_RTTを0x2000 0000 に配置するための変更】
SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT@));
↓
SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT@0x20000000));
RTT Viewer のRTT Control Block検出の設定画面
Auto Detection を選択した理由
RTT Control Blockの検索手段は、3種類あります。
「Address」:RTT Control Blockのアドレスをピンポイントで指定する
「Search Range」:検索する領域を指定する
「Auto Detection」:自動で検索する(デフォルトの指定。当初製品版では接続できなかった)
Addressは、リンクのたびにアドレスが変化する(リンク時アドレス指定がない場合)ので都度設定の変更が必要、Search Rangeの場合、マイコンが変わると設定変更が必要となるため、Auto Detectionを使用したいと思いました。
そこで、サンプルと製品版で異なる箇所を探すためにリンクで作成されるMAPファイルを比較したところ、RTTの構造体のアドレスが、サンプルは、RAMの先頭付近にあり、製品版はRAMの後端にある事が分かりました。前記をもとに、構造体をRAMの先頭に配置した所、製品版でも「Auto Detection」で接続する事ができました。
今回使用したマイコンだけ、この現象が発生するかどうかは分からないのですが、「Auto Detection」で、コネクトできない場合は、RTT Control Blockのアドレスを変更してみてください。
最後に
通信速度が速く、製品版でもデバッグ用のターミナル出力が行えるRTTを活用しましょう。