Raspberry Pi Pico でシリアル通信: "hello, world" を贈る
Raspberry Pi Pico (以下 Pico) は UART (Universal Asynchronous Receiver/Transmitter) によるシリアル通信が可能です。今回も例によって『インターフェース』誌 2023 年 7 月号のサンプルプログラムを使わせていただき、シリアル通信を試してみます。
目次
使用する機材
今回は第 2 回の記事で列挙した機材をすべて使用します。
Raspberry Pi Pico H
Debug Probe
今回は GDB によるデバッグは行いませんが、Debug Probe に搭載されている UART-USB 変換器を使ってパソコンに接続します。
ブレッドボード
必須ではありませんが、あれば簡単に Pico の UART と Debug Probe を接続することができます。E-CALL ENTERPRISE 社の EIC-801 あたりが Pico にはちょうどいいサイズです。
Pico への給電用 USB ケーブル
接続は図 1 のようになります。ブレッドボードがよくわからないという方は取りあえず EIC-801 を買ってきて、Pico の 1 番ピン (BOOTSEL ボタンや LED があるあたりに「1」とシルク印刷されているピン) が「5-c」の穴に来るように Pico を挿してください。そして Debug Probe に付属の UART 通信用ジャンパケーブル (オス) の黄色線を「5-a」、橙色線を「6-a」、黒色線を「7-a」の穴にそれぞれ挿してください。この配線の意味については「Pico の UART」の節と「おまけ」の節を参照してください。
サンプルプログラムについて
今回使用するサンプルプログラムは『インターフェース』誌 2023 年 7 月号 pp.58-59 に掲載されている hello,world プログラムです。前回まで使用した L チカプログラムとほぼ同じですが、チカチカを開始する前に Pico の UART を使用して相手局に「hello,world」を送信します。GitHub で公開されているので clone してきてください。その中の part_2/sect_4 ディレクトリに今回使うサンプルコードが収められています。
% git clone https://github.com/ytoyoyama/interface_trykernel.git
% ls interface_trykernel/part_2/sect_4/
application/ boot/ include/ kernel/ linker/
サンプルプログラムのシリアル通信設定は、表 1 のように固定されています。
項目 | 設定値 |
---|---|
ボーレート1) | 115200 |
データビット | 8 bit |
パリティ | なし |
ストップビット | 1 bit |
フロー制御 | なし |
余談ですが、「ボーレート (単位: baud)」と「ビットレート (単位: bps)」は同義に使われがちですが別物だそうです。
- ボーレート = 1 秒間の変調回数
- ビットレート = 1 秒間に伝送するビット数
シリアル通信では 1 baud = 1 bps になるため、両者が一致します。参考 URL:
- ボーレート(baudrate)と転送速度(bps)https://kei-sakaki.jp/2008/04/06/baudrate-and-bps/
Pico の UART
Pico の UART には UART0、UART1 の 2 チャンネルがあり、デフォルトで利用可能なのは UART0 です。UART0 の送信線 (UART0 TX) は 1 番ピン、受信線 (UART0 RX) は 2 番ピンからそれぞれ取り出せます ([1] Chapter 1 参照)。また、信号の基準電圧となる GND がすぐとなりの 3 番ピンに用意されています。よってこの 1~3 番のピンを使って通信を行います。
UART のレジスタ設定
Pico の、というよりも Pico に搭載されているマイコン RP2040 の UART0 関連レジスタは 0x40034000~ の番地に存在します ([2] 4.2.8 節)。当該ソースコードは kernel/syslib.c のtm_com_init
関数です。
UART0 CR レジスタ (syslib.c 14 行目)
主に UART0 のチャンネル自体に関する設定を行っています。EN ビット (bit0) を立てて UART0 そのものを有効にし、TXE (bit1)、RXE (bit2) を立てて送受信をともに可能としています。また、RTSEN (bit14)、CTSEN (bit15) を 0 にすることでハードウェアフロー制御を無効にしています。
UART0 LCR_H レジスタ (syslib.c 13 行目)
表 1 に基づいてシリアル通信設定を行っています。
- PEN (bit1) = 0 でパリティなし
- STP2 (bit3) = 0 でストップビット 1
- FEN (bit4) = 1 で FIFO (送信用、受信用のバッファ) 有効
- WLEN (bit5,6) = 3 でデータビット 8
UART0 IBRD、FBRD レジスタ (syslib.c 11、12 行目)
ボーレートが 115200 となるように設定している部分ですが、ここにセットする値の計算はちょっと厄介です。詳細は [2] 4.2.3.2.1 節および 4.2.7.1 節を参照してください。それによればボーレートはちょうど 115200 とはならずに 115207 となり、誤差は約 0.006 % となります。UART での 2 局間の相対的な許容誤差は 4% 程度とのことなので (下記 URL 参照)、1 局分を 2% としても十分小さいといえるのではないでしょうか (たぶん…)。
- FAQ 1007024 : ボーレート誤差https://ja.na4.teamsupport.com/knowledgeBase/17793983
Makefile を書く
第 2 回の記事で作った L チカ用の Makefile をちょっと変更します。PRGNAME
を hello に変更、ソースが置かれているディレクトリを ../../part_2/sect_4 に変更、vpath
に kernel ディレクトリを追加、の 3 ヵ所です。
--- ../sect_3/Makefile 2023-10-20 11:53:24.662084000 +0900
+++ Makefile 2023-10-27 22:51:11.180798000 +0900
@@ -1,10 +1,10 @@
-PRGNAME := blink
+PRGNAME := hello
ARCH = arm-none-eabi
LIBAEABI := 0
-SRCROOTDIR := ../../part_2/sect_3
-vpath %.c $(SRCROOTDIR)/application:$(SRCROOTDIR)/boot
+SRCROOTDIR := ../../part_2/sect_4
+vpath %.c $(SRCROOTDIR)/application:$(SRCROOTDIR)/boot:$(SRCROOTDIR)/kernel
TOOLDIR := ../tools
BLDDIR := ./build
EXEFILE = $(BLDDIR)/$(PRGNAME)
sect_4 ディレクトリに Makefile を追加したことで、~/pico/repo/interface_trykernel/ 以下のディレクトリは次のようになりました (前回以前の分も含む)。★印は私が追加したディレクトリとファイルです。
% tree ~/pico/repo/interface_trykernel/
~/pico/repo/interface_trykernel/
├── build_part2 ★
│ ├── libs ★
│ │ └── libaeabi-cortexm0.a ★
│ ├── sect_3 ★
│ │ └── Makefile ★
│ ├── sect_4 ★
│ │ └── Makefile ★
│ └── tools ★
│ ├── elf2uf2 ★
│ └── picowrite.sh ★
├── part_2
│ ├── sect_3
│ └── sect_4
...
この Makefile と picowrite.sh は GitHub でも公開しています。
あとはこれまでと同様に、ビルドしてフラッシュメモリに書き込みます。
% cd ~/pico/repo/interface_trykernel/part_2/sect_4/
% gmake
# ../tools/picowrite.sh build/hello.uf2
cu コマンドを使って通信確認する
話を簡単にするために、書き込み完了後 Pico および Debug Probe の USB ケーブルを抜いてパソコンから切り離した状態になっているとします。ここから動作確認を始めましょう。まず UART で通信可能な状態にします。Debug Probe の USB ケーブルをパソコンに挿し、端末エミュレータを新しく開いてシリアル通信ソフトを起動します。FreeBSD では標準で cu コマンドが利用できます。
# cu -s 115200 -l /dev/cuaU0
Connected
-s
オプションでボーレートを指定します。パリティビットはデフォルトで「なし」です。データビットは 8、ストップビットは 1 で固定のようです (マニュアルに記載なし)。cuaU0 の部分は環境によって変わるかもしれません。とはいえ Debug Probe のように USB シリアル変換器で接続する場合は、たいてい cuaU0 や cuaU1 になると思います。ちなみに今回は GDB によるデバッグを行うわけではないので、OpenOCD は起動しておかなくても大丈夫です。
これで受信の準備ができたので、Pico の USB ケーブルを挿して電源を入れてみます。「hello,world」と表示されて Pico の LED が点滅を開始すれば成功です。
# cu -s 115200 -l /dev/cuaU0
Connected
hello,world
よさそうですね、Pico からのメッセージをたしかに受け取ることができました。シェルに戻るには「~.
」 (チルダとピリオド) を入力します。
おまけ: ブレッドボード覚え書き
電子工作に慣れていないもので、ここにブレッドボードの初歩を書きとめておきます。無用の方は読み飛ばしてください。
ブレッドボードは形状も大きさもさまざまなものが売っていますが、本稿でおすすめした EIC-801 は図 2 のような概形をしています (ポンチ絵なので細部は正確ではありません)。
- 縦に見たときに、30 行 (1 ~ 30) × 10 列 (a ~ j) = 300 個の穴 (ソケット) があり、各行の a ~ e と f ~ j はそれぞれ電気的につながっています (緑で描いたライン)。図 1 の例では黄色のジャンパ線を「5-a」の位置に挿しましたが、「5-b」でも (物理的には厳しいものの、理屈のうえでは「5-d」や「5-e」でも) いいわけです。
- その両脇は電源供給用のラインで、プラス側、マイナス側それぞれ縦方向に電気的につながっています (赤、青で描いたライン)。※ 今回は USB から給電するので、このラインは使いません。
- a ~ e 列の島と f ~ j 列の島の間には溝が切られていて、両者は電気的にも切断されています。
- ブレッドボードにマイコンボードを挿すときには、必ずこの溝をまたぐように挿します (図 3)。じゃないと基板の両端のピンどうしが接続されて短絡してしまいます (まあこのサイズなら溝をまたがないように挿そうと思っても挿せませんけど…)。
参考資料
[1] | Raspberry Pi Pico データシート https://datasheets.raspberrypi.com/pico/pico-datasheet.pdf |
[2] | RP2040 データシート https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf |
広告