日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux利器:QEMU!用它模拟开发板能替代真开发板?

發布時間:2023/12/20 linux 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux利器:QEMU!用它模拟开发板能替代真开发板? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

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系統吧。

QEMU安裝

我們安裝的是 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

第一步:U-Boot 代碼下載:

git clone https://gitlab.denx.de/u-boot/u-boot.git

下載完后,可以看到 configs 目錄下有針對這款開發板的配置文件:

vexpress_ca9x4_defconfig

第二步:編譯

make vexpress_ca9x4_defconfig make?CROSS_COMPILE=arm-linux-gnueabihf-?all

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

編譯 Buildroot

啟動一個 Arm Linux 系統,一般都要必須的三件套:Bootloader、Linux Kernel、rootfs(根文件系統)。

在很久以前,制作 rootfs 是一件很麻煩的事情:交叉編譯 busybox,然后手動建立標準的 Linux 系統目錄,再把編譯 busybox 生成的各種文件和庫拷貝過來。如果還需要其他的模塊,再交叉編譯。如果交叉編譯的某個模塊依賴其他的庫,還想要辦法解決這個依賴關系。最后還要手動建立設備節點,設置對應的權限。一步一步做下去,任意一個環節都不能出錯。否則啟動的時候不知道會遇到什么莫名其妙的問題。

Buildroot 項目出現之后,如同它的 Slogan:MakingEmbedded Linux Easy,構建 rootfs 就變得輕松了許多,用一個群友的話說:

自從用了buildroot,我就告別了刀耕火種的野蠻生活。那種文件系統自己定制,需要任何工具都要自己下源碼交叉編譯然后被各種庫問題搞的焦頭爛額的時代一去不復返了。

◆?代碼下載:

git clone git://git.buildroot.net/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

交叉編譯工具 Linaro GCC 的安裝可以參考前面的文章:一次搞定 Arm Linux 交叉編譯。

Build options選項:

第一個選項是設置最后生成的配置文件的保存路徑,buildroot 可以針對不同的板子生成特定的 defconfig 文件,默認保存在 configs 目錄下。

自己修改各項配置后,執行make savedefconfig命令,就會生成新的 defconfig 文件:

下次編譯之前,可以直接執行make ca9_mini_defconfig命令來加載已有的配置。

第二個選項設置 buildroot 下載的各種第三方包的存儲路徑,默認在 dl 目錄下:

設置 Toolchain

因為這里使用電腦上自己安裝的 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 并編譯。

退出執行make命令開始編譯。

Buildroot 編譯的過程中會自動通過網絡下載需要的各種包,所以要保證網絡暢通。

編譯完成后輸入信息如下圖:

編譯Linux Kernel

1)代碼下載

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.

2)配置

把前面 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

編譯完成。

如果在編譯 Linux kernel 或者 u-boot 的過程中,遇到什么錯誤,可以參考我之前的文章:LinuxKernel 和 U-Boot 編譯的那些事。

啟動QEMU

前面說了,QEMU 可以模擬 sd 卡等外設。我們就把編譯好的固件放在一個模塊的 sdcard 上,讓 QEMU 從這張模擬的 sd 卡上啟動 Linux 系統:

制作 sd 卡鏡像,并將它格式化成 fat 格式:

dd if=/dev/zero of=sd.img bs=4096 count=4096 mkfs.vfat sd.img

把編譯好的 kernel zImage 和 dtb 文件拷貝到 sd.img 中

sudo?mount?sd.img?/mnt/?-o?loop,rw sudo?cp?arch/arm/boot/zImage?/mnt/ sudo?cp?arch/arm/boot/dts/vexpress-v2p-ca9.dtb?/mnt/ sudo?umount?/mnt

啟動 QEMU

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

-M 參數指定啟動的板子為 vexpress-a9。

-m 指定這塊板子的內存為 512MB。

-kernel 指定 QEMU 啟動時首先執行的程序,我們這里指定為前面編譯好的 u-boot 可以執行文件。

-sd 參數指定前面制作的 sd.img。

因為我們這里是從命令行啟動,所以加了 nographic 參數。

可以看到 u-boot 已經順利啟動并進入命令,下面我們來啟動 Linux Kernel。

首先通過 fatload 命令把 sd.img 里面的 zImage 和 dtb 文件讀到開發板的內存中:

fatload?mmc?0:0 0x62008000?zImage fatload?mmc?0:0?0x64008000?vexpress-v2p-ca9.dtb

這里面的 0x62008000 和 0x64008000 分別對應 zImage 和 dtb 文件在內存中的加載地址,這兩個地址是怎么來的呢:

在 Linux Kernel 中,有如下定義:?

這個 textofs 定義的就是 Linux kernel zImage 執行地址對應的內存偏移地址,默認偏移為 0x8000。

在 u-boot 命令行中輸入bdinfo命令,可以查到這塊開發板內存的起始地址:

可以看到這塊開發板的內存其實地址為 0x60000000,所以對應內核的起始地址為:0x62008000

dtb 的加載地址沒有特別的要求,一般注意和 Linux Kernel Image 避開,不要重疊即可。

通過 bootz 命令啟動 Linux Kernel:

bootz 0x62008000 - 0x64008000

?

啟動到最后輸入root就可以進入命令行控制臺。

到這里,我們就順利的在 QEMU 上把 Arm linux 運行起來了。

QEMU 能否完全替代開發板?

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 就是一款召之即來的利器!

END

? 推薦閱讀:

? ??專輯|Linux文章匯總

? ??專輯|程序人生

? ??專輯|C語言

嵌入式Linux

微信掃描二維碼,關注我的公眾號?

總結

以上是生活随笔為你收集整理的Linux利器:QEMU!用它模拟开发板能替代真开发板?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。