目次: Zephyr
やっとcmakeを通過したので、いよいよビルドに挑みます。
In file included from ../include/arch/cpu.h:25, from ../include/kernel_includes.h:34, from ../include/kernel.h:17, from zephyr/arch/riscv/core/offsets/offsets.c:16: ../include/arch/riscv/arch.h:25:10: fatal error: soc.h: No such file or directory #include <soc.h> ^~~~~~~ compilation terminated. ninja: build stopped: subcommand failed.
他のsoc.hを見ると、soc_common.h, devicetree.hというヘッダをインクルードしているようです。それに習っておきます。
/*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file SoC configuration macros for the Spike series processor
*/
#ifndef __RISCV_SPIKE_SOC_H_
#define __RISCV_SPIKE_SOC_H_
#include <soc_common.h>
#include <devicetree.h>
#endif /* __RISCV_SPIKE_SOC_H_ */
再びビルドすると、今度はPLIC_* がないと怒られます。
zephyr/drivers/interrupt_controller/intc_plic.c: In function 'riscv_plic_irq_enable': zephyr/drivers/interrupt_controller/intc_plic.c:45:41: error: 'DT_PLIC_IRQ_EN' undeclared (first use in this function); did you mean 'PLIC_IRQS'? volatile u32_t *en = (volatile u32_t *)DT_PLIC_IRQ_EN; ^~~~~~~~~~~~~~ PLIC_IRQS
RISC-V Privileged系のSoCではPLICという割り込みコントローラのドライバが自動的に有効になります。今回、動作させるに当たってPLICのサポートは不要なので、zephyr/boards/riscv/hoge/hoge_defconfigで無効にします。具体的にはCONFIG_PLIC=nを足します。
この後cmakeからやり直してみると、
zephyr/drivers/timer/riscv_machine_timer.c: In function 'set_mtimecmp': zephyr/drivers/timer/riscv_machine_timer.c:28:31: error: 'RISCV_MTIMECMP_BASE' undeclared (first use in this function) volatile u32_t *r = (u32_t *)RISCV_MTIMECMP_BASE; ^~~~~~~~~~~~~~~~~~~ zephyr/drivers/timer/riscv_machine_timer.c:28:31: note: each undeclared identifier is reported only once for each function it appears in zephyr/drivers/timer/riscv_machine_timer.c: In function 'mtime': zephyr/drivers/timer/riscv_machine_timer.c:47:31: error: 'RISCV_MTIME_BASE' undeclared (first use in this function) volatile u32_t *r = (u32_t *)RISCV_MTIME_BASE; ^~~~~~~~~~~~~~~~ [87/94] Linking C static library zephyr/kernel/libkernel.a ninja: build stopped: subcommand failed.
CLINTのレジスタmtime, mtimecmpのアドレスを必要としているようです。
他のSoCを眺めてみると、CLINTのレジスタアドレスを定義する場所はsoc.hのようです。しかし肝心のアドレスがわかりません。QEMUのドキュメントに載っていれば簡単でしたが、見当たらなかったのでQEMUのソースコードを見ます。
// https://github.com/qemu/qemu/blob/master/hw/riscv/spike.c
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
} spike_memmap[] = {
[SPIKE_MROM] = { 0x1000, 0x11000 },
[SPIKE_CLINT] = { 0x2000000, 0x10000 },
[SPIKE_DRAM] = { 0x80000000, 0x0 },
};
// https://github.com/qemu/qemu/blob/master/include/hw/riscv/sifive_clint.h
enum {
SIFIVE_SIP_BASE = 0x0,
SIFIVE_TIMECMP_BASE = 0x4000,
SIFIVE_TIME_BASE = 0xBFF8
};
ベースアドレスが0x02000000で、レジスタのオフセットアドレスもわかりました。soc.hに追記します。
(2/19訂正: MTIMECMP_BASEとMTIME_BASEのアドレスが逆だったので、修正しました)
/* Timer configuration */
#define RISCV_MTIMECMP_BASE 0x02004000
#define RISCV_MTIME_BASE 0x0200bff8
再びビルドします。やっとビルドをパスしました。
$ ninja [0/1] Re-running CMake... -- Zephyr version: 2.1.99 -- Selected BOARD hoge -- Loading zephyr/boards/riscv/hoge/hoge.dts as base hoge.dts.pre.tmp:22.17-25.5: Warning (simple_bus_reg): /soc/serial: missing or empty reg/ranges property also defined at hoge.dts.pre.tmp:37.8-39.3 Devicetree header saved to 'zephyr/build/zephyr/include/generated/devicetree_unfixed.h' Parsing zephyr/Kconfig Loaded configuration 'zephyr/build/zephyr/.config' No change to configuration in 'zephyr/build/zephyr/.config' No change to Kconfig header in 'zephyr/build/zephyr/include/generated/autoconf.h' -- Cache files will be written to: /home/katsuhiro/.cache/zephyr -- Configuring done -- Generating done -- Build files have been written to: zephyr/build [89/94] Linking C executable zephyr/zephyr_prebuilt.elf Memory region Used Size Region Size %age Used RAM: 12752 B 16 KB 77.83% IDT_LIST: 25 B 2 KB 1.22% [94/94] Linking C executable zephyr/zephyr.elf
まだめでたしめでたし、ではありません。
生成されたバイナリを実行すると何かエラーが表示されるものの、Hello worldは表示されません。残念です。
$ /usr/bin/qemu-system-riscv32 -nographic -machine spike -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/build/zephyr/zephyr.elf qemu-system-riscv32: clint: time_hi write not implemented qemu-system-riscv32: clint: time_lo write not implemented qemu-system-riscv32: clint: time_hi write not implemented
このままでは全く何も実行されていないのか、惜しいところまで実行されたのか判別が付きません。以前ご紹介した(2020年1月31日の日記参照)デバッグオプション -sと -Sを使い、gdbで追跡します。
復習ですが、オプション -sはGDBの接続をlocalhost:1234で受け付け、-SはエミュレータをHalted状態で起動しgdbから再開要求をするまで動かないで待っている、という意味です。
$ riscv64-zephyr-elf-gdb zephyr/build/zephyr/zephyr.elf GNU gdb (crosstool-NG 1.24.0.60-a152d61) 8.3.1 Copyright (C) 2019 Free Software Foundation, Inc. ... (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x00001000 in ?? () (gdb) b main Breakpoint 1 at 0x800006d4: file zephyr/samples/hello_world/src/main.c, line 12. (gdb) c Continuing. Breakpoint 1, main () at zephyr/samples/hello_world/src/main.c:12 12 printk("Hello World! %s
", CONFIG_BOARD);
ターゲット(QEMU)に接続し、mainにブレークを設定して、実行を継続しています。Hello worldのmain関数に到達していることがわかります。素晴らしいですね。printkは呼ばれているものの、文字が出ないことが問題だとわかりました。
Hello worldを拝むには、シリアルのドライバを追加する必要があります。続きはまた次回。
< | 2020 | > | ||||
<< | < | 02 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | - | 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 |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.15.
using GD bundled (2.1.0 compatible)(png support.)