Arduino UNO R4の周辺回路レジスタをモニターするプログラム
Arduino UNO R4の周辺回路レジスタをモニターするプログラムを作りました。
上の画像は、低消費電力非同期汎用タイマ(AGT)のレジスタのモニター出力です。AGT は 1ms を刻む millis()
で使われていて、「1」が立ってるビットを ユーザーズマニュアル で調べると、次のことが分かります。
-
AGT コントロールレジスタ (AGTCR)
-
TSTART[1]
およびTCSTF[1]
カウント動作が開始され、カウントが実行中であることを示しています。
-
-
AGT モードレジスタ 1 (AGTMR1)
-
TMOD[3]
「パルス幅測定モード」で動作しています。 -
TCK[3]
周辺回路用クロックPCLKB
(24MHz)の 分周比 をカウントソースとしています。
-
-
AGT カウンタレジスタ (AGT)
-
AGT[16]
秒を 3000 回カウントして1ms としています。
-
AGT だけじゃなく、汎用 I/O 端子のレジスタをモニターする機能も入れたので、誰かの役に立つことを願い、紹介したいと思います!
FSP ユーザーマニュアル には、レジスタ、及びその下のビットフィールへのアクセスは、MCU タイプ別に定義された構造体により、次のルールに従うと定義されています。
上の例で言えば、AGT0
の コントロールレジスタ AGTCR
の下にあるビットフィールド TSTART
へのアクセスは、次のようになります。
PeripheralMonitor の紹介
仕組みはとても簡単です。UNO R4 ボードで読み取ったレジスタ情報をシリアル通信でホスト PC に送り、Tera Term 等の VT100 端末エミュレータ ソフトで表示します。プログラムは UNO R4 用ライブラリとして GitHub のリポジトリ PeripheralMonitor に上げました。
ホスト PC との接続
Arduino 公式リファレンス に従い、UNO R4 Minima/WiFi の D0 (Rx)
と D1 (Tx)
を、秋月で入手できる FT234X や CH340E などの USB シリアル変換モジュールに繋ぎます。接続は、Arduino 側の Rx
を 相手側の Tx
に、Tx
を Rx
につなぐ、クロス接続です。もちろん USB 側は PC に繋ぎます。
動作環境
僕の環境はとても古く、参考にならない部分もあるとは思いますが、一応記しておきます。
-
Windows:
Intel Mac 上の Parallels で動作する Windows 7 -
MacOS:
MacBook Pro (Late 2013), Big Sur (macOS バージョン 11.7.10) -
Arduino IDE
バージョン: 2.3.2、UNO R4 ボードマネージャ: 1.1.0 -
シリアル通信のプロトコル
送信側のSERIAL_8N1
と合わせるため、データ長やパリティ、フロー制御はデフォルトのままにします。
Windows の場合
FT234X は自動でデバイスドライバがインストールされ、Tera Term の最大ボーレート 921600
まで OK でした。
一方の CH340E は 製造元のページ からデバイスドライバ(Windows 7 まで対応との記述あり)をダウンロード&インストールしましたが、ボーレートを下げたり delay()
を咬ませたりしても文字化けが起きてしまいました。
Mac ではちゃんと動作しているので、デバイスドライバか OS に問題がありそうです。Windows 10 以上で確認ができればよかったのですが…。勘弁してください
Mac の場合
FT234X、CH340E とも問題なく正常に動作しました。デバイスドライバは、 を立ち上げ、ls -l /dev/tty.*
の実行結果から、それらしい名前のファイルを見つけます。
以下は僕の環境の場合ですが、/dev/tty.usbserial-DK0G1BIL
が該当します。
Arduino IDE がアップロード用に使うデバイスと区別するには、「アプリケーション → ユーティリティ → システム情報.app」、または から「この Mac について → システムレポート → ハードウェア → USB」で得られる情報と付き合わせるのが確実です。
続いて、見つけたデバイスファイル名とボーレートを screen
コマンドに渡し、エミュレータを起動します。僕の Mac では、230400
がボーレートの最大でした。
エミュレータから抜けるには CTRL-a
+ k
を入力します。またターミナルの表示がバグったら reset
コマンドで正常に戻せます(理由は後述しますが、ほぼ確実にバグります)。
スケッチのインストールと実行
リアルタイムクロック (RTC) の Periodic Interrupt を流用し、一定時間ごとに画面を更新するサンプルスケッチを用意しました。ここでは手っ取り早く、ライブラリをインストールして実行する方法を示します。
- GitHub のリポジトリ から最新版の .zip ファイルを ダウンロードします。
- Arduino IDE のメニュー「スケッチ → ライブラリのインクルード → .ZIP形式のライブラリをインストール…」からダウンロードした .zip ファイルを読み込ませます。
- 続いて「ファイル → スケッチ例 → PeripheralMonitor → monitor_by_rtc」から、スケッチの サンプル を開きます。
- でコンパイル&アップロードすると、エミュレータに初期画面が表示されます。
画面の説明
全部で5つの画面があります。スケッチの サンプル では、D13
ピンの「ポート mn 端子機能選択レジスタ(PmnPFS)」の画面を表示します。
Arduino IDE のシリアルモニタに ?
か help
を入力すると、使えるコマンドを表示します。超簡単な CLI ですネ。また画面が乱れた時はリターンキーのみの入力で再描画します。
1. PORTS 画面
ports
と入力すると、ポート 1 からポート 4 まで、ポートコントロールレジスタ(PCNTR1 〜 PCNTR4)の中身を 4 桁の 16 進数で表示します。[]
内の数字はビット幅です。
各ポートには、それぞれ 0 〜 15 のビットに対応づけられた、最大で 16 本の I/O 端子(ピン)が割り当てられています。
プログラムではなり振り構わず表示してしまいますが、ユーザーズマニュアル によると、全てのピンが存在するわけではなく、下表のように構成されています。
ポートごとのピンの構成表
ポート | ピン(パッケージ: 64ピン) | 本数 |
---|---|---|
ポート 0 | P000 ~ P004, P010 ~ P015 | 11 |
ポート 1 | P100 ~ P113 | 14 |
ポート 2 | P200, P201, P204 ~ P206, P212 ~ P215 | 9 |
ポート 3 | P300 ~ P304 | 5 |
ポート 4 | P400 ~ P402, P407 ~ P411 | 8 |
ポート 5 | P500 ~ P502 | 3 |
ポート 6 | なし | 0 |
ポート 7 | なし | 0 |
ポート 8 | なし | 0 |
ポート 9 | P914, P915 | 2 |
サンプル画像 では、ポート 1 の PODR
(端子出力データ、0: Low 出力、1: High 出力)と PIDR
(端子状態、0: Low レベル、1: High レベル)がチラチラと変化する様子が見えます。これを次のコマンドで、詳細に確認することが出来ます。
2. PORT 画面
例えば port1
のように、port
に続けて 0 〜 9 を入力すると、各ポートのコントロールレジスタの中身を確認できます。
サンプル画像では、PODR
と PIDR
の3ビット目、即ちピン P102
で、何かが起きていることが確認できます。
3. PmnPFS 画面
例えば p102
のように、p
に続けて 0 〜 9 のポート番号 m
と 00 〜 15 のピン番号 n
を入力すると、ポート mn 端子機能選択レジスタ(PmnPFS)を表示します。
このレジスタは、ポートコントロールレジスタと重複する一部のビット列を含み、入出力の機能を制御するビットフィールドで構成されています。
重複するビットフィールドへのアクセス方法について
例えば P102
の PmnPFS
レジスタの下にあるビットフィールド PODR
に「1」を書き込むコードは、次の2つのパターンが可能です。
一方 PODR
は、ポートコントロールレジスタ PCNTR1
のビットフィールド PODR
とも重複するので、次の方法でも可能です。
上の例の様に、書き込むビットフィールドが1つの場合、敢えて可読性の低い方法を選択するのはナンセンスですが、複数のビットフィールドをまとめて設定する場合、レジスタへのアクセス回数が極力少なくなるよう、複数の方法が提供されています。
詳しくは FSP ユーザーマニュアル の実例を参照してください。
4. PINS 画面
単に pins
と入力すると、ボード上のデジタルピンとアナログピンの PmnPFS
レジスタを一覧表示します。表示上、D10
〜 D13
は Da
〜 Dd
としています。
また逆引きも可能で、例えば d13
を入力すると、Minima では P111
を、WiFi では P102
を表示します。
5. AGT 画面
冒頭に示した AGT レジスタの画面を表示するには、agt0
または agt1
と入力します。
この画面は、「BGM再生用に作成したArduino UNO R4用タイマライブラリの解説」で FspTimer クラス をテストするときに欲しかった機能で、ようやく実現しました
画面表示と実行速度について
画面のカーソル制御に ANSI エスケープコード を使っている関係上、特に Mac では通信が途切れるとシーケンスが乱れ、バグったような状態になります。このような状態になったら、コマンド reset
を入力してください。正常に戻ります。
また、本来は PC 側で curses ライブラリ や GUI ソフトで画面制御すべきを、Arduino ボード側で行っているため、それなりの時間を要します。下の表は、シリアル通信のボーレートと各画面の実行時間を micros()
で計測した結果です。
Baud Rate | PORTS [ms] | PORTx [ms] | PINS [ms] | Pxxx [ms] | AGTx [ms] | Windows | MacOS |
---|---|---|---|---|---|---|---|
115200 |
44.903 | 26.336 | 198.231 | 11.660 | 24.006 | ○ | ○ |
230400 |
23.815 | 13.620 | 105.974 | 6.014 | 12.327 | ○ | ○ |
460800 |
13.248 | 7.255 | 59.804 | 3.187 | 6.486 | ○ | × |
921600 |
7.957 | 4.069 | 36.668 | 1.773 | 3.560 | ○ | × |
数値には文字列の生成と通信の時間を含んでいて、ほぼボーレートと反比例の関係にあることから、通信にかかる時間が支配的であることが分かります。
Blutooth を使えばもう少し速くなるとは思いますが、他のプログラムと組み合わせてデバッグに使える程のリアルタイム性はなく、あくまで学習用というワケです。
周辺回路のレジスタ定義について
以前の記事 で解説したR7FA4M1AB.svd
には、周辺回路のレジスタやアドレスが定義されてますが、プログラミングには R7FA4M1AB.h
が便利です。
このファイルは Arduino 階層の深いところにあります。以下は Mac での例です(1.2.0
はボードマネージャのバージョン)。
これを手作業で見つけ出すのは激ムズです。そんな時、Mac や Linux の人なら次の find
コマンドが便利です。
このコマンドは、以下の様に働きます。
-
.
が示す現在のディレクトリから、-name
で示される.h
ファイルを探し、 -
-exec
〜\;
で囲まれたコマンドを実行し、 -
{}
でファイルへのパスをgrep
に渡し、 -
-w
でワード単位にR_PORT1
を検索し、 -
-print
で検索に引っ掛かったファイルへのパスを出力する。
find
には沢山のオプションがあるので、幾つかを覚えておくと便利ですョ
おまけ
Minima の汎用 I/O 端子レジスタを観察していたら、何やら P204
の状態がフラついているのが観測されました。
ご存知の方も多いと思いますが、Minima の回路図 を見ると、これは基盤裏側の LOVE
ピンですネ。
この LOVE
ピンは Arduino Forum でも取り上げられていて、このピンを GND に落とすだけの、なんちゃってタッチセンサを実験している人がいました。
さらに、とても研究熱心な Delta_G さん が ユーザーズマニュアル を元に作り込んだライブラリもありました。33 分にもなる 解説の YouTube 動画 は勉強になります!
今後の予定は…
何を作るにせよ、割り込みコントローラユニット (ICU) やイベントリンクコントローラ (ELC) がキモになりそうな気がしています。
Arduino IDE のデバッグ機能にある CORTEX PERIPHERALS
は、とても使い勝手が悪いので、作ってみるカモです
ご参考
PeripheralMonitor を作るに当たり、参考にさせて頂いたサイトです。