You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QEMU双实例Arm Cortex-M7共享内存读写无输出问题排查

问题:独立QEMU实例无法访问自定义共享内存地址0x10000000

我编写了两段代码:一段将字符串“Hello”写入内存地址0x10000000,另一段从该地址读取内容并打印。两段代码的链接脚本中均将0x10000000定义为共享内存,在两个独立的QEMU实例中运行(模拟Arm Cortex-M7处理器,目标机为lm3s811evb)。目前两段代码均已运行,但控制台无任何输出。使用GDB调试时,无法访问0x10000000地址的内存。

写入代码

// 写入目标内存地址
#define MEMORY_ADDRESS 0x10000000

// 将字符串写入指定内存地址的函数
void write_string_to_memory(char* address, const char* str) {
    while (*str != '\0') {
        *address = *str;
        address++;
        str++;
    }
    // 字符串末尾添加终止符
    *address = '\0';
}

// 入口函数
void main() {
    // 将内存地址转换为字符指针
    char* memory_address = (char*)MEMORY_ADDRESS;

    // 向指定地址写入字符串"hello"
    write_string_to_memory(memory_address, "hello");

    // 无限循环(暂停程序)
    while (1);
}

链接脚本

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000
    SHARED_MEMORY (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00001000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000
}

SECTIONS
{
    .text :
    {
        _text = .;
        KEEP(*(.isr_vector))
        *(.text*)
        *(.rodata*)
        _etext = .;
    } > FLASH

    .data : AT(ADDR(.text) + SIZEOF(.text))
    {
        _sdata = .;
        *(vtable)
        *(.data*)
        _edata = .;
    } > SRAM

    .bss :
    {
        _sbss = .;
        *(.bss*)
        *(COMMON)
        _ebss = .;
    } > SRAM

    .shared_memory :
    {
        /* 定义共享内存段 */
        _shared_memory_start = .;
        *(.shared_memory*)
        _shared_memory_end = .;
    } > SHARED_MEMORY
}

编译运行命令

arm-none-eabi-ld -T linker_lm3s811.ld main1-string.o startup1.o -o main1-string.elf
./qemu-system-arm -M lm3s811evb -kernel main1-string.elf -nographic

GDB调试信息

Breakpoint 1, main () at main1-string.c:18
18          char* memory_address = (char*)MEMORY_ADDRESS;
(gdb)  x/s 0x10000000
0x10000000:     <error: Cannot access memory at address 0x10000000>

解决方案

1. QEMU lm3s811evb默认不识别自定义地址空间

QEMU对lm3s811evb的模拟严格遵循真实芯片的内存映射,而真实LM3S811芯片不存在0x10000000起始的内存区域。你在链接脚本中自定义的地址空间,QEMU不会主动创建,因此无法访问。

2. 跨QEMU实例实现共享内存的正确方法

两个独立QEMU实例默认完全隔离,需借助主机共享内存文件实现数据互通:

步骤1:在主机创建共享内存文件

# 创建4KB大小的共享内存文件(匹配你定义的0x1000长度)
truncate -s 4k /tmp/qemu_shared_mem

步骤2:启动QEMU时映射共享内存到目标地址

修改QEMU启动命令,通过参数将主机共享内存映射到目标机的0x10000000地址:

# 启动写入程序的QEMU实例
./qemu-system-arm -M lm3s811evb -kernel main1-string.elf -nographic \
  -device virtio-mem-pci,memdev=shmem0 -object memory-backend-file,id=shmem0,path=/tmp/qemu_shared_mem,size=0x1000,share=on

# 启动读取程序的QEMU实例,绑定同一个共享内存文件
./qemu-system-arm -M lm3s811evb -kernel main2-read.elf -nographic \
  -device virtio-mem-pci,memdev=shmem0 -object memory-backend-file,id=shmem0,path=/tmp/qemu_shared_mem,size=0x1000,share=on

3. 修复内存访问权限问题

即使完成映射,Cortex-M的MPU(内存保护单元)可能阻止地址访问:

  • 若启用MPU,需添加对0x10000000~0x10000FFF区域的读写权限配置
  • 你的链接脚本已将SHARED_MEMORY设为rwx,这部分无需修改

4. 控制台无输出排查点

如果读取程序有打印逻辑但无输出,检查:

  • 是否正确初始化UART串口(lm3s811evb的UART0默认对应QEMU控制台)
  • 打印函数是否基于裸机实现(裸机环境无标准库printf支持,需自行实现串口发送逻辑)

内容的提问来源于stack exchange,提问作者ankita7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:01:01