Linux利器:QEMU!用它模擬開發板能替代真開發板?

2021-12-27 嵌入式大雜燴

不想錯過我的推送,記得右上角-查看公眾號-設為星標,摘下星星送給我!

QEMU,搞嵌入式開發的一定不陌生,最近各大群裡都討論瘋了,說它是Linux利器一點也不誇張。它是一款知名的而且開源的模擬器(官網:https://www.qemu.org/),它能在 X86 PC 上運行(其實它也可以在你的 Arm 開發板上運行,我們今天先不討論這種場景),能夠模擬 Arm、MIPS、RISC-V 等各種 CPU 和開發板,以及 網卡、音效卡、鍵盤、sdcard、emmc、usb等各種外設。

你可以把它當作一塊召之即來的開發板,在上面運行 U-Boot、Linux Kernel、甚至 Ubuntu 等各種軟體和作業系統。

有時候我們想體驗一下 mainline 上最新的 U-Boot 或者 Linux Kernel,可是卻發現手邊沒有合適的板子,或者手邊的板子搭載的 U-Boot 和 Linux Kernel 版本都比較低,這時候 QEMU 可以幫你迅速實現這一願望。

我是Andy, Linux內核開發者。現從事Arm晶片上Linux 系統移植和優化工作,並向 u-boot 和 linux kernel開源社區貢獻了大量補丁。從 Cortex-M3 到 Arm64,RT-Thread 到 Linux kernel, hack 不止,其樂無窮。受達爾聞邀約為嵌入式開發愛好者分享這篇好文,更多我的文章,可以關注我的公眾號:HackforFun接下來我帶領大家一起來感受一下QEMU的強大和樂趣:手把手教你在 Ubuntu 系統中通過 QEMU 來運行基於 Arm CPU 的Linux系統吧。我們安裝的是 Arm 版本的 QEMU,如果直接在 Ubuntu 上用sudo apt install qemu-system-arm命令安裝的話,得到的 QEMU 版本比較舊,最好直接通過源碼去編譯。

我在 Ubuntu 18.04 系統上發現系統默認安裝的 QEMU 在圖形模式(不帶 -nographic 參數)下無法啟動。

參考上面步驟編譯成功後,得到:qemu-system-arm和qemu-system-aarch64。前者用來模擬 32 位的 Arm cpu,比如 Arm9 /Arm11、 Cortex-A7/A9/A15 。後者用來模擬 64 位的 Arm cpu,比如 Arm Cortex A53,A57。可以用qemu-system-arm -machine help命令來查看所支持的開發板:

是不是有很多熟悉的開發板都在裡面,i.MX、EXYNOS 這些知名的晶片都有包含。

這裡我們使用 vexpress-a9 這款開發板。vexpress-a9 是 Arm 公司自己設計的一款 4 核 Cortex-A9 開發板,U-Boot、Linux Kernel 和 QEMU 對這款開發板都做了完整的支持。第一步:U-Boot 代碼下載:下載完後,可以看到 configs 目錄下有針對這款開發板的配置文件:

第二步:編譯

make vexpress_ca9x4_defconfigmake CROSS_COMPILE=arm-linux-gnueabihf- all

最終編譯生成 elf 格式的可執行文件 u-boot 和純二進位文件u-boot.bin,其中 QEMU 可以啟動的為 elf 格式的可執行文件 u-boot。

啟動一個 Arm Linux 系統,一般都要必須的三件套:Bootloader、Linux Kernel、rootfs(根文件系統)。在很久以前,製作 rootfs 是一件很麻煩的事情:交叉編譯 busybox,然後手動建立標準的 Linux 系統目錄,再把編譯 busybox 生成的各種文件和庫拷貝過來。如果還需要其他的模塊,再交叉編譯。如果交叉編譯的某個模塊依賴其他的庫,還想要辦法解決這個依賴關係。最後還要手動建立設備節點,設置對應的權限。一步一步做下去,任意一個環節都不能出錯。否則啟動的時候不知道會遇到什麼莫名其妙的問題。Buildroot 項目出現之後,如同它的 Slogan:MakingEmbedded Linux Easy,構建 rootfs 就變得輕鬆了許多,用一個群友的話說:自從用了buildroot,我就告別了刀耕火種的野蠻生活。那種文件系統自己定製,需要任何工具都要自己下源碼交叉編譯然後被各種庫問題搞的焦頭爛額的時代一去不復返了。

Buildroot 代碼倉庫默認只包含一個編譯框架,所以代碼量很小,下載起來很快。真正構建 rootfs需要的各種代碼包是根據你的配置選項,在編譯的時候才開始下載的。Buildroot 提供了和 U-Boot、Linux Kernel 等主流開源項目一樣的 menucoinfig 配置接口,可以通過make help來查詢所支持的各種命令:

開發者只要執行make menuconfig命令,就能通過這個熟悉的界面去選擇自己需要的各種組件,定製自己的 rootfs:首先要配置的是 Target options 選項:大部分 Arm 都是小端模式,所以選上 little endian 。這款開發板的 CPU 是 cortex-A9。我們將使用 Linaro GCC 進行編譯,Linaro 的 GCC 默認都打開了 hardfloat 的支持,所以選上 VFP extension 和 EABIhf

第一個選項是設置最後生成的配置文件的保存路徑,buildroot 可以針對不同的板子生成特定的 defconfig 文件,默認保存在 configs 目錄下。自己修改各項配置後,執行make savedefconfig命令,就會生成新的 defconfig 文件:

下次編譯之前,可以直接執行make ca9_mini_defconfig命令來加載已有的配置。第二個選項設置 buildroot 下載的各種第三方包的存儲路徑,默認在 dl 目錄下:

因為這裡使用電腦上自己安裝的 toolchain,所以我們這裡選 External toolchainCustom toolchain然後在 Toolchain path 中填寫 toolchian 在電腦上安裝的位置,如果不知道具體位置,用which命令查看:

另外要注意 Toolchain prefix 這個前綴別寫錯。設置 toolchain 的版本和用來編譯這個 toolchain 的內核頭文件的內核的版本:Toolchain 的版本我們根據 Toolchain 的名字或者通過arm-linux-gnueabihf-gcc  -v 命令就可以查到。編譯 Toolchain 的內核頭文件對應的內核的版本是什麼呢?我們在這個選項上敲 h 鍵,會看到下面的幫助選項:

原來這個版本可以在 toolchain 裡面的 version.h 這個文件查到:
arm-linux-gnueabihf/libc/usr/include/linux/version.h

263680 對應的十六進位為 0x40600,右移 16 位,得到的版本號為 4。這就是上面 4.0.x 的由來。這裡也教給了大家一個小竅門:當我們在 make menuconfig 做配置的時候,如果遇到了看不懂的選項,直接在這個選項上敲 h 鍵,會看到一些有用的幫助信息,對這個選項做進一步解釋。因為 vexpress_a9 內核啟動的控制臺的名字叫做 ttyAMA0,所以我們還要在 :System configuration->Run a getty(login prompt) after boot選項中配置 TTY Port 為 ttyAMA0。否則文件系統掛載後無法進入控制臺。

我們把編譯的 rootfs 以 initramfs 的形式和 Linux Kernel 連結在一起,為了讓根文件系統鏡像儘量小,可以對文件系統採用 lz4 壓縮,所以 Filesystem images 還要做如下配置:

到這裡一個最精簡的 buildroot 已經配置完成。如果還需要其他的命令或者工具,可以在 Target Packages 下面開啟:如果你需要的某個模塊,buildroot 裡面沒有,還可以自己添加:比如加入上面這個補丁,就可以讓 buildroot 在編譯的時候自動下載 https://github.com/rockchip-linux/io.git 並編譯。Buildroot 編譯的過程中會自動通過網絡下載需要的各種包,所以要保證網絡暢通。
git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Linux mainline 已經有了對 vexpress_a9 這塊板子的支持:

這裡面的 ca 就是 Cortex-a 的簡寫,所以 ca9 就是 Cortex-A9,ca15 就是 Cortex-A15.把前面 buildroot 編譯的 rootfs.cpio.lz4 拷貝到 linux kernel 根目錄下:
cp../buildroot/output/images/rootfs.cpio.lz4 .make ARCH=arm vexpress_defconfig

執行make ARCH=arm menuconfig命令,我們修改一些基本的配置:在 General setup->Initramfs source file處填寫 rootfs.cpio.lz4, 就是我們前面從 Buildroot 拷貝過來的 rootfs,這裡面我們把它和內核編譯在一起,當然,rootfs也可以單獨作為一個文件,放在獨立的分區去加載,這種方式我們可以留在以後去嘗試。

在 Kernel hacking->printk and dmesg options選項中選中第一項,這樣列印的內核 log 前面會附帶有時間戳信息,比較好看。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  -j8

前面說了,QEMU 可以模擬 sd 卡等外設。我們就把編譯好的固件放在一個模塊的 sdcard 上,讓 QEMU 從這張模擬的 sd 卡上啟動 Linux 系統: 製作 sd 卡鏡像,並將它格式化成 fat 格式:
dd if=/dev/zero of=sd.img bs=4096 count=4096mkfs.vfat sd.img

把編譯好的 kernel zImage 和 dtb 文件拷貝到 sd.img 中
sudo mount sd.img /mnt/ -o loop,rwsudo cp arch/arm/boot/zImage /mnt/sudo cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb /mnt/sudo umount /mnt

sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel ../uboot-imx/u-boot-nographic  -sd sd.img

-M 參數指定啟動的板子為 vexpress-a9。-kernel 指定 QEMU 啟動時首先執行的程序,我們這裡指定為前面編譯好的 u-boot 可以執行文件。因為我們這裡是從命令行啟動,所以加了 nographic 參數。可以看到 u-boot 已經順利啟動並進入命令,下面我們來啟動 Linux Kernel。 首先通過 fatload 命令把 sd.img 裡面的 zImage 和 dtb 文件讀到開發板的內存中:
fatload mmc 0:0 0x62008000 zImagefatload mmc 0:0 0x64008000 vexpress-v2p-ca9.dtb

這裡面的 0x62008000 和 0x64008000 分別對應 zImage 和 dtb 文件在內存中的加載地址,這兩個地址是怎麼來的呢:這個 textofs 定義的就是 Linux kernel zImage 執行地址對應的內存偏移地址,默認偏移為 0x8000。在 u-boot 命令行中輸入bdinfo命令,可以查到這塊開發板內存的起始地址:可以看到這塊開發板的內存其實地址為 0x60000000,所以對應內核的起始地址為:0x62008000dtb 的加載地址沒有特別的要求,一般注意和 Linux Kernel Image 避開,不要重疊即可。 通過 bootz 命令啟動 Linux Kernel:
bootz 0x62008000 - 0x64008000

到這裡,我們就順利的在 QEMU 上把 Arm linux 運行起來了。QEMU 是一個模擬器,它和真正的開發板還是有一定的區別:它無法完全模擬真實的硬體行為,也很難模擬一個 gpio 讓你去拉高拉低或去點一個 led 燈,又或者去模擬 dram,一個 LCD 接口,讓你去接一個顯示屏….看起來它不能模擬的東西太多了,那它到底有什麼用呢?它的強項是模擬實現那些不涉及具體硬體外設的場景,比如:你想快速體驗一下最新的 u-boot 和 linux kernel,它拿過來就能跑。你想在 Arm 上運行 Ubuntu、Debian 這些時髦的 Linux 發行版,用它就行。你想研究u-boot 或者 linux kernel 的啟動流程,它也很合適。我有時候在具體的開發板上移植 Linux 內核的時候,發現某個流程跑的很異常,我又不確定正常的流程是什麼樣的時候,我就直接拿 QEMU 來跑一下做對比。你想學習 Arm 彙編,完全可以在 QEMU 上跑,配合 GDB 就能單步調試啦。你想學習 Linux 設備樹,它可以拿來做實驗….再或者你想編譯某個開源的項目在 Arm 開發板上運行,而交叉編譯比較困難,就可以考慮直接在 QEMU 上運行一個 Arm Ubuntu 來編譯,也許會簡單很多。假設你以前一直玩單片機、做硬體,也想體驗下 Arm Linux 開發,用 QEMU 試試再適合不過了。用在對的場景,QEMU 就是一款召之即來的利器!

我們是妮mo,達爾聞創始人,只講技術不撩漢的小姐姐。達爾聞在線教育平臺旨在服務電子行業專業人士,提供技能培訓視頻,覆蓋各細分領域熱門話題,比如嵌入式,FPGA,人工智慧等。並針對不同人群量身定製分層級學習內容,例如常用知識點,拆解評測,電賽/智能車/考研等,歡迎關注。

官網:www.darwinlearns.com

B站:達爾聞

QQ群:786258064

相關焦點

  • Linux下使用QEMU構建ARM運行環境
    本文的搭建過程都是基於vexpress A9開發板進行的,這號稱是qemu模擬得最好的arm開發板。 /v3.x/linux-3.17.tar.xz 2.安裝arm的交叉編譯工具鏈sudo apt-get install gcc-arm-linux-gnueabi 3.編譯Linux內核生成vexpress開發板子的config文件:make CROSS_COMPILE=arm-linux-gnueabi
  • 不用買開發板, 使用 SkyEye 模擬 ARM Linux
    對於希望學習 ARM 彙編的同學而言, 購買 ARM 開發板進行板上實測無疑是一個有效的方法,不過購買 ARM 開發板需要一筆費用,而且每次測試都需要連接開發板,比較麻煩。這裡介紹一個 ARM 模擬器——SkyEye,通過 SkyEye 我們可以直接在一臺 PC 上完成 ARM 彙編程序的開發和調試了,擺脫了 ARM 開發板的限制,真是不錯!
  • Hi3516DV300核心板/開發板;Hi3516EV100+4G+AUDIO RTMP開發板;海思系列開發板/核心板定製開發
    開發板智能視頻分析 *集成神經網絡加速引擎,處理性能達 1.0Tops*集成智能計算加速引擎(含跟蹤、人臉校正)                       掃碼了解更多開發板/核心板信息
  • STM32最小系統板教程第一章|開發板資源介紹
    ST官方提供強大且易用的標準庫函數,使開發過程更加方便快捷,我們這款最小系統板性價比高,做工精緻,教程資料詳細,因此對於日常工作的輔助開發,高校學生及廣大初學者入門一款MCU來說,都是一個非常好的選擇。1.1  開發板簡介TJ-STM32F103-Micro是基於STM32F103C8T6的最小系統板。
  • RT-Thread教程一之Linux下開發環境及QEMU配置
    ├── qemu-dbg.bat                     ├── qemu-dbg.sh                      ├── qemu-nographic.sh                ├── qemu.sh         //這是我們的啟動腳本
  • 【BTS002】用CSR8510A10 dongle在S3C2440開發板上體驗BTStack
    本文介紹在ARM開發板上驗證測試BTStack,PC端用的是ubuntu進行編譯,ARM開發板用的是S3C2440,HCI藍牙用的是
  • 【官方視頻教程】QEMU讓你無需開發板即可玩溜RT-Thread
    先來補充幾個概念性的內容:env: 是 RT-Thread 推出的開發輔助工具,針對基於 RT-Thread 作業系統的項目工程,提供編譯構建環境、圖形化系統配置及軟體包管理功能。其內置的 menuconfig 提供了簡單易用的配置剪裁工具,可對內核、組件和軟體包進行自由裁剪,使系統以搭積木的方式進行構建。
  • 使用QEMU搭建ARM64實驗環境
    :vim+ctags+cscope對於Linux愛好者,你是否也有這樣的困擾,為了學習Linux而去購買昂貴的開發版,這大可不必,QEMU模擬器幾乎可以滿足你的需求,足夠你去學習Linux,它能夠模擬x86, arm, riscv等各種處理器架構,本文將向你呈現的不是QEMU/虛擬化的原理解讀,而是如何搭建一個用於學習linux的QEMU環境
  • 預熱 | 萬眾期待的單片機、Linux二合一的STM32MP157開發板亮相
    均支持於100ask_stm32mp157_pro硬體開發平臺,廣泛應用於生活的各種智能場景。百問網STM32mp157開發板GUI演示視頻我們為什麼要做STM32mp157開發板?從教學角度看硬體描述Cortex M4跑單片機、RTOS,用keil開發,跟STM32F103一模一樣Cortex A7*2跑Linux,可以引入SMP的知識,以覆蓋單CPU系統的知識GPU可以實現更炫的GUI效果,可以跑一些AI算法從做產品角度看硬體描述MPU+MCU需要單片機+Linux的場合,用STM32MP157就可以實現GPU可以實現更炫的GUI效果,可以跑一些AI算法性價比高作為多核異構的晶片
  • 三種常用的Arduino開發板
    相信很多讀者都會有這個疑問,甚至有人認為手中的開發板就是Arduino。維基百科上說,「Arduino是一塊單板的微控制器和一整套開發軟體,它的硬體包含一個以ATMEL AVR單片機為核心的開發板和其它各種I/O板;軟體包括一個標準程式語言開發環境和在開發板上運行的燒錄程序。」
  • qemu-pwn-基礎知識
    公眾號預期是一周兩更,所以接下來也會直接以專題的形式更新,周三更新qemu逃逸pwn相關專題,周日更新linux內核pwn相關專題。前言最近開始研究qemu,想看看qemu逃逸相關的知識,看了一些資料,學習pwn qemu首先要對qemu的一些基礎知識有一定的掌握。qemu 是純軟體實現的虛擬化模擬器,幾乎可以模擬任何硬體設備。
  • 眾多的開發板,如何選擇(下)
    不同於我們以前見過的基於8位或16位微控制器的開發板,基於ARM Cortex-的Netduino是使用32-bit 的STM32Fx微控制器打造的。  開發板的作業系統是.NET Micro Framework。這些開發板用C#編譯,可直接用Microsoft Visual C# Express 2010編譯,這使其非常強大和靈活。
  • QEMU/KVM磁碟在線備份
    tag: qemu, kvm, disk, live, backup, incremental, bitmap小慢哥的原創文章,歡迎轉載目錄▪ 1. 本文緣由▪ 2. 最終能實現什麼▪ 3. 環境說明▪ 4. 常用命令一覽▪ 5. 磁碟在線備份的4種方式▪ 6. 查詢磁碟對應的設備名▪ 7. 什麼是bitmap▪ 8.
  • 【小技巧】用SD卡傳文件到開發板就是這麼簡單!
    主機開發環境: Ubuntu9.10內核: Linux2.6.22.6(資料光碟-> systems目錄)文件系統
  • Linux Lab 發布 v0.6,正式支持真實硬體開發板
    Linux Lab 是一套用於 Linux 內核學習、開發和測試的即時實驗室,可以極速搭建和使用,功能強大,用法簡單!Linux Lab Logo可以用它來高效地學習處理器架構、Linux 內核、嵌入式 Linux 系統、C 語言編程、Linux 彙編、Shell 編程等。
  • 設計一款基於樹莓派或Arduino更強大的FPGA開發板
    Arduino 和 樹莓派 開發板是顛覆嵌入式系統開發方式的登峰造極之作。從前,嵌入式系統的開發從硬體開始。項目步驟一般如下:規範系統要求,包括粗略估計處理速度和 I/O 要求。選擇符合功率、性能和價格要求的適當微控制器或微處理器。連接硬體原型。調試硬體原型。如有必要,編寫少量驅動程序代碼來調動線路。
  • 善用虛機搭建網絡拓撲,助力NFV開發——虛機構建篇
    如果您正在進行NFV相關的開發,您可能會碰到如下的調試環境搭建問題:在完成代碼編寫後如何快速進行功能調試和驗證,最好能將編碼、功能調試驗證在本地就可以完成
  • 2021年最佳RP2040開發板
    首先,只有三個模擬輸入引腳,而許多第三方開發板有四個或更多。這意味著您最多只能使用三個電位計或1.5個模擬操縱杆。它也只有2MB的存儲空間,儘管對於大多數編碼來說已經足夠了。另一個縮減是 Pico 使用了 micro-USB 接口,而不是更流行的 USB-C 接口。