Zephyr で raspi pico の LED をチカチカさせてみた

# はじめに
最近、[Zephyr](https://zephyrproject.org/) [^1] という RTOS に興味があります。
POSIX に対応していて、[ネットワークの機能](https://docs.zephyrproject.org/latest/connectivity/networking/overview.html) [^2] も充実しているようです。

本記事では、LED を点滅させる [Blinky Sample](https://docs.zephyrproject.org/latest/samples/basic/blinky/README.html) [^3] の動作確認を Raspberry Pi Pico で行います。
なお、コマンドの出力結果は適宜省略しています。

# 環境構築
Zephyr の中の方によると「環境構築は Ubuntu がおすすめ」ということだったので、N100 Windows ミニ PC に Ubuntu 24.04 をインストールしました。

## マシンスペック
```console
$ cat /proc/cpuinfo | grep 'model name' | uniq
model name	: Intel(R) N100

$ cat /proc/meminfo | grep -i memtotal | tr -s ' ' | cut -f2,3 -d' ' | tr -d ' B' | tr [:lower:] [:upper:] | numfmt --from=auto --to=iec-i
16Gi

$ lsblk -N -o NAME,TYPE,SIZE,MODEL
NAME    TYPE   SIZE MODEL
nvme0n1 disk 476.9G 512GB SSD
```

## OS
```console
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.1 LTS"

$ uname -srvmpio
Linux 6.8.0-51-generic #52-Ubuntu SMP PREEMPT_DYNAMIC Thu Dec  5 13:09:44 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
```

### 余談
元々は、Windows を潰してしまおうと思ったのですが、Ubuntu のインストーラーにデュアルブートの選択肢があったので試しに選んでみたところ、さくっとインストールできました。
ただ、インストール時の設定がよくなかったのか、PC の電源を入れると選択肢が表示されずに Windows が自動起動してしまうので、Ubuntu を使いたい場合は毎回 UEFI の設定メニューに入り GRUB を立ち上げる必要があります。
さすがに不便なので、時間のあるときに GRUB のメニューが表示されるようにしたいと思います。

## Zephyr
基本的には、公式ドキュメントの [Getting Started Guide](https://docs.zephyrproject.org/latest/develop/getting_started/index.html) [^4] に従います。

### OS の更新
```console
~ $ sudo apt update && sudo apt upgrade -y
~ $ reboot # 念の為再起動
```

### 依存パッケージのインストール
```console
~ $ sudo apt install --no-install-recommends git cmake ninja-build gperf \
  ccache dfu-util device-tree-compiler wget \
  python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \
  make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1
```

メインとなるツールのバージョンを確認します。

```console
~ $ cmake --version # >= 3.20.5
cmake version 3.28.3

CMake suite maintained and supported by Kitware (kitware.com/cmake).

~ $ python3 --version # >= 3.10
Python 3.12.3

~ $ dtc --version # >= 1.4.6
Version: DTC 1.7.0
```

### Zephyr の取得と Python の依存パッケージインストール
まずは、Python の `venv` パッケージをインストールします。

```console
~ $ sudo apt install python3-venv
```

次に、Python の仮想環境を作成し、アクティベートします。

```console
~ $ python3 -m venv ~/zephyrproject/.venv
~ $ source ~/zephyrproject/.venv/bin/activate
```

アクティベートに成功すると、プロンプトに `(.venv)` というプレフィックスが追加されます。

[West コマンド](https://docs.zephyrproject.org/latest/develop/west/index.html) [^5] をインストールします。

```console
(.venv) ~ $ pip install west
```

Zephyr のソースコードを取得します。

```console
(.venv) ~ $ west init ~/zephyrproject
(.venv) ~ $ cd ~/zephyrproject
(.venv) ~/zephyrproject $ west update
```

[Zephyr CMake Package](https://docs.zephyrproject.org/latest/build/zephyr_cmake_package.html) [^6] をエクスポートします。

```console
(.venv) ~/zephyrproject $ west zephyr-export
```

Zephyr に必要な pip パッケージをインストールします。

```console
(.venv) ~/zephyrproject $ west packages pip --install
```

### Zephyr SDK のインストール
[Zephyr SDK](https://docs.zephyrproject.org/latest/develop/toolchains/zephyr_sdk.html) [^7] をインストールします。
コマンドを打つだけですが、完了までそれなりに時間がかかりました。

```console
(.venv) ~/zephyrproject $ cd ~/zephyrproject/zephyr
(.venv) ~/zephyrproject/zephyr $ west sdk install
```

# Blinky Sample
こちらも[公式ドキュメント](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#build-the-blinky-sample) [^8] に従って作業を進めます。

## ビルド
書き込み先のボード名を指定する必要があるので調べます。

```console
(.venv) ~/zephyrproject/zephyr $ west boards | grep rpi
rpi_pico2
rpi_pico
rpi_5
rpi_4b
```

ビルドします。

```console
(.venv) ~/zephyrproject/zephyr $ west build -p always -b rpi_pico samples/basic/blinky
-- west build: making build dir /home/reodon/zephyrproject/zephyr/build pristine
-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /home/reodon/zephyrproject/zephyr/samples/basic/blinky
-- CMake version: 3.28.3
-- Found Python3: /home/reodon/zephyrproject/.venv/bin/python3 (found suitable version "3.12.3", minimum required is "3.10") found components: Interpreter 
-- Cache files will be written to: /home/reodon/.cache/zephyr
-- Zephyr version: 4.0.99 (/home/reodon/zephyrproject/zephyr)
-- Found west (found suitable version "1.3.0", minimum required is "0.14.0")
-- Board: rpi_pico, qualifiers: rp2040
-- ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK
-- Found host-tools: zephyr 0.17.0 (/home/reodon/zephyr-sdk-0.17.0)
-- Found toolchain: zephyr 0.17.0 (/home/reodon/zephyr-sdk-0.17.0)
-- Found Dtc: /home/reodon/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/bin/dtc (found suitable version "1.6.0", minimum required is "1.4.6") 
-- Found BOARD.dts: /home/reodon/zephyrproject/zephyr/boards/raspberrypi/rpi_pico/rpi_pico.dts
-- Generated zephyr.dts: /home/reodon/zephyrproject/zephyr/build/zephyr/zephyr.dts
-- Generated pickled edt: /home/reodon/zephyrproject/zephyr/build/zephyr/edt.pickle
-- Generated zephyr.dts: /home/reodon/zephyrproject/zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /home/reodon/zephyrproject/zephyr/build/zephyr/include/generated/zephyr/devicetree_generated.h
-- Including generated dts.cmake file: /home/reodon/zephyrproject/zephyr/build/zephyr/dts.cmake
Parsing /home/reodon/zephyrproject/zephyr/Kconfig
Loaded configuration '/home/reodon/zephyrproject/zephyr/boards/raspberrypi/rpi_pico/rpi_pico_defconfig'
Merged configuration '/home/reodon/zephyrproject/zephyr/samples/basic/blinky/prj.conf'
Configuration saved to '/home/reodon/zephyrproject/zephyr/build/zephyr/.config'
Kconfig header saved to '/home/reodon/zephyrproject/zephyr/build/zephyr/include/generated/zephyr/autoconf.h'
-- Found GnuLd: /home/reodon/zephyr-sdk-0.17.0/arm-zephyr-eabi/arm-zephyr-eabi/bin/ld.bfd (found version "2.38") 
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /home/reodon/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
-- Using ccache: /usr/bin/ccache
-- Configuring done (5.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/reodon/zephyrproject/zephyr/build
-- west build: building application
[1/141] Preparing syscall dependency handling

[7/141] Generating include/generated/zephyr/version.h
-- Zephyr version: 4.0.99 (/home/reodon/zephyrproject/zephyr), build: v4.0.0-2771-gfdf0ec2e5f9c
[8/141] Performing configure step for 'second_stage_bootloader'
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/reodon/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/reodon/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The ASM compiler identification is GNU
-- Found assembler: /home/reodon/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: /home/reodon/zephyrproject/zephyr/build/bootloader
[9/141] Performing build step for 'second_stage_bootloader'
[1/2] Building ASM object CMakeFiles/boot_stage2.dir/home/reodon/zephyrproject/modules/hal/rpi_pico/src/rp2040/boot_stage2/boot2_w25q080.S.obj
[2/2] Linking ASM executable boot_stage2
[141/141] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
      BOOT_FLASH:         256 B        256 B    100.00%
           FLASH:       15620 B    2096896 B      0.74%
             RAM:        3968 B       264 KB      1.47%
        IDT_LIST:          0 GB        32 KB      0.00%
Generating files from /home/reodon/zephyrproject/zephyr/build/zephyr/zephyr.elf for board: rpi_pico
Converted to uf2, output size: 32256, start address: 0x10000000
Wrote 32256 bytes to zephyr.uf2

(.venv) ~/zephyrproject/zephyr $ echo $?
0
```

ビルドは成功したように見えます。

## 書き込み
公式ドキュメントに注釈がいくつかあるので、このままでは失敗しそうですが書き込みをしてみました。

```console
(.venv) ~/zephyrproject/zephyr $ west flash
-- west flash: rebuilding
[1/10] Performing build step for 'second_stage_bootloader'
ninja: no work to do.
[3/3] Completed 'second_stage_bootloader'
-- west flash: using runner openocd
-- runners.openocd: Flashing file: /home/reodon/zephyrproject/zephyr/build/zephyr/zephyr.hex
Open On-Chip Debugger 0.11.0+dev-00728-gb6f95a16c-dirty (2024-10-20-01:26)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
set_adapter_speed_if_not_set
swd
Can't find target/rp2040.cfg
FATAL ERROR: command exited with status 1: /home/reodon/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/bin/openocd -s /home/reodon/zephyrproject/zephyr/boards/raspberrypi/rpi_pico/support -s /home/reodon/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/share/openocd/scripts -f /home/reodon/zephyrproject/zephyr/boards/raspberrypi/rpi_pico/support/openocd.cfg -c 'source [find interface/cmsis-dap.cfg]' -c 'transport select swd' -c 'source [find target/rp2040.cfg]' -c 'set_adapter_speed_if_not_set 2000' '-c init' '-c targets' -c 'reset init' -c 'flash write_image erase /home/reodon/zephyrproject/zephyr/build/zephyr/zephyr.hex' -c 'reset run' -c shutdown
```

案の定失敗しました。

[Raspberry Pi Pico への書き込みに関するドキュメント](https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi_pico/doc/index.html#flashing) [^9] がありました。
こちらによると：

1. Using SEGGER JLink
2. Using OpenOCD
3. Using UF2

の3つの方法があるようです。
どの方法もよくわからないので、一番簡単に見える UF2 を利用する方法を試してみました。

### Using UF2
ドキュメントにある通り、Raspberry Pi Pico の `BOOTSEL` ボタンを押しながら電源を入れ、下記コマンドを実行しました。

```console
(.venv) ~/zephyrproject/zephyr $ cp ./build/zephyr/zephyr.uf2 /media/reodon/RPI-RP2/
```

すると、LED がチカチカし始めました！

# おわりに
元々は、古いノート PC に Ubuntu をクリーンインストールしたのですが、サンプルプログラムをビルドする直前に壊れてしまったので、急遽ミニ PC で環境構築をすることになりました。
そんなトラブルもありましたが、今後も Zephyr の勉強を続けたいと思います。
まずは、[Raspberry Pi Debug Probe](https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html) [^10] を使った書き込みを試します。



[^1]: https://zephyrproject.org/
[^2]: https://docs.zephyrproject.org/latest/connectivity/networking/overview.html
[^3]: https://docs.zephyrproject.org/latest/samples/basic/blinky/README.html
[^4]: https://docs.zephyrproject.org/latest/develop/getting_started/index.html
[^5]: https://docs.zephyrproject.org/latest/develop/west/index.html
[^6]: https://docs.zephyrproject.org/latest/build/zephyr_cmake_package.html
[^7]: https://docs.zephyrproject.org/latest/develop/toolchains/zephyr_sdk.html
[^8]: https://docs.zephyrproject.org/latest/develop/getting_started/index.html#build-the-blinky-sample
[^9]: https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi_pico/doc/index.html#flashing
[^10]: https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html