コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2020年2月3日 >>> 2020年2月3日
link もっと後

2020年2月3日

Zephyr OSで遊ぼう その2 - ボードを追加してビルド

目次: Zephyr

前回ninjaを実行したときに嫌というほどエラーが出ました。エラーを追う前に、コンフィグがあっているかチェックしたいと思います。

ZephyrはLinux Kernelと似たコンフィグのシステム(Kconfig)を持っています。使い方もLinuxと似ており、ninja menuconfigとすると、ケバケバしい色(私の環境だと真っ白+黄色になる……)の画面が表示されます。


menuconfigの画面

なぜかArchitectureがx86となっていたり、SoCがLiteXになっていたり、色々おかしいです。なぜこうなってしまったかは後にして、手当たり次第でそれらしい値に直すと、Board Selectionに今回追加したHoge targetが出現します。

menuconfigで手修正する箇所
$ ninja menuconfig

Architecture (x86 architecture)  --->
  ( ) RISCV architectureを選択

SoC/CPU/Configuration Selection (LiteX VexRiscv system implementation)  --->
  ( ) SiFive Freedom SOC implementationを選択

コンフィグがそれらしくなったらninjaでビルドします。

menuconfigで手修正後のビルド
$ ninja

zephyr/samples/hello_world/src/main.c:12:30: error: 'CONFIG_BOARD' undeclared (first use in this function); did you mean 'CONFIG_ARCH'?
  printk("Hello World! %s\n", CONFIG_BOARD);
                              ^~~~~~~~~~~~
                              CONFIG_ARCH

...

In file included from ../include/devicetree.h:12,
                 from ../soc/riscv/riscv-privilege/sifive-freedom/soc.h:15,
                 from ../include/arch/riscv/arch.h:25, 
                 from ../include/arch/cpu.h:23,
                 from ../include/kernel_includes.h:34, 
                 from ../include/kernel.h:17,
                 from zephyr/drivers/interrupt_controller/intc_plic.c:13:
zephyr/drivers/interrupt_controller/intc_plic.c: In function 'riscv_plic_irq_enable':
zephyr/include/generated/devicetree_fixups.h:8:25: error: 'DT_INST_0_SIFIVE_PLIC_1_0_0_IRQ_EN_BASE_ADDRESS' undeclared (first use in this function)
 #define DT_PLIC_IRQ_EN  DT_INST_0_SIFIVE_PLIC_1_0_0_IRQ_EN_BASE_ADDRESS
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

...

先程よりはマシになりましたが、まだエラーが山のように出ます。エラーの種類を大別するとCONFIG_BOARDの定義がない、DT_INST_ なんちゃらの定義がない、に分けられます。

最初のCONFIG_BOARDについては、いかにもボード側で定義しなければならなさそうな名前です。おなじみ他のボードを参照(boards/riscv/qemu_riscv32/Kconfig.defconfigなど)すると、Kconfig.boardで定義したconfig BOARD_HOGEが定義されているときに限り、CONFIG_BOARDにボード名のデフォルト値を設定していました。

つまり、このように書けば良いみたいです。

Kconfig.defconfig

# SPDX-License-Identifier: Apache-2.0

if BOARD_HOGE

config BOARD
	default "hoge"

endif

それ以外のDT_INST_ なんちゃらの定義については、少し複雑です。

Zephyrのデバイスツリーの扱い

Linuxではデバイスツリーファイル(*.dts)をデバイスツリーコンパイラdtcでコンパイルして、Flattened Device Tree(fdt)という形式のバイナリにします。fdtはカーネル内部に組み込んだり、ブートローダが起動時にカーネルに渡すなどして利用されます。

しかしZephyrはそもそもdtcを使わず、Pythonで処理します。デバイスツリーを書き間違えるとPythonスクリプトが怒ってくるのですが、これが理由みたいです。なんだと?と思う方はZephyrのドキュメント(Devicetree - Zephyr Project Documentation)をご参照ください。下記に引用します。

Note: In addition to the Python code above, the standard dtc DTS compiler is also run on the devicetree. This is just to catch any errors or warnings it generates. The output is unused.

ドキュメントのGenerated macrosの章を見ると、デバイスツリーからDT_INST_ なんちゃら、というマクロを生成する、という説明があり、ビルドエラーの原因となったマクロの仲間のようです。

デバイスツリーを足そう

推測するにデバイスツリーを何も定義していないことが、DT_INST_ なんちゃらマクロが存在しないことの原因ではないでしょうか?他のボード(boards/riscv/qemu_riscv32/qemu_riscv32.dtsなど)がデバイスツリーをどうしているか、見ながら真似してみます。

hoge.dts

/* SPDX-License-Identifier: Apache-2.0 */

/dts-v1/;

#include <riscv32-fe310.dtsi>

/ {
	model = "Hoge Board";
	compatible = "hoge,hoge";

	chosen {
		zephyr,console = &uart0;
		zephyr,shell-uart = &uart0;
		zephyr,sram = &dtim;
		zephyr,flash = &flash0;
	};
};

&gpio0 {
	status = "okay";
};

&uart0 {
	status = "okay";
	current-speed = <115200>;
	clock-frequency = <16000000>;
};

&spi0 {
	status = "okay";

	#address-cells = <1>;
	#size-cells = <0>;
	reg = <0x10014000 0x1000 0x20400000 0xc00000>;
	flash0: flash@0 {
		compatible = "issi,is25lp128", "jedec,spi-nor";
		size = <134217728>;
		label = "FLASH0";
		jedec-id = [96 60 18];
		reg = <0>;
		// Dummy entry
		spi-max-frequency = <0>;
	};
};

ほぼ全てコピーしただけです。ビルドしてみると、最後の方まで行きますが、いくつかシンボルがないと言われます。ログはフルパスが出ていて鬱陶しいので意味が残る程度に削っています。

デバイスツリー定義後のビルドエラー
$ ninja

...

riscv64-zephyr-elf/bin/ld: zephyr/arch/arch/riscv/core/libarch__riscv__core.a(isr.S.obj): in function `.L0 ':
zephyr/arch/riscv/core/isr.S:244: undefined reference to `_sw_isr_table'
riscv64-zephyr-elf/bin/ld: zephyr/kernel/libkernel.a(sched.c.obj): in function `z_reset_time_slice':
zephyr/kernel/sched.c:276: undefined reference to `z_clock_elapsed'
riscv64-zephyr-elf/bin/ld: zephyr/kernel/libkernel.a(timeout.c.obj): in function `elapsed':
zephyr/kernel/timeout.c:69: undefined reference to `z_clock_elapsed'
collect2: error: ld returned 1 exit status
%
ninja: build stopped: subcommand failed.

これらのシンボルはドライバが提供するもののようですので、コンフィグでそれらしきものをONにしていきます。

コンフィグ追加
General Architecture Options  --->
  Interrupt Configuration  --->
    [ ] Use generated IRQ tablesを選択

General Kernel Options  --->
  [ ] Execute in place

Device Drivers  --->
  [ ] Serial Drivers  ----
    [ ] Enable UART Interrupt supportを選択
    [ ] SiFive Freedom serial driver (NEW)  ----
      [ ] Enable SIFIVE Port 0 (NEW)  ---- を選択

  [ ] Console drivers  ---
    [ ] Use UART for console (NEW) を選択

  Timer Drivers  --->
    [ ] RISCV Machine Timerを選択

  [ ] GPIO Drivers  ----
    [ ] SiFive Freedom Processor GPIO driver (NEW)  ---- を選択

  [ ] Enable board pinmux driver  ----
    [ ] SiFive Freedom SOC pinmux driver (NEW)  ----

このように全て手動で設定する必要はない(後々不要となる)ので、あまり詳しくなる必要はないですが、

SiFive関連
SiFiveのSoCなのでコンフィグを片っ端からONにしています
Use generated IRQ tables
_sw_isr_tableシンボルの定義に関わっています
Execute in Place(XIP)
ONにしないと、ビルドしたときにRAMサイズから溢れているというエラーで怒られます
RISCV Machine Timer
z_clock_elapsedシンボルの定義に関わっています

コンフィグがそれらしくなったらninjaでビルドして、実行します。

コンフィグ追加後、ビルド&実行
$ ninja

...

Memory region         Used Size  Region Size  %age Used
             ROM:       13165 B        12 MB      0.10%
             RAM:        3808 B        16 KB     23.24%
        IDT_LIST:         569 B         2 KB     27.78%
[98/98] Linking C executable zephyr/zephyr.elf

$ /usr/bin/qemu-system-riscv32 -nographic -machine sifive_e -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel /home/katsuhiro/share/projects/oss/zephyr/build/zephyr/zephyr.elf

*** Booting Zephyr OS build zephyr-v2.1.0-1471-g7e7a4426d835  ***
Hello World! hoge

実行できました。Hello Worldの後ろがボード名(CONFIG_BOARD)です。無事、アプリがhogeボード上で動いたということですね。次回は面倒くさかった手動コンフィグの撲滅に挑みます。

編集者:すずき(2023/09/24 12:04)

コメント一覧

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



link もっと前
2020年2月3日 >>> 2020年2月3日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<02>>>
------1
2345678
9101112131415
16171819202122
23242526272829

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
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 2024年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/24 08:36