WSL 下面 Buildroot + QEMU 环境记录一下
下面是你在使用 Buildroot + QEMU 构建和运行嵌入式 Linux 系统时的 完整安装和使用流程(含命令),适用于在 WSL(Ubuntu)环境下进行开发。
一、Buildroot 安装与构建流程
1. 获取 Buildroot 源码
wget https://buildroot.org/downloads/buildroot-2025.05-rc1.tar.gz
tar -xzf buildroot-2025.05-rc1.tar.gz
mv buildroot-2025.05-rc1 buildroot-master
cd buildroot-master
2. 配置 Buildroot(可选)
你可以用默认配置开始:
make qemu_arm_versatile_defconfig
或者进入图形界面定制:
make menuconfig
推荐配置调整(在 menuconfig 中):
- Target options→ Architecture:- ARM (little endian)
- Toolchain→- Build cross toolchain:- Yes
- System configuration→- Root password:空
- Target packages→ 勾选常用工具(如- nano,- htop,- busybox,- dropbear等)
- Filesystem images→ Enable- ext2/3/4 root filesystem
3. 编译 Buildroot 系统
make -j$(nproc)
这个过程特别慢会下载很多第三方库
 出现 make clean 之后再make
构建完成后,输出文件在:
output/images/
├── rootfs.ext2      # 根文件系统
├── zImage           # 内核镜像
├── vexpress-v2p-ca9.dtb  # (如果你配置的是 vexpress 板子)
二、QEMU 安装
1. 安装 QEMU for ARM(如果未安装):
sudo apt update
sudo apt install qemu-system-arm
三、使用 QEMU 启动模拟器
直接运行下面的start-qemu.sh 脚本就行

四、挂载/编辑 rootfs.ext2(可选)
你可以在宿主机编辑 rootfs.ext2 的内容,比如添加文件:
sudo mount -o loop output/images/rootfs.ext2 /mnt
sudo cp hello /mnt/root/
sudo umount /mnt
五、交叉编译你自己的程序
假设你有 hello.c:
#include <stdio.h>
int main() {printf("Hello from ARM!\n");return 0;
}
使用 Buildroot 提供的交叉编译器:
output/host/bin/arm-*-gcc hello.c -o hello
然后复制到 rootfs 中,如上所述。
常见问题排查
| 问题 | 解决方案 | 
|---|---|
| cannot use stdio by multiple character devices | 改用 -serial mon:stdio替代-serial stdio | 
| QEMU 启动后无输出 | 检查 console=参数,是否和板子匹配 (ttyAMA0for ARM) | 
| rootfs 无法挂载 | 确保用 root=/dev/mmcblk0 rw rootwait(SD卡模拟) | 
| 无法编译 | 执行 make clean && make,确保 host 系统有完整工具链(如build-essential,libncurses-dev等) | 
如果你有特定的需求,比如:
- 添加 SSH 支持
- 使用 initramfs 而非 rootfs.ext2
- 支持网络功能、NFS、USB、I2C 等
可以继续告诉我,我可以帮你扩展配置。






#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>// PL061 GPIO 寄存器地址(基于 Versatile Express,vexpress-a9)
// 参考:ARM Versatile Express 技术参考手册
#define GPIO_BASE 0x10013000 // GPIO 控制器基地址
#define GPIO_DIR  0x400      // 方向寄存器偏移(0x400)
#define GPIO_SET  0x01C      // 数据寄存器偏移(设置高电平)
#define GPIO_CLEAR 0x028     // 数据寄存器偏移(清除低电平)
#define GPIO_PIN  (1 << 0)   // 使用 GPIO0(可根据需要修改)int main() {int fd;void *gpio_base;volatile unsigned int *gpio_dir;volatile unsigned int *gpio_set;volatile unsigned int *gpio_clear;// 打开 /dev/mem 以访问物理内存fd = open("/dev/mem", O_RDWR | O_SYNC);if (fd < 0) {perror("无法打开 /dev/mem");return 1;}// 映射 GPIO 寄存器gpio_base = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);if (gpio_base == MAP_FAILED) {perror("mmap 失败");close(fd);return 1;}// 设置寄存器指针gpio_dir = (unsigned int *)(gpio_base + GPIO_DIR);gpio_set = (unsigned int *)(gpio_base + GPIO_SET);gpio_clear = (unsigned int *)(gpio_base + GPIO_CLEAR);// 设置 GPIO0 为输出*gpio_dir |= GPIO_PIN;printf("LED 点灯程序开始运行...\n");fflush(stdout);// 循环点亮和熄灭 LEDwhile (1) {// 点亮 LED(设置 GPIO0 高电平)*gpio_set = GPIO_PIN;printf("LED 点亮\n");fflush(stdout);sleep(1);// 熄灭 LED(设置 GPIO0 低电平)*gpio_clear = GPIO_PIN;printf("LED 熄灭\n");fflush(stdout);sleep(1);}// 清理(实际上不会到达这里)munmap(gpio_base, 4096);close(fd);return 0;
}

 

