今回から、Renode というオープンソースの組込みデバイスのエミュレータを試していきます。
簡単に言うと、QEMU と同じ位置付けの OSS です。QEMU よりも、組込みデバイスのサポートが充実しているようです。
それでは、やっていきます。
はじめに
「QEMUを動かす」の記事一覧です。良かったら参考にしてください。
・第2回:STM32(ARM Cortex-M)をQEMUで動かす(ソースコード確認編)
・第3回:STM32(ARM Cortex-M)をQEMUで動かす(スタートアップルーチン編)
・第4回:STM32(ARM Cortex-M)をQEMUで動かす(リンカスクリプト編)
・第5回:STM32(ARM Cortex-M)のELFファイルの内容を確認する
・第6回:STM32(ARM Cortex-M)のELFファイル⇔バイナリの変換を行う
・第7回:STM32(ARM Cortex-M)のバイナリから構築したELFファイルをQEMUで動かす
・第8回:QEMUのビルドに必要なxpm(xPack Project Manager)について学ぶ
・第9回:QEMUをソースからビルドして動かす
・第10回:QEMUのソースコードを変更してSTM32の動作を変える
・第11回:QEMUに似たRenodeというOSSの組込みデバイスエミュレータを試す ← 今回 ・第12回:QEMUに似たRenodeでSTM32をGDBを使ってデバッグする
まず、Renode の公式サイトは以下です。
Renode の公式のドキュメントは以下です。
https://renode.readthedocs.io/en/latest/
また、GitHub は以下です。
https://github.com/renode/renode
今回は、Renode のインストールと、サンプルソースの動作確認をやっていきます。
Renodeのインストール
インストール手順は、公式の GitHub に書かれているので、それに従います。
と言っても、Renode 自体は、portable を選べば、解凍するだけです。
依存しているパッケージとして、mono-complete パッケージを先にインストールする必要があります。
それではやっていきます。
mono-completeのインストール
以下の公式サイトの手順に従います。
今回は、VirtualBox の Ubuntu 22.04 にインストールしますが、Ubuntu 20.04 の手順までしか書かれてないですね。Ubuntu 20.04 の手順に従います。
$ sudo apt install ca-certificates gnupg ca-certificates はすでに最新バージョン (20230311ubuntu0.22.04.1) です。 gnupg はすでに最新バージョン (2.2.27-3ubuntu2.1) です。 $ sudo gpg --homedir /tmp --no-default-keyring --keyring /usr/share/keyrings/mono-official-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF gpg: keybox'/usr/share/keyrings/mono-official-archive-keyring.gpg'が作成されました gpg: /tmp/trustdb.gpg: 信用データベースができました gpg: 鍵A6A19B38D3D831EF: 公開鍵"Xamarin Public Jenkins (auto-signing) <releng@xamarin.com>"をインポートしました gpg: 処理数の合計: 1 gpg: インポート: 1 $ echo "deb [signed-by=/usr/share/keyrings/mono-official-archive-keyring.gpg] https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list deb [signed-by=/usr/share/keyrings/mono-official-archive-keyring.gpg] https://download.mono-project.com/repo/ubuntu stable-focal main $ sudo apt update $ sudo apt install mono-devel
結構多きかったですね。
$ mono -V Mono JIT compiler version 6.12.0.200 (tarball Tue Jul 11 21:37:50 UTC 2023) Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com TLS: __thread SIGSEGV: altstack Notifications: epoll Architecture: amd64 Disabled: none Misc: softdebug Interpreter: yes LLVM: yes(610) Suspend: hybrid GC: sgen (concurrent by default)
バージョン 6.12 がインストールされました。Renode には、バージョン 5.2 以上が必要という条件でした。
依存関係のパッケージインストール
続いて、他の依存関係のパッケージをインストールします。
$ sudo apt-get install policykit-1 libgtk2.0-0 screen uml-utilities gtk-sharp2 libc6-dev gcc python3 python3-pip
Renodeのダウンロードとインストール
Renode 用に専用の作業ディレクトリを作って、そこに Renode をダウンロードします。
$ mkdir renode $ cd renode $ wget https://github.com/renode/renode/releases/download/v1.15.0/renode-1.15.0.linux-portable.tar.gz
公式の手順では、解凍に -C と --strip-components=1 を使っていますが、同じことを実現するのに、別の手順を使うのは、効率が良くないと思います。
ということで、普通のやり方にします。
$ tar zxvf renode-1.15.0.linux-portable.tar.gz $ renode_1.15.0_portable/renode -v Renode v1.15.0.27975 build: 9111b18e-202403181532 build type: Release runtime: Mono 4.0.30319.42000
Renode のインストールは以上です。
STM32で動作確認
公式のドキュメントには、STM32 のチュートリアルは見当たりませんでした。代わりに以下のページを見つけました。
少し古いですが、このページのチュートリアルをやっていきます。
サンプルソースのビルド
起動方法が現在のものとは異なっていたり、エミュレーション開始時の挙動が少し異なります。
$ git clone https://github.com/memfault/interrupt.git $ cd interrupt/example/renode/ $ make git clone https://github.com/libopencm3/libopencm3.git libopencm3 Cloning into 'libopencm3'... remote: Enumerating objects: 30727, done. remote: Counting objects: 100% (149/149), done. remote: Compressing objects: 100% (104/104), done. remote: Total 30727 (delta 83), reused 75 (delta 45), pack-reused 30578 Receiving objects: 100% (30727/30727), 7.04 MiB | 25.76 MiB/s, done. Resolving deltas: 100% (20039/20039), done. Initializing OPENCM3 Lib git -C libopencm3 checkout 89074d6a13ed7febba04d3c421ce7bf2b7972156 Note: switching to '89074d6a13ed7febba04d3c421ce7bf2b7972156'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c <new-branch-name> Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 89074d6a stm32h7: fix inverted VOS settings for Vcore. make -C libopencm3 make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' に入ります GENHDR include/libopencm3/stm32/f0/irq.json /usr/bin/env: `python': そのようなファイルやディレクトリはありません make[1]: *** [Makefile:59: include/libopencm3/stm32/f0/irq.json.genhdr] エラー 127 make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' から出ます make: *** [Makefile:17: libopencm3/89074d6a13ed7febba04d3c421ce7bf2b7972156] エラー 2
エラーが出ました。Git でエラーが出てるようです?ので、対処します。
$ cd libopencm3/ $ git switch - $ cd .. $ make Initializing OPENCM3 Lib git -C libopencm3 checkout 89074d6a13ed7febba04d3c421ce7bf2b7972156 HEAD is now at 89074d6a stm32h7: fix inverted VOS settings for Vcore. make -C libopencm3 make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' に入ります GENHDR include/libopencm3/stm32/f0/irq.json /usr/bin/env: `python': そのようなファイルやディレクトリはありません make[1]: *** [Makefile:59: include/libopencm3/stm32/f0/irq.json.genhdr] エラー 127 make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' から出ます make: *** [Makefile:17: libopencm3/89074d6a13ed7febba04d3c421ce7bf2b7972156] エラー 2
Git は原因ではなかったかもしれません。python が無いと言われてます。python3 はあるので、シンボリックリンクを作って対応します。
$ which python3 /usr/bin/python3 $ cd /usr/bin/ $ sudo ln -s python3 python $ cd - $ make Initializing OPENCM3 Lib git -C libopencm3 checkout 89074d6a13ed7febba04d3c421ce7bf2b7972156 HEAD is now at 89074d6a stm32h7: fix inverted VOS settings for Vcore. make -C libopencm3 make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' に入ります GENHDR include/libopencm3/stm32/f0/irq.json GENHDR include/libopencm3/stm32/f1/irq.json GENHDR include/libopencm3/stm32/f2/irq.json (長いので省略) CC sync.c CC dwt.c AR libopencm3_pac55xx.a make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode/libopencm3' から出ます touch libopencm3/89074d6a13ed7febba04d3c421ce7bf2b7972156 Building renode example app make -f Makefile_renode_example.mk make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode' に入ります CC renode-example.c GENLNK stm32f407vgt6 LD renode-example.elf OBJCOPY renode-example.bin make[1]: ディレクトリ '/home/daisuke/svn_/renode/interrupt/example/renode' から出ます
ビルドは成功したようです。
実行してみる
Renode は解凍したディレクトリ以下のパスを、@xxx という形で、相対パスで指定できるようです。生成された ELFファイルのシンボリックリンクを Renode のディレクトリに作ることにします。
$ cd renode_1.15.0_portable/ $ ln -s ../interrupt/example/renode/renode-example.elf
それでは、Renode を起動していきます。
$ ./renode
Renode を起動すると、Renode モニターと呼ばれる、Renode 用のコンソールが自動的に立ち上がります(下図の右側のウィンドウ)。

この Renode モニターで、以下のように、環境の構築、評価ボードの指定、ELF ファイルのロード、UART 用のモニターの起動、GDB の設定などを行い、最後に start でエミュレーションを開始します。
(monitor) mach create (machine-0) machine LoadPlatformDescription @platforms/boards/stm32f4_discovery-kit .repl (machine-0) sysbus LoadELF @renode-example.elf (machine-0) showAnalyzer sysbus.usart2 (machine-0) machine StartGdbServer 3333 (machine-0) start
しかし、チュートリアルにもあるように、今回の評価ボードの設定が、CCM メモリに対応していないため、以下のような大量の警告が出ます。
18:04:50.1427 [WARNING] sysbus: [cpu: 0x8000D94] WriteDoubleWord to non existing peripheral at 0x1004CC3C, value 0x0.
チュートリアルの方で、CCM の設定を作ってくれているので、それを使います。拡張子が repl のファイルは、REnode PLatform という Renode の設定ファイルです。
$ cp ../interrupt/example/renode/add-ccm.repl ./ $ cat add-ccm.repl ccm: Memory.MappedMemory @ sysbus 0x10000000 size: 0x10000
ついでに、シェルスクリプトのように、自動的に設定などを実行するファイルもコピーしておきます。この拡張子が resc のファイルも Renode で使うファイルで、REnode SCripts から来ているようです。
先ほど、手動で実行した内容が、書かれています。
$ cp ../interrupt/example/renode/renode-config.resc ./ cat renode-config.resc :name: STM32F4 Discovery Printf :description: This script runs the usart_printf example on stm32f4 discovery $name?="STM32F4_Discovery" $bin?=@renode-example.elf # Create Machine & Load config mach create $name machine LoadPlatformDescription @platforms/boards/stm32f4_discovery-kit.repl machine LoadPlatformDescription @add-ccm.repl # Create a terminal window showing the output of UART2 showAnalyzer sysbus.usart2 # Enable GDB machine StartGdbServer 3333 macro reset """ sysbus LoadELF $bin """ runMacro $reset
では、今度は、rescファイルを使って実行します。Renode の起動に引数として、rescファイルを指定することが出来ます。
$ ./renode renode-config.resc
起動した Renodeモニターに、「start」を入力します。

USART で警告が出てるのが気になりますが、とりあえず、動作したようです。
おわりに
今回は、QEMU に似た、Renode というエミュレータを動かしてみました。
少し使ってみた印象としては、QEMU より扱いやすく、UI(ユーザインタフェース)が洗練されている感じです。QEMU は、CCMデータRAM に対応していませんでしたが、Renode は、設定を追加するだけで対応できました。
また、QEMU は、Eclipse で使えましたが、Renode は、VSCode のデバッグに公式のドキュメントとして対応しています(QEMU も VSCode で動かせると思います)。
次回は、Renode で GDB を使ってデバッグをしてみたいと思います。
この記事が誰かの役に立てば嬉しいです。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。