嵌入式編程中使用qemu能夠做什么?
背景
學習QEMU以后,為了拓展視野,才發現QEMU可以做這么多的事情。
原文鏈接(有刪改):https://www.eet-china.com/mp/a56346.html
仿真裸機或RTOS編程
qemu的是指令翻譯進行的,所以可以根據實際的需求進行相應的裸機開發和學習,比如語言學習,嵌入式C語言,嵌入式RUST語言,等等項目。一些github上的好用學習型的項目也會對qemu進行支持,用RUST語言在arm上的編程,即使手上沒有很好的硬件的條件,也能夠去學習RUST語言在嵌入式編程上的使用。
然而嵌入式開發往往會和硬件打交道,qemu也提供了不同類別的硬件,比如flash,網卡,sd卡,中斷,串口等等,這些對於學習不同的體系架構,也有着非常關鍵的作用。
指令驗證
除此之外,也可以在qemu的支持上做了一些擴展開發,比如在riscv的生態支持上對gd32的rv-star在中科院軟件研究所的基礎上做了一些研究,同時對nuclei的各種處理器系列做了適配。這樣對於軟件層面的驗證更加有用,比如去運行一下nuclei-sdk,或者對於RISCV的V擴展的支持的nmsis的支持。
qemu-system-riscv64 -M nuclei_n,download=ilm -cpu nuclei-nx600fdp -nodefaults -nographic -serial stdio -kernel CMSIS/nmsis_release/NMSIS/DSP/Examples/RISCV/riscv_matrix_example/dsp_example.elf
這樣可以進行相關的dsp的驗證工作。因為nmsis
是基於arm的cmsis
在riscv上的一份移植,其中實現了許多的加速運算的demo,比如矩陣運算,卷積,圖像處理等等,這些指令同樣也可以在nuclei qemu中計算出正確的結果。
利用qemu作為底層研究將會非常的高效。同時,善於借助gdb等調試工具,將能夠非常容易的找到問題出現的點。
利用qemu網絡編程研究
由於qemu的網絡可以直接連接主機的網絡,對這方面的研究可以從網絡協議棧,網絡的上層應用編程等等進行研究。例如去研究lwip協議棧的實現等等。
其中socket的編程部分實際上是通用的,無論是arm架構、mips架構或者riscv架構,借助qemu的好處在於可以采用一個架構平台,進行協議棧或者上層開發后,可以無縫的移植到自己的真實的板子上,非常方便進行整體業務的聯調。
對於qemu riscv64 virt平台,整個系統從底層的virtio或者e1000的網卡設備提供數據的收發、中斷消息機制之外,rt-thread也通過提供lwip協議棧的支持,這樣整個網絡鏈路才是比較合理的。開發起來也比較的方便。
在物聯網模塊的開發方面,采用qemu,也可以不用rt-thread,直接裸機驅動virt上的e1000網卡驅動,然后借助對寄存器的讀寫操作,移植其他的網絡協議棧,從而實現網絡數據的收發工作,網絡編程的上層對接阿里雲、騰訊雲等雲服務器,非常容易的實現業務的編程,同時調試方面,qemu的gdb調試功能也是非常的強大,也可以dump出內存進行ram parse分析。
嵌入式圖形開發
因為嵌入式編程的實現,也會多少涉及到圖形編程,當接上LCD屏后,其中的顯示驅動對上層應用暴露出來的實際上是一塊顯存,通過對顯存的讀寫,flush進行lcd的圖像更新。
在圖像編程方面,qemu也提供了顯示窗口。這種顯示窗口可以為gui相關的開發工作帶來很多便捷。
進行嵌入式Linux的開發
進行Linux開發工作,如果深入去學習某一個設備的開發,當然少不了不斷的對Linux的內核部分進行編譯和下載,這是一個十分耗時的工作,如果只是進行應用程序的開發,可能感覺不到許多的差別,但是一旦涉及到Linux內核的分析,頻繁的下載也會浪費大量的時間。
當使用qemu后,這種問題將會得到很好的解決,采用qemu進行內核層面的裁剪,進行內核層面模塊化的驗證工作后,再進行移植,讓其變得更加通用,不僅僅針對這個項目有效,而且也為自己積累了很多經驗。
$ qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext3
WARNING: Image format was not specified for 'rootfs.ext3' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
Booting Linux on physical CPU 0x0
Linux version 4.14.0 (schips@odm-android-fs) (gcc version 7.5.0 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)) #1 SMP Fri Jul 16 21:25:45 CST 2021
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writeback
CPU: All CPU(s) started in SVC mode.
percpu: Embedded 16 pages/cpu @9fbae000 s36428 r8192 d20916 u65536
Built 1 zonelists, mobility grouping on. Total pages: 130048
Kernel command line: root=/dev/mmcblk0 rw console=ttyAMA0
log_buf_len individual max cpu contribution: 4096 bytes
log_buf_len total cpu_extra contributions: 12288 bytes
log_buf_len min size: 16384 bytes
log_buf_len: 32768 bytes
early log buf free: 15000(91%)
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 509556K/524288K available (6144K kernel code, 402K rwdata, 1368K rodata, 1024K init, 169K bss, 14732K reserved, 0K cma-reserved)
Virtual kernel memory layout:
從分析linux的loader,分析Linux的驅動框架,內存管理,多核管理等等,都能夠非常方便進行調試工作。
在實際硬件設備沒有穩定之前,對軟件項目進行評估,qemu是非常好用的工具。