コグノスケ


2021年 8月 2日

シンタックス・ハイライト

コードのキーワードハイライトに使っている highlight.js(公式サイトへのリンク)を 11.2.0 にしました。導入したのは 7年も前(2014年 9月 11日の日記参照)ですが、バージョンアップはスムーズにできました。

API に変更があって initHighlightingOnLoad() が deprecated になりました。代わりに highlightAll() を呼べば OK です。ファイル名も微妙に変わっていました。スクリプトは highlight.pack.js から highlight.min.js に、CSS は vs.css から vs.min.css になっていました(Visual Studio スタイルの CSS を使う場合の設定、この他にもスタイルはたくさんあります)。

編集者: すずき(更新: 2021年 8月 5日 13:02)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 3日

udev で PCI デバイスのパーミッションを設定する

PCI デバイスを使った実験をする際にコンフィグ空間やメモリ空間を読み書きしたいときがあります。メモリ空間の読み書き程度ならば、わざわざ PCI デバイスドライバを書かなくても /sys/bus/pci/devices/*/ にある resourceN ファイルにアクセスすれば良いです。

PCI デバイスはコンフィグ空間に BAR (Base Address Register) という 32bit レジスタが 6個あり、メモリ空間を PC 側のアドレスのどこにマッピングするかを指定します。BAR がそのまま resourceN に対応しています。

最近は 64bit アドレスでマッピングするデバイスも多いですが、その際は連続する BAR を 2つ使ってマッピング先のアドレスを指定します。実際に見たほうが早いと思うので、私の使っているマシンのグラフィックカード NVIDIA GeForce GT 1030 を例にしましょう。

lspci で BAR を確認
# lspci | grep VGA

08:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)

# lspci -s 08:00.0 -v

08:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1) (prog-if 00 [VGA controller])
        Subsystem: Micro-Star International Co., Ltd. [MSI] GP108 [GeForce GT 1030]
        Flags: bus master, fast devsel, latency 0, IRQ 84, IOMMU group 14
        Memory at f6000000 (32-bit, non-prefetchable) [size=16M]    ★BAR0: resource0
        Memory at e0000000 (64-bit, prefetchable) [size=256M]       ★BAR1: resource1(64bit アドレス空間なので BAR2 も使われる)
        Memory at f0000000 (64-bit, prefetchable) [size=32M]        ★BAR3: resource3(64bit アドレス空間なので BAR4 も使われる)
        I/O ports at d000 [size=128]                                ★BAR5: resource5
        Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
        Capabilities: [60] Power Management version 3
        Capabilities: [68] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [78] Express Legacy Endpoint, MSI 00
        Capabilities: [100] Virtual Channel
        Capabilities: [128] Power Budgeting <?>
        Capabilities: [420] Advanced Error Reporting
        Capabilities: [600] Vendor Specific Information: ID=0001 Rev=1 Len=024 <?>
        Capabilities: [900] Secondary PCI Express
        Kernel driver in use: nvidia
        Kernel modules: nvidia

デバイスの位置(08:00.0)と、マッピングしているアドレスが BAR0, 1, 3, 5 の 4つ あることがわかります。/sys/bus/pci/devices 経由で PCI デバイスの BAR1 でマップされているメモリを読み出します。

GeForce GT 1030 BAR1 の先頭をダンプ
# cd /sys/bus/pci/devices/0000\:08\:00.0/

# ma -k resource1 dd 0

00000000  ff000020 ff00082c  ff000020 ff00082c
00000010  ff3c0020 ff42082c  ff990020 ffa50027
00000020  ffa10020 ffa10027  ffa50020 ff990027
00000030  ff420020 ff3c0027  ff000020 ff000027
00000040  ff000020 ff000027  ff000020 ff000027
00000050  ff000020 ff000027  ff000020 ff000027
00000060  ff000020 ff000027  ff000020 ff000027
00000070  ff000020 ff000027  ff000020 ff000027
00000080  ff000020 ff000027  ff000020 ff000027
00000090  ff3c0020 ff420027  ffb90020 ffa50027
000000a0  ffa50020 ffb90027  ffa90020 ffa50027
000000b0  ff420020 ff3c0027  ff000020 ff000027
000000c0  ff000020 ff000027  ff000020 ff000027
000000d0  ff000020 ff000027  ff000020 ff000027
000000e0  ff000020 ff000027  ff000020 ff000027
000000f0  ff000020 ff000027  ff000020 ff000027
00000100

読み出しツールは何を使っても構いませんが、サイズがめっちゃでかい(256MB)ので「頭から読む系のツール(hexdump やテキストエディタ)」は使わないほうが無難です。今回は拙作の memaccess(GitHub へのリンク)を使いました。

ちなみに resourceN を読みだそうとすると怒られるときは、NVIDIA のドライバをロードしていないかチェックしてみてください。

NVIDIA のグラフィックドライバをロードしているとき、アンロードしたときの挙動
# ma -k resource0 dd 0

mmap: Invalid argument

# cat /proc/iomem

...
e0000000-fec2ffff : PCI Bus 0000:00
  e0000000-f1ffffff : PCI Bus 0000:08
    e0000000-efffffff : 0000:08:00.0
    f0000000-f1ffffff : 0000:08:00.0
  f6000000-f70fffff : PCI Bus 0000:08
    f6000000-f6ffffff : 0000:08:00.0
      f6000000-f6ffffff : nvidia    ★BAR0 を nvidia ドライバが使用中なので mmap できない
    f7080000-f7083fff : 0000:08:00.1
      f7080000-f7083fff : ICH HD audio
...

# rmmod nvidia_uvm nvidia_drm nvidia_modeset nvidia

# cat /proc/iomem

...
e0000000-fec2ffff : PCI Bus 0000:00
  e0000000-f1ffffff : PCI Bus 0000:08
    e0000000-efffffff : 0000:08:00.0
    f0000000-f1ffffff : 0000:08:00.0
  f6000000-f70fffff : PCI Bus 0000:08
    f6000000-f6ffffff : 0000:08:00.0    ★nvidia ドライバがアンロードされた
    f7080000-f7083fff : 0000:08:00.1
      f7080000-f7083fff : ICH HD audio
...

# ma -k resource0 dd 0

00000000  138000a1 00000000  00000000 bad00200
00000010  bad00200 bad00200  bad00200 bad00200
00000020  bad00200 bad00200  bad00200 bad00200
00000030  bad00200 bad00200  bad00200 bad00200
00000040  bad00200 bad00200  bad00200 bad00200
00000050  bad00200 bad00200  bad00200 bad00200
00000060  bad00200 bad00200  bad00200 bad00200
00000070  bad00200 bad00200  bad00200 bad00200
00000080  0000008f bad00200  bad00200 bad00200
00000090  bad00200 bad00200  bad00200 bad00200
000000a0  bad00200 bad00200  bad00200 bad00200
000000b0  bad00200 bad00200  bad00200 bad00200
000000c0  bad00200 bad00200  bad00200 bad00200
000000d0  bad00200 bad00200  bad00200 bad00200
000000e0  bad00200 bad00200  bad00200 bad00200
000000f0  bad00200 bad00200  bad00200 bad00200
00000100

ドライバが管理しているメモリを横から読み書きされたらたまったもんじゃないですから、この挙動は当然ですね。え?読み出しなら良いのでは?と思われるかもしれませんが、読み出しをトリガーに動作したり、読み出すと値が変化するレジスタなどは珍しくないので、勝手に読み出すのも実はダメなのです。

パーミッション面倒くさい

先ほど /sys/bus/pci/devices 以下のファイルを ls -l などで見た方はお気づきかと思いますが、root しか読めないようなパーミッションになっています。

resourceN のパーミッション設定
# cd /sys/bus/pci/devices/0000\:08\:00.0/

# ls -l resource*

-r--r--r-- 1 root root      4096  8月  2 22:08 resource
-rw------- 1 root root  16777216  8月  2 22:10 resource0
-rw------- 1 root root 268435456  8月  2 22:10 resource1
-rw------- 1 root root 268435456  8月  2 22:10 resource1_wc
-rw------- 1 root root  33554432  8月  2 22:10 resource3
-rw------- 1 root root  33554432  8月  2 22:10 resource3_wc
-rw------- 1 root root       128  8月  2 22:10 resource5

誰でもデバイスのメモリにアクセスできるのはマズいですから、セキュリティ上この設定は真っ当です。真っ当ですが、実験に使うときはいちいち sudo するのが面倒なのも事実です。手動で chmod や chown してパーミッションを変えれば sudo 不要にできますが、いくつか欠点があります。

  • デバイス ID 0000:08:00.0 が常に同じとは限らない(カードの増設、撤去で変動する)
  • PC をリブートすると元に戻ってしまう

どこにいるかわからないデバイスを操作したいときは、udev の出番です。

udev でパーミッションを変える

前置きが長くなりましたが、やっと本題です。/etc/udev/rules.d に 99-hogehoge.rules のようなファイルを作ります。全ての PCI デバイスのパーミッションを全開にする必要はないので、ベンダー ID とデバイス ID で GeForce GT 1030 だけ該当するようにフィルタリングしましょう。

ベンダー ID とデバイス ID の確認(lspci を使う方法)
# lspci -s 08:00.0

08:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)

# lspci -s 08:00.0 -n

08:00.0 0300: 10de:1d01 (rev a1)
              |    `--- Device ID
              `--- Vendor ID

他の条件をフィルタリングに使いたいときは、udevadm info を使うと、vendor や device も含んだ全ての属性を見ることができます。

ベンダー ID とデバイス ID の確認(udevadm info を使う方法)
# udevadm info -a -p /sys/bus/pci/devices/0000:08:00.0 | less

...
  looking at device '/devices/pci0000:00/0000:00:03.1/0000:08:00.0':
    KERNEL=="0000:08:00.0"
    SUBSYSTEM=="pci"
    DRIVER==""
    ATTR{ari_enabled}=="0"
...
    ATTR{revision}=="0xa1"
    ATTR{subsystem_device}=="0x8c98"
    ATTR{subsystem_vendor}=="0x1462"
    ATTR{vendor}=="0x10de"    ★ベンダー ID
...

ID が判明したらルールファイルを書きます。/sys/bus/pci/devices/* のディレクトリと配下のファイル全てに group と other の Read/Write パーミッションを付加します。%p は設定中のデバイスのパスが入る変数です。

udev のルール設定
SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{device}=="0x1d01", RUN+="/bin/chmod -R go+rw /sys%p"

注意点は「RUN はシェルじゃない」ことです。パスの補完、ワイルドカード、パイプ、リダイレクトなどは使えません。私は最初 resource* と書いて「そんなファイルはない」と言われたり、/bin/chmod なのに /usr/bin/chmod と書いていて、何も実行されなくて悩みました(Ubuntu は /usr/bin/chmod だったりするので、さらにややこしいです)。

udev ルールの反映
# udevadm trigger

# cd /sys/bus/pci/devices/0000\:08\:00.0/

# ls -l resource*

-r--rw-rw- 1 root root      4096  8月  2 23:10 resource
-rw-rw-rw- 1 root root  16777216  8月  2 23:10 resource0
-rw-rw-rw- 1 root root 268435456  8月  2 23:10 resource1
-rw-rw-rw- 1 root root 268435456  8月  2 23:10 resource1_wc
-rw-rw-rw- 1 root root  33554432  8月  2 23:10 resource3
-rw-rw-rw- 1 root root  33554432  8月  2 23:10 resource3_wc
-rw-rw-rw- 1 root root       128  8月  2 23:10 resource5

ルールファイルを書いたら設定を反映させると、resourceN ファイルのパーミッションが変わっているはずです。変わっていない場合はおそらくルールの書き方が間違っているので、修正が必要です。

udev ルールのデバッグ

むしろこちらが本題かもしれません。udev の RUN ルールは「シェルじゃない」ので、普段シェル上で使っているコマンドをコピペしてもまず動かないです。間違っている場合は主に 2パターンで、

  • フィルタリングのルールが間違っている
  • RUN の書き方が間違っている

前者に関しては RUN でログを出すとわかります。例えば RUN+="/usr/bin/logger AAAAAAAA" のようにすると、udevadm trigger を実行した後に /var/log/syslog にメッセージが出ます。

ログが出なければフィルタリングの条件を全部削って試してください。それでもログが出なければおそらく logger のパスが間違っています。which logger で出てくるパスと RUN に書いたパスが合っているか確認してください。特に /bin と /usr/bin は間違えやすいです。

後者に関しては RUN に書いたコマンドが失敗すると syslog にエラーが記録されるはずですので、間違ってワイルドカードやパイプなどを書いていないかチェックしてみると良いです。

syslog に記録されるエラーの例
Aug  1 22:56:51 blackbird systemd-udevd[2775846]: 0000:08:00.0: Process '/bin/chmod -R go+rw /sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0*' failed with exit code 1.

ログを見てもすぐにわからないような場合は、地道に「コマンド名だけにして実行されるか?」「引数を 1つずつ足していって動くか?」を確認するのが一番良いです。

編集者: すずき(更新: 2021年 8月 5日 15:02)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 10日

再び挙動のおかしい Kindle Fire HD

目次: Kindle - まとめリンク

第七世代 Kindle Fire HD の挙動がどんどんおかしくなってきています。前にも発生した(2018年 11月 17日の日記参照)、買った本を認識しなくなる病気です。ここのところおかしくなりすぎだぞ?頑張ってくれ Kindle さん。

前回はスクリーンショットを取り損ねたので、今回はスクリーンショット付きでお届けします。

本を買ったことを認識できていない機能としては、

  • ライブラリ
  • 「次の作品」機能


ライブラリ「すべて」だと認識できていない


「次の作品」機能も認識できていない

逆に本を買ったことを認識できている機能としては、

  • ストア
  • ストアのシリーズ買い


ストアは認識できている


ストアのシリーズも認識できている

です。そろそろファクトリリセットの時期なんですかね……?

直せるか?

ファクトリリセットは時間かかって嫌なので、なんとか直せないかなと頑張りましたけど、前回の解決策なども通じずじまいで駄目でした。

  • 「購入」を押す→「問題が発生」
  • 「今すぐ読む」を押す→永遠にダウンロードされない
  • 2018年の解決策 1: シリーズページの「今すぐ読む」(緑色)→永遠にダウンロードされない
  • 2018年の解決策 2: コンテンツ管理サービスアプリのデータを消去→変化なし


購入を試みるとエラー


ダウンロードを試みると永遠に終わらない

となりました。どうやっても「役立たずスキルに……」の3巻を読めません。困ったね。

救世主

Twitter で Kindle の文句ばっかり言ってたせいか、最近 Amazon のサポートデスクの人から Twitter でリプライをいただけることがあります。

たぶん世界中に私のようなヤツが一杯いるんでしょう。中の人も相当お疲れなようで、かなり機械的というか、マニュアルかなんかありそうな対応(最初に FAQ に案内され、それでも駄目だって言うと、サポートデスクチャットを案内される)ですけど……。いやまあ、声掛けていただけるだけありがたいことですよね、うん……。

サポートデスクの人曰く、Amazon のトラブルシューティング(Amazon.co.jp ヘルプ - Kindle 本がライブラリに表示されない)を参考に試してみてほしいとのことでした。こんな内容です。

  • お使いのモバイル端末がインターネットに接続されていることを確認します。
  • Kindle アプリを同期します。
  • Kindle 無料アプリをアップデートします。
  • Whispersync がオンになっていることを確認します。
  • 注文履歴で Kindle での購入が正常に行われたかを確認し、支払方法に問題がないことを確認します。
  • コンテンツと端末の管理を使用して、ご希望の端末に本を配信します。
  • アプリが正しい Amazon アカウントに登録されていることを確認します。複数のアカウントをお持ちの場合は、その本が別のアカウントから購入されている可能性があります。
  • アプリを登録解除して再度登録します。
  • Kindle 無料アプリをアンインストールして再インストールします。この手順では、ライブラリ全体を再度ダウンロードする必要がありますので、最後にお試しください。

上から順に試してみると、6番目の「コンテンツと端末の管理を使用して、ご希望の端末に本を配信します。」が大当たりでした。スゲエ。この手の FAQ 系の手順で直ったことって一切ないんで、これが初めてかも??


本の配信をやり直す方法

未読/既読、どこまで読んだか?情報はキレイさっぱり消えていました。配信したかどうかすら忘れてるんだもん、そりゃそうか。

とまあ、この通り Kindle はいつ何が消えるか予想がつかないため、しおり、位置保存、などの機能は一切信用しませんし、使うこともないですね……。

余談

Amazon サポートデスクの人に「なんで勝手に配信解除されたのでしょうか」って Twitter で聞いたらシカトされました。悲しいよ。

今回に限らないですが、Amazon サポートデスクの人に「どうしたらいいですか?」と聞くと超スピードで答えてくれます(最終奥義は返金です)が、「どうしてこうなるんですか?」って聞くとシカトされる傾向にあります。Amazon は開発部門とサポート部門の距離が遠くて答えを持ってない、機密漏洩等を恐れて意図的に知らせていない、とかかな?

色々事情がありそうなことは察しますが、こちらも人間なのでシカトは辛いよね……。普通に「技術面の質問はわかりません or お答えできかねます」って言ってくれたら「そうなのか〜」で終わりなんだけど。何か過去にモメごとでもあったのかもね?

編集者: すずき(更新: 2021年 12月 24日 00:35)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする




2021年 8月 14日

Facebook の内蔵ブラウザを無効にする方法

Facebook は内蔵ブラウザで、Web サイトへのリンクを開きます。私は Web サイトはブラウザで開いてほしい(タブが残せるし、あとで閲覧履歴を確認することもできる)ので、この挙動はぜひとも無効化したいです。

今まで無効化する方法がわからなくて困っていましたが、今日、設定を頭から試していたら、
[設定] - [メディア] - [リンクを外部で開く]
を ON にすると外部のブラウザで開いてくれることがわかりました。Web サイトってメディアか……?まあやりたいことはできたから良いか。

LINE はわからずじまい

LINE も内蔵ブラウザでリンクを開きます。無効化したいですが、設定にそのような項目が見当たりません。うーん、嫌な挙動ですね。

メモ: 技術系の話は Facebook から転記しておくことにした。

編集者: すずき(更新: 2021年 10月 6日 01:53)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 16日

Debian Testing と Zephyr SDK その 4 - ローカルパッチの仕組みが 0.13 で変わった

目次: Zephyr を調べる - まとめリンク

Zephyr を最新にしたところ SDK のバージョンが古いと怒られてしまいました。

Zephyr SDK 0.13 にアップデートしたところ「Debian Testing には Python 3.8 が無くて GDB が動かない」問題が再発しました。Python 3.9 を使い、不具合を治すパッチを当てないといけません(その 1〜3 を参照)が、以前と同様の方法ではダメなようです。

調べてみると少し仕組みが変わっています。バージョン 0.12 までは Upstream の tarball を参照し、ローカルでパッチを持っていました。バージョン 0.13 は newlib-nano, binutils, gcc, gdb, newlib については GitHub の Zephyr プロジェクト以下にあるフォークされたソースコード(パッチ適用済み)を参照し、tarball を作成するように変更されました。

今まではローカルでパッチを当てる仕組みが動いていたため、パッチファイルを 1つ追加するだけで修正を適用できましたが、0.13 からローカルでパッチを当てる仕組み自体を使わなくなったため、パッチファイルを置いても修正が適用されなくなりました。困った。

解決方法その 1 - 0.12 互換の設定に戻す

バージョン 0.12 以前の設定と同じように sdk-ng/patches/gdb の下にあるパッチファイルを見るようにする方法です。まずローカルパッチ機能を有効にするため、コンフィグを追加します。追加する場所はどこでも良い(順序は特にない)です。私はファイルの最後に追加しています。

ローカルパッチを有効にするためのコンフィグ追加
# sdk-ng/configs/riscv64.config

...

CT_PATCH_BUNDLED_LOCAL=y
CT_LOCAL_PATCH_DIR="${CT_TOP_DIR}/../../patches"

注意点としては GDB のバージョンは 9.2 ですが、パッチのディレクトリ名は tarball の名前に準じて git-xxxxxxxx のようにしなければならないことです。ディレクトリ名を 9.2 にするとパッチが無視されます。例えば今回試した環境では git-76b05e96 だったので、sdk-ng/patches/gdb/git-76b05e96/0007-gdb-fix-python3.9.patch のように置けば良いです。

もし git-xxxxxxxx のバージョンがわからないときは、configs/riscv64.config の CT_GDB_DEVEL_REVISION を見るとリビジョンが書いてありますが、ぶっちゃけ一旦ビルドしてみてビルドログを見た方が早いです。

解決方法その 2 - Crosstool-NG のパッチセットに追加する

動きにややクセがあるもののバージョン 0.13 だとこちらのほうが変更量が少なくスマートです。0.12 でも同じ方法が使えると思いますが、未確認です。

Zephyr SDK の配下にある Crosstool-NG はパッチセットを持っています。パッチセットに追加しておけば初回ビルド時(sdk-ng/share 以下にファイルコピーが行われる)にパッチを持っていってくれます。例えば sdk-ng/crosstool-ng/packages/gdb/git-76b05e96/0007-gdb-fix-python3.9.patch のように置けばよいです。

注意点としては、その 1 同様の点でディレクトリ名(git-xxxxxxxx)に気をつけること、もう 1つあって「コピーのタイミング」にクセがあることです。Crosstool-NG のパッチセットは sdk-ng/share 配下にコピーされますが、これは go.sh の初回実行時しかコピーされません。

パッチファイルを追加するなど、再びコピーを実行してほしい場合 sdk-ng/bin と sdk-ng/share を消してから go.sh を実行すると初回の処理が再実行されるようです。ただ go.sh はヘルプが一切なく、私のやり方が正しいかどうか良くわからないのが欠点です……。

ログを入れたいときの注意点

Crosstool-NG のパッチ当てを行っているスクリプト functions は sdk-ng/crosstool-ng/scripts/functions が元のスクリプトですが、Zephyr SDK のビルドでは初回ビルド実行時に sdk-ng/share/crosstool-ng/scripts/functions にコピーされます。ビルド時はコピーしたスクリプトを実行します。

そのためスクリプトにログなどを入れたい場合、コピーの方(sdk-ng/share/crosstool-ng/scripts/functions)を改変しないと効果がないです。ご注意を。

編集者: すずき(更新: 2021年 8月 17日 00:30)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 18日

HiFive Unmatched の動作周波数

目次: RISC-V - まとめリンク

以前 HiFive Unleashed の動作周波数を調べました(2019年 7月 4日の日記参照)。今回は HiFive Unmatched の動作周波数を調べます。Unmatched に元々書き込んである Linux を起動したあと、PRCI レジスタ領域を見てみました。ダンプすると下記のようになっています。

PRCI レジスタ領域のダンプ
0x10000000:     0xc0000000      0x820544c2      0x00000000      0x820d1180
0x10000010:     0x80000000      0x00000000      0x00000000      0x8206b982
0x10000020:     0x80000000      0x00000000      0x0000006f      0x00000004
0x10000030:     0x00000000      0x00000000      0x030187c1      0x00000000
0x10000040:     0x00000000      0x00000000      0x00000000      0x00000000
0x10000050:     0x82063bc2      0x80000000      0x00000000      0x00000000
0x10000060:     0x00000000      0x00000000      0x00000000      0x00000000

ビット 31 が PLL enable ですので、オフセット 0x4:core_pll, 0xc: ddr_pll, 0x1c: gemgxl_pll, 0x50: hfpclk_pll の設定が有効になっているようです。

いずれの PLL 設定もビットフィールドの意味は同じで、[5:0] divr, [14:6] divf, [17:15] divq です。ビットフィールドが 4bit 境界にないので、Python などで PLL の設定値を表示させると楽だと思います。

SiFive U740 の仕様書(7. Clocking and Reset)を見ると、PLL の出力周波数 fout は
fout = fin / (div_r + 1) * 2 * (div_f + 1) / 2 ^ (div_q)
とのこと。PLL の入力 fin はいずれの PLL も同じで hfclk という 26MHz の外部クロックです。

各 PLL 設定の意味
>> def dump(val):
...     r = val & 0x3f
...     f = (val >> 6) & 0x1ff
...     q = (val >> 15) & 0x7
...     o = 26 / (r + 1) * 2 * (f + 1) / pow(2, q)
...     print("r", r, "f", f, "q", q, "freq", o)

>>> dump(0x820544c2)
r 2 f 275 q 2 freq 1196.0

>>> dump(0x820d1180)
r 0 f 70 q 2 freq 923.0

>>> dump(0x8206b982)
r 2 f 230 q 5 freq 125.12499999999999

>>> dump(0x82063bc2)
r 2 f 239 q 4 freq 260.0

出力結果を見ると core_pll:1196MHz, ddr_pll:923MHz, gemgxl_pll:125.125MHz, hfpclk_pll: 260MHz という設定です。どうしてこの値なのかはわからないですけど、参考になります。

range フィールドの意味

PLL 設定に [20:18] range というフィールドがあるのですが、SiFive の仕様書には説明が書かれていません。クロック周りは Analog Bits という会社の CLN28HPC Wide Range PLL を使っているようですが、PLL の詳細仕様は NDA を結ばないと知ることができません。うーむ、不親切……。

しかし SiFive の人たちは Linux のクロックドライバを作ってくれており、実装から PLL の仕様を窺い知ることができます。ドライバは linux/drivers/clk/analogbits/wrpll-cln28hpc.c にあります。

PLL の range 設定の実装

/**
 * __wrpll_calc_filter_range() - determine PLL loop filter bandwidth
 * @post_divr_freq: input clock rate after the R divider
 *
 * Select the value to be presented to the PLL RANGE input signals, based
 * on the input clock frequency after the post-R-divider @post_divr_freq.
 * This code follows the recommendations in the PLL datasheet for filter
 * range selection.
 *
 * Return: The RANGE value to be presented to the PLL configuration inputs,
 *         or a negative return code upon error.
 */
static int __wrpll_calc_filter_range(unsigned long post_divr_freq)
{
	if (post_divr_freq < MIN_POST_DIVR_FREQ ||
	    post_divr_freq > MAX_POST_DIVR_FREQ) {
		WARN(1, "%s: post-divider reference freq out of range: %lu",
		     __func__, post_divr_freq);
		return -ERANGE;
	}

	switch (post_divr_freq) {
	case 0 ... 10999999:
		return 1;
	case 11000000 ... 17999999:
		return 2;
	case 18000000 ... 29999999:
		return 3;
	case 30000000 ... 49999999:
		return 4;
	case 50000000 ... 79999999:
		return 5;
	case 80000000 ... 129999999:
		return 6;
	}

	return 7;
}

単純に入力を switch 文で見ているだけです。説明を見ると post-R-divider とあるので fin / (divr + 1) の周波数を見て決めれば良さそうですね。この情報を公開していただけるのは非常にありがたいのですが、NDA は大丈夫なんですかね……?大した情報ではないとはいえ、ちょっと心配になってしまいます。

編集者: すずき(更新: 2021年 8月 21日 02:42)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 20日

Zephyr on HiFive Unmatched

目次: Zephyr を調べる - まとめリンク

最近 Zephyr を HiFive Unmatched に移植しています。基本的には Unmatched と Unleashed は似ています。メモリマップなどの大枠の仕様はほぼ同じですが、クロック周りを初めとして仕様が違う部分もあります。今日気づいたのは、

違うところUnmatchedUnleashed
外付けの水晶発振器の周波数26MHz33MHz
ペリフェラルクロックhfpclk_pllcore_pll の 1/2
DDR 領域リセット直後は使えないリセット直後から使える

安易に Unleashed から実装をコピーして楽しようとしたらハマりました……。

ロードする場所

HiFive Unleashed はリセット直後から DDR にアクセスできるかなり変わったボードで、Zephyr は DDR にロードしてしまえば動きました。しかし HiFive Unmatched の DDR は初期化しないと使えないため、Zephyr を DDR にロードする作戦は使えません。代わりとしては、

  • DTIM(Data Tightly-Integrated Memory)
  • L2-LIM(Loosely Integrated Memory)

DTIM はアクセスが一定速度かつ高速(1ワード、2クロック)で、リセット直後から使用可能で、RTOS にとって理想的なメモリ領域ですが、サイズが 8KiB しかありません。Zephyr はデータ領域は 10KB 前後、コード領域は 50KB 超えることもザラで、DTIM にはどうやっても載りません。

Zephyr って RTOS の中では割とデカい部類なのでしょうか?Flash ROM に書き込んで XIP(eXecution In Place)する使い方が前提だから、コード領域のサイズはあまり気にしていないのかもしれませんけど。

L2-LIM は L2 キャッシュが RAM 代わりになる機能です。試してみるとリセット直後から読めますし、サイズも 2MB と十分な大きさです。L2-LIM の弱点は L2 キャッシュの動作モードをキャッシュモードに変更すると、二度と L2-LIM として使えなくなることです。本来の使い方としては DDR を初期化するまでの「一時的なデータ&コード置き場」が役目です。

今のところ Zephyr で高速コアの U74 は動かさないでしょうし、L2 キャッシュを有効にすることはないでしょう。たぶん。L2-LIM に Zephyr のメインメモリ領域として活躍していただくことにしましょう。

編集者: すずき(更新: 2021年 9月 15日 00:02)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 21日

インフラの民営化

上水道を売り払う自治体が出ました(下水道はこれまでもあった)。宮城県、水道3事業の運営権を売却へ 国内で初めて - 日経新聞。過疎地は水道維持費が大赤字と思われるので、速攻で廃止され昔ながらの井戸に戻るでしょう。

井戸=危険ではないですが、井戸の水質は「自己責任」でケチって検査せず使い続ける人達を止められないという点は気になるところです。自治体の基準としても「飲用井戸の衛生確保は、原則として設置者の自己責任」とあります(飲用井戸の衛生管理について - 千葉県より)。

汚染された井戸から疫病が発生、過疎地から都市部に大流行……なんて未来は笑えません。が、昔の日本や今の後進国では起きてた話ですし十分ありえますね。令和は昭和へ回帰する時代かもしれません。国の衰退、生活レベルの低下、衛生面の悪化といった悪い点でね……。

メモ: 技術系?の話は Facebook から転記しておくことにした。

編集者: すずき(更新: 2022年 4月 5日 11:42)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 26日

ワクチン 1回目

自治体の接種会場に行きました。ワクチンはファイザー製でした。

入り口には警備員さんがいましたが、予約システムの予約票は確認されないため「予約してまーす」って言ったら誰でも入れそうでした。が、多少嘘つきが混ざる程度は特に問題ないでしょう。

会場に入れないほど混んだり、1人も来ないなどの事態さえ発生しなければ、別に誰に打ったって良いわけですから。

医療従事者のみなさま

ワクチン接種会場には毎日嫌になるほど人が来ていると思いますが、看護師を始めとした医療従事者の皆様は非常に親切かつ効率的に働いていました。日本の医療は最高だよ、ありがてぇ。

午後だったせいなのか、問診の先生はかなりお疲れモードで、半分目が死んでました。お疲れ様です、無理はしないでください……。

肩が痛い

ワクチンを打った後は、肩こりみたいな痛さ、とか、肩にパンチを食らったような痛さ、と言われてますが、体験したら意味がわかりました。これは痛い……。

編集者: すずき(更新: 2021年 9月 17日 01:55)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 29日

ノート PC でゲームは辛いよ

最近の PC ゲームは画面がとてもキレイですね。シミュレーションゲームなど画質とゲーム性があまり関係ないものであっても、こだわりを感じます。海外レーベルのゲームにリアルな画作りが多い印象です。

画面が美しいのはありがたいですけど、我が家のノート PC に積まれてるディスクリート GPU(Radeon RX 550 Mobile)はあまり性能が高い方ではなく、画質をかなり下げないと「コマ送りかな……??」といわんばかりの描画速度になります。

我が家の重いゲーム、上位三傑

そもそもシミュレーションゲーム好きで、画質や動き重視のゲームは持ってないですが、それでもノート PC には荷が重いゲームたちがいます。

No.1 は The Hunter: Call of the Wild です。画質を上げると景色の描写が非常に美しいです。描画の処理もべらぼうに重いです。我が家の PC では画質をほぼ最低ランクにしても、草むらなどのオブジェクトの多い場所に突っ込むと、画面がガクガクしてライフルの狙いがつけられません。無駄に難易度が上がる……。

不思議なことに七面鳥だけ、動物の大きさの割に描画が異常に遅くて、描画範囲に入った瞬間に画面がガクガクし始めます。直接見なくても居ることだけはわかるエスパーになれます。

No.2 は Dyson Sphere Program です。ダイソン球の浮かぶ宇宙、開発中の惑星の景色が素晴らしくキレイです。ゲームの序盤はノート PC でも何ともないんですけど、ゲームの中盤(別の星系に進出する時期)あたりの惑星状に大量の建築物がある状態だと遅くなります。

ジェットで空高く飛び上がったり、惑星間航行で惑星に着陸するときなど、地表の建物が大量に視界に入ってくると、途端に画面がガクガクしてあらぬ方向に飛んでいきます。どこいくんだー。

No.3 は Assetto Corsa です。車やコースの描写が非常に美しいです。レースゲームは PlayStation 3 あたりで実写と見紛うばかりの画質になりましたが、さらに進化していると思います。ただこのゲーム、最適化を相当頑張っているのか、見た目の綺麗さから想像するより描画の負荷が軽くて驚きます。ロードは遅いけど……。

適当に走るくらいならノート PC でも遊べますが、レースゲームは他のゲームに比較してコマ落ちが致命的ですからね。ノート PC の GPU で遊ぶのは精神衛生上良くないですね。

編集者: すずき(更新: 2022年 5月 26日 02:42)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 8月 31日

開発環境としての HiFive Unmatched

目次: RISC-V - まとめリンク

最近は HiFive Unmatched(HiFive Unleashed も使い勝手はほぼ同じ)を使っていることが多いのですが、このボードは開発環境としてはなかなか魅力的です。素敵なところをいくつか挙げると、

  • USB ケーブル 1本で JTAG と UART が同時に使える(JTAG の箱が要らない)
  • 元々 Linux 用のボードなので、1GHz クラスの RV64IMAC 1コア+RV64GC 4コア、USB、PCIe、GPIO、SPI など重厚なハードが揃っている
  • SoC の仕様書が公開されていて、誰でもアクセスできる

他社のボードもいくつか使いましたけど、USB-JTAG チップ搭載のボードはあまり見かけません。通常は JTAG を使いたいと思ったら、JTAG の箱(私は SEGGER J-LINK EDU を使っています)が必要です。が、HiFive 系のボードは JTAG の箱が不要です。これは地味に嬉しいです。

製品では切り捨てられがちな JTAG

JTAG はベアメタルやブートローダのようなローレベル開発で重宝しますが、製品のボードにはまず搭載されることはないです。理由は単純。JTAG はデバッグ用の機能で、正常動作しているときには全く使わないからです。ボードのコストアップにしかならず、製品用の設計では真っ先に切られる機能です。以前、メーカーに居た時もデバッグ機能はソフトハード関わらず真っ先に切られていました。

利用者目線から見ると、デバッグ機能を切って安くあげるのは大正義です。利用者はまずデバッグ機能なんて使いませんし、デバッグ機能を悪用して機器に侵入するなどの被害を防ぐ効果もあります。

とはいえ開発者目線から見るとデバッグ機能のないボードや SoC は、トラブったとき解析しづらくて困ります……。なので、SoC レベルではデバッグ機能 ON、ボードレベルでは OFF にしておいて、不具合解析の際は特殊な治具を繋いでボードレベルのデバッグ機能を ON にする設計を良く見かけます。

編集者: すずき(更新: 2021年 9月 6日 21:05)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報