1.前言嵌入式開發的過程中,很多時間都是要和硬件設備打交道,通過程序控制硬件的具體行為,這些往往是單片機延續下來的開發模式,在目前復雜的嵌入式系統中,很多都需要借助設計模式來進行開發,比如文件系統,網絡,圖形,算法等等,這些如果能夠利用軟件模擬器進行開發,可以大大的減少上板調試的時間。減少硬件連接的煩惱,在家也能隨時分析軟件代碼。
在實際項目的開發過程中,qemu也非常的有用,例如當進行網絡編程時,往往都會直接使用socket編程,其上層接口符合POSIX接口,這樣上層應用的開發和底層驅動便可以很簡單的分離出來,將工作細節進行合理的劃分。而當進行嵌入式GUI編程設計時,也可以通過framebuffer,來進行各種界面的設計。同時,如果想新學習一款嵌入式編程語言,或者深入理解一些處理器的架構方面的知識,通過裸機編程,直接到qemu上運行也能夠非常方便的進行探究工作。
下面舉出一些qemu實際好用的應用來進行詳細的描述。
2.嵌入式的裸機或RTOS編程
qemu的是指令翻譯進行的,所以可以根據實際的需求進行相應的裸機開發和學習,比如語言學習,嵌入式C語言,嵌入式RUST語言,等等項目。一些github上的好用學習型的項目也會對qemu進行支持,用RUST語言在arm上的編程,即使手上沒有很好的硬件的條件,也能夠去學習RUST語言在嵌入式編程上的使用。
針對arm的編程,qemu也可以模擬出許多的架構出來,通過對這些架構的學習和掌握,可以加快對架構編程的理解。
。/qemu-system-arm -M virt -cpu ?
Available CPUs:
arm1026
arm1136
arm1136-r2
arm1176
arm11mpcore
arm926
arm946
cortex-a15
cortex-a7
cortex-a8
cortex-a9
cortex-m0
cortex-m3
cortex-m33
cortex-m4
cortex-m55
cortex-m7
cortex-r5
cortex-r5f
max
pxa250
pxa255
pxa260
pxa261
pxa262
pxa270-a0
pxa270-a1
pxa270
pxa270-b0
pxa270-b1
pxa270-c0
pxa270-c5
sa1100
sa1110
ti925t
然而嵌入式開發往往會和硬件打交道,qemu也提供了不同類別的硬件,比如flash,網卡,sd卡,中斷,串口等等,這些對于學習不同的體系架構,也有著非常關鍵的作用。
比如學習cortex-m3或者aarch64編程,采用qemu,運行自己寫的裸機代碼,能夠非常方便的進行各種實驗。
在進行rtos的開發過程中,經常會采用qemu作為調試工具,進行龍芯、樹莓派、riscv相關的開發和驗證工作。在rtos中,比較關鍵的是上下文的切換,通過對寄存器信息的保存和恢復,另外就是中斷的處理,能夠很好的理解架構的底層編程方式。
以前的時候,也做過aarch64上的qemu編程,也是最開始基于qemu,然后慢慢的移植到樹莓派上面,因為外設一致,代碼層面不用改變,直接可以將qemu運行通過的固件放到樹莓派的sd卡中也一樣能夠正常的運行。
上圖是在qemu的rt-thread/bsp/raspberry-pi/raspi3-64中編譯的固件在qemu上的運行效果,基本上完成對aarch64體系架構中的棧幀、中斷、mmu的支持,以及外設部分SD卡、圖形、串口、mbox的支持。該固件也可以直接放到樹莓派硬件的sd卡中運行,其效果和在qemu效果一樣。
除此之外,我也在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中計算出正確的結果。
由于對riscv的p擴展和v擴展的支持,使得其行為和實際硬件板子無差異。在qemu做算法優化和研究也是非常值得去嘗試的。雖然qemu是用軟件去模擬真實計算結果,但是從指令集的優化層面上來說,當功能邏輯實現正確后再移植到板子上做性能測試,這才是高效的處理方法。
在支持baremetal編程和rtos編程方面,nuclei-sdk也做了一些工作,可以更加好的觀察分析軟件的具體行為。
qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/rtthread/msh/msh.elf
Nuclei SDK Build Time: May 31 2021, 1118
Download Mode: ILM
CPU Frequency 168290222 Hz
| /
- RT - Thread Operating System
/ | 3.1.3 build May 31 2021
2006 - 2019 Copyright by rt-thread team
Hello RT-Thread!
msh 》
msh 》ps
thread pri status sp stack size max used left tick error
-------- --- ------- ---------- ---------- ------ ---------- ---
tshell 6 ready 0x000000d8 0x00001000 10% 0x0000000a 000
tidle 7 ready 0x00000078 0x00000200 23% 0x00000020 000
main 2 suspend 0x000000b8 0x00000400 17% 0x00000013 000
msh 》
也可以支持其他的rtos,例如下面的ucosii和freertos等等。
ucosii的運行效果如下:
qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/ucosii/demo/demo.elf
Nuclei SDK Build Time: May 31 2021, 1145
Download Mode: ILM
CPU Frequency 182521692 Hz
Start ucosii.。。
create start task success
start all task.。。
task3 is running.。。 1
task2 is running.。。 1
task1 is running.。。 1
task3 is running.。。 2
task2 is running.。。 2
task3 is running.。。 3
task2 is running.。。 3
task1 is running.。。 2
task3 is running.。。 4
task2 is running.。。 4
task3 is running.。。 5
task2 is running.。。 5
freertos的運行效果如下:
qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/freertos/demo/demo.elf
Nuclei SDK Build Time: May 31 2021, 1145
Download Mode: ILM
CPU Frequency 232205516 Hz
Before StartScheduler
Enter to task_1
task1 is running 0.。。。。
Enter to task_2
task2 is running 0.。。。。
timers Callback 0
timers Callback 1
task1 is running 1.。。。。
task2 is running 1.。。。。
timers Callback 2
timers Callback 3
task1 is running 2.。。。。
task2 is running 2.。。。。
利用qemu作為底層研究將會非常的高效。同時,善于借助gdb等調試工具,將能夠非常容易的找到問題出現的點。
3.利用qemu網絡編程
研究由于qemu的網絡可以直接連接主機的網絡,對這方面的研究可以從網絡協議棧,網絡的上層應用編程等等進行研究。例如去研究lwip協議棧的實現等等。
我寫過一個qemu上的e1000網卡設備的驅動,針對于qemu riscv64的virt版本。
https://github.com/bigmagic123/rt-thread/tree/riscv_virt_network
針對rt-thread的qemu riscv的virt64版本,可以進行如下的設置。
其中其底層的驅動為e1000,為qemu提供了網絡數據的收發、以及網絡數據包的接收中斷服務。
借助rt-thread上適配的lwip驅動程序,可以非常容易的實現上層網絡編程應用。
比如借助rt-thread的IOT軟件包
使能一些例子
最后可以測試一下web的通信情況。
當然,上述這個例子只是一個非常簡單網絡編程的演示,其中socket的編程部分實際上是通用的,無論是arm架構、mips架構或者riscv架構,借助qemu的好處在于可以采用一個架構平臺,進行協議棧或者上層開發后,可以無縫的移植到自己的真實的板子上,非常方便進行整體業務的聯調。
對于qemu riscv64 virt平臺,整個系統從底層的virtio或者e1000的網卡設備提供數據的收發、中斷消息機制之外,rt-thread也通過提供lwip協議棧的支持,這樣整個網絡鏈路才是比較合理的。開發起來也比較的方便。
在物聯網模塊的開發方面,采用qemu,也可以不用rt-thread,直接裸機驅動virt上的e1000網卡驅動,然后借助對寄存器的讀寫操作,移植其他的網絡協議棧,從而實現網絡數據的收發工作,網絡編程的上層對接阿里云、騰訊云等云服務器,非常容易的實現業務的編程,同時調試方面,qemu的gdb調試功能也是非常的強大,也可以dump出內存進行ram parse分析。
4.嵌入式圖形開發
因為嵌入式編程的實現,也會多少涉及到圖形編程,當接上LCD屏后,其中的顯示驅動對上層應用暴露出來的實際上是一塊顯存,通過對顯存的讀寫,flush進行lcd的圖像更新。
在圖像編程方面,qemu也提供了顯示窗口。這種顯示窗口可以為gui相關的開發工作帶來很多便捷。
關于嵌入式圖像編程,可以參考
rt-threadsp
aspberry-pi
aspi3-64
相關的bsp,只需要完善顯示程序即可。
可以尋找一張bmp的圖片,圖片大小為800x480的圖片。
利用Image2Lcd的工具進行圖像轉換成數組。
最后將數組程序編譯到程序代碼中,將該數組放到顯存中即可。
一切準備就緒后,就能夠進行顯示器的開發了。
#define LCD_BUF_SIZE (800 * 480)
extern unsigned char gImage_1[];
void lcd_test()
{
struct rt_device *lcd;
struct rt_device_graphic_info *test_lcd_info;
test_lcd_info = rt_malloc(sizeof( struct rt_device_graphic_info));
//找到lcd lcd = (struct rt_device *)rt_device_find(“lcd”);
rt_kprintf(“lcd get info:
”);
rt_device_control(lcd, RTGRAPHIC_CTRL_GET_INFO, test_lcd_info);
rt_kprintf(“lcd width is %d
”, test_lcd_info-》width);
rt_kprintf(“lcd height is %d
”, test_lcd_info-》height);
rt_kprintf(“lcd bpp is %d
”, test_lcd_info-》bits_per_pixel);
rt_memcpy(test_lcd_info-》framebuffer, &gImage_1[0], LCD_BUF_SIZE*4);
//刷新圖片
rt_device_control(lcd, RTGRAPHIC_CTRL_RECT_UPDATE, NULL);
rt_thread_delay(20);
}
如果要進行觸摸操作,qemu也進行了基本的支持,只需移植相關的底層驅動即可進行開發工作,非常的高效和方便。
5.進行嵌入式Linux的開發
進行Linux開發工作,如果深入去學習某一個設備的開發,當然少不了不斷的對Linux的內核部分進行編譯和下載,這是一個十分耗時的工作,如果只是進行應用程序的開發,可能感覺不到許多的差別,但是一旦涉及到Linux內核的分析,頻繁的下載也會浪費大量的時間。
當使用qemu后,這種問題將會得到很好的解決,采用qemu進行內核層面的裁剪,進行內核層面模塊化的驗證工作后,再進行移植,讓其變得更加通用,不僅僅針對這個項目有效,而且也為自己積累了很多經驗。
從分析linux的loader,分析Linux的驅動框架,內存管理,多核管理等等,都能夠非常方便進行調試工作。
在實際硬件設備沒有穩定之前,對軟件項目進行評估,qemu是非常好用的工具。
6.小結
接觸很多軟件開發工作中,使用qemu確實能夠在一定程度上節省時間,提高軟件調試與分析的效率。
用軟件模擬硬件的操作行為,本質上來說和實際的硬件操作區別不大,因為在嵌入式編程中,最底層的指令集的行為已經在qemu中實現的很好了,硬件模擬方面,qemu也大致能夠模擬操作寄存器后,處理器的行為,這些在對qemu的底層支持和學習的過程中已經進行了大量的實驗和研究。
理解qemu的使用,會對嵌入式軟件原理有著更加深刻的理解,從更大的層面上來說,虛擬化的行為本來就是一種很好的解決方案,去設計一個嵌入式軟件方案,去演示一個底層軟件,或者節約下載調試時間,開發嵌入式上層業務系統軟件的功能層面來說,qemu都是值得去研究和使用的工具。
編輯:jq
-
顯示器
+關注
關注
21文章
4983瀏覽量
140100 -
驅動
+關注
關注
12文章
1844瀏覽量
85345 -
編程
+關注
關注
88文章
3623瀏覽量
93798 -
LCD屏
+關注
關注
0文章
122瀏覽量
15457
原文標題:嵌入式編程中使用qemu能夠做什么?
文章出處:【微信號:Embeded_IoT,微信公眾號:嵌入式IoT】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論