Zephyr on HiFive1(RISC-V RV32)

RISC-V上でZephyrが動作する環境ができてきました。
公式のチュートリアルに沿って実行すれば良いのですが、そのままでは幾つかハマった点があったのでメモ。

#環境
OS: Windows10 VMware Player15上のUbuntu 18.04
Zephyr: v1.14.0-rc3 (https://github.com/zephyrproject-rtos/zephyr)
Board: SiFive HiFive1 (https://www.sifive.com/boards/hifive1) 

#参照ページ
Zephyr Project "RISC-V - Getting Started Guide" https://risc-v-getting-started-guide.readthedocs.io/en/latest/

#Setup
Ubuntuではチュートリアルに従って足りないパッケージがあれば追加しました。
\$ sudo apt install --no-install-recommends git cmake ninja-build gperf \
　　　　　　　　ccache dfu-util device-tree-compiler wget \
　　　　　　　　python3-pip python3-setuptools python3-wheel xz-utils file make gcc \
　　　　　　　　gcc-multilib

###cmakeバージョン
Ubuntu18.04では3.10が入ってますがZephyrが3.13.1以上を要求してきました。
cmakeのdebパッケージに対応したものが無かったため、こちら (https://cmake.org/download/) からcmake-3.14.1-Linux-x86_64.tar.gzをダウンロードしました。
\$ tar zxvf cmake-3.14.1-Linux-x86_64.tar.gz
\$ export PATH=cmake-3.14.1-Linux-x86_64/bin:$PATH

###dtcバージョン
device tree compilerもUbuntu18.04のものはバージョンが古いと言われました。
こちら (https://packages.ubuntu.com/cosmic/amd64/device-tree-compiler/download) から1.4.7-1をダウンロードしました。
\$ sudo apt install ./device-tree-compiler_1.4.7-1_amd64.deb

#環境変数の設定
後で良いですが、Zephyrインストールと動作の過程で幾つか設定が必要になりました。
\$ export ZEPHYR_BASE=/home/work/zephyr #zephyrをgit cloneするディレクトリ
\$ export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
\$ export ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk #Zephyr SDKのインストールディレクトリ

#Zephyrのダウンロードと設定
\$ git clone https://github.com/zephyrproject-rtos/zephyr
\$ cd zephyr   # (← \$ZEPHYR_BASE)
\$ pip3 install --user -r scripts/requirements.txt
\$ export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
\$ . ./zephyr-env.sh

#Zephyr SDKのダウンロード
公式ページには0.9.5で記載されているのですが、インストールの過程で古いと怒られました。
まだNG版なのか分からないですが、動作確認のため取り急ぎ0.10.0にしておきます。
\$ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.10.0/zephyr-sdk-0.10.0-setup.run
\$ chmod 755 zephyr-sdk-0.10.0-setup.run
\$ sudo ./zephyr-sdk-0.10.0-setup.run
Verifying archive integrity... All good.
Uncompressing SDK for Zephyr  100% 
Enter target directory for SDK (default: /opt/zephyr-sdk/):  #デフォルトは/opt下
Installing SDK to /opt/zephyr-sdk
Creating directory /opt/zephyr-sdk
Success
 [\*] Installing x86 tools... 
 [\*] Installing arm tools... 
 [\*] Installing arc tools... 
 [\*] Installing iamcu tools... 
 [\*] Installing nios2 tools... 
 [\*] Installing xtensa tools... 
 [\*] Installing riscv32 tools... 
 [\*] Installing additional host tools... 
Success installing SDK. SDK is ready to be used.

#HiFive1で動作させるアプリケーションのビルド
hello_worldの中身をいじって動作させてみます。printkを2行追加。
元々がWindRiverのRocketだったことが分かります。
\$ vi $ZEPHYR_BASE/samples/hello_world/src/main.c
![image.png](https://qiita-image-store.s3.amazonaws.com/0/324827/89964ad8-531b-28e1-8227-d71bf938e751.png)

\$ mkdir build-example
\$ cd build-example
\$ cmake -DBOARD=hifive1 \$ZEPHYR_BASE/samples/hello_world
Zephyr version: 1.14.0
-- Selected BOARD hifive1
-- Loading /home/work/boards/riscv32/hifive1/hifive1.dts as base
-- Overlaying /home/work/dts/common/common.dts
Parsing Kconfig tree in /home/work/zephyr/Kconfig
Loading /home/work/zephyr/build-example/zephyr/.config as base
Configuration written to '/home/work/zephyr/build-example/zephyr/.config'
-- Cache files will be written to: /home/.cache/zephyr
-- Configuring done
-- Generating done
-- Build files have been written to: /home/work/zephyr/build-example

\$ make -j \$(nproc)
[  1%] Built target kobj_types_h_target
[  2%] Built target syscall_macros_h_target
[  3%] Built target driver_validation_h_target
[  4%] Generating misc/generated/syscalls.json
[  7%] Built target syscall_list_h_target
Scanning dependencies of target offsets
[  8%] Building C object zephyr/CMakeFiles/offsets.dir/arch/riscv32/core/offsets/offsets.c.obj
[  8%] Built target offsets
[  9%] Built target offsets_h
Scanning dependencies of target linker_script_target
Scanning dependencies of target app
[ 10%] Generating linker.cmd
Scanning dependencies of target zephyr
Scanning dependencies of target kernel
[ 11%] Building C object CMakeFiles/app.dir/src/main.c.obj
[ 11%] Built target linker_script_target
[ 12%] Linking C static library app/libapp.a
Scanning dependencies of target lib__libc__minimal
[ 12%] Built target app
[ 13%] Building C object zephyr/lib/libc/minimal/CMakeFiles/lib__libc__minimal.dir/source/stdlib/malloc.c.obj
Scanning dependencies of target boards__riscv32__hifive1
[ 14%] Building C object zephyr/lib/libc/minimal/CMakeFiles/lib__libc__minimal.dir/source/stdout/stdout_console.c.obj
[ 15%] Linking C static library liblib__libc__minimal.a
[ 16%] Building C object zephyr/boards/riscv32/hifive1/CMakeFiles/boards__riscv32__hifive1.dir/pinmux.c.obj
[ 17%] Building C object zephyr/boards/riscv32/hifive1/CMakeFiles/boards__riscv32__hifive1.dir/clock.c.obj
[ 27%] Built target lib__libc__minimal
[ 28%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/common/isr_tables.c.obj
[ 29%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/device.c.obj
Scanning dependencies of target drivers__gpio
[ 30%] Linking C static library libboards__riscv32__hifive1.a
[ 31%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/common/sw_isr_common.c.obj
[ 32%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/errno.c.obj
[ 33%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/cpu_idle.c.obj
[ 34%] Building C object zephyr/drivers/gpio/CMakeFiles/drivers__gpio.dir/gpio_sifive.c.obj
[ 35%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/fatal.c.obj
[ 36%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/idle.c.obj
[ 36%] Built target boards__riscv32__hifive1
[ 37%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/irq_manage.c.obj
[ 38%] Linking C static library libdrivers__gpio.a
[ 39%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/init.c.obj
[ 40%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/irq_offload.c.obj
Scanning dependencies of target drivers__spi
[ 41%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/mailbox.c.obj
[ 42%] Building ASM object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/isr.S.obj
[ 42%] Built target drivers__gpio
[ 43%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/prep_c.c.obj
Scanning dependencies of target drivers__serial
[ 44%] Building C object zephyr/drivers/spi/CMakeFiles/drivers__spi.dir/spi_sifive.c.obj
[ 45%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/mem_slab.c.obj
[ 46%] Building ASM object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/reset.S.obj
[ 47%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/mempool.c.obj
[ 48%] Linking C static library libdrivers__spi.a
[ 50%] Building ASM object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/swap.S.obj
[ 51%] Building C object zephyr/drivers/serial/CMakeFiles/drivers__serial.dir/uart_sifive.c.obj
[ 52%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/msg_q.c.obj
[ 53%] Building C object zephyr/CMakeFiles/zephyr.dir/arch/riscv32/core/thread.c.obj
[ 54%] Linking C static library libdrivers__serial.a
[ 55%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/mutex.c.obj
[ 55%] Built target drivers__spi
[ 56%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/pipes.c.obj
[ 57%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/fdtable.c.obj
[ 58%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/mempool.c.obj
[ 59%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/queue.c.obj
[ 59%] Built target drivers__serial
[ 61%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/sem.c.obj
[ 61%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/sched.c.obj
[ 62%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/rb.c.obj
[ 63%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/stack.c.obj
[ 64%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/system_work_q.c.obj
[ 65%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/thread_entry.c.obj
[ 66%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/work_q.c.obj
[ 67%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/thread.c.obj
[ 68%] Building C object zephyr/CMakeFiles/zephyr.dir/lib/os/printk.c.obj
[ 69%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/thread_abort.c.obj
[ 70%] Building C object zephyr/CMakeFiles/zephyr.dir/soc/riscv32/riscv-privilege/common/idle.c.obj
[ 71%] Building ASM object zephyr/CMakeFiles/zephyr.dir/soc/riscv32/riscv-privilege/common/soc_irq.S.obj
[ 72%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/work_q.c.obj
[ 73%] Building C object zephyr/CMakeFiles/zephyr.dir/soc/riscv32/riscv-privilege/common/soc_common_irq.c.obj
[ 75%] Building C object zephyr/CMakeFiles/zephyr.dir/drivers/interrupt_controller/plic.c.obj
[ 76%] Building C object zephyr/CMakeFiles/zephyr.dir/drivers/console/uart_console.c.obj
[ 77%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/smp.c.obj
[ 78%] Building C object zephyr/CMakeFiles/zephyr.dir/drivers/pinmux/pinmux_sifive.c.obj
[ 79%] Building C object zephyr/CMakeFiles/zephyr.dir/drivers/timer/sys_clock_init.c.obj
[ 81%] Building C object zephyr/CMakeFiles/zephyr.dir/drivers/timer/riscv_machine_timer.c.obj
[ 81%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/timeout.c.obj
[ 82%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/timer.c.obj
[ 83%] Building C object zephyr/kernel/CMakeFiles/kernel.dir/atomic_c.c.obj
[ 84%] Linking C static library libzephyr.a
[ 85%] Linking C static library libkernel.a
[ 91%] Built target zephyr
[ 92%] Built target kernel
[ 93%] Linking C executable zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
             ROM:       18176 B        12 MB      0.14%
             RAM:        4272 B        16 KB     26.07%
        IDT_LIST:         553 B         2 KB     27.00%
[ 94%] Built target zephyr_prebuilt
Scanning dependencies of target linker_pass_final_script_target
[ 95%] Generating linker_pass_final.cmd
[ 95%] Built target linker_pass_final_script_target
[ 96%] Generating isr_tables.c
Scanning dependencies of target kernel_elf
[ 97%] Building C object zephyr/CMakeFiles/kernel_elf.dir/isr_tables.c.obj
[ 98%] Linking C executable zephyr.elf
Generating files from zephyr.elf for board: hifive1
[100%] Built target kernel_elf

#HiFive1のFlashへの書き込み
\$ cd $ZEPHYR_BASE/build-example/zephyr
makeによるbuildの結果、ここに zephyr.elfができています。

OpenOCDで接続してGDBで書き込みです。
openocdが必要なのですが、SiFiveのfreedom-e-sdkを用意しておきます。
チュートリアルに記載されているPATHも少し古いようです。
また、openocdコマンドに&をつけてバックグラウンド実行しないとうまくいきませんでした。

\$ git clone https://github.com/sifive/freedom-e-sdk

\$ sudo openocd -f freedom-e-sdk/bsp/sifive-hifive1/openocd.cfg &
Open On-Chip Debugger 0.10.0+dev-00198-g35eed36f (2018-12-16-20:53)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
adapter speed: 10000 kHz
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi_tdo_sample_edge falling"
Info : clock speed 10000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x10e31913 (mfg: 0x489 (SiFive, Inc.), part: 0x0e31, ver: 0x1)
Info : Examined RISCV core; XLEN=32, misa=0x40001105
Info : Listening on port 3333 for gdb connections
Info : [0] Found 2 triggers
halted at 0x20400904 due to debug interrupt
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

GDBからFlashのプロテクトを解除してelfをUSB経由で書き込みます。
\$ riscv32-unknown-elf-gdb
(gdb)set remotetimeout 240
(gdb)target extended-remote localhost:3333
(gdb)monitor reset halt
(gdb)monitor flash protect 0 64 last off
(gdb)load zephyr.elf 　　 #buildで生成されたelfファイル
(gdb)monitor resume

#HiFive1での動作確認
シリアル通信ができるターミナルから、ttyUSBxに115200 baudで接続し、HiFive1ボードのリセットボタンを押します。
\$ sudo gtkterm
![image.png](https://qiita-image-store.s3.amazonaws.com/0/324827/94f0b9b5-7c6f-efe1-0569-03be8d0ba578.png)

Zephyr OS上で表示をタスクとして実行できました。
オープンCPUとオープンRTOSの組み合わせで色々できそうです。

##QEMU
ちなみにQEMU版であれば、アプリケーションビルドのあとに make run だけで実行できるようになっています。

\$ make run
[  1%] Built target kobj_types_h_target
[  2%] Built target syscall_macros_h_target
[  3%] Generating misc/generated/syscalls.json
[  6%] Built target syscall_list_h_target
[  7%] Built target driver_validation_h_target
[  8%] Built target offsets
[  9%] Built target offsets_h
[ 34%] Built target kernel
[ 36%] Built target app
[ 37%] Built target linker_script_target
[ 70%] Built target zephyr
[ 82%] Built target lib__libc__minimal
[ 85%] Built target boards__riscv32__hifive1
[ 87%] Built target drivers__gpio
[ 89%] Built target drivers__spi
[ 91%] Built target drivers__serial
[ 93%] Built target zephyr_prebuilt
[ 94%] Built target linker_pass_final_script_target
[ 98%] Built target kernel_elf
Scanning dependencies of target run
[100%] 
To exit from QEMU enter: 'CTRL+a, x'
[QEMU] CPU: riscv32
***** Booting Zephyr OS v1.14.0-rc3-137-g6c6217e8b330 *****
Hello World! hifive1
From Heisei to Reiwa in Japan! hifive1
2019/04/07 hifive1
QEMU: Terminated
[100%] Built target run