目次: Zephyr
以前、RISC-V QEMUの -machine virtで、シリアルドライバ16550を使う設定を作りましたが、Zephyr 2.3.0で動かなくなってしまいました。悲しい。
変更点はレジスタアドレスシフト量の設定方法です。DT_NS16550_REG_SHIFTで設定する方式でしたが、デバイスツリーから設定するように変更されました。
commit 70a0063b69b06812c5726077646cffae3b8e199c Author: Kumar Gala <kumar.gala@linaro.org> Date: Fri Mar 27 06:03:59 2020 -0500 drivers: serial: uart_ns16550: Convert to new DT_INST macros Convert older DT_INST_ macro use the new include/devicetree.h DT_INST macro APIs. Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
// zephyr/drivers/serial/uart_ns16550.c
-#ifdef DT_INST_0_NS16550_REG_SHIFT
-#define UART_REG_ADDR_INTERVAL (1<<DT_INST_0_NS16550_REG_SHIFT)
+#if DT_INST_NODE_HAS_PROP(0, reg_shift)
+#define UART_REG_ADDR_INTERVAL (1<<DT_INST_PROP(0, reg_shift))
#endif
デバイスツリーに何を書けば良いのかは、デバイスツリーのドキュメント(ns16550.yaml)を見ましょう。プロパティ名と説明が書いてあります。
// zephyr/dts/bindings/serial/ns16550.yaml
properties:
reg:
required: true
reg-shift:
type: int
required: false
description: quantity to shift the register offsets by
// zephyr/dts/riscv/riscv32-virt.dtsi
...
uart0: serial@10000000 {
compatible = "ns16550";
reg = <0x10000000 0x100>;
clock-frequency = <3686400>;
label = "uart_0";
current-speed = <115200>;
reg-shift = <0>; /* ★これを追加★ */
};
// zephyr/soc/riscv/riscv-privilege/rv32-virt/soc.h
...
/* ★★下記定義は全て不要★★ */
#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_INST_0_NS16550_BASE_ADDRESS
#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_INST_0_NS16550_CURRENT_SPEED
#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_INST_0_NS16550_CLOCK_FREQUENCY
#define DT_UART_NS16550_PORT_0_NAME DT_INST_0_NS16550_LABEL
#define DT_NS16550_REG_SHIFT 0
以上の修正を入れて動かします。
$ qemu-system-riscv32 -nographic -machine virt -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf -bios none
*** Booting Zephyr OS build zephyr-v2.3.0-2350-g2f294fcc2da8 ***
Hello World! QEMU RV32 virt board
動きました。良かった良かった。
目次: Zephyr
Zephyr 2.3.0にバージョンアップしたところ、またHogeボードのビルドが通らなくなりました。
一点目はUARTドライバのCMakeListsです。zephyr_library_sources_if_kconfig() がなくなったため、書き方が変わりました。
commit 244f826e3c7333bb92fb53a65c50ee5cbd8a2ea0 Author: Carles Cufi <carles.cufi@nordicsemi.no> Date: Fri Jul 31 13:52:40 2020 +0200 cmake: remove _if_kconfig() functions This set of functions seem to be there just because of historical reasons, stemming from Kbuild. They are non-obvious and prone to errors, so remove them in favor of the `_ifdef()` ones with an explicit `CONFIG_` condition. Script used: git grep -l _if_kconfig | xargs sed -E -i "s/_if_kconfig\(\s*(\w*)/_ifdef(CONFIG_\U\1\E \1/g" Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
# drivers/serial/CMakeLists.txt
zephyr_library_sources_if_kconfig(uart_spike.c)
下記に変更
zephyr_library_sources_ifdef(CONFIG_UART_SPIKE uart_spike.c)
二点目は整数型です。Zephyrはu8_t, u16_t, u32_tのような独自の整数型を持っていましたが、C99の型に置き換えられました。drivers/serial/uart_spike.cの実装を書き換える必要があります。
commit a1b77fd589dbe7284c17b029f251426a724abd47 Author: Kumar Gala <kumar.gala@linaro.org> Date: Wed May 27 11:26:57 2020 -0500 zephyr: replace zephyr integer types with C99 types git grep -l 'u\(8\|16\|32\|64\)_t' | \ xargs sed -i "s/u\(8\|16\|32\|64\)_t/uint\1_t/g" git grep -l 's\(8\|16\|32\|64\)_t' | \ xargs sed -i "s/s\(8\|16\|32\|64\)_t/int\1_t/g" Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
三点目はDT_INST_0_SPIKE_UART_SPIKE_LABELマクロです。こいつは元々、訳のわからない名前で直しようがないので、SiFiveのシリアルドライバの履歴を参考に直します。履歴を見ると2回ほど変わっています。
マクロ名のルールはDT_INST_<INSTANCE>_<COMPAT>_<PROP> だったみたいです。今初めて知りました。やっぱりこの書き方は意味不明と思ったのか、DT_INST_PROP(0, label) という形式になりました。さらに今はDT_INST_LABEL(0) という形式に落ち着いています。
★★DT_INST_PROP(0, label) になったコミット commit 8f84520130a346957ac2e2bdff1d6a51bca13af0 Author: Kumar Gala <kumar.gala@linaro.org> Date: Tue Mar 10 17:24:43 2020 -0500 drivers: serial: uart_sifive: convert to new DT API Use the new devicetree.h API instead of the legacy macros. Signed-off-by: Kumar Gala <kumar.gala@linaro.org> ★★DT_INST_LABEL(0) になったコミット commit 74d459fb66b10a5a0614a582fb0375d8b4a78c9e Author: Kumar Gala <kumar.gala@linaro.org> Date: Thu Apr 2 13:13:47 2020 -0500 drivers: serial: sifive: use DT_INST_LABEL macro Replace a few cases that should have been DT_INST_LABEL instead. Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
このマクロの罠はそれだけに留まらず、ソースコードの先頭に下記マクロを定義する必要があります。依然として訳がわかりません。ZephyrはDviceTree周りの仕様が不安定です。
// zephyr/drivers/serial/uart_spike.c
#define DT_DRV_COMPAT spike_uart_spike
最後はリンカーです。これは元々のコードのコンフィグが間違っていたことに起因します。ROM領域がないのにCONFIG_XIPが有効になっていました。
$ ninja ... x-tools/riscv64-zephyr-elf/lib/gcc/riscv64-zephyr-elf/8.3.0/../../../../riscv64-zephyr-elf/bin/ld: invalid origin for memory region ROM collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed.
エラーメッセージからは何が原因か読み取れないですね。こういうときはビルドディレクトリのリンカースクリプト(zephyr/linker.cmd)をうまく行く場合と、うまく行かない場合で見比べます。
/* zephyr/build/zephyr/linker.cmd */
OUTPUT_ARCH("riscv")
OUTPUT_FORMAT("elf32-littleriscv")
MEMORY
{
ROM (rx) : ORIGIN = 541065216, LENGTH = 12582912
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = ((16) << 10)
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}
/* zephyr/build/zephyr/linker.cmd */
OUTPUT_ARCH("riscv")
OUTPUT_FORMAT("elf32-littleriscv")
MEMORY
{
ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE /* ★★ここがおかしい★★ */
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = ((32) << 10)
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}
このスクリプトは下記のファイルから生成されているようです。HogeボードはROM領域を使う前提ではないので、領域そのものが要りません。ROM領域を葬るにはCONFIG_XIPをnにすれば良さそうです。ファイルはboards/riscv/hoge/hoge_defconfigです。
// include/arch/riscv/common/linker.ld
MEMORY
{
#ifdef CONFIG_XIP
#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay)
#define ROM_BASE DT_REG_ADDR(DT_CHOSEN(zephyr_flash))
#define ROM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_flash))
#elif DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), jedec_spi_nor, okay)
/* For jedec,spi-nor we expect the spi controller to memory map the flash
* and for that mapping to be the second register property of the spi
* controller.
*/
#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash))
#define ROM_BASE DT_REG_ADDR_BY_IDX(SPI_CTRL, 1)
#define ROM_SIZE DT_REG_SIZE_BY_IDX(SPI_CTRL, 1)
#endif
ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE /* ★★CONFIG_XIPが無効ならこの行ごと消える★★ */
#endif
RAM (rwx) : ORIGIN = CONFIG_SRAM_BASE_ADDRESS, LENGTH = KB(CONFIG_SRAM_SIZE)
/* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}
以上の修正を入れて動かします。
$ qemu-system-riscv32 -nographic -machine spike -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf -bios none *** Booting Zephyr OS build zephyr-v2.3.0-2349-g0769bb760b2a *** Hello World! hoge
やっと動きました。良かった良かった。
目次: Zephyr
最近のRISC-V向けQEMUでspike, virtを起動すると、下記のようなエラーで怒られてしまいます。
$ qemu-system-riscv32 -nographic -machine spike -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf qemu-system-riscv32: Unable to load the RISC-V firmware "opensbi-riscv32-spike-fw_jump.elf"
このエラーの原因はQEMU RISC-V向けの仕様変更によるものです。machineがspike, virtのときに、自由にBIOSを選べるように変わりました。ですがZephyrを起動する際には、特にBIOSは必要ないため、noneを指定すればOKです。
$ qemu-system-riscv32 -nographic -machine spike -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf -bios none *** Booting Zephyr OS build v2.2.0-rc1-123-gcaca3f60b012 *** Hello World! hoge
ZephyrだけでなくQEMUも日々進化しているのですね。
目次: 車
先週、突然知らない番号から電話が掛かってきました。何だか焦った様子でした。要約すると「アパートの駐車場で隣に駐車している者です、駐車しようとして、あなたの車にぶつけてしまいました」とのことでした。車の様子を確認したところ、見事にバンパーの右前が取れていました。ああー……。
後日、保険屋さんと修理屋さん(スーパーオートバックス)から電話があり、車を引き取りに来る日時等を決めました。そして今日、レガシィさんはフロントバンパー修理のため旅立っていきました。
修理屋さん曰く「右ライトもAssy交換で新品になるだろう」とのこと。新品交換後の右ライトに対し、古ぼけた左ライトの明るさがアンバランスになるのはうまくないので、左ライトの研磨もお願いしました。残念ながら左ライトの研磨は保険が効かず自費になりそうですが、曇っていたライトが明るくなるから良しとしましょう。
代車はホンダのフィットでした。
総じて良い車だと思います。レガシィとの違いとしては、
昔のフィットに乗ったときアクセルオフ時のエンブレが急すぎて車酔いしたので、正直好きな車ではなかったのですが、今のフィットは素敵な車です。新しい車って確実に良くなってますね。
ADAS(前車の車間検知、車線逸脱の警告)も搭載されていて面白いです。たまに誤検知?するのか、何もないところで突然ピー!と警告音が鳴ったり、車線逸脱の警告とともにハンドルがンゴゴー!って言い出すのはご愛敬です。
目次: ROCK64/ROCKPro64
先日KADHAS VIM2, VIM3を購入したため、ARMボードがさらに増え置き場がなくなりました。既存のボードをコンパクトに収納できないかと画策し、目を付けたのがROCK64です。現在ROCK64は純正ケースに入れて使っていますが、ギリシャの神殿を思わせる立派な柱と、無駄にでかいアクリル板のせいで、すっっごい邪魔です。
ROCK64はRaspberry Pi 3とほぼ同じ大きさですから、Raspberry Pi 3のケースを流用できるはずです。
改造のベースになるケースは、TinkerBoardやRaspberry Pi 3の格納で活躍しているPhysical Computing Labの3ple Decker Raspberry Piケース(公式サイトへのリンク)です。
Rasberry Pi 3は電源がUSB micro Bですが、ROCK64はACアダプタなので、全く形が合いません。アクリルケースの穴を削って広げる必要があります。もう一か所、ROCK64の個体差か(or単に設計の問題か?)ヘッドホンジャックがケースとズレていて、プラグが刺さらないため、これも直さないといけません。
削り方はリューターにプラスチック用のビットを付けてゴリゴリ削るだけです。厚さも面積も大したことないので、力業でどうにでもなると思います。アクリルを削ると変なにおいがしますね。焦げてるのかな……?
ケースを削り終わりました。ROCK64の端子がちゃんと外から見えています。
元よりROCK64用のケースではないので、様々な不都合が発生します。
Pi P5+ Busが使用不能になる点は諦めました。Rasberry Pi 3にはないピンヘッダなので致し方無しです。このピンヘッダから引き出していたS/PDIFが利用不可能になりました。さよならS/PDIFさん。
PWR, RESETボタンはケースを開ければ押せますが、面倒です。今後はPWRボタンに頼らない運用を考えるべきでしょう。
ボードが固定できない問題はどうにもなりませんでした。microSDの上部を抑えるケース側のツメがうまくハマりません。
もう少しきちんと調べてみると、ROCK64はRasberry Pi 3よりmicroSDスロットに厚みがあるせいで、microSDの上部を抑えるケース側のツメがうまくハマらないようです。
スロットの厚さはどうしようもないので、泣く泣くケース側のツメを折りました。
ツメがないので、microSDカードがケースに引っ掛かってギリギリケースに固定されている状態です。ROCK64の40pinのピンヘッダ(Pi-2 Bus)にジャンパケーブルを抜き差しすると、microSDにかなり力が掛かります。これは良くないですね……。
Pi-2 Busへのケーブル抜き差しは結構固いため、そのうちmicroSDスロットが変形するか、microSDが折れて壊れると思います。幸いなことに、今は頻繁にピンヘッダのケーブル抜き差しはしませんから、しばらくこの状態でも使えるでしょう。
目次: ROCK64/ROCKPro64
TwitterでCavium Thunder X3はサーバ向け汎用ARM SoCではなくなるかもしれない、という話を見かけました。Cavium(今はMarvellに買収されました)は独自ARM CPUコアを作って頑張ってたメーカーです。
ARM自体はまだまだめげることなく、サーバ向けに売りたい(Armのサーバ向け戦略十年の計は実を結ぶか、新プロセッサ「Neoverse」 - MONOist)ようですが、肝心のARM系SoCメーカーやサーバベンダーがARM系サーバで成功している様子がないです。
以前Qualcomm Centriqも鳴り物入りでサーバ向けARM SoCに参入しましたが、2018年にあっさり撤退(Arm SoCの開発部門を秘かに閉鎖していたQualcomm - EE Times Japan)しています。モバイルの王者Qualcommをもってしても困難な道のようです。
サーバ向けプロセッサはIntelが9割取っているらしいので、崩すのはなかなか容易ではありませんね……。
サーバ向けとして発表されているARMメニーコア系SoCを列挙してみました。年代はチップがローンチされたおおよその時期です。間違ってたらごめんなさい。
こんな感じですかね?SC2A11はホームページでサーバ向けと謳っていたので、リストに入れてます。でもCA53コアなので、性能的にはThunder X2辺りと並べるのはちょっと厳しい……かな?
目次: ALSA
デスクトップPCにはスピーカーを繋いでいませんが、たまに音声再生を確認したいことがあります。スピーカーを繋ぎ変えても良いですが、ALSAのループバックデバイスを使うと簡単に音声を転送したり、ファイルに記録したりできます。
ループバックデバイスとは再生した音声がそのまま戻ってきて(ループバック)録音できるデバイスのことです。ヘッドフォンの出力端子を、マイクロフォンの入力端子に繋いでループさせた状態を想像してもらうとわかりやすいと思います。
ALSAのループバックデバイス(aloop)は、ALSAの標準的な機能です。普通の環境だとロードされていないはずなので、modprobeでロードします。
# modprobe snd-aloop $ cat /proc/asound/pcm 00-03: HDMI 0 : HDMI 0 : playback 1 00-07: HDMI 1 : HDMI 1 : playback 1 00-08: HDMI 2 : HDMI 2 : playback 1 00-09: HDMI 3 : HDMI 3 : playback 1 00-10: HDMI 4 : HDMI 4 : playback 1 01-00: ALC1220 Analog : ALC1220 Analog : playback 1 : capture 1 01-01: ALC1220 Digital : ALC1220 Digital : playback 1 01-02: ALC1220 Alt Analog : ALC1220 Alt Analog : capture 1 02-00: Loopback PCM : Loopback PCM : playback 8 : capture 8 ★このデバイスhw:2を使用する 02-01: Loopback PCM : Loopback PCM : playback 8 : capture 8
ロードし終わるとPCMデバイスが1つ増えます。上記の場合は02-xx(02-00と02-01)が増えています。
ループバックデバイスはサブデバイス0が再生用、サブデバイス1が録音用となっています。先ほどの例でいうと、再生時はhw:2,0を使い、録音時はhw:2,1を使います。
$ aplay test.wav -D hw:2,0 Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
#### ファイルに記録する場合 $ arecord -D hw:2,1 -r 48000 -f S16_LE -c 2 test2.wav Recording WAVE 'test2.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo #### ネットワーク経由で送る場合 $ arecord -D hw:2,1 -r 48000 -f S16_LE -c 2 | nc 192.168.1.10 5555 Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
私の家のスピーカーは、今のところROCK64に繋がっています。ROCK64にネットワーク経由で送って、下記のように受け取れば「ほぼ」リアルタイムでデスクトップPCの音声が確認できます。
$ nc -l 5555 | aplay -D hw:0 Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
受け取る方は先頭のWAVヘッダでサンプリング周波数やチャネル数を知ることができるため、-rや -cを指定する必要はありません。指定しても構いませんが無視されるはずです。
「ほぼ」リアルタイムと書いた理由は、上記の方法だと人間が余裕でわかるくらいの遅延が発生してしまうからです。ちゃんと測っていませんが、0.5秒くらい遅れてるかも?これでも簡易的な音声確認としては十分ですし、気にしなくでも良いでしょう。
< | 2020 | > | ||||
<< | < | 09 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | - | - | - |
合計:
本日: