win7中编译qemu-system-arm,仿真arm设备

1、下载qemu源码,实验通过的是5.2.0,

2、下载msys2,在msys2中通过pacman指令安装mingw32,mingw64编译不能通过。

3、运行mingw32.exe,安装依赖包,缺什么安装什么,编译过程有提示

4、不用mingw32自带的python,mingw32默认安装的是3.12,配置时总是提示Cannot use 3.12, Python >= 3.6 is required。3.12竟然小于3.6!!! 估计用的字串比较,没找到好的跳过的办法,后来用另外下载的python3.8

5、进入qemu源码文件夹,配置,关闭不必要的功能,

bash 复制代码
./configure \
  --target-list=arm-softmmu \
  --python="C:/Users/Administrator/AppData/Local/Programs/Python/Python38/python.exe" \
  --audio-drv-list= \
  --block-drv-rw-whitelist= \
  --block-drv-ro-whitelist= \
  --disable-slirp \
  --disable-vde \
  --disable-netmap \
  --disable-libiscsi \
  --disable-libnfs \
  --disable-sdl \
  --disable-gtk \
  --disable-vnc \
  --disable-cocoa \
  --disable-gnutls \
  --disable-nettle \
  --disable-gnutls \
  --disable-gcrypt \
  --disable-seccomp \
  --disable-brlapi \
  --disable-curl \
  --disable-libxml2 \
  --disable-live-block-migration \
  --disable-numa \
  --disable-tpm \
  --disable-libssh \
  --disable-virtfs \
  --disable-virtiofsd \
  --disable-xen \
  --disable-rdma \
  --disable-pvrdma \
  --disable-tools \
  --disable-docs \
  --disable-user \
  --disable-guest-agent

6、进入 build ,用ninja -j$(nproc)编译,就可生成 qemu-system-arm.exe

7、修改挂载的设备在qemu->hw->arm,versatilepb.c(这个看各人用什么开机器仿真)versatile_init()函数中修改,可把所有设备初始化都注释了,自己定义。从 cpu = ARM_CPU(cpuobj);/*之后一直到*/versatile_binfo.ram_size = machine->ram_size;

8、中间添加 my_soc_init(sysmem); 这个函数中实现 内存、设备

cpp 复制代码
//flash固件
//0x00000000-0x00400000
    {
   		MemoryRegion *ram2 = g_new(MemoryRegion, 1);
   		uint8_t *ram2_data = g_malloc(0x400000);
   		memory_region_init_ram_ptr(ram2, NULL, "ram-flash", 0x400000, ram2_data);
   		memory_region_add_subregion(sysmem, 0x00000000, ram2);
       }
//内存
  //0x20000000-0x20800000
    {
		MemoryRegion *ram2 = g_new(MemoryRegion, 1);
		uint8_t *ram2_data = g_malloc(0x800000);
		memory_region_init_ram_ptr(ram2, NULL, "ram-20000000", 0x800000, ram2_data);
		memory_region_add_subregion(sysmem, 0x20000000, ram2);
    }
//设备
   /*  0xC0C82000 - 定时器 (4KB) */
    {

        MemoryRegion *mr = g_new(MemoryRegion, 1);
        memory_region_init_io(mr, NULL, &timer_ops, NULL,
                            "timer", 0x1000);
        memory_region_add_subregion(sysmem, 0xC0C82000, mr);
        fprintf(stderr, "  已映射: 定时器 0xC0C82000-0xC0C82FFF (4KB)\n");
    }

static uint64_t timer_read(void *opaque, hwaddr offset, unsigned size)
{
    if (offset == 0x08) {
        /* 计数器寄存器:每次读取增加 1000 */

        return ((uint32_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)-canon_timer_counter);
    }

    else if (offset == 0x0C) {
        /* 控制寄存器:总是返回 1(已启动) */
        return 1;
    }
    else if(offset == 0x404){
    	 return 1;
    } else{
    	 fprintf(stderr, "my soc 未知地址:0x%8x\n",(uint32_t)opaque);
    	return 0;
    }
}

//
static void timer_write(void *opaque, hwaddr offset,
                       uint64_t value, unsigned size)
{
	 if (offset == 0x0c) {
	       //计数器寄存器重置
	        canon_timer_counter =(uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));

	        return ;
	    }

}

static const MemoryRegionOps timer_ops = {
    .read = timer_read,
    .write = timer_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = { .min_access_size = 4, .max_access_size = 4 },
    .impl = { .min_access_size = 4, .max_access_size = 4 },
};
//========0xC0C82000-0xC0C82FFF

9、再下一gdb,将cmd建立一个快捷方式,将下面文件保存存成bat文件,1键调试

cpp 复制代码
@echo off
REM chcp 65001 >nul
REM setlocal enabledelayedexpansion

title bin调试工具
color 0A

REM 注意: 等号两边不能有空格!
set CONFIG_FILE=qemu_debug_config.ini
set QEMU_PATH=E:\SoftEngin\tools\qemu32
set GDB_PATH=E:\SoftEngin\tools\eabi\bin
set QEMU=qemu-system-arm.exe
set GDB=arm-none-eabi-gdb.exe
set FIRMWARE_FILE=firmware.bin
set QEMU_MACHINE=versatilepb
set QEMU_CPU=arm946
set QEMU_MEMORY=64M
set DEBUG_PORT=1234
set MONITOR_PORT=5555
set ARCHITECTURE=arm
set ENTRY_POINT=0x000000
set LOAD_BASE=0x000000
set BREAKPOINTS=0x10C
set LOG_DIR=debug_output
set LOG_FILE=log.txt
set PYTHONPATH=E:\SoftEngin\tools\Python27
echo %PATH% | findstr /i "%QEMU_PATH%" >nul
if errorlevel 1 (  
 set path=C:\windows\system32;C:\windows;E:\SoftEngin\tools\Python27;%GDB_PATH%;%QEMU_PATH%
) 

echo 步骤1: 检查端口占用
netstat -an | findstr ":1234" >nul
if not errorlevel 1 (
    echo 警告: 端口1234被占用
    echo 尝试停止占用进程...
    for /f "tokens=5" %%p in ('netstat -ano ^| findstr ":1234"') do (
        taskkill /F /PID %%p 2>nul && echo 已停止进程: %%p
    )
    timeout /t 1 /nobreak >nul
)



REM 检查必要文件




if not exist "%FIRMWARE_FILE%" (
    echo 错误: 固件文件不存在: %FIRMWARE_FILE%
    pause
    exit /b 1   
)

if not exist "%QEMU_PATH%\%QEMU%" (
    echo 错误: QEMU文件不存在: %QEMU%    
    pause
    exit /b 1
)

REM 比较文件时间
for %%I in ("E:\SoftEngin\tools\msys32\home\Administrator\qemu-5.2.0\build\%QEMU%") do set SOURCE_TIME=%%~tI
for %%I in ("%QEMU_PATH%\%QEMU%") do set TARGET_TIME=%%~tI
if "%SOURCE_TIME%" gtr "%TARGET_TIME%" (

    echo qemu被重新编译,更新。
    copy /Y "E:\SoftEngin\tools\msys32\home\Administrator\qemu-5.2.0\build\%QEMU%" "%QEMU_PATH%\%QEMU%"   
) else (
 REM   echo 目标文件已是最新,无需更新。
)



if not exist "%GDB_PATH%\%GDB%" (
    echo 错误: GDB文件不存在: %GDB%
    echo 注意: 需要arm-none-eabi-gdb.exe,不是普通gdb
    pause
    exit /b 1
)



REM 创建日志目录
if not exist "!LOG_DIR!" mkdir "!LOG_DIR!"

REM 处理命令行参数
if not "%~1"=="" set BREAKPOINTS=%~1

echo ====================================================
echo                调试配置
echo ====================================================
echo 固件文件:   %FIRMWARE_FILE%
echo QEMU机器:   %QEMU_MACHINE%
echo CPU类型:    %QEMU_CPU%
echo 内存大小:   %QEMU_MEMORY%
echo 调试端口:   %DEBUG_PORT%
echo 监控端口:   %MONITOR_PORT%
echo 入口地址:   %ENTRY_POINT%
echo 断点地址:  	%BREAKPOINTS%
echo ====================================================
echo.

echo 正在启动QEMU模拟器...
echo.

REM 启动QEMU(修复了参数格式)    -m %QEMU_MEMORY% ^
start "QEMU 模拟器" /B "%QEMU%" ^
    -M %QEMU_MACHINE% ^
    -cpu %QEMU_CPU% ^
    -m %QEMU_MEMORY% ^
    -device loader,file="%FIRMWARE_FILE%",addr=0x0  ^
    -s -S ^
    -monitor none ^
    -nographic ^
    -nodefaults ^
    -serial none 
  
echo 等待2秒让QEMU启动...
timeout /t 2 /nobreak >nul

echo.

REM 检查QEMU是否在运行
tasklist /FI "IMAGENAME eq %QEMU%" 2>nul | findstr "qemu-system-arm" >nul
if errorlevel 1 (
    echo 错误: QEMU可能没有成功启动   
    exit /b 1
   
)



echo 启动GDB调试器...
%GDB% -q ^
	-ex "target remote :%DEBUG_PORT%" ^
    -ex "b *%BREAKPOINTS%" ^
    -ex "display/i $pc" ^
    -ex "c"
echo.


taskkill /F /IM "%QEMU%" >nul 2>&1
if errorlevel 1 (
    echo QEMU进程未运行或无法终止
) else (
    echo QEMU进程已强制终止
)

taskkill /F /IM "%GDB%" >nul 2>&1
if errorlevel 1 (
    echo GDB进程未运行或无法终止
) else (
    echo GDB进程已强制终止
)


echo 调试会话结束
timeout /t 1 /nobreak >nul
exit /b 0

10、找不到dll可以下载官方qemu包或者用pacman安装qemu,将里面的dll复制到编译的qemu-system-arm.exe文件一起。注意32位软件要对应,否则会出现运行错误。

相关推荐
zhangx1234_1 小时前
C语言 数据在内存中的存储
c语言·开发语言
嵌入小生0072 小时前
双向链表、双向循环链表之间的异同---嵌入式入门---Linux
linux·c语言·数据结构·链表·嵌入式·小白
BoJerry7772 小时前
数据结构——单链表(不带头)【C】
c语言·开发语言·数据结构
进击的小头2 小时前
设计模式组合应用:智能硬件控制系统
c语言·设计模式
EmbedLinX3 小时前
FreeRTOS 学习笔记
c语言·笔记·学习
学嵌入式的小杨同学3 小时前
【Linux 封神之路】文件操作 + 时间编程实战:从缓冲区到时间格式化全解析
linux·c语言·开发语言·前端·数据库·算法·ux
浪客灿心3 小时前
Linux的Ext系列文件系统
linux·运维·服务器·c语言
日拱一卒——功不唐捐4 小时前
交换排序:冒泡排序和快速排序(C语言)
c语言·数据结构·算法
敲皮裤的代码4 小时前
《C语言》操作符详解
c语言
小魏每天都学习13 小时前
【算法——c/c++]
c语言·c++·算法