Linux の USB Gadget シリアル接続を Raspberry pi で使う備忘録です.
動作確認したデバイスとOS
動作することを確認した環境は以下の通りですが,USB Gadget に対応した SBC なら恐らく動くと思います.
- DEVICE: Raspberry pi4
- OS: Raspberry pi OS (64bit)
Raspberry pi OS への書き込みは Raspberry pi OS imager for Linux を使ったのですが,さいきんの ver. だと,Media Player OS の一つとして Volumio とか moOde audio player とかも選べるんですね.なお,導入後の最低限の設定(アップデートなど)については,

辺りをご覧ください.
Linux Gadget USB CDC-ACM の有効化
過ネールモジュール g_serial.ko を読み込んで有効化する方法もあるのですが,今回は将来的に拡張性を持たせるため Multifunction Composite Gadget として有効化します.
まず,行わなければならないのは USB gadget の有効化とカーネルモジュールの読み込みです./boot/config.txt と /etc/modules に以下を追加します.
$ sudo vi /boot/config.txt .... # Enable DWC2 USB Driver dtoverlay=dwc2 .... $ sudo vi /etc/modules # /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. dwc2 libcomposite ....
次に /sys/kernel/config/usb_gadget 以下に USB CDC-ACM の設定を書き込み,有効化します.この部分の詳しい解説は,
やその周辺の資料をご覧ください.なお,今回はこの部分を on.CDC-ACM-gadget というファイル名のシェルスクリプトとしています.
$ sudo vi /usr/local/bin/on.CDC-ACM-gadget #!/bin/sh cd /sys/kernel/config/usb_gadget /usr/bin/mkdir g1 cd g1 /bin/echo 0x1d6b > idVendor /bin/echo 0x0104 > idProduct /usr/bin/mkdir strings/0x409 /bin/echo "23081301"> strings/0x409/serialnumber /bin/echo "Labohyt" > strings/0x409/manufacturer /bin/echo "CDC-ACM Gadget" > strings/0x409/product /usr/bin/mkdir configs/c.1 /usr/bin/mkdir configs/c.1/strings/0x409 /usr/bin/mkdir functions/acm.GS0 /usr/bin/ln -s functions/acm.GS0 configs/c.1/ /usr/bin/ls /sys/class/udc > UDC $ sudo chmod +x /usr/local/bin/on.CDC-ACM-gadget
このシェルスクリプトを実行すれば Raspberry pi OS に /dev/ttyGS0 が現れるはずです.
$ ls -alF /dev/ttyGS0 crw------- 1 hyt tty 236, 0 Aug 14 10:48 /dev/ttyGS0
また,適当なPCとRaspberry pi4のUSB-Cポートを接続すると,Linux Foundation Multifunction Composite Gadget というデバイスが出来ます.なお,PCのOSが Linux の場合は,/dev/ttyACM0 というデバイスが新たに現れるはずです.以下は私の使っている elementary os 7 (ubuntu 22.04) での認識の様子です.
$ lsusb ... Bus 001 Device 046: ID 1d6b:0104 Linux Foundation Multifunction Composite Gadget ... $ ls -alF /dev/ttyACM0 crw-rw---- 1 root dialout 166, 0 8月 14 11:04 /dev/ttyACM0
この段階では単にシリアル通信ができるだけの状態で,Raspberry pi OS のシェルにアクセス(ログイン)はできません.シリアル通信が正常に行えるかどうかを試したい場合は,minicom を Raspberry pi OS 側は /dev/ttyGS0 に接続し,PC側から適当なシリアル通信に対応したターミナル(Windows なら TeraTerem など)を使って接続してみてください.また,詳細については以下をご覧ください.
なお,いくつかの Linux 用のターミナルの使い方のヒントをこの記事の後半に記しています.
agetty の設定
前の節に記したとおり,単に USB CDC-ACM を有効化しただけではシェルにアクセスできません.Linux の場合,ログインプロンプトの表示やシェルの起動は getty 系のプログラムで行われますが,今回はその実装の一つである agetty を使います.
と言っても,実は Raspberry pi OS の場合は,systemd を使ってこれを以下のように簡単に設定できます.
$ sudo systemctl enable [email protected] $ sudo systemctl start [email protected]
ただし,このままだと再起動すると USB CDC-ACM が有効になっていないことから,依存関係のエラーでサービスが起動してきてくれません.このため,再起動したら自動的に USB CDC-ACM が有効化されるよう /etc/rc.local に以下の記述を付け加えます.
$ sudo vi /etc/rc.local ..... /usr/local/bin/on.CDC-ACM-gadget exit 0
よりスマートな方法として,systemd の ExecStartPre の利用も試してみましたが,/etc/ttyGS0 がない場合は ExecStartPre に記したコマンドが実行されないようで,結果的に USB CDC-ACM が自動的に有効になってくれません.仕方ないので rc.local を使っていますが,最初の接続にかなり時間がかかったり,接続はされるがなぜかいつまでたってもプロンプトが出てこなかったりすることがあるので,どなたかより良い方法をご存知の方がおられたらコメントして頂けると助かります.
デフォルトの systemd の設定だと login と password を聞いてきますが,これが面倒な場合は,
$ sudo systemctl edit [email protected] ### Editing /etc/systemd/system/[email protected]/override.conf ### Anything between here and the comment below will become the new contents of the file [Service] ExecStart= ExecStart=-/sbin/agetty --autologin hyt --keep-baud 115200,57600,38400,9600 %I $TERM .....
のようにしてください.なお,systemctl edit についてのわかり易い解説は,
辺りをご覧いただければと思います.また,上を見ると ExeStart の後ろに実行するものを何も記していない行がありますが,このように記さないとなぜかうまく行きません.この部分についてもなぜなのかご存知のかたがおられましたらコメントに記していただければと思います.
Linux でシリアル接続する備忘録
最後に Linux でシリアル接続するときに覚えておかないといけない(覚えておいた方が良い)ことをいくつか記しておきます.
まず,上記の設定をしただけだと,Linux 系の PC から接続するときにルート権限が必要になってしまいます.一般ユーザー権限で接続したい場合は,
$ sudo gpasswd -a $USER dialout
として dialout グループにユーザーを追加する必要があります.
次に Linux でシリアル接続するアプリは調べてみると,
- minicom
- cu
- screen
などがあるようです(Ubuntu だとどれも apt で入ります).このうち,多分最も高機能なのが minicom ですが,使い方に癖があり個人的にはかなり使いにくいです.また,screen も同様です(screen は有名なターミナルマルチプレクサですが,私の場合は tmux に慣れてしまったのでいまさら使い方覚える気はない).ということで,結局 cu を普通は使うことが多いのですが,動作確認などのために,以下簡単な使い方を示しておきます.
minicom
- minicom -s で起動すると設定画面が出てくる
- メニューから Serial port setup を選び /dev/ttyACM0 を入力
- Exit を選びしばらく待つと接続
- 終了したい場合は CTRL + a のあとに z, x の順で選択
### minicom の設定 $ LANG=C minicom -s # minicom の設定メニュー ┌─────[configuration]──────┐ │ Filenames and paths │ │ File transfer protocols │ │ Serial port setup │ │ Modem and dialing │ │ Screen and keyboard │ │ Save setup as dfl │ │ Save setup as.. │ │ Exit │ │ Exit from Minicom │ └──────────────────────────┘ ### minicom の Serial port setup のメニュー ┌───────────────────────────────────────────────────────────────────────┐ │ A - Serial Device : /dev/ttyACM0 │ │ B - Lockfile Location : /var/lock │ │ C - Callin Program : │ │ D - Callout Program : │ │ E - Bps/Par/Bits : 115200 8N1 │ │ F - Hardware Flow Control : Yes │ │ G - Software Flow Control : No │ │ H - RS485 Enable : No │ │ I - RS485 Rts On Send : No │ │ J - RS485 Rts After Send : No │ │ K - RS485 Rx During Tx : No │ │ L - RS485 Terminate Bus : No │ │ M - RS485 Delay Rts Before: 0 │ │ N - RS485 Delay Rts After : 0 │ │ │ │ Change which setting? │ └───────────────────────────────────────────────────────────────────────┘ ### minicom でシリアル接続直後の様子 Welcome to minicom 2.8 OPTIONS: I18n Port /dev/ttyACM0, 11:54:55 Press CTRL-A Z for help on special keys Linux rbp41 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Mon Aug 14 11:33:06 JST 2023 on ttyGS0 hyt@rbp41:~$ ### minicom で CTRL+a のあとに z を入力した様子 ### コピーして適当なターミナルに貼り付けてみてください Welcome to minicom 2.8 ┌───────────────────────────────────────────────────────────────────┐ │ Minicom Command Summary │ OPTIONS: I18n │ │ Port /dev/ttyACM0, 11:54│ Commands can be called by CTRL-A <key> │ │ │ Press CTRL-A Z for help │ Main Functions Other Functions │ │ │ Linux rbp41 6.1.21-v8+ #│ Dialing directory..D run script (Go)....G | Clear Screen.......C │ │ Send files.........S Receive files......R | cOnfigure Minicom..O │ The programs included wi│ comm Parameters....P Add linefeed.......A | Suspend minicom....J │ the exact distribution t│ Capture on/off.....L Hangup.............H | eXit and reset.....X │ individual files in /usr│ send break.........F initialize Modem...M | Quit with no reset.Q │ │ Terminal settings..T run Kermit.........K | Cursor key mode....I │ Debian GNU/Linux comes w│ lineWrap on/off....W local Echo on/off..E | Help screen........Z │ permitted by applicable │ Paste file.........Y Timestamp toggle...N | scroll Back........B │ Last login: Mon Aug 14 1│ Add Carriage Ret...U │ hyt@rbp41:~$ │ │ │ Select function or press Enter for none. │ └───────────────────────────────────────────────────────────────────┘
cu
- cu -s 9600 -l /dev/ttyACM0 で接続できます.
### cu で実際に接続してみた様子 $ cu -s 115200 -l /dev/ttyACM0 Connected. hyt@rbp41:~$
screen
- screen /dev/ttyACM0 9600 で接続できます.
- CTRL + a のあとに k と入力
以上!