SOLID未分類 QEMUでハードウェアなし開発(連載21)
(2023/11/06)
[連載21] QEMUでハードウェアなし開発
今回は、QEMUを使って、ハードウェアがない状態で開発する方法についてご紹介します。
一言で言うとハードウェアのシミュレータです。
組み込みのソフトウェア開発を開始するためには、まずハードウェアが手元にないと、ビルドまでしかできませんよね。
しかしQEMUを使うと、ハードウェアを仮想的に実現してくれます。
そうはいっても、動くのってCPUと割り込みとメモリくらいでしょ?
と、お思いかもしれません。
違います。
定義しさえすれば、いろんなハードウェアをエミュレートできます。
UARTとか、I2Cとか、SPIとか。。。
QEMUの公式サイトはこちらです。
https://www.qemu.org/
QEMUには、
・Full-system emulation:CPUのブートからすべてエミュレートする
・User-mode emulation:ユーザ―モードアプリのみエミュレートする
があります。
SOLIDは、Full-system emulation版を組み込んでいます。
すなわち、リセットベクタフェッチから始まるCPUの動作を模倣しています。
SOLIDでは、標準構成で、複数CPUs(32 or 64ビット、単一 or マルチCPU)、割り込み、メモリに加え、UARTが使用できます。
SDKを購入すると、その他のハードウェアを追加することも可能です。
お願いすると有償サポートもしてもらえます。
UARTだけなので完全にとはいかなくとも、以下のような要求を満たせそうですね。
・評価ボードが出来上がるまで時間がかかる。
・ソフトウェア開発者全員にいきわたる台数の評価ボードを作るのが難しい。
・評価ボードを送付できない拠点でソフトウェアの開発を行いたい。
とはいえ、UARTだけでも、
・ソフトウェアの基幹部分を作成しておきたい
・ARMコアの勉強をしたい
等の目的に使用できますね。
では早速試してみましょう。
SOLID for QEMUについては、以下URLで解説されています。
https://solid.kmckk.com/SOLID/doc/latest/qemu/qemu.html
ここからは、チュートリアルに従って試していきましょう。
まずSOLID-QEMU-<バージョン>.exeというファイルを入手します。
(SOLIDのライセンスを契約すると、入手できます)
インストールは簡単です。
そのSOLID-QEMU-<バージョン>.exeを実行すればOKです。
詳細は以下URLをご覧ください。
https://solid.kmckk.com/SOLID/doc/latest/qemu/tutorial/install.html
以下URLに従って実行していきます。
https://solid.kmckk.com/SOLID/doc/latest/qemu/tutorial/samples.html
マルチコアのデモプロジェクトを動かしてみます。
(サンプルプロジェクトは既に取得しています。)
① ソリューションファイルqemu-virtmini-aarch64-fmp3-2CPU-test-stack-usage-recog-Sを開きます。
② PARTNER-JetをPCに接続
ビルドにはライセンスが必要なので、PARTNER-Jet2をPCに接続して、ライセンスが取得できるようにしておきます。
③ ビルド
通常通りビルドします。
④ デバッグ開始します。
[Partner QEMU Debug Engine]ボタン押下でデバッグが開始されます。
⑤ 実行中
プログラムが実行されました。
Qemu-system-aarch64.exeが自動的に起動され、ログ出力が表示されています。
では、ブレークしてみて、ローカル変数を表示したりしてみましょう。
あらかじめブレークポイントを設定しておき、デバッグ開始してみます。
ブレークで停止し、デバッグに必要そうなウインドウをいろいろ開けてみました。
ローカル変数も表示されているし、RTOSビューアも、並列スタックも、各コア状態も。。。
ハードウェアがある場合と変わりませんね。
例外をわざと発生させてみて、ハードウェアがある場合と同じかどうかみてみましょう。
発生させる例外はMMU例外にしましょう。
0番地付近は仮想アドレスに物理メモリがマップされていません。
という事で、0番地にライトアクセスをしてみましょう。
適当に以下のコードを追加し、ビルドして実行してみます。
uint32_t *p;
p = 0;
*p = 0;
[デバッグ例外]ウインドウが表示され、Data Abort Exceptionと通知してくれました。
ハードウェアがある場合はこちら。同じですね。
https://note.com/yn_2022/n/ne8a0329d2fb1#c957e24e-1e6e-4948-97c0-a817de80a97a
次にスタックオーバーフローを発生させてみます。
void rec_func(){
rec_func();
}
この再帰関数を延々コールするとオーバーフローしますね。
スタックがオーバーフローしてるっぽいよ、と教えてくれました。
ハードウェアがある場合と同じですね。
https://note.com/yn_2022/n/ne8a0329d2fb1#87c24647-2aa4-49f3-bd7a-af21ec65cdbb
コードカバレジを取ってみましょう。
こちらで書いた内容をそっくりそのまま試してみます。
https://note.com/yn_2022/n/na660efb50d37
取れました。
その他、関数トレース、ローダー機能、アドレスサニタイザ機能などなど、ハードウェアがある場合と同じように使用することができます。
ハードウェアがある場合と同じにならない可能性が一番高いのは、周辺I/Oですよね。
これについても、想定のハードウェア構成に近づけることは可能です。
(どこまでやるか、ですが)
どこで定義されているのかについて、以下のURLで解説されています。
https://solid.kmckk.com/SOLID/doc/latest/qemu/virtualboard.html
以下の部品が標準で搭載されています。
CPU: ARM Cortex-A53(シングルコア or マルチコア)
割り込みコントローラ: GIC-400
タイマ: Generic Timer
UART: PL011
ROMなし、RAM 2GB
ハードウェア構成を知るためにQEMUが参照するのは、.dtb (device tree blob)ファイルです。dtsファイルはそのソースファイルです。
これらはプロジェクトのqemuフォルダ内にあります。
このファイルは、コアの数によって形式が違います。
(CPUの数以外のハードウェア構成は同じです。)
今回使用した2-CPUコアの場合、dual-aarch64.dtsで定義されています。
例えば、RAMのサイズについては以下のように定義されています。
この値を変更すれば、標準構成の2GBから変更することができます。
では、周辺I/Oについてはどうでしょうか。
UARTを見てみます。
ここで、UARTチャンネル名を変更したり、UART本数を増やしたりができます。
UARTの出力先についても、標準ではQEMUのコンソールとなっていますが、TCPポートに変更することもできます。
詳細はこちら。
https://solid.kmckk.com/SOLID/doc/latest/qemu/virtualboard.html#uart
DTSファイルの変更を反映されるためには、SOLID付属のdtcコマンドでdtbファイルを再生成します。
手順については以下のURLで紹介されています。
https://solid.kmckk.com/SOLID/doc/latest/qemu/virtualboard.html#id5
その他、I2C等の別の周辺I/Oを追加するには、別途SDKを購入するか有償サポートが必要です。
手軽にこういったシミュレータが使えるのは嬉しいですね。
QEMUというと、ちょっと使うのにハードルがあるイメージがあったのですが、SOLIDでは既に開発ツールの一つとして組み込まれているので、サクッと使えました。
それに各周辺I/Oがないからといって、何もできないわけではありませんよね。
ソフトウェアの構造、大枠を作ることはできるわけです。
タスクの個数や役割を決めたり、ローダブルモジュールとして切り分けるところを作成したり、いろいろとできます。
それに例えばI2C経由でセンサをアクセスするところは空関数にしておいて、後でハードウェアが入手できたら実装する、という手順で開発するなどできそうです。
また、冒頭で書いた通り、SOLIDではQEMUのFull-system emulation版を組み込んでいるため、リセット解除からのCPU動作をエミュレートしています。
ハードウェアはなくとも本物のCPUの動きを見ることができるので、ARMコアの学習にももってこいですね。
CPUの学習をしたいだけなのにハードウェアのトラブルに悩まされる、、、という事もありませんしね。
次回は、引き続きSOLID for QEMUの機能についてご紹介をする予定です。