RZboard V2L[1]に触れる機会があり、その際に聞かれて操作を促した内容を紹介。あくまで必要に迫られた時の操作に限定しているため、yoctoが具体的にどうのこうのやらDRP-AIの環境整備といったネタには触れていない。
にわかでやるための、ありきたりかつ間違えようの無い操作のみを雑多に記載しているため、後々はこちら[2]のリソースが参考になるかと。
いずれにせよRZ/V2LはDRP-AIが主たる目的で、Linuxはその介添えに過ぎない。OSが動いても余力がある訳ではないので、遊び甲斐は無い。
Yocto Project[4]に目を通すまでも無く、以下の手順を踏めば基本的にブートイメージが生成できる事になっている。
https://github.com/Avnet/meta-rzboard/tree/rzboard_dunfell_5.10_v3[5]
ここではビルド環境としてUbuntu 20.04 LTSを新規でインストールしたPCを使ってみた。なお使い込んだOSだとうまくいかないようで、真っ新な状態でUbuntuをインストールし直せば大抵は解消するようだ。ちなみに最新のUbuntuは以ての外である。
大半の操作はCUI上で行う。まずはUbuntu上へ必要なツール類をインストール。ちなみに「$」はターミナルのプロンプトのつもりなので、入力するものではない。もちろんインターネットに接続している前提。
$ sudo apt install -y gawk wget git-core diffstat unzip texinfo gcc-multilib \ build-essential chrpath socat cpio python3 python3-pip python3-pexpect \ xz-utils debianutils iputils-ping libsdl1.2-dev xterm p7zip-full libyaml-dev \ rsync curl locales bash-completion
次にrenesasから提供されるドライバやライブラリ等の圧縮ファイルを展開するためのスクリプトをダウンロード。
$ cd ~/ $ wget https://raw.githubusercontent.com/Avnet/meta-rzboard/rzboard_dunfell_5.10_v3/tools/create_yocto_rz_src.sh
ダウンロードしたcreate_yocto_rz_src.shに記述されているパッケージだが、renesasのサイトで公開されているものの方が新しい場合がある。2023/10/11現在以下が最新の模様(簡便化のため直リンクご容赦、リンク先はrenesasのアカウントが必要)。適宜create_yocto_rz_src.shを修正。
スクリプトを実行し、更に必要なファイルをgit cloneしたらおもむろにイメージを生成(bitbake)。bitbakeはPCのリソースをフルに使う処理なので、PCは良く冷やす事。今回使ったPCでは夜寝る前に仕掛けて朝起きたら終わっていた感じだが、ここ最近のマルチコアのPCを使っても数時間かかるかと。
$ cd ~ $ bash create_yocto_rz_src.sh $ cd ~/yocto_rzboard/ $ git clone https://github.com/Avnet/meta-rzboard.git -b rzboard_dunfell_5.10_v3 $ mkdir -p ./build/conf $ cp meta-rzboard/conf/rzboard/* build/conf/ $ source poky/oe-init-build-env build/ $ bitbake avnet-core-image
ターミナル上に赤い文字と共にERRORが表示されていなければ、「~/yocto_rzboard/build/tmp/deploy/images/rzboard」の中に成果物が生成されている。avnet-core-image-rzboard-~.wicができていればまずはOK。もしrenesas社から提供されるアーカイブファイルが更新されているのを見かけたら、更新された部分のみcreate_yocto_rz_src.shを修正しスクリプトを実行すれば良い。エラーが出て止まっていた場合はbitbakeを繰り返すことで成功する事が多いが、どうにもならない場合は原因を特定するスキルが無い限り真っさらからやり直した方が早道かも。
これぐらいの数とサイズのファイルが含まれるので、HDDの空き容量には注意。
最後にwicファイルをRZBboard上のeMMCに書き込むのだが、USBシリアルコンバータの準備が面倒だったので、ここではSDカードにイメージを書き込んで済ませた。
Windowsを使ってwicファイルをSDカードに書き込む場合は、Win32 Disk Imager[16]を使えばwicファイルと書き込み先のSDカードのドライブを指定するだけなので簡単。ubuntuを使ってSDカードへ書き込む場合は、bmaptoolを準備をしておくと良いかも(と書いておきながらbmaptoolで書き込んだSDカードは時々起動に失敗するのでダメかも)。
RZBoardをSDカードでブートさせる際はSW1-1とSW1-2は共にOFFで。
以下にこちらでbitmakeした生成ファイル(ディスクイメージ・u-boot)を晒しておく。7zipで圧縮してあるので展開した上で使用する事。ブラウザのダウンロードでは途中で中断したファイルが生成される可能性が高いので、wget等のダウンローダを使う事をお勧めする。
先のavnetが提供する環境は、少しでも欲張ると色々足りない。初めてでもこの程度であれば大事には至らないといった範疇で少し改造してみる。
概ね「~/yocto_rzboard/build/conf/local.conf」のへの追記で対応。Python好いている御仁向けに少しモジュールを追加、Dropbear SSHでは何かと不都合があったのでOpenSSHに入れ替え、timezoneが無いので追加、guiアプリを作ってみたかったのでgtk+3追加、またbmaptool[20]使ってイメージを書き込む際に使われるブロックマップの生成も促す。
IMAGE_INSTALL_append = " python3-pip python3-pyserial python3-numpy python3-psutil python3-pygobject gtk+3" IMAGE_INSTALL_append = " packagegroup-core-ssh-openssh openssh-sftp-server" IMAGE_INSTALL_append = " tzdata" DEFAULT_TIMEZONE = "Asia/Tokyo" IMAGE_FSTYPES += " wic.bmap"
追記したらイメージ生成。
$ cd ~/yocto_rzboard $ source poky/oe-init-build-env build/ $ bitbake avnet-core-image
その他のパッケージ追加も大抵はこの手でOKな事が多い。
日本語のサポートは含まれていないので、日本語を含むファイルの扱いが困難。文字化けする程度であれば無視すれば済むが、日本語を含むファイルの編集となると少々難儀である。GUIを含めて日本語を表示できるようにするにはlocal.confに次を追記してbitbakeする。
IMAGE_LINGUAS ?= "ja-jp ja-jp.euc-jp" GLIBC_GENERATE_LOCALES = "en_GB.UTF-8 en_US.UTF-8 ja_JP.UTF-8 ja_JP.EUC-JP" IMAGE_INSTALL_append = " ttf-vlgothic ttf-sazanami-gothic ttf-sazanami-mincho"
起動したらlocalectlでロケールを設定したら一度再起動。リモートターミナルの文字コードがUTF-8になってさえいれば、Linuxが再起動した後から一部コマンドのヘルプが日本語化され、UTF-8で記述されたファイルの編集や閲覧が文字化けしなくなる。
$ export LC_ALL=ja_JP.UTF-8 $ localectl set-locale LANG=ja_JP.UTF-8 $ reboot
weston-terminalも日本語表示に対応する。
USB機器のデバイスドライバ絡みであれば、menuconfigで済む場合が多い。
$ cd ~/yocto_rzboard $ source poky/oe-init-build-env build/ $ bitbake -c menuconfig linux-renesas
編集が終わったら「.config」として保存。
再びイメージ生成。大して時間はかからない。
$ bitbake -c savedefconfig linux-renesas $ bitbake avnet-core-image
menuconfigするのに何か足りなければ追加しておく。
$ sudo apt install tmux libevent-dev ncurse-*
デフォルトでは必要最低限程度のサイズでイメージが生成されるため、残りのSDカードの容量は未使用状態である。Hardware User Guide[26]の12.3に記載されている操作を行えば、SDカードの最大サイズまで拡張できる。なお態々debug connectorを経由して操作する必要は無い。
root@rzboard:~# df -h ファイルシス サイズ 使用 残り 使用% マウント位置 /dev/root 3.5G 2.8G 468M 86% / devtmpfs 426M 4.0K 426M 1% /dev tmpfs 651M 0 651M 0% /dev/shm tmpfs 651M 9.9M 641M 2% /run tmpfs 651M 0 651M 0% /sys/fs/cgroup tmpfs 651M 0 651M 0% /tmp tmpfs 651M 24K 651M 1% /var/volatile /dev/mmcblk0p1 100M 22M 78M 22% /boot tmpfs 131M 0 131M 0% /run/user/0 root@rzboard:~# fdisk /dev/mmcblk0 fdisk (util-linux 2.35.1) へようこそ。 ここで設定した内容は、書き込みコマンドを実行するまでメモリのみに保持されます。 書き込みコマンドを使用する際は、注意して実行してください。 コマンド (m でヘルプ): p ディスク /dev/mmcblk0: 29.74 GiB, 31914983424 バイト, 62333952 セクタ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0xcb176a81 デバイス 起動 開始位置 終了位置 セクタ サイズ Id タイプ /dev/mmcblk0p1 * 32 204831 204800 100M c W95 FAT32 (LBA) /dev/mmcblk0p2 204832 7824703 7619872 3.6G 83 Linux コマンド (m でヘルプ): d パーティション番号 (1,2, 既定値 2): 2 パーティション 2 を削除しました。 コマンド (m でヘルプ): n パーティションタイプ p 基本パーティション (1 primary, 0 extended, 3 free) e 拡張領域 (論理パーティションが入ります) 選択 (既定値 p): p パーティション番号 (2-4, 既定値 2): 2 最初のセクタ (204832-62333951, 既定値 206848): 204832 最終セクタ, +/-セクタ番号 または +/-サイズ{K,M,G,T,P} (204832-62333951, 既定値 62333951): 新しいパーティション 2 をタイプ Linux、サイズ 29.6 GiB で作成しました。 パーティション #2 には ext4 署名が書き込まれています。 署名を削除しますか? [Y]es/[N]o: N コマンド (m でヘルプ): w パーティション情報が変更されました。 ディスクを同期しています。 root@rzboard:~# resize2fs /dev/mmcblk0p2 resize2fs 1.45.7 (28-Jan-2021) Filesystem at /d[ 662.106753] EXT4-fs (mmcblk0p2): resizing filesystem from 952484 to 7766140 blocks ev/mmcblk0p2 is [ 662.115758] EXT4-fs (mmcblk0p2): resizing filesystem from 952484 to 7766016 blocks mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 4 [ 664.033021] EXT4-fs (mmcblk0p2): resized filesystem to 7766016 The filesystem on /dev/mmcblk0p2 is now 7766140 (4k) blocks long. root@rzboard:~#
UARTのデバッグポート(J19)を使わずに全ての操作を完結させることができないので、手持ちのUSBシリアル変換モジュール[28]を使用。通信にかかる3つの端子は配列が一致しているので、適当なメスピンヘッダをモジュールにハンダしてJ19に装着。
デフォルトでは「/boot/uEnv.txt」の記載内容が少ないので追記。特にmacアドレス(ethaddr)を設定しないままだと起動の度にランダムな値になり、それに伴いルーターからのIPアドレスの割り当てがコロコロ変わって少し面倒。
fdtfile=rzboard.dtb enable_overlay_cm33=1 enable_overlay_disp=hdmi enable_overlay_uart2=yes enable_overlay_i2c=yes enable_overlay_gpio=yes enable_overlay_adc=yes enable_overlay_audio=yes #fdt_extra_overlays=rzboard-mipi-ph720128t003.dtbo #fdt_extra_overlays=1.dtbo 2.dtbo 3.dtbo ethaddr=AA:BB:CC:DD:EE:FF
westonにはターミナルしか登録されていないので寂しいが、gui絡みのアプリケーションを実行した際の出力先になる。「/etc/xdg/weston/weston.ini」に以下を追記しておくと良い場合は設定すべし。
[output] name=HDMI-A-1 mode=1280x720@60 #mode=1920x1080@60 [keyboard] keymap_rules=evdev keymap_layout=jp vt-switching=true
westonを再起動
$ systemctl restart weston@root
[launcher]とか追加すると多少は使い物になるかなと。
現状では上記設定にかかわらず最近の高解像度のモニターでは表示されないことが多いので、解像度はさほど高くなく複数入力の無いインテリでないものを使うことをお勧めする。
またOSが立ち上がる途中でHDMIケーブルを後差しすると表示されなかったり、後差ししないと表示されない等など人によって違うことを言われるが、調べがついていないので正直なところ良くわからない。
WiFiを使うのであればLinux Yocto User Manual[30]の3.11に記載されている操作ではなく、ConnManを使うのが簡単。レシピではConnManのサービス化を止められていたので、まずは起動(以後定期的にスキャンが発動し、その都度シリアルポートにログを吐くようになるので注意)。
$ systemctl enable connman $ systemctl start connman
次にconnmanctlをインタラクティブモードで操作。
$ connmanctl connmanctl> enable wifi #WiFiをイネーブル Enabled wifi connmanctl> scan wifi #周辺のWiFiルータを検索 Scan completed for wifi connmanctl> services #検索結果を表示 .... * AR MyWiFiSSID wifi_abcdabcdabcd_aabbccddeeffaa_managed_psk .... connmanctl> agent on #エージェントを登録 Agent registered connmanctl> connect wifi_abcdabcdabcd_aabbccddeeffaa_managed_psk #検索結果のHASH値を使ってWiFiルータへつなぐ Agent RequestInput wifi_abcdabcdabcd_aabbccddeeffaa_managed_psk Passphrase = [ Type=psk, Requirement=mandatory, Alternates=[ WPS ] ] WPS = [ Type=wpspin, Requirement=alternate ] Passphrase? PASSPHRASE #WiFiルータの暗号化キーを入力 Connected wifi_abcdabcdabcd_aabbccddeeffaa_managed_psk connmanctl> quit #ひとまず終了
駆け足だがこれでつながっているので、ifconfig等で確認。
自動接続については、検索結果にあるWiFiルータのSSIDとHASH値を元に、/var/lib/connman/MyWiFiSSID-psk.configの名前で次のファイルを作成。MyWiFiSSID・HASH値・PASSPHRASEは適宜変更の事。
[service_wifi_abcdabcdabcd_aabbccddeeffaa_managed_psk] Type = wifi Name = MyWiFiSSID Passphrase = PASSPHRASE AutoConnect = True
RZBoardを再起動した際にIPアドレスが割り当てられていれば成功。WiFiに限らずBluetoothや有線LANにも使え、IPアドレスを固定させることも可。
Windowsが必要とされているのはeMMCへイメージを書き込む時以外に無いのだが、リモートクライアントとしてなら使い道はある。その際はsshクライアントのPuTTY[32]を使えば便利。
リモートログインするなら
putty.exe -ssh -pw avnet root@rzboard:22
相互のファイル転送には同梱のpscpが使える。次のようなバッチを作っておくとコマンドライン上でのファイルコピーがお気楽(毎回ログインしに行くため遅い)。
@rem win to rzboard @pscp.exe -scp -unsafe -pw avnet %1 root@rzboard:%2
@rem rzboard to win @pscp.exe -scp -unsafe -pw avnet root@rzboard:%1 %2
もっと横着するならguiベースのsftpクライアントを使えば良い。以下の3つをインストールすればWindowsのドライブとしてrzboardをマウントできる。
マウントしたドライブ上のファイルを特定のツールで開こうとしてもドライブが見えなかったり、エディタ等で直接見に行くと時折待たされることがあるが、概ね許容範囲かと思う。
DHCPで割り当てられたRZBoardのIPアドレスが分からないからシリアルターミナルをつないでいるというのであれば、先の通り「rzboard」の名前で見つかる筈。逆にRZBoardからWindows PCや他のLinux PCの場合は「名前.local」で届く。
$ ping winpc.local -c 4 PING winpc.local (192.168.11.15): 56 data bytes 64 bytes from 192.168.11.15: seq=0 ttl=128 time=380.467 ms 64 bytes from 192.168.11.15: seq=1 ttl=128 time=148.134 ms 64 bytes from 192.168.11.15: seq=2 ttl=128 time=18.441 ms 64 bytes from 192.168.11.15: seq=3 ttl=128 time=41.408 ms --- winpc.local ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max = 18.441/147.112/380.467 ms $
HATの電源ボタンを押してもRZBoardの電源が入らない。PMICの詳細が公開されていないので不確かだが、ブロック図から推察してPMICにボタン入力が無いとレギュレータが生きず、DXHATのKILLが解放されないのだろう。
その後RZBoardのS1を押しながらHAT側の電源ボタンを押すと電源が入り、またS1を押しっぱなしでも電源が切れることは無い事がわかった。
S1の押下状態を維持するように短絡しておけば、HATの電源ボタンのみで電源供給のON/OFFは完結する。
なおDXHATの電源ボタンによるOSのシャットダウン励起は、憶測で色々試しすぎてRZBoardのGPIOが壊れてしまったようなのでペンディング。
RZBoard側にプルアップ抵抗が装備されていないようで、HAT上のI2CバスリピータのAサイドが正常に機能しない。
こちらも改造して良いのであれば、RZBoardのJ1-3(SDA1)とJ1-5(SCL1)をそれぞれ適当な値の抵抗を介してJ1-1(3V3)へ接続。
なおHATには電源バックアップされたRTCが載っているのだが、RZBoardのPMICにもRTCが装備されているようなのと、ドライバやレシピ云々の話になるのでひとまず放置。I2Cで直接アクセスして遊ぶ分には問題ない。
半二重I/FにSCIF2をつなぐには以下の箇所を半田ジャンパする。
Dynamixel Libraryについては、該当ポートを"/dev/ttySC2"に読み替えた上でDXHATのドキュメント[41]の操作が一通り使える。
なおDynamixel Libraryのソースには日本語が含まれているので、先の日本語化対応しておかないと文字化けし、エディタで閲覧や編集が困難。
また通信速度を変えて試したところ、ボーレートジェネレータの分解能のせいか、1Mbps以上のボーレートは3M/1.5M/1Mbpsでのみ一致し、3Mbpsでは挙動が一部不審、3Mbpsを超えることはできなかった。
GPIOが活性化していれば回せる。
#!/bin/bash echo 193 > /sys/class/gpio/export echo out > /sys/class/gpio/P9_1/direction echo 1 > /sys/class/gpio/P9_1/value
しかしRaspberry Pi程の発熱がある訳でも無いのに、ビュービュー言わせながらファンを回し続ける意味は無い。以下のように温度を取得しそれに応じてファンを微風で回すプログラムをあてがえば十分。デーモンに登録して自動起動させれば良いだろう。
#include <stdio.h> #include <stdbool.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> int fd_temp = -1; int fd_fan = -1; int fd_pb = -1; int fd_shut = -1; volatile sig_atomic_t term = 0; void handler (int sig, siginfo_t *info, void *ctx) { term = 1; } bool init (void) { int f, ff; // GPIOO9 (OUT) if ((f = open ("/sys/class/gpio/export", O_WRONLY)) == -1) { perror ("Unable to config GPIO9"); return false; } else { write (f, "193", 3); close (f); if ((ff = open ("/sys/class/gpio/P9_1/direction", O_WRONLY)) == -1) { perror ("Unable to config GPIO9"); return false; } else { write (ff, "out", 3); close (ff); if ((fd_fan = open ("/sys/class/gpio/P9_1/value", O_WRONLY)) == -1) { perror ("Unable to config GPIO9"); return false; } } } // GPIO48 (IN) if ((f = open ("/sys/class/gpio/export", O_WRONLY)) == -1) { perror ("Unable to config GPIO48"); return false; } else { write (f, "507", 3); close (f); if ((ff = open ("/sys/class/gpio/P48_3/direction", O_WRONLY)) == -1) { perror ("Unable to config GPIO48"); return false; } else { write (ff, "in", 2); close (ff); if ((fd_pb = open ("/sys/class/gpio/P48_3/value", O_RDONLY)) == -1) { perror ("Unable to config GPIO48"); return false; } } } // GPIO12 (OUT) if ((f = open ("/sys/class/gpio/export", O_WRONLY)) == -1) { perror ("Unable to open GPIO12"); return false; } else { write (f, "216", 3); close (f); if ((ff = open ("/sys/class/gpio/P12_0/direction", O_WRONLY)) == -1) { perror ("Unable to open GPIO12"); return false; } else { write (ff, "out", 3); close (ff); if ((fd_shut = open ("/sys/class/gpio/P12_0/value", O_WRONLY)) == -1) { perror ("Unable to open GPIO12"); return false; } } } // Temperatrue if ((fd_temp = open ("/sys/class/thermal/thermal_zone0/temp", O_RDONLY)) == -1) { perror ("Unable to open temp"); return false; } return true; } double get_temp (void) { char s[20]; lseek(fd_temp, 0, SEEK_SET); if (read (fd_temp, &s, sizeof(s)) > 0) { int t; sscanf (s, "%d", &t); fsync (fd_temp); return t / 1000.0; } return 999; } void set_fan (bool b) { write (fd_fan, b ? "1" : "0", 1); } bool get_pb (void) { char c; lseek(fd_pb, 0, SEEK_SET); read (fd_pb, &c, 1); return (c == '0'); } void set_shut (bool b) { write (fd_pb, b ? "1" : "0", 1); } int main (void) { double t; int cnt = 0, duty = 1; struct sigaction act; act.sa_sigaction = handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, NULL) < 0) { return 1; } act.sa_sigaction = handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGTERM, &act, NULL) < 0) { return 1; } if (init ()) { while (!term) { t = get_temp (); if (get_pb ()) duty = 10; else if (t > 55) duty = 10; else if (t > 50) duty = 6; else if (t > 45) duty = 4; else duty = 1; for (int i = 0; i < 10; i++) { set_fan (duty >= cnt); cnt++; if (cnt > 10) cnt = 0; usleep (5000); } } set_fan (0); close (fd_temp); close (fd_fan); close (fd_pb); close (fd_shut); return 0; } return 1; }
調子が良ければ概ね20秒程度でwestonの起動まで行きつく。ひとまずシンプルなアプリケーションがどの程度動くかを見るために、手持ちのRealSenseとシリアルサーボモータをつないで動かしてみたときの画面をキャプチャしてみた。
動画の最後、Power down後のpanicは横着してブートローダを更新しなかったからに他ならず。bitbakeした時に生成されたブートローダのイメージファイルをQSPIに書き込み、ようやく事なきを得る。ちなみにSDカードでブートする設定ではu-bootのsaveenvが失敗するため、環境変数やら設定等を覚えてくれることはない。
またブートローダ更新のついでにeMMCにもLinuxのイメージを書き込もうとしたところ、とてつもなく時間がかかる。ドキュメントにある操作中の画面のキャプチャでは114684KBの転送に15秒とあるので、その20倍以上かかる状況は何かおかしい。書き込み用のバッチを動かしていたPCをWiFiにつなげていた事が原因。有線に切り替える事で解消。
更にubuntuをホストPCとしているなら、シリアルターミナルのためだけにWindowsのTeraTermを引っ張り出してくる必要はない。そのPCにUSBシリアルI/Fをつないでターミナルにすれば良いまで。
$ screen /dev/ttyUSB0 115200,cs8
他に気づいたこととして、UARTから吐かれるログのタイミングからして極端に動作が遅い時がある。何に依存しているのか調べていないが、電源ON直後からDDRのクロック周波数が落ちている挙動に見受けられる。
J18/J20は使わないと勿体ない機能が含まれている。ヘッダは2-2367197-8[44]なので、ハウジングの2-2367198-8[45]を使って外線つなぐべし。
(This host) = https://www.besttechnology.co.jp